void skip_value()

in src/detail/skip_value.cpp [135:211]


void skip_value(decode_context &context) {
  enum state {
    done = 0,
    want = 1 << 0,
    need = 1 << 1,
    read_sep = 1 << 2,
    read_key = 1 << 3,
    read_val = 1 << 4,

    want_sep = want | read_sep,
    want_key = want | read_key,
    need_key = need | read_key,
    want_val = want | read_val,
    need_val = need | read_val
  };

  // We can deal with the first 64 nesting levels {[[{[[ ... ]]}]]} without heap
  // allocations. Most reasonable JSON will have way less than this, but in case
  // we encounter an unusual JSON file (perhaps one designed to stack overflow),
  // the nesting stack will be moved over to the heap.
  detail::stack<char, 64> stack;

  auto inside = 0;
  auto closer = int_fast16_t(std::numeric_limits<int16_t>::max());  // a value outside the range of a 'char'
  auto pstate = need_val;

  while (json_likely(context.remaining() && pstate != done)) {
    if (json_likely(inside)) {
      skip_any_whitespace(context);
    }

    const auto c = peek_unchecked(context);

    if (c == ',' && (pstate & read_sep)) {
      skip_unchecked_1(context);
      pstate = (inside == '{' ? need_key : need_val);
      continue;
    }

    if (c == '"' && (pstate & read_key)) {
      skip_string(context);
      skip_any_whitespace(context);
      skip_1(context, ':');
      pstate = need_val;
      continue;
    }

    if (c == closer && !(pstate & need)) {
      skip_unchecked_1(context);
      inside = stack.pop();
      closer = inside + 2;  // '{' + 2 == '}', '[' + 2 == ']'
      pstate = (inside ? want_sep : done);
      continue;
    }

    fail_if(context, pstate & read_key, "Expected '\"'");
    fail_if(context, pstate & read_sep, inside == '{' ?
        "Expected ',' or '}'" :
        "Expected ',' or ']");

    if (c == '{' || c == '[') {
      skip_unchecked_1(context);
      stack.push(inside);
      inside = c;
      closer = inside + 2;  // '{' + 2 == '}', '[' + 2 == ']'
      pstate = (inside == '{' ? want_key : want_val);
      continue;
    }

    skip_simple_value(context);
    pstate = (inside ? want_sep : done);
  }

  fail_if(context, inside == '{', "Expected '}'");
  fail_if(context, inside == '[', "Expected ']'");
  fail_if(context, pstate != done, "Unexpected EOF");
}