[Tarantool-patches] [PATCH v2 1/2] Refactor decNumberFromString

Chris Sosnin k.sosnin at tarantool.org
Wed Jun 24 19:53:31 MSK 2020


Allow parsing a valid beginning of the string to unify the behavior
with strto* functions.

Needed for tarantool/tarantool#4415
---
 decNumber.c | 19 +++++++++++--------
 decNumber.h | 26 +++++++++++++-------------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/decNumber.c b/decNumber.c
index 85deb13..e248656 100644
--- a/decNumber.c
+++ b/decNumber.c
@@ -545,7 +545,7 @@ char * decNumberToEngString(const decNumber *dn, char *string){
 /*                                                                    */
 /* If bad syntax is detected, the result will be a quiet NaN.         */
 /* ------------------------------------------------------------------ */
-decNumber * decNumberFromString(decNumber *dn, const char chars[],
+const char * decNumberFromString(decNumber *dn, const char chars[],
                                 decContext *set) {
   Int   exponent=0;                // working exponent [assume 0]
   uByte bits=0;                    // working flags [assume +ve]
@@ -557,6 +557,7 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
   const char *dotchar=NULL;        // where dot was found
   const char *cfirst=chars;        // -> first character of decimal part
   const char *last=NULL;           // -> last digit of decimal part
+  const char *end=chars;
   const char *c;                   // work
   Unit  *up;                       // ..
   #if DECDPUN>1
@@ -649,17 +650,18 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
 
      else if (*c!='\0') {          // more to process...
       // had some digits; exponent is only valid sequence now
+      status=0;                    // we have a number already
+      end=c;                       // backup for invalid exponent
       Flag nege;                   // 1=negative exponent
       const char *firstexp;        // -> first significant exponent digit
-      status=DEC_Conversion_syntax;// assume the worst
-      if (*c!='e' && *c!='E') break;
+      if (*c!='e' && *c!='E') goto finalize;
       /* Found 'e' or 'E' -- now process explicit exponent */
       // 1998.07.11: sign no longer required
       nege=0;
       c++;                         // to (possible) sign
       if (*c=='-') {nege=1; c++;}
        else if (*c=='+') c++;
-      if (*c=='\0') break;
+      if (*c<'0' || *c>'9') goto finalize;
 
       for (; *c=='0' && *(c+1)!='\0';) c++;  // strip insignificant zeros
       firstexp=c;                            // save exponent digit place
@@ -667,8 +669,8 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
         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;
+
+      end=c;
 
       // (this next test must be after the syntax checks)
       // if it was too long the exponent may have wrapped, so check
@@ -678,9 +680,10 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
         // [up to 1999999999 is OK, for example 1E-1000000998]
         }
       if (nege) exponent=-exponent;     // was negative
-      status=0;                         // is OK
       } // stuff after digits
 
+      else end=c;
+finalize:
     // Here when whole string has been inspected; syntax is good
     // cfirst->first digit (never dot), last->last digit (ditto)
 
@@ -772,7 +775,7 @@ decNumber * decNumberFromString(decNumber *dn, const char chars[],
 
   if (allocres!=NULL) free(allocres);   // drop any storage used
   if (status!=0) decStatus(dn, status, set);
-  return dn;
+  return end;
   } /* decNumberFromString */
 
 /* ================================================================== */
diff --git a/decNumber.h b/decNumber.h
index 85a3f3f..ffaa3d8 100644
--- a/decNumber.h
+++ b/decNumber.h
@@ -101,19 +101,19 @@
   /* decNumber public functions and macros                            */
   /* ---------------------------------------------------------------- */
   /* Conversions                                                      */
-  decNumber * decNumberFromInt32(decNumber *, int32_t);
-  decNumber * decNumberFromUInt32(decNumber *, uint32_t);
-  decNumber * decNumberFromInt64(decNumber *, int64_t);
-  decNumber * decNumberFromUInt64(decNumber *, uint64_t);
-  decNumber * decNumberFromString(decNumber *, const char *, decContext *);
-  char      * decNumberToString(const decNumber *, char *);
-  char      * decNumberToEngString(const decNumber *, char *);
-  uint32_t    decNumberToUInt32(const decNumber *, decContext *);
-  uint64_t    decNumberToUInt64(const decNumber *, decContext *);
-  int32_t     decNumberToInt32(const decNumber *, decContext *);
-  int64_t     decNumberToInt64(const decNumber *, decContext *);
-  uint8_t   * decNumberGetBCD(const decNumber *, uint8_t *);
-  decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
+  decNumber  * decNumberFromInt32(decNumber *, int32_t);
+  decNumber  * decNumberFromUInt32(decNumber *, uint32_t);
+  decNumber  * decNumberFromInt64(decNumber *, int64_t);
+  decNumber  * decNumberFromUInt64(decNumber *, uint64_t);
+  const char * decNumberFromString(decNumber *, const char *, decContext *);
+  char       * decNumberToString(const decNumber *, char *);
+  char       * decNumberToEngString(const decNumber *, char *);
+  uint32_t     decNumberToUInt32(const decNumber *, decContext *);
+  uint64_t     decNumberToUInt64(const decNumber *, decContext *);
+  int32_t      decNumberToInt32(const decNumber *, decContext *);
+  int64_t      decNumberToInt64(const decNumber *, decContext *);
+  uint8_t    * decNumberGetBCD(const decNumber *, uint8_t *);
+  decNumber  * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
 
   /* Operators and elementary functions                               */
   decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *);
-- 
2.21.1 (Apple Git-122.3)



More information about the Tarantool-patches mailing list