| 1234 | } |
| 1235 | |
| 1236 | CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, |
| 1237 | uoffset_t *ovalue) { |
| 1238 | ParseDepthGuard depth_guard(this); |
| 1239 | ECHECK(depth_guard.Check()); |
| 1240 | |
| 1241 | size_t fieldn_outer = 0; |
| 1242 | auto err = ParseTableDelimiters( |
| 1243 | fieldn_outer, &struct_def, |
| 1244 | [&](const std::string &name, size_t &fieldn, |
| 1245 | const StructDef *struct_def_inner) -> CheckedError { |
| 1246 | if (name == "$schema") { |
| 1247 | ECHECK(Expect(kTokenStringConstant)); |
| 1248 | return NoError(); |
| 1249 | } |
| 1250 | auto field = struct_def_inner->fields.Lookup(name); |
| 1251 | if (!field) { |
| 1252 | if (!opts.skip_unexpected_fields_in_json) { |
| 1253 | return Error("unknown field: " + name); |
| 1254 | } else { |
| 1255 | ECHECK(SkipAnyJsonValue()); |
| 1256 | } |
| 1257 | } else { |
| 1258 | if (IsIdent("null") && !IsScalar(field->value.type.base_type)) { |
| 1259 | ECHECK(Next()); // Ignore this field. |
| 1260 | } else { |
| 1261 | Value val = field->value; |
| 1262 | if (field->flexbuffer) { |
| 1263 | flexbuffers::Builder builder(1024, |
| 1264 | flexbuffers::BUILDER_FLAG_SHARE_ALL); |
| 1265 | ECHECK(ParseFlexBufferValue(&builder)); |
| 1266 | builder.Finish(); |
| 1267 | // Force alignment for nested flexbuffer |
| 1268 | builder_.ForceVectorAlignment(builder.GetSize(), sizeof(uint8_t), |
| 1269 | sizeof(largest_scalar_t)); |
| 1270 | auto off = builder_.CreateVector(builder.GetBuffer()); |
| 1271 | val.constant = NumToString(off.o); |
| 1272 | } else if (field->nested_flatbuffer) { |
| 1273 | ECHECK( |
| 1274 | ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner)); |
| 1275 | } else { |
| 1276 | ECHECK(ParseAnyValue(val, field, fieldn, struct_def_inner, 0)); |
| 1277 | } |
| 1278 | // Hardcoded insertion-sort with error-check. |
| 1279 | // If fields are specified in order, then this loop exits |
| 1280 | // immediately. |
| 1281 | auto elem = field_stack_.rbegin(); |
| 1282 | for (; elem != field_stack_.rbegin() + fieldn; ++elem) { |
| 1283 | auto existing_field = elem->second; |
| 1284 | if (existing_field == field) |
| 1285 | return Error("field set more than once: " + field->name); |
| 1286 | if (existing_field->value.offset < field->value.offset) break; |
| 1287 | } |
| 1288 | // Note: elem points to before the insertion point, thus .base() |
| 1289 | // points to the correct spot. |
| 1290 | field_stack_.insert(elem.base(), std::make_pair(val, field)); |
| 1291 | fieldn++; |
| 1292 | } |
| 1293 | } |
nothing calls this directly
no test coverage detected