| 1490 | } |
| 1491 | |
| 1492 | CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, |
| 1493 | uoffset_t *ovalue) { |
| 1494 | ParseDepthGuard depth_guard(this); |
| 1495 | ECHECK(depth_guard.Check()); |
| 1496 | |
| 1497 | size_t fieldn_outer = 0; |
| 1498 | auto err = ParseTableDelimiters( |
| 1499 | fieldn_outer, &struct_def, |
| 1500 | [&](const std::string &name, size_t &fieldn, |
| 1501 | const StructDef *struct_def_inner) -> CheckedError { |
| 1502 | if (name == "$schema") { |
| 1503 | ECHECK(Expect(kTokenStringConstant)); |
| 1504 | return NoError(); |
| 1505 | } |
| 1506 | auto field = struct_def_inner->fields.Lookup(name); |
| 1507 | if (!field) { |
| 1508 | if (!opts.skip_unexpected_fields_in_json) { |
| 1509 | return Error("unknown field: " + name); |
| 1510 | } else { |
| 1511 | ECHECK(SkipAnyJsonValue()); |
| 1512 | } |
| 1513 | } else { |
| 1514 | if (IsIdent("null") && !IsScalar(field->value.type.base_type)) { |
| 1515 | ECHECK(Next()); // Ignore this field. |
| 1516 | } else { |
| 1517 | Value val = field->value; |
| 1518 | if (field->flexbuffer) { |
| 1519 | flexbuffers::Builder builder(1024, |
| 1520 | flexbuffers::BUILDER_FLAG_SHARE_ALL); |
| 1521 | ECHECK(ParseFlexBufferValue(&builder)); |
| 1522 | builder.Finish(); |
| 1523 | // Force alignment for nested flexbuffer |
| 1524 | builder_.ForceVectorAlignment(builder.GetSize(), sizeof(uint8_t), |
| 1525 | sizeof(largest_scalar_t)); |
| 1526 | auto off = builder_.CreateVector(builder.GetBuffer()); |
| 1527 | val.constant = NumToString(off.o); |
| 1528 | } else if (field->nested_flatbuffer) { |
| 1529 | ECHECK( |
| 1530 | ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner)); |
| 1531 | } else { |
| 1532 | ECHECK(ParseAnyValue(val, field, fieldn, struct_def_inner, 0)); |
| 1533 | } |
| 1534 | // Hardcoded insertion-sort with error-check. |
| 1535 | // If fields are specified in order, then this loop exits |
| 1536 | // immediately. |
| 1537 | auto elem = field_stack_.rbegin(); |
| 1538 | for (; elem != field_stack_.rbegin() + fieldn; ++elem) { |
| 1539 | auto existing_field = elem->second; |
| 1540 | if (existing_field == field) |
| 1541 | return Error("field set more than once: " + field->name); |
| 1542 | if (existing_field->value.offset < field->value.offset) break; |
| 1543 | } |
| 1544 | // Note: elem points to before the insertion point, thus .base() |
| 1545 | // points to the correct spot. |
| 1546 | field_stack_.insert(elem.base(), std::make_pair(val, field)); |
| 1547 | fieldn++; |
| 1548 | } |
| 1549 | } |
nothing calls this directly
no test coverage detected