[Tarantool-patches] [PATCH 1/2] Allow leading and trailing whitespaces in FromString
Chris Sosnin
k.sosnin at tarantool.org
Sun Jun 7 15:38:46 MSK 2020
Hi! Thank you for the review!
> On 6 Jun 2020, at 16:48, Serge Petrenko <sergepetrenko at tarantool.org> wrote:
>
>
> 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)
You are right, thank you for the catch!
I applied the change on the branch.
>
>> 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