static int json_get_array_size(struct json_parse_state_s* state) { size_t elements = 0; if ('[' != state->src[state->offset]) { // expected array to begin with leading '[' return 1; } // skip leading '[' state->offset++; state->dom_size += sizeof(struct json_array_s); while (state->offset < state->size) { if (json_skip_whitespace(state)) { // reached end of buffer before array was complete! return 1; } if (']' == state->src[state->offset]) { // skip trailing ']' state->offset++; // finished the object! break; } // if we parsed at least once element previously, grok for a comma if (0 < elements) { if (',' != state->src[state->offset]) { // expected a comma where there was none! return 1; } // skip comma state->offset++; if (json_skip_whitespace(state)) { // reached end of buffer before array was complete! return 1; } } if (json_get_value_size(state)) { // value parsing failed! return 1; } // successfully parsed an array element! elements++; } state->dom_size += sizeof(struct json_value_s) * elements; state->dom_size += sizeof(struct json_array_element_s) * elements; return 0; }
struct json_value_s* json_parse(const void* src, size_t src_size) { struct json_parse_state_s state; void* allocation; if (0 == src || 2 > src_size) { // absolute minimum valid json is either "{}" or "[]" return 0; } state.src = src; state.size = src_size; state.offset = 0; state.dom_size = 0; state.data_size = 0; if (json_get_value_size(&state)) { // parsing value's size failed (most likely an invalid JSON DOM!) return 0; } // our total allocation is the combination of the dom and data sizes (we // first encode the structure of the JSON, and then the data referenced by // the JSON values) allocation = malloc(state.dom_size + state.data_size); if (0 == allocation) { // malloc failed! return 0; } // reset offset so we can reuse it state.offset = 0; state.dom = allocation; state.data = state.dom + state.dom_size; state.dom += sizeof(struct json_value_s); if (json_parse_value(&state, (struct json_value_s* )allocation)) { // really bad chi here free(allocation); return 0; } return allocation; }
static int json_get_object_size(struct json_parse_state_s* state) { size_t elements = 0; if ('{' != state->src[state->offset]) { // expected object to begin with leading '{' return 1; } // skip leading '{' state->offset++; state->dom_size += sizeof(struct json_object_s); while (state->offset < state->size) { if (json_skip_whitespace(state)) { // reached end of buffer before object was complete! return 1; } if ('}' == state->src[state->offset]) { // skip trailing '}' state->offset++; // finished the object! break; } // if we parsed at least once element previously, grok for a comma if (0 < elements) { if (',' != state->src[state->offset]) { // expected a comma where there was none! return 1; } // skip comma state->offset++; if (json_skip_whitespace(state)) { // reached end of buffer before object was complete! return 1; } } if (json_get_string_size(state)) { // string parsing failed! return 1; } if (json_skip_whitespace(state)) { // reached end of buffer before object was complete! return 1; } if (':' != state->src[state->offset]) { // colon seperating name/value pair was missing! return 1; } // skip colon state->offset++; if (json_skip_whitespace(state)) { // reached end of buffer before object was complete! return 1; } if (json_get_value_size(state)) { // value parsing failed! return 1; } // successfully parsed a name/value pair! elements++; } state->dom_size += sizeof(struct json_string_s) * elements; state->dom_size += sizeof(struct json_value_s) * elements; state->dom_size += sizeof(struct json_object_element_s) * elements; return 0; }
static int json_get_array_size(struct json_parse_state_s *state) { size_t elements = 0; int allow_comma = 0; if ('[' != state->src[state->offset]) { // expected array to begin with leading '[' state->error = json_parse_error_unknown; return 1; } // skip leading '[' state->offset++; state->dom_size += sizeof(struct json_array_s); while (state->offset < state->size) { if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } if (']' == state->src[state->offset]) { // skip trailing ']' state->offset++; // finished the object! break; } // if we parsed at least once element previously, grok for a comma if (allow_comma) { if (',' == state->src[state->offset]) { // skip comma state->offset++; allow_comma = 0; } else if (!(json_parse_flags_allow_no_commas & state->flags_bitset)) { state->error = json_parse_error_expected_comma; return 1; } if (json_parse_flags_allow_trailing_comma & state->flags_bitset) { continue; } else { if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } } } if (json_get_value_size(state, /* is_global_object = */ 0)) { // value parsing failed! return 1; } // successfully parsed an array element! elements++; allow_comma = 1; } state->dom_size += sizeof(struct json_value_s) * elements; state->dom_size += sizeof(struct json_array_element_s) * elements; return 0; }
static int json_get_object_size(struct json_parse_state_s *state, int is_global_object) { size_t elements = 0; int allow_comma = 0; if (!is_global_object) { if ('{' != state->src[state->offset]) { state->error = json_parse_error_unknown; return 1; } // skip leading '{' state->offset++; } state->dom_size += sizeof(struct json_object_s); while (state->offset < state->size) { if (!is_global_object) { if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } if ('}' == state->src[state->offset]) { // skip trailing '}' state->offset++; // finished the object! break; } } else { // we don't require brackets, so that means the object ends when the input // stream ends! if (json_skip_all_skippables(state)) { break; } } // if we parsed at least once element previously, grok for a comma if (allow_comma) { if (',' == state->src[state->offset]) { // skip comma state->offset++; allow_comma = 0; } else if (!(json_parse_flags_allow_no_commas & state->flags_bitset)) { // if we are required to have a comma, and we found none, bail out! state->error = json_parse_error_expected_comma; return 1; } if (json_parse_flags_allow_trailing_comma & state->flags_bitset) { continue; } else { if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } } } if (json_get_key_size(state)) { // key parsing failed! state->error = json_parse_error_invalid_string; return 1; } if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } if (json_parse_flags_allow_equals_in_object & state->flags_bitset) { if ((':' != state->src[state->offset]) && ('=' != state->src[state->offset])) { state->error = json_parse_error_expected_colon; return 1; } } else { if (':' != state->src[state->offset]) { state->error = json_parse_error_expected_colon; return 1; } } // skip colon state->offset++; if (json_skip_all_skippables(state)) { state->error = json_parse_error_premature_end_of_buffer; return 1; } if (json_get_value_size(state, /* is_global_object = */ 0)) { // value parsing failed! return 1; } // successfully parsed a name/value pair! elements++; allow_comma = 1; } state->dom_size += sizeof(struct json_string_s) * elements; state->dom_size += sizeof(struct json_value_s) * elements; state->dom_size += sizeof(struct json_object_element_s) * elements; return 0; }
struct json_value_s *json_parse_ex(const void *src, size_t src_size, size_t flags_bitset, struct json_parse_result_s *result) { struct json_parse_state_s state; void *allocation; if (result) { result->error = json_parse_error_none; result->error_offset = 0; result->error_line_no = 0; result->error_row_no = 0; } if (0 == src) { // invalid src pointer was null! return 0; } else if (!(json_parse_flags_allow_global_object & flags_bitset) && src_size < 2) { // absolute minimum valid json is either "{}" or "[]" return 0; } state.src = src; state.size = src_size; state.offset = 0; state.line_no = 1; state.line_offset = 0; state.error = json_parse_error_none; state.dom_size = 0; state.data_size = 0; state.flags_bitset = flags_bitset; if (json_get_value_size( &state, /* is_global_object = */ ( json_parse_flags_allow_global_object & state.flags_bitset))) { // parsing value's size failed (most likely an invalid JSON DOM!) if (result) { result->error = state.error; result->error_offset = state.offset; result->error_line_no = state.line_no; result->error_row_no = state.offset - state.line_offset; } return 0; } // our total allocation is the combination of the dom and data sizes (we // first encode the structure of the JSON, and then the data referenced by // the JSON values) allocation = malloc(state.dom_size + state.data_size); if (0 == allocation) { // malloc failed! return 0; } // reset offset so we can reuse it state.offset = 0; state.dom = allocation; state.data = state.dom + state.dom_size; state.dom += sizeof(struct json_value_s); json_parse_value( &state, /* is_global_object = */ ( json_parse_flags_allow_global_object & state.flags_bitset), (struct json_value_s *)allocation); return allocation; }