Merge pull request #101 from DaveGamble/simplify-correctness

Simplify some code and improve correctness
This commit is contained in:
Max Bruckner 2017-02-07 21:29:11 +01:00 committed by GitHub
commit e65ea3a45b
2 changed files with 61 additions and 141 deletions

196
cJSON.c
View File

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

View File

@ -169,8 +169,10 @@ extern void cJSON_Minify(char *json);
#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s)) #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. */ /* 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_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
#define cJSON_SetNumberValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val)) /* 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 */ /* Macro for iterating over an array */
#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next) #define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next)