Tarantool development patches archive
 help / color / mirror / Atom feed
From: Chris Sosnin <k.sosnin@tarantool.org>
To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org,
	v.shpilevoy@tarantool.org
Subject: [Tarantool-patches] [PATCH v2 1/2] Refactor decNumberFromString
Date: Wed, 24 Jun 2020 19:53:31 +0300	[thread overview]
Message-ID: <7e17dc729687c7c61da5f761e4302e6e78b9d01f.1593017012.git.k.sosnin@tarantool.org> (raw)
In-Reply-To: <cover.1593017012.git.k.sosnin@tarantool.org>

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)

  reply	other threads:[~2020-06-24 16:53 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-24 16:53 [Tarantool-patches] [PATCH v2 0/2] decNumber utilites for SQL Chris Sosnin
2020-06-24 16:53 ` Chris Sosnin [this message]
2020-06-24 22:22   ` [Tarantool-patches] [PATCH v2 1/2] Refactor decNumberFromString Vladislav Shpilevoy
2020-06-25 14:21     ` Chris Sosnin
2020-06-24 16:53 ` [Tarantool-patches] [PATCH v2 2/2] Add IsInt method for checking the fractional part of a number Chris Sosnin
2020-06-24 22:23   ` Vladislav Shpilevoy
2020-06-25 14:22     ` Chris Sosnin
2020-06-25 21:04 ` [Tarantool-patches] [PATCH v2 0/2] decNumber utilites for SQL Vladislav Shpilevoy
2020-06-26 10:57 ` Serge Petrenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7e17dc729687c7c61da5f761e4302e6e78b9d01f.1593017012.git.k.sosnin@tarantool.org \
    --to=k.sosnin@tarantool.org \
    --cc=sergepetrenko@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v2 1/2] Refactor decNumberFromString' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox