| @@ -663,9 +663,9 @@ int32_t json_object_get_int(const struct json_object *jso) | |||||
| if (o_type == json_type_string) | 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) | if (json_parse_int64(get_string_component(jso), &cint64) != 0) | ||||
| return 0; /* whoops, it didn't work. */ | return 0; /* whoops, it didn't work. */ | ||||
| o_type = json_type_int; | 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; | char buf[128], *p, *q; | ||||
| int size; | int size; | ||||
| /* Although JSON RFC does not support | /* 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)) | if (isnan(jso->o.c_double)) | ||||
| { | { | ||||
| size = snprintf(buf, sizeof(buf), "NaN"); | 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') | if (*errPtr != '\0') | ||||
| { | { | ||||
| errno = EINVAL; | 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) && | if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && | ||||
| (ERANGE == errno)) | (ERANGE == errno)) | ||||
| cdouble = 0.0; | cdouble = 0.0; | ||||
| @@ -153,10 +153,10 @@ json_object_iter_init_default(void) | |||||
| struct json_object_iterator iter; | 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; | iter.opaque_ = NULL; | ||||
| return iter; | return iter; | ||||
| @@ -20,7 +20,8 @@ | |||||
| extern "C" { | extern "C" { | ||||
| #endif | #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); | typedef void (json_object_private_delete_fn)(struct json_object *o); | ||||
| @@ -52,8 +53,8 @@ struct json_object | |||||
| struct { | struct { | ||||
| union { | union { | ||||
| /* optimize: if we have small strings, we can store them | /* 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 *ptr; | ||||
| char data[LEN_DIRECT_STRING_DATA]; | char data[LEN_DIRECT_STRING_DATA]; | ||||
| } str; | } 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) | static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx) | ||||
| { | { | ||||
| int i, len = strlen(path); | 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 (len == 1) { | ||||
| if (isdigit((unsigned char)path[0])) { | if (isdigit((unsigned char)path[0])) { | ||||
| *idx = (path[0] - '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(), | /* 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)) | if (json_object_is_type(parent, json_type_object)) | ||||
| return json_object_object_add(parent, path, value); | 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; | errno = ENOENT; | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -158,7 +161,8 @@ static int json_pointer_get_recursive( | |||||
| return rc; | return rc; | ||||
| if (endp) { | 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); | 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 char json_false_str[] = "false"; | ||||
| static const int json_false_str_len = sizeof(json_false_str) - 1; | 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) | 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; | tok->err = json_tokener_success; | ||||
| /* this interface is presently not 64-bit clean due to the int len argument | /* 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)) { | if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) { | ||||
| tok->err = json_tokener_error_size; | tok->err = json_tokener_error_size; | ||||
| return NULL; | 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") */ | 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 | /* 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; | int is_negative = 0; | ||||
| const char *_json_inf_str = json_inf_str; | const char *_json_inf_str = json_inf_str; | ||||
| if (!(tok->flags & JSON_TOKENER_STRICT)) | 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. | /* 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) == '-') | if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-') | ||||
| { | { | ||||
| is_negative = 1; | 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); | unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); | ||||
| printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2); | printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2); | ||||
| } else if (IS_HIGH_SURROGATE(tok->ucs_char)) { | } 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; | got_hi_surrogate = tok->ucs_char; | ||||
| /* Not at end, and the next two chars should be "\u" */ | /* Not at end, and the next two chars should be "\u" */ | ||||
| if ((len == -1 || len > (tok->char_offset + 2)) && | 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[1] == '\\') && | ||||
| (str[2] == 'u')) | (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) ) { | if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) { | ||||
| printbuf_memappend_fast(tok->pb, | printbuf_memappend_fast(tok->pb, | ||||
| (char*) utf8_replacement_char, 3); | (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)) { | if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { | ||||
| printbuf_memappend_fast(tok->pb, | printbuf_memappend_fast(tok->pb, | ||||
| (char*) utf8_replacement_char, 3); | (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->ucs_char = 0; | ||||
| tok->st_pos = 0; | tok->st_pos = 0; | ||||
| continue; /* other json_tokener_state_escape_unicode */ | |||||
| /* other json_tokener_state_escape_unicode */ | |||||
| continue; | |||||
| } else { | } 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, | printbuf_memappend_fast(tok->pb, | ||||
| (char*) utf8_replacement_char, 3); | (char*) utf8_replacement_char, 3); | ||||
| } | } | ||||
| @@ -684,7 +688,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { | 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); | printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); | ||||
| goto out; | goto out; | ||||
| } | } | ||||
| @@ -741,14 +746,16 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| /* non-digit characters checks */ | /* non-digit characters checks */ | ||||
| /* note: since the main loop condition to get here was | /* 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 (c == '.') { | ||||
| if (tok->is_double != 0) { | if (tok->is_double != 0) { | ||||
| /* '.' can only be found once, and out of the exponent part. | /* '.' 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; | tok->err = json_tokener_error_parse_number; | ||||
| goto out; | 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 (c == '-' && case_len != negativesign_next_possible_location) { | ||||
| /* If the negative sign is not where expected (ie | /* 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; | tok->err = json_tokener_error_parse_number; | ||||
| goto out; | goto out; | ||||
| } | } | ||||
| @@ -979,7 +987,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| /* unexpected char after JSON data */ | /* unexpected char after JSON data */ | ||||
| tok->err = json_tokener_error_parse_unexpected; | 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 && | if(state != json_tokener_state_finish && | ||||
| saved_state != json_tokener_state_finish) | saved_state != json_tokener_state_finish) | ||||
| tok->err = json_tokener_error_parse_eof; | tok->err = json_tokener_error_parse_eof; | ||||
| @@ -93,8 +93,8 @@ struct json_tokener | |||||
| struct printbuf *pb; | struct printbuf *pb; | ||||
| int max_depth, depth, is_double, st_pos; | int max_depth, depth, is_double, st_pos; | ||||
| /** | /** | ||||
| * See json_tokener_get_parse_end() | |||||
| */ | |||||
| * See json_tokener_get_parse_end() | |||||
| */ | |||||
| int char_offset; | int char_offset; | ||||
| enum json_tokener_error err; | enum json_tokener_error err; | ||||
| unsigned int ucs_char; | 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; | 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; | wpos = 0; | ||||
| while(wpos < wsize) { | while(wpos < wsize) { | ||||
| if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { | if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { | ||||
| @@ -260,16 +261,18 @@ void* rpl_realloc(void* p, size_t n) | |||||
| #endif | #endif | ||||
| #define NELEM(a) (sizeof(a) / sizeof(a[0])) | #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) | 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. | rotates. | ||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||
| */ | */ | ||||
| /* clang-format off */ | |||||
| #define mix(a,b,c) \ | #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 | 11 8 15 26 3 22 24 | ||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||
| */ | */ | ||||
| /* clang-format off */ | |||||
| #define final(a,b,c) \ | #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 | #ifdef VALGRIND | ||||
| # define PRECISE_MEMORY_ACCESS 1 | |||||
| #define PRECISE_MEMORY_ACCESS 1 | |||||
| #elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */ | #elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */ | ||||
| # define PRECISE_MEMORY_ACCESS 1 | |||||
| #define PRECISE_MEMORY_ACCESS 1 | |||||
| #elif defined(__has_feature) | #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 | #endif | ||||
| #ifndef PRECISE_MEMORY_ACCESS | #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 */ | #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 */ | #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. | /* a simple hash function similiar to what perl does for strings. | ||||
| * for good results, the string should not be excessivly large. | * 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) { | if (random_seed == -1) { | ||||
| RANDOM_SEED_TYPE seed; | RANDOM_SEED_TYPE seed; | ||||
| /* we can't use -1 as it is the unitialized sentinel */ | /* 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 | #if SIZEOF_INT == 8 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 | ||||
| #define USE_SYNC_COMPARE_AND_SWAP 1 | #define USE_SYNC_COMPARE_AND_SWAP 1 | ||||
| #endif | #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) | 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... */ | /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ | ||||
| if(n < 0) { return -2; } | if(n < 0) { return -2; } | ||||
| @@ -124,9 +124,10 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) | |||||
| size = vsnprintf(buf, 128, msg, ap); | size = vsnprintf(buf, 128, msg, ap); | ||||
| va_end(ap); | va_end(ap); | ||||
| /* if string is greater than stack buffer, then use dynamic string | /* 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) { | if(size == -1 || size > 127) { | ||||
| va_start(ap, msg); | va_start(ap, msg); | ||||
| if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } | if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } | ||||
| @@ -9,6 +9,7 @@ static struct { | |||||
| int errno_value; | int errno_value; | ||||
| const char *errno_str; | const char *errno_str; | ||||
| } errno_list[] = { | } errno_list[] = { | ||||
| /* clang-format off */ | |||||
| #define STRINGIFY(x) #x | #define STRINGIFY(x) #x | ||||
| #define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]} | #define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]} | ||||
| ENTRY(EPERM), | ENTRY(EPERM), | ||||
| @@ -52,6 +53,7 @@ static struct { | |||||
| ENTRY(EAGAIN), | ENTRY(EAGAIN), | ||||
| { 0, (char *)0 } | { 0, (char *)0 } | ||||
| }; | }; | ||||
| /* clang-format on */ | |||||
| // Enabled during tests | // Enabled during tests | ||||
| int _json_c_strerror_enable = 0; | int _json_c_strerror_enable = 0; | ||||
| @@ -32,30 +32,32 @@ static const char *input_json_str = "{ " | |||||
| "'m~n': 8 " | "'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 */ | /* Example from RFC */ | ||||
| static void test_example_get() | static void test_example_get() | ||||
| @@ -67,6 +69,7 @@ static void test_example_get() | |||||
| int i; | int i; | ||||
| }; | }; | ||||
| /* Create a map to iterate over for the ints */ | /* Create a map to iterate over for the ints */ | ||||
| /* clang-format off */ | |||||
| struct json_pointer_map_s_i json_pointers[] = { | struct json_pointer_map_s_i json_pointers[] = { | ||||
| { "/", 0 }, | { "/", 0 }, | ||||
| { "/a~1b", 1 }, | { "/a~1b", 1 }, | ||||
| @@ -79,6 +82,7 @@ static void test_example_get() | |||||
| { "/m~0n", 8 }, | { "/m~0n", 8 }, | ||||
| { NULL, 0} | { NULL, 0} | ||||
| }; | }; | ||||
| /* clang-format on */ | |||||
| jo1 = json_tokener_parse(input_json_str); | jo1 = json_tokener_parse(input_json_str); | ||||
| assert(NULL != jo1); | assert(NULL != jo1); | ||||
| @@ -310,8 +310,9 @@ struct incremental_step { | |||||
| { "fail", 5, 2, json_tokener_error_parse_boolean, 1 }, | { "fail", 5, 2, json_tokener_error_parse_boolean, 1 }, | ||||
| /* Although they may initially look like they should fail, | /* 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", 9, 4, json_tokener_success, 0 }, | ||||
| { &"null123"[4], 4, 3, json_tokener_success, 1 }, | { &"null123"[4], 4, 3, json_tokener_success, 1 }, | ||||
| { "nullx", 5, 4, json_tokener_success, 0 }, | { "nullx", 5, 4, json_tokener_success, 0 }, | ||||
| @@ -357,8 +358,9 @@ struct incremental_step { | |||||
| { "[,1]", -1, 1, json_tokener_error_parse_unexpected, 1 }, | { "[,1]", -1, 1, json_tokener_error_parse_unexpected, 1 }, | ||||
| /* This behaviour doesn't entirely follow the json spec, but until we have | /* 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, -1, json_tokener_success, 0 }, | ||||
| { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 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; | chars = _vscprintf(fmt, ap)+1; | ||||
| #else /* !defined(WIN32) */ | #else /* !defined(WIN32) */ | ||||
| /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite | /* 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; | chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; | ||||
| if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ | if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ | ||||
| #endif /* defined(WIN32) */ | #endif /* defined(WIN32) */ | ||||