@@ -663,9 +663,9 @@ int32_t json_object_get_int(const struct json_object *jso) | |||
if (o_type == json_type_string) | |||
{ | |||
/* | |||
* Parse strings into 64-bit numbers, then use the | |||
* 64-to-32-bit number handling below. | |||
*/ | |||
* Parse strings into 64-bit numbers, then use the | |||
* 64-to-32-bit number handling below. | |||
*/ | |||
if (json_parse_int64(get_string_component(jso), &cint64) != 0) | |||
return 0; /* whoops, it didn't work. */ | |||
o_type = json_type_int; | |||
@@ -896,9 +896,10 @@ static int json_object_double_to_json_string_format(struct json_object* jso, | |||
char buf[128], *p, *q; | |||
int size; | |||
/* Although JSON RFC does not support | |||
NaN or Infinity as numeric values | |||
ECMA 262 section 9.8.1 defines | |||
how to handle these cases as strings */ | |||
* NaN or Infinity as numeric values | |||
* ECMA 262 section 9.8.1 defines | |||
* how to handle these cases as strings | |||
*/ | |||
if (isnan(jso->o.c_double)) | |||
{ | |||
size = snprintf(buf, sizeof(buf), "NaN"); | |||
@@ -1084,10 +1085,10 @@ double json_object_get_double(const struct json_object *jso) | |||
} | |||
/* | |||
* Check that the conversion terminated on something sensible | |||
* | |||
* For example, { "pay" : 123AB } would parse as 123. | |||
*/ | |||
* Check that the conversion terminated on something sensible | |||
* | |||
* For example, { "pay" : 123AB } would parse as 123. | |||
*/ | |||
if (*errPtr != '\0') | |||
{ | |||
errno = EINVAL; | |||
@@ -1095,16 +1096,16 @@ double json_object_get_double(const struct json_object *jso) | |||
} | |||
/* | |||
* If strtod encounters a string which would exceed the | |||
* capacity of a double, it returns +/- HUGE_VAL and sets | |||
* errno to ERANGE. But +/- HUGE_VAL is also a valid result | |||
* from a conversion, so we need to check errno. | |||
* | |||
* Underflow also sets errno to ERANGE, but it returns 0 in | |||
* that case, which is what we will return anyway. | |||
* | |||
* See CERT guideline ERR30-C | |||
*/ | |||
* If strtod encounters a string which would exceed the | |||
* capacity of a double, it returns +/- HUGE_VAL and sets | |||
* errno to ERANGE. But +/- HUGE_VAL is also a valid result | |||
* from a conversion, so we need to check errno. | |||
* | |||
* Underflow also sets errno to ERANGE, but it returns 0 in | |||
* that case, which is what we will return anyway. | |||
* | |||
* See CERT guideline ERR30-C | |||
*/ | |||
if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && | |||
(ERANGE == errno)) | |||
cdouble = 0.0; | |||
@@ -153,10 +153,10 @@ json_object_iter_init_default(void) | |||
struct json_object_iterator iter; | |||
/** | |||
* @note Make this a negative, invalid value, such that | |||
* accidental access to it would likely be trapped by the | |||
* hardware as an invalid address. | |||
*/ | |||
* @note Make this a negative, invalid value, such that | |||
* accidental access to it would likely be trapped by the | |||
* hardware as an invalid address. | |||
*/ | |||
iter.opaque_ = NULL; | |||
return iter; | |||
@@ -20,7 +20,8 @@ | |||
extern "C" { | |||
#endif | |||
#define LEN_DIRECT_STRING_DATA 32 /**< how many bytes are directly stored in json_object for strings? */ | |||
/**< how many bytes are directly stored in json_object for strings? */ | |||
#define LEN_DIRECT_STRING_DATA 32 | |||
typedef void (json_object_private_delete_fn)(struct json_object *o); | |||
@@ -52,8 +53,8 @@ struct json_object | |||
struct { | |||
union { | |||
/* optimize: if we have small strings, we can store them | |||
* directly. This saves considerable CPU cycles AND memory. | |||
*/ | |||
* directly. This saves considerable CPU cycles AND memory. | |||
*/ | |||
char *ptr; | |||
char data[LEN_DIRECT_STRING_DATA]; | |||
} str; | |||
@@ -41,8 +41,9 @@ static void string_replace_all_occurrences_with_char(char *s, const char *occur, | |||
static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx) | |||
{ | |||
int i, len = strlen(path); | |||
/* this code-path optimizes a bit, for when we reference the 0-9 index range in a JSON array | |||
and because leading zeros not allowed */ | |||
/* this code-path optimizes a bit, for when we reference the 0-9 index range | |||
* in a JSON array and because leading zeros not allowed | |||
*/ | |||
if (len == 1) { | |||
if (isdigit((unsigned char)path[0])) { | |||
*idx = (path[0] - '0'); | |||
@@ -124,12 +125,14 @@ static int json_pointer_set_single_path( | |||
} | |||
/* path replacements should have been done in json_pointer_get_single_path(), | |||
and we should still be good here */ | |||
* and we should still be good here | |||
*/ | |||
if (json_object_is_type(parent, json_type_object)) | |||
return json_object_object_add(parent, path, value); | |||
/* Getting here means that we tried to "dereference" a primitive JSON type (like string, int, bool). | |||
i.e. add a sub-object to it */ | |||
/* Getting here means that we tried to "dereference" a primitive JSON type | |||
* (like string, int, bool).i.e. add a sub-object to it | |||
*/ | |||
errno = ENOENT; | |||
return -1; | |||
} | |||
@@ -158,7 +161,8 @@ static int json_pointer_get_recursive( | |||
return rc; | |||
if (endp) { | |||
*endp = '/'; /* Put the slash back, so that the sanity check passes on next recursion level */ | |||
/* Put the slash back, so that the sanity check passes on next recursion level */ | |||
*endp = '/'; | |||
return json_pointer_get_recursive(obj, endp, value); | |||
} | |||
@@ -68,24 +68,26 @@ static const int json_true_str_len = sizeof(json_true_str) - 1; | |||
static const char json_false_str[] = "false"; | |||
static const int json_false_str_len = sizeof(json_false_str) - 1; | |||
static const char* json_tokener_errors[] = { | |||
"success", | |||
"continue", | |||
"nesting too deep", | |||
"unexpected end of data", | |||
"unexpected character", | |||
"null expected", | |||
"boolean expected", | |||
"number expected", | |||
"array value separator ',' expected", | |||
"quoted object property name expected", | |||
"object property name separator ':' expected", | |||
"object value separator ',' expected", | |||
"invalid string sequence", | |||
"expected comment", | |||
"invalid utf-8 string", | |||
"buffer size overflow" | |||
/* clang-format off */ | |||
static const char *json_tokener_errors[] = { | |||
"success", | |||
"continue", | |||
"nesting too deep", | |||
"unexpected end of data", | |||
"unexpected character", | |||
"null expected", | |||
"boolean expected", | |||
"number expected", | |||
"array value separator ',' expected", | |||
"quoted object property name expected", | |||
"object property name separator ':' expected", | |||
"object value separator ',' expected", | |||
"invalid string sequence", | |||
"expected comment", | |||
"invalid utf-8 string", | |||
"buffer size overflow" | |||
}; | |||
/* clang-format on */ | |||
const char *json_tokener_error_desc(enum json_tokener_error jerr) | |||
{ | |||
@@ -261,10 +263,11 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
tok->err = json_tokener_success; | |||
/* this interface is presently not 64-bit clean due to the int len argument | |||
and the internal printbuf interface that takes 32-bit int len arguments | |||
so the function limits the maximum string size to INT32_MAX (2GB). | |||
If the function is called with len == -1 then strlen is called to check | |||
the string length is less than INT32_MAX (2GB) */ | |||
* and the internal printbuf interface that takes 32-bit int len arguments | |||
* so the function limits the maximum string size to INT32_MAX (2GB). | |||
* If the function is called with len == -1 then strlen is called to check | |||
* the string length is less than INT32_MAX (2GB) | |||
*/ | |||
if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) { | |||
tok->err = json_tokener_error_size; | |||
return NULL; | |||
@@ -390,12 +393,12 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */ | |||
{ | |||
/* If we were guaranteed to have len set, then we could (usually) handle | |||
* the entire "Infinity" check in a single strncmp (strncasecmp), but | |||
* since len might be -1 (i.e. "read until \0"), we need to check it | |||
* a character at a time. | |||
* Trying to handle it both ways would make this code considerably more | |||
* complicated with likely little performance benefit. | |||
*/ | |||
* the entire "Infinity" check in a single strncmp (strncasecmp), but | |||
* since len might be -1 (i.e. "read until \0"), we need to check it | |||
* a character at a time. | |||
* Trying to handle it both ways would make this code considerably more | |||
* complicated with likely little performance benefit. | |||
*/ | |||
int is_negative = 0; | |||
const char *_json_inf_str = json_inf_str; | |||
if (!(tok->flags & JSON_TOKENER_STRICT)) | |||
@@ -421,9 +424,9 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
} | |||
} | |||
/* We checked the full length of "Infinity", so create the object. | |||
* When handling -Infinity, the number parsing code will have dropped | |||
* the "-" into tok->pb for us, so check it now. | |||
*/ | |||
* When handling -Infinity, the number parsing code will have dropped | |||
* the "-" into tok->pb for us, so check it now. | |||
*/ | |||
if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-') | |||
{ | |||
is_negative = 1; | |||
@@ -620,10 +623,10 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); | |||
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2); | |||
} else if (IS_HIGH_SURROGATE(tok->ucs_char)) { | |||
/* Got a high surrogate. Remember it and look for the | |||
* the beginning of another sequence, which should be the | |||
* low surrogate. | |||
*/ | |||
/* Got a high surrogate. Remember it and look for | |||
* the beginning of another sequence, which | |||
* should be the low surrogate. | |||
*/ | |||
got_hi_surrogate = tok->ucs_char; | |||
/* Not at end, and the next two chars should be "\u" */ | |||
if ((len == -1 || len > (tok->char_offset + 2)) && | |||
@@ -631,17 +634,17 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
(str[1] == '\\') && | |||
(str[2] == 'u')) | |||
{ | |||
/* Advance through the 16 bit surrogate, and move on to the | |||
* next sequence. The next step is to process the following | |||
* characters. | |||
*/ | |||
/* Advance through the 16 bit surrogate, and move | |||
* on to the next sequence. The next step is to | |||
* process the following characters. | |||
*/ | |||
if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) { | |||
printbuf_memappend_fast(tok->pb, | |||
(char*) utf8_replacement_char, 3); | |||
} | |||
/* Advance to the first char of the next sequence and | |||
* continue processing with the next sequence. | |||
*/ | |||
/* Advance to the first char of the next sequence and | |||
* continue processing with the next sequence. | |||
*/ | |||
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { | |||
printbuf_memappend_fast(tok->pb, | |||
(char*) utf8_replacement_char, 3); | |||
@@ -649,12 +652,13 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
} | |||
tok->ucs_char = 0; | |||
tok->st_pos = 0; | |||
continue; /* other json_tokener_state_escape_unicode */ | |||
/* other json_tokener_state_escape_unicode */ | |||
continue; | |||
} else { | |||
/* Got a high surrogate without another sequence following | |||
* it. Put a replacement char in for the hi surrogate | |||
* and pretend we finished. | |||
*/ | |||
/* Got a high surrogate without another sequence following | |||
* it. Put a replacement char in for the hi surrogate | |||
* and pretend we finished. | |||
*/ | |||
printbuf_memappend_fast(tok->pb, | |||
(char*) utf8_replacement_char, 3); | |||
} | |||
@@ -684,7 +688,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
goto out; | |||
} | |||
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { | |||
if (got_hi_surrogate) /* Clean up any pending chars */ | |||
/* Clean up any pending chars */ | |||
if (got_hi_surrogate) | |||
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); | |||
goto out; | |||
} | |||
@@ -741,14 +746,16 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
/* non-digit characters checks */ | |||
/* note: since the main loop condition to get here was | |||
an input starting with 0-9 or '-', we are | |||
protected from input starting with '.' or | |||
e/E. */ | |||
* an input starting with 0-9 or '-', we are | |||
* protected from input starting with '.' or | |||
* e/E. | |||
*/ | |||
if (c == '.') { | |||
if (tok->is_double != 0) { | |||
/* '.' can only be found once, and out of the exponent part. | |||
Thus, if the input is already flagged as double, it | |||
is invalid. */ | |||
* Thus, if the input is already flagged as double, it | |||
* is invalid. | |||
*/ | |||
tok->err = json_tokener_error_parse_number; | |||
goto out; | |||
} | |||
@@ -767,8 +774,9 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
} | |||
if (c == '-' && case_len != negativesign_next_possible_location) { | |||
/* If the negative sign is not where expected (ie | |||
start of input or start of exponent part), the | |||
input is invalid. */ | |||
* start of input or start of exponent part), the | |||
* input is invalid. | |||
*/ | |||
tok->err = json_tokener_error_parse_number; | |||
goto out; | |||
} | |||
@@ -979,7 +987,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
/* unexpected char after JSON data */ | |||
tok->err = json_tokener_error_parse_unexpected; | |||
} | |||
if (!c) { /* We hit an eof char (0) */ | |||
if (!c) { | |||
/* We hit an eof char (0) */ | |||
if(state != json_tokener_state_finish && | |||
saved_state != json_tokener_state_finish) | |||
tok->err = json_tokener_error_parse_eof; | |||
@@ -93,8 +93,8 @@ struct json_tokener | |||
struct printbuf *pb; | |||
int max_depth, depth, is_double, st_pos; | |||
/** | |||
* See json_tokener_get_parse_end() | |||
*/ | |||
* See json_tokener_get_parse_end() | |||
*/ | |||
int char_offset; | |||
enum json_tokener_error err; | |||
unsigned int ucs_char; | |||
@@ -189,7 +189,8 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const | |||
return -1; | |||
} | |||
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ | |||
/* CAW: probably unnecessary, but the most 64bit safe */ | |||
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); | |||
wpos = 0; | |||
while(wpos < wsize) { | |||
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { | |||
@@ -260,16 +261,18 @@ void* rpl_realloc(void* p, size_t n) | |||
#endif | |||
#define NELEM(a) (sizeof(a) / sizeof(a[0])) | |||
static const char* json_type_name[] = { | |||
/* If you change this, be sure to update the enum json_type definition too */ | |||
"null", | |||
"boolean", | |||
"double", | |||
"int", | |||
"object", | |||
"array", | |||
"string", | |||
/* clang-format off */ | |||
static const char *json_type_name[] = { | |||
/* If you change this, be sure to update the enum json_type definition too */ | |||
"null", | |||
"boolean", | |||
"double", | |||
"int", | |||
"object", | |||
"array", | |||
"string", | |||
}; | |||
/* clang-format on */ | |||
const char *json_type_to_name(enum json_type o_type) | |||
{ | |||
@@ -178,15 +178,17 @@ on, and rotates are much kinder to the top and bottom bits, so I used | |||
rotates. | |||
------------------------------------------------------------------------------- | |||
*/ | |||
/* clang-format off */ | |||
#define mix(a,b,c) \ | |||
{ \ | |||
a -= c; a ^= rot(c, 4); c += b; \ | |||
b -= a; b ^= rot(a, 6); a += c; \ | |||
c -= b; c ^= rot(b, 8); b += a; \ | |||
a -= c; a ^= rot(c,16); c += b; \ | |||
b -= a; b ^= rot(a,19); a += c; \ | |||
c -= b; c ^= rot(b, 4); b += a; \ | |||
a -= c; a ^= rot(c, 4); c += b; \ | |||
b -= a; b ^= rot(a, 6); a += c; \ | |||
c -= b; c ^= rot(b, 8); b += a; \ | |||
a -= c; a ^= rot(c,16); c += b; \ | |||
b -= a; b ^= rot(a,19); a += c; \ | |||
c -= b; c ^= rot(b, 4); b += a; \ | |||
} | |||
/* clang-format on */ | |||
/* | |||
------------------------------------------------------------------------------- | |||
@@ -213,16 +215,18 @@ and these came close: | |||
11 8 15 26 3 22 24 | |||
------------------------------------------------------------------------------- | |||
*/ | |||
/* clang-format off */ | |||
#define final(a,b,c) \ | |||
{ \ | |||
c ^= b; c -= rot(b,14); \ | |||
a ^= c; a -= rot(c,11); \ | |||
b ^= a; b -= rot(a,25); \ | |||
c ^= b; c -= rot(b,16); \ | |||
a ^= c; a -= rot(c,4); \ | |||
b ^= a; b -= rot(a,14); \ | |||
c ^= b; c -= rot(b,24); \ | |||
c ^= b; c -= rot(b,14); \ | |||
a ^= c; a -= rot(c,11); \ | |||
b ^= a; b -= rot(a,25); \ | |||
c ^= b; c -= rot(b,16); \ | |||
a ^= c; a -= rot(c,4); \ | |||
b ^= a; b -= rot(a,14); \ | |||
c ^= b; c -= rot(b,24); \ | |||
} | |||
/* clang-format on */ | |||
/* | |||
@@ -252,184 +256,195 @@ acceptable. Do NOT use for cryptographic purposes. | |||
------------------------------------------------------------------------------- | |||
*/ | |||
static uint32_t hashlittle( const void *key, size_t length, uint32_t initval) | |||
/* clang-format off */ | |||
static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) | |||
{ | |||
uint32_t a,b,c; /* internal state */ | |||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ | |||
/* Set up the internal state */ | |||
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; | |||
u.ptr = key; | |||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { | |||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ | |||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ | |||
while (length > 12) | |||
{ | |||
a += k[0]; | |||
b += k[1]; | |||
c += k[2]; | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 3; | |||
} | |||
/*----------------------------- handle the last (probably partial) block */ | |||
/* | |||
* "k[2]&0xffffff" actually reads beyond the end of the string, but | |||
* then masks off the part it's not allowed to read. Because the | |||
* string is aligned, the masked-off tail is in the same word as the | |||
* rest of the string. Every machine with memory protection I've seen | |||
* does it on word boundaries, so is OK with this. But VALGRIND will | |||
* still catch it and complain. The masking trick does make the hash | |||
* noticably faster for short strings (like English words). | |||
* AddressSanitizer is similarly picky about overrunning | |||
* the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html | |||
*/ | |||
uint32_t a,b,c; /* internal state */ | |||
union | |||
{ | |||
const void *ptr; | |||
size_t i; | |||
} u; /* needed for Mac Powerbook G4 */ | |||
/* Set up the internal state */ | |||
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; | |||
u.ptr = key; | |||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { | |||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ | |||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ | |||
while (length > 12) | |||
{ | |||
a += k[0]; | |||
b += k[1]; | |||
c += k[2]; | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 3; | |||
} | |||
/*----------------------------- handle the last (probably partial) block */ | |||
/* | |||
* "k[2]&0xffffff" actually reads beyond the end of the string, but | |||
* then masks off the part it's not allowed to read. Because the | |||
* string is aligned, the masked-off tail is in the same word as the | |||
* rest of the string. Every machine with memory protection I've seen | |||
* does it on word boundaries, so is OK with this. But VALGRIND will | |||
* still catch it and complain. The masking trick does make the hash | |||
* noticably faster for short strings (like English words). | |||
* AddressSanitizer is similarly picky about overrunning | |||
* the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html | |||
*/ | |||
#ifdef VALGRIND | |||
# define PRECISE_MEMORY_ACCESS 1 | |||
#define PRECISE_MEMORY_ACCESS 1 | |||
#elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */ | |||
# define PRECISE_MEMORY_ACCESS 1 | |||
#define PRECISE_MEMORY_ACCESS 1 | |||
#elif defined(__has_feature) | |||
# if __has_feature(address_sanitizer) /* Clang's ASAN */ | |||
# define PRECISE_MEMORY_ACCESS 1 | |||
# endif | |||
#if __has_feature(address_sanitizer) /* Clang's ASAN */ | |||
#define PRECISE_MEMORY_ACCESS 1 | |||
#endif | |||
#endif | |||
#ifndef PRECISE_MEMORY_ACCESS | |||
switch(length) | |||
{ | |||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; | |||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; | |||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; | |||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; | |||
case 8 : b+=k[1]; a+=k[0]; break; | |||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break; | |||
case 6 : b+=k[1]&0xffff; a+=k[0]; break; | |||
case 5 : b+=k[1]&0xff; a+=k[0]; break; | |||
case 4 : a+=k[0]; break; | |||
case 3 : a+=k[0]&0xffffff; break; | |||
case 2 : a+=k[0]&0xffff; break; | |||
case 1 : a+=k[0]&0xff; break; | |||
case 0 : return c; /* zero length strings require no mixing */ | |||
} | |||
switch(length) | |||
{ | |||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; | |||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; | |||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; | |||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; | |||
case 8 : b+=k[1]; a+=k[0]; break; | |||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break; | |||
case 6 : b+=k[1]&0xffff; a+=k[0]; break; | |||
case 5 : b+=k[1]&0xff; a+=k[0]; break; | |||
case 4 : a+=k[0]; break; | |||
case 3 : a+=k[0]&0xffffff; break; | |||
case 2 : a+=k[0]&0xffff; break; | |||
case 1 : a+=k[0]&0xff; break; | |||
case 0 : return c; /* zero length strings require no mixing */ | |||
} | |||
#else /* make valgrind happy */ | |||
const uint8_t *k8 = (const uint8_t *)k; | |||
switch(length) | |||
{ | |||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; | |||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ | |||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ | |||
case 9 : c+=k8[8]; /* fall through */ | |||
case 8 : b+=k[1]; a+=k[0]; break; | |||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ | |||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ | |||
case 5 : b+=k8[4]; /* fall through */ | |||
case 4 : a+=k[0]; break; | |||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ | |||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ | |||
case 1 : a+=k8[0]; break; | |||
case 0 : return c; | |||
} | |||
const uint8_t *k8 = (const uint8_t *)k; | |||
switch(length) | |||
{ | |||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; | |||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ | |||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ | |||
case 9 : c+=k8[8]; /* fall through */ | |||
case 8 : b+=k[1]; a+=k[0]; break; | |||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ | |||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ | |||
case 5 : b+=k8[4]; /* fall through */ | |||
case 4 : a+=k[0]; break; | |||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ | |||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ | |||
case 1 : a+=k8[0]; break; | |||
case 0 : return c; | |||
} | |||
#endif /* !valgrind */ | |||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { | |||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ | |||
const uint8_t *k8; | |||
/*--------------- all but last block: aligned reads and different mixing */ | |||
while (length > 12) | |||
{ | |||
a += k[0] + (((uint32_t)k[1])<<16); | |||
b += k[2] + (((uint32_t)k[3])<<16); | |||
c += k[4] + (((uint32_t)k[5])<<16); | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 6; | |||
} | |||
/*----------------------------- handle the last (probably partial) block */ | |||
k8 = (const uint8_t *)k; | |||
switch(length) | |||
{ | |||
case 12: c+=k[4]+(((uint32_t)k[5])<<16); | |||
b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ | |||
case 10: c+=k[4]; | |||
b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 9 : c+=k8[8]; /* fall through */ | |||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ | |||
case 6 : b+=k[2]; | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 5 : b+=k8[4]; /* fall through */ | |||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ | |||
case 2 : a+=k[0]; | |||
break; | |||
case 1 : a+=k8[0]; | |||
break; | |||
case 0 : return c; /* zero length requires no mixing */ | |||
} | |||
} else { /* need to read the key one byte at a time */ | |||
const uint8_t *k = (const uint8_t *)key; | |||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */ | |||
while (length > 12) | |||
{ | |||
a += k[0]; | |||
a += ((uint32_t)k[1])<<8; | |||
a += ((uint32_t)k[2])<<16; | |||
a += ((uint32_t)k[3])<<24; | |||
b += k[4]; | |||
b += ((uint32_t)k[5])<<8; | |||
b += ((uint32_t)k[6])<<16; | |||
b += ((uint32_t)k[7])<<24; | |||
c += k[8]; | |||
c += ((uint32_t)k[9])<<8; | |||
c += ((uint32_t)k[10])<<16; | |||
c += ((uint32_t)k[11])<<24; | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 12; | |||
} | |||
/*-------------------------------- last block: affect all 32 bits of (c) */ | |||
switch(length) /* all the case statements fall through */ | |||
{ | |||
case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */ | |||
case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */ | |||
case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */ | |||
case 9 : c+=k[8]; /* FALLTHRU */ | |||
case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */ | |||
case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */ | |||
case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */ | |||
case 5 : b+=k[4]; /* FALLTHRU */ | |||
case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */ | |||
case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */ | |||
case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */ | |||
case 1 : a+=k[0]; | |||
break; | |||
case 0 : return c; | |||
} | |||
} | |||
} | |||
else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) | |||
{ | |||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ | |||
const uint8_t *k8; | |||
final(a,b,c); | |||
return c; | |||
/*--------------- all but last block: aligned reads and different mixing */ | |||
while (length > 12) | |||
{ | |||
a += k[0] + (((uint32_t)k[1])<<16); | |||
b += k[2] + (((uint32_t)k[3])<<16); | |||
c += k[4] + (((uint32_t)k[5])<<16); | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 6; | |||
} | |||
/*----------------------------- handle the last (probably partial) block */ | |||
k8 = (const uint8_t *)k; | |||
switch(length) | |||
{ | |||
case 12: c+=k[4]+(((uint32_t)k[5])<<16); | |||
b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ | |||
case 10: c+=k[4]; | |||
b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 9 : c+=k8[8]; /* fall through */ | |||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16); | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ | |||
case 6 : b+=k[2]; | |||
a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 5 : b+=k8[4]; /* fall through */ | |||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16); | |||
break; | |||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ | |||
case 2 : a+=k[0]; | |||
break; | |||
case 1 : a+=k8[0]; | |||
break; | |||
case 0 : return c; /* zero length requires no mixing */ | |||
} | |||
} | |||
else | |||
{ | |||
/* need to read the key one byte at a time */ | |||
const uint8_t *k = (const uint8_t *)key; | |||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */ | |||
while (length > 12) | |||
{ | |||
a += k[0]; | |||
a += ((uint32_t)k[1])<<8; | |||
a += ((uint32_t)k[2])<<16; | |||
a += ((uint32_t)k[3])<<24; | |||
b += k[4]; | |||
b += ((uint32_t)k[5])<<8; | |||
b += ((uint32_t)k[6])<<16; | |||
b += ((uint32_t)k[7])<<24; | |||
c += k[8]; | |||
c += ((uint32_t)k[9])<<8; | |||
c += ((uint32_t)k[10])<<16; | |||
c += ((uint32_t)k[11])<<24; | |||
mix(a,b,c); | |||
length -= 12; | |||
k += 12; | |||
} | |||
/*-------------------------------- last block: affect all 32 bits of (c) */ | |||
switch(length) /* all the case statements fall through */ | |||
{ | |||
case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */ | |||
case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */ | |||
case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */ | |||
case 9 : c+=k[8]; /* FALLTHRU */ | |||
case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */ | |||
case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */ | |||
case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */ | |||
case 5 : b+=k[4]; /* FALLTHRU */ | |||
case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */ | |||
case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */ | |||
case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */ | |||
case 1 : a+=k[0]; | |||
break; | |||
case 0 : return c; | |||
} | |||
} | |||
final(a,b,c); | |||
return c; | |||
} | |||
/* clang-format on */ | |||
/* a simple hash function similiar to what perl does for strings. | |||
* for good results, the string should not be excessivly large. | |||
@@ -457,7 +472,7 @@ static unsigned long lh_char_hash(const void *k) | |||
if (random_seed == -1) { | |||
RANDOM_SEED_TYPE seed; | |||
/* we can't use -1 as it is the unitialized sentinel */ | |||
while ((seed = json_c_get_random_seed()) == -1); | |||
while ((seed = json_c_get_random_seed()) == -1) {} | |||
#if SIZEOF_INT == 8 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 | |||
#define USE_SYNC_COMPARE_AND_SWAP 1 | |||
#endif | |||
@@ -638,7 +653,8 @@ json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) | |||
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) | |||
{ | |||
ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ | |||
/* CAW: fixed to be 64bit nice, still need the crazy negative case... */ | |||
ptrdiff_t n = (ptrdiff_t)(e - t->table); | |||
/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ | |||
if(n < 0) { return -2; } | |||
@@ -124,9 +124,10 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) | |||
size = vsnprintf(buf, 128, msg, ap); | |||
va_end(ap); | |||
/* if string is greater than stack buffer, then use dynamic string | |||
with vasprintf. Note: some implementation of vsnprintf return -1 | |||
if output is truncated whereas some return the number of bytes that | |||
would have been written - this code handles both cases. */ | |||
* with vasprintf. Note: some implementation of vsnprintf return -1 | |||
* if output is truncated whereas some return the number of bytes that | |||
* would have been written - this code handles both cases. | |||
*/ | |||
if(size == -1 || size > 127) { | |||
va_start(ap, msg); | |||
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } | |||
@@ -9,6 +9,7 @@ static struct { | |||
int errno_value; | |||
const char *errno_str; | |||
} errno_list[] = { | |||
/* clang-format off */ | |||
#define STRINGIFY(x) #x | |||
#define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]} | |||
ENTRY(EPERM), | |||
@@ -52,6 +53,7 @@ static struct { | |||
ENTRY(EAGAIN), | |||
{ 0, (char *)0 } | |||
}; | |||
/* clang-format on */ | |||
// Enabled during tests | |||
int _json_c_strerror_enable = 0; | |||
@@ -32,30 +32,32 @@ static const char *input_json_str = "{ " | |||
"'m~n': 8 " | |||
"}"; | |||
static const char *rec_input_json_str = "{" | |||
"'arr' : [" | |||
"{" | |||
"'obj': [" | |||
"{},{}," | |||
"{" | |||
"'obj1': 0," | |||
"'obj2': \"1\"" | |||
"}" | |||
"]" | |||
"}" | |||
"]," | |||
"'obj' : {" | |||
"'obj': {" | |||
"'obj': [" | |||
"{" | |||
"'obj1': 0," | |||
"'obj2': \"1\"" | |||
"}" | |||
"]" | |||
"}" | |||
"}" | |||
"}"; | |||
/* clang-format off */ | |||
static const char *rec_input_json_str = | |||
"{" | |||
"'arr' : [" | |||
"{" | |||
"'obj': [" | |||
"{},{}," | |||
"{" | |||
"'obj1': 0," | |||
"'obj2': \"1\"" | |||
"}" | |||
"]" | |||
"}" | |||
"]," | |||
"'obj' : {" | |||
"'obj': {" | |||
"'obj': [" | |||
"{" | |||
"'obj1': 0," | |||
"'obj2': \"1\"" | |||
"}" | |||
"]" | |||
"}" | |||
"}" | |||
"}"; | |||
/* clang-format on */ | |||
/* Example from RFC */ | |||
static void test_example_get() | |||
@@ -67,6 +69,7 @@ static void test_example_get() | |||
int i; | |||
}; | |||
/* Create a map to iterate over for the ints */ | |||
/* clang-format off */ | |||
struct json_pointer_map_s_i json_pointers[] = { | |||
{ "/", 0 }, | |||
{ "/a~1b", 1 }, | |||
@@ -79,6 +82,7 @@ static void test_example_get() | |||
{ "/m~0n", 8 }, | |||
{ NULL, 0} | |||
}; | |||
/* clang-format on */ | |||
jo1 = json_tokener_parse(input_json_str); | |||
assert(NULL != jo1); | |||
@@ -310,8 +310,9 @@ struct incremental_step { | |||
{ "fail", 5, 2, json_tokener_error_parse_boolean, 1 }, | |||
/* Although they may initially look like they should fail, | |||
the next few tests check that parsing multiple sequential | |||
json objects in the input works as expected */ | |||
* the next few tests check that parsing multiple sequential | |||
* json objects in the input works as expected | |||
*/ | |||
{ "null123", 9, 4, json_tokener_success, 0 }, | |||
{ &"null123"[4], 4, 3, json_tokener_success, 1 }, | |||
{ "nullx", 5, 4, json_tokener_success, 0 }, | |||
@@ -357,8 +358,9 @@ struct incremental_step { | |||
{ "[,1]", -1, 1, json_tokener_error_parse_unexpected, 1 }, | |||
/* This behaviour doesn't entirely follow the json spec, but until we have | |||
a way to specify how strict to be we follow Postel's Law and be liberal | |||
in what we accept (up to a point). */ | |||
* a way to specify how strict to be we follow Postel's Law and be liberal | |||
* in what we accept (up to a point). | |||
*/ | |||
{ "[1,2,3,]", -1, -1, json_tokener_success, 0 }, | |||
{ "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, | |||
@@ -24,7 +24,8 @@ static int vasprintf(char **buf, const char *fmt, va_list ap) | |||
chars = _vscprintf(fmt, ap)+1; | |||
#else /* !defined(WIN32) */ | |||
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite | |||
our buffer like on some 64bit sun systems.... but hey, its time to move on */ | |||
* our buffer like on some 64bit sun systems.... but hey, its time to move on | |||
*/ | |||
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; | |||
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ | |||
#endif /* defined(WIN32) */ | |||