[Tarantool-patches] [PATCH 1/2] Allow leading and trailing whitespaces in FromString

Serge Petrenko sergepetrenko at tarantool.org
Sat Jun 6 16:48:25 MSK 2020


05.06.2020 18:41, Chris Sosnin пишет:
> This is needed for SQL, since these whitespaces are allowed in
> conversions from string.
>
> Needed for tarantool/tarantool#4415

Hi! Thanks for the patch!

See one comment below.

> ---
>   decNumber.c | 44 +++++++++++++++++++++++++++++---------------
>   1 file changed, 29 insertions(+), 15 deletions(-)
>
> diff --git a/decNumber.c b/decNumber.c
> index 85deb13..7c53bc3 100644
> --- a/decNumber.c
> +++ b/decNumber.c
> @@ -555,9 +555,9 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>     Unit  *allocres=NULL;            // -> allocated result, iff allocated
>     Int   d=0;                       // count of digits found in decimal part
>     const char *dotchar=NULL;        // where dot was found
> -  const char *cfirst=chars;        // -> first character of decimal part
> +  const char *cfirst=NULL;         // -> first character of decimal part
>     const char *last=NULL;           // -> last digit of decimal part
> -  const char *c;                   // work
> +  const char *c, *p;               // work
>     Unit  *up;                       // ..
>     #if DECDPUN>1
>     Int   cut, out;                  // ..
> @@ -571,6 +571,9 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>     #endif
>   
>     do {                             // status & malloc protection
> +    for (; *chars==' '; ++chars);  // skip leading whitespaces
> +    cfirst=chars;
> +
>       for (c=chars;; c++) {          // -> input character
>         if (*c>='0' && *c<='9') {    // test for Arabic digit
>           last=c;
> @@ -590,13 +593,14 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>             cfirst++;
>             continue;}
>           }
> +      for (p=c; *p==' '; ++p);
Looks like this `for` loop should go below.
>         // *c is not a digit, or a valid +, -, or '.'
>         break;
>         } // c
>   

Here, ^ (This guy's formatting is confusing as hell, I know)

>       if (last==NULL) {              // no digits yet
>         status=DEC_Conversion_syntax;// assume the worst
> -      if (*c=='\0') break;         // and no more to come...
> +      if (*p=='\0') break;         // and no more to come...
>         #if DECSUBSET
>         // if subset then infinities and NaNs are not allowed
>         if (!set->extended) break;   // hopeless
> @@ -626,7 +630,8 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>         // now either nothing, or nnnn payload, expected
>         // -> start of integer and skip leading 0s [including plain 0]
>         for (cfirst=c; *cfirst=='0';) cfirst++;
> -      if (*cfirst=='\0') {         // "NaN" or "sNaN", maybe with all 0s
> +      for (p=cfirst; *p==' '; ++p);
> +      if (*p=='\0') {              // "NaN" or "sNaN", maybe with all 0s
>           status=0;                  // it's good
>           break;                     // ..
>           }
> @@ -635,7 +640,8 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>           if (*c<'0' || *c>'9') break; // test for Arabic digit
>           last=c;
>           }
> -      if (*c!='\0') break;         // not all digits
> +      for (p=c; *p==' '; ++p);
> +      if (*p!='\0') break;         // not all digits
>         if (d>set->digits-1) {
>           // [NB: payload in a decNumber can be full length unless
>           // clamped, in which case can only be digits-1]
> @@ -647,7 +653,7 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>         bits=dn->bits;               // for copy-back
>         } // last==NULL
>   
> -     else if (*c!='\0') {          // more to process...
> +     else if (p==c && *p!='\0') {  // more to process...
>         // had some digits; exponent is only valid sequence now
>         Flag nege;                   // 1=negative exponent
>         const char *firstexp;        // -> first significant exponent digit
> @@ -659,16 +665,18 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>         c++;                         // to (possible) sign
>         if (*c=='-') {nege=1; c++;}
>          else if (*c=='+') c++;
> -      if (*c=='\0') break;
> -
> -      for (; *c=='0' && *(c+1)!='\0';) c++;  // strip insignificant zeros
> +      for (p=c; *p==' '; ++p);
> +      if (*p=='\0') break;
> +      // strip insignificant zeros
> +      for (; *c=='0' && *(c+1)!='\0' && *(c+1)!=' ';) c++;
>         firstexp=c;                            // save exponent digit place
>         for (; ;c++) {
>           if (*c<'0' || *c>'9') break;         // not a digit
>           exponent=X10(exponent)+(Int)*c-(Int)'0';
>           } // c
>         // if not now on a '\0', *c must not be a digit
> -      if (*c!='\0') break;
> +      for (p=c; *p==' '; ++p);
> +      if (*p!='\0') break;
>   
>         // (this next test must be after the syntax checks)
>         // if it was too long the exponent may have wrapped, so check
> @@ -681,6 +689,11 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
>         status=0;                         // is OK
>         } // stuff after digits
>   
> +     else if (*p!='\0') {    // whitespaces in the middle
> +       status=DEC_Conversion_syntax;
> +       break;
> +     }
> +
>       // Here when whole string has been inspected; syntax is good
>       // cfirst->first digit (never dot), last->last digit (ditto)
>   
> @@ -7739,12 +7752,13 @@ static decNumber *decDecap(decNumber *dn, Int drop) {
>   /*   if (decBiStr(test, "mike", "MIKE")) ...                          */
>   /* ------------------------------------------------------------------ */
>   static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
> -  for (;;targ++, str1++, str2++) {
> +  const char *end=strchr(targ, ' ');
> +  if (end==NULL)
> +    end=targ+strlen(targ);
> +  for (;targ<end; targ++, str1++, str2++) {
>       if (*targ!=*str1 && *targ!=*str2) return 0;
> -    // *targ has a match in one (or both, if terminator)
> -    if (*targ=='\0') break;
> -    } // forever
> -  return 1;
> +    } // for
> +  return *str1=='\0';
>     } // decBiStr
>   
>   /* ------------------------------------------------------------------ */

-- 
Serge Petrenko



More information about the Tarantool-patches mailing list