Selaa lähdekoodia

Merge pull request #101 from DaveGamble/simplify-correctness

Simplify some code and improve correctness
Max Bruckner 8 vuotta sitten
vanhempi
commit
e65ea3a45b
2 muutettua tiedostoa jossa 59 lisäystä ja 139 poistoa
  1. 55 137
      cJSON.c
  2. 4 2
      cJSON.h

+ 55 - 137
cJSON.c

@@ -164,83 +164,53 @@ void cJSON_Delete(cJSON *c)
 /* Parse the input text to generate a number, and populate the result into item. */
 static const unsigned char *parse_number(cJSON *item, const unsigned char *num)
 {
-    double n = 0;
-    double sign = 1;
-    double scale = 0;
-    int subscale = 0;
-    int signsubscale = 1;
+    double number = 0;
+    unsigned char *endpointer = NULL;
 
-    /* Has sign? */
-    if (*num == '-')
+    number = strtod((const char*)num, (char**)&endpointer);
+    if ((num == endpointer) || (num == NULL))
     {
-        sign = -1;
-        num++;
-    }
-    /* is zero */
-    if (*num == '0')
-    {
-        num++;
+        /* parse_error */
+        return NULL;
     }
-    /* Number? */
-    if ((*num >= '1') && (*num <= '9'))
+
+    item->valuedouble = number;
+
+    /* use saturation in case of overflow */
+    if (number >= INT_MAX)
     {
-        do
-        {
-            n = (n * 10.0) + (*num++ - '0');
-        }
-        while ((*num >= '0') && (*num<='9'));
+        item->valueint = INT_MAX;
     }
-    /* Fractional part? */
-    if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9'))
+    else if (number <= INT_MIN)
     {
-        num++;
-        do
-        {
-            n = (n  *10.0) + (*num++ - '0');
-            scale--;
-        } while ((*num >= '0') && (*num <= '9'));
+        item->valueint = INT_MIN;
     }
-    /* Exponent? */
-    if ((*num == 'e') || (*num == 'E'))
+    else
     {
-        num++;
-        /* With sign? */
-        if (*num == '+')
-        {
-            num++;
-        }
-        else if (*num == '-')
-        {
-            signsubscale = -1;
-            num++;
-        }
-        /* Number? */
-        while ((*num>='0') && (*num<='9'))
-        {
-            subscale = (subscale * 10) + (*num++ - '0');
-        }
+        item->valueint = (int)number;
     }
+    item->type = cJSON_Number;
 
-    /* number = +/- number.fraction * 10^+/- exponent */
-    n = sign * n * pow(10.0, (scale + subscale * signsubscale));
+    return endpointer;
+}
 
-    item->valuedouble = n;
-    /* use saturation in case of overflow */
-    if (n >= INT_MAX)
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+double cJSON_SetNumberHelper(cJSON *object, double number)
+{
+    if (number >= INT_MAX)
     {
-        item->valueint = INT_MAX;
+        object->valueint = INT_MAX;
     }
-    else if (n <= INT_MIN)
+    else if (number <= INT_MIN)
     {
-        item->valueint = INT_MIN;
+        object->valueint = INT_MIN;
     }
     else
     {
-        item->valueint = (int)n;
+        object->valueint = cJSON_Number;
     }
-    item->type = cJSON_Number;
 
-    return num;
+    return object->valuedouble = number;
 }
 
 /* calculate the next largest power of 2 */
@@ -411,99 +381,47 @@ static unsigned char *print_number(const cJSON *item, printbuffer *p)
 static unsigned parse_hex4(const unsigned char *str)
 {
     unsigned int h = 0;
+    size_t i = 0;
 
-    /* first digit */
-    if ((*str >= '0') && (*str <= '9'))
-    {
-        h += (unsigned int) (*str) - '0';
-    }
-    else if ((*str >= 'A') && (*str <= 'F'))
-    {
-        h += (unsigned int) 10 + (*str) - 'A';
-    }
-    else if ((*str >= 'a') && (*str <= 'f'))
-    {
-        h += (unsigned int) 10 + (*str) - 'a';
-    }
-    else /* invalid */
-    {
-        return 0;
-    }
-
-
-    /* second digit */
-    h = h << 4;
-    str++;
-    if ((*str >= '0') && (*str <= '9'))
-    {
-        h += (unsigned int) (*str) - '0';
-    }
-    else if ((*str >= 'A') && (*str <= 'F'))
-    {
-        h += (unsigned int) 10 + (*str) - 'A';
-    }
-    else if ((*str >= 'a') && (*str <= 'f'))
-    {
-        h += (unsigned int) 10 + (*str) - 'a';
-    }
-    else /* invalid */
-    {
-        return 0;
-    }
-
-    /* third digit */
-    h = h << 4;
-    str++;
-    if ((*str >= '0') && (*str <= '9'))
+    for (i = 0; i < 4; i++)
     {
-        h += (unsigned int) (*str) - '0';
-    }
-    else if ((*str >= 'A') && (*str <= 'F'))
-    {
-        h += (unsigned int) 10 + (*str) - 'A';
-    }
-    else if ((*str >= 'a') && (*str <= 'f'))
-    {
-        h += (unsigned int) 10 + (*str) - 'a';
-    }
-    else /* invalid */
-    {
-        return 0;
-    }
+        /* parse digit */
+        if ((*str >= '0') && (*str <= '9'))
+        {
+            h += (unsigned int) (*str) - '0';
+        }
+        else if ((*str >= 'A') && (*str <= 'F'))
+        {
+            h += (unsigned int) 10 + (*str) - 'A';
+        }
+        else if ((*str >= 'a') && (*str <= 'f'))
+        {
+            h += (unsigned int) 10 + (*str) - 'a';
+        }
+        else /* invalid */
+        {
+            return 0;
+        }
 
-    /* fourth digit */
-    h = h << 4;
-    str++;
-    if ((*str >= '0') && (*str <= '9'))
-    {
-        h += (unsigned int) (*str) - '0';
-    }
-    else if ((*str >= 'A') && (*str <= 'F'))
-    {
-        h += (unsigned int) 10 + (*str) - 'A';
-    }
-    else if ((*str >= 'a') && (*str <= 'f'))
-    {
-        h += (unsigned int) 10 + (*str) - 'a';
-    }
-    else /* invalid */
-    {
-        return 0;
+        if (i < 3)
+        {
+            /* shift left to make place for the next nibble */
+            h = h << 4;
+            str++;
+        }
     }
 
     return h;
 }
 
 /* first bytes of UTF8 encoding for a given length in bytes */
-static const unsigned char firstByteMark[7] =
+static const unsigned char firstByteMark[5] =
 {
     0x00, /* should never happen */
     0x00, /* 0xxxxxxx */
     0xC0, /* 110xxxxx */
     0xE0, /* 1110xxxx */
-    0xF0, /* 11110xxx */
-    0xF8,
-    0xFC
+    0xF0 /* 11110xxx */
 };
 
 /* Parse the input text into an unescaped cstring, and populate item. */

+ 4 - 2
cJSON.h

@@ -169,8 +169,10 @@ extern void cJSON_Minify(char *json);
 #define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
 
 /* When assigning an integer value, it needs to be propagated to valuedouble too. */
-#define cJSON_SetIntValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
-#define cJSON_SetNumberValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+extern double cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object) ? cJSON_SetNumberHelper(object, (double)number) : (number))
 
 /* Macro for iterating over an array */
 #define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next)