Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}