| 2750 | } |
| 2751 | |
| 2752 | CheckedError Parser::ParseDecl(const char *filename) { |
| 2753 | std::vector<std::string> dc = doc_comment_; |
| 2754 | bool fixed = IsIdent("struct"); |
| 2755 | if (!fixed && !IsIdent("table")) return Error("declaration expected"); |
| 2756 | NEXT(); |
| 2757 | std::string name = attribute_; |
| 2758 | EXPECT(kTokenIdentifier); |
| 2759 | StructDef *struct_def; |
| 2760 | ECHECK(StartStruct(name, &struct_def)); |
| 2761 | struct_def->doc_comment = dc; |
| 2762 | struct_def->fixed = fixed; |
| 2763 | if (filename && !opts.project_root.empty()) { |
| 2764 | struct_def->declaration_file = |
| 2765 | &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths)); |
| 2766 | } |
| 2767 | ECHECK(ParseMetaData(&struct_def->attributes)); |
| 2768 | struct_def->sortbysize = |
| 2769 | struct_def->attributes.Lookup("original_order") == nullptr && !fixed; |
| 2770 | EXPECT('{'); |
| 2771 | while (token_ != '}') ECHECK(ParseField(*struct_def)); |
| 2772 | if (fixed) { |
| 2773 | const auto force_align = struct_def->attributes.Lookup("force_align"); |
| 2774 | if (force_align) { |
| 2775 | size_t align; |
| 2776 | ECHECK(ParseAlignAttribute(force_align->constant, struct_def->minalign, |
| 2777 | &align)); |
| 2778 | struct_def->minalign = align; |
| 2779 | } |
| 2780 | if (!struct_def->bytesize) return Error("size 0 structs not allowed"); |
| 2781 | } |
| 2782 | struct_def->PadLastField(struct_def->minalign); |
| 2783 | // Check if this is a table that has manual id assignments |
| 2784 | auto &fields = struct_def->fields.vec; |
| 2785 | if (!fixed && fields.size()) { |
| 2786 | size_t num_id_fields = 0; |
| 2787 | for (auto it = fields.begin(); it != fields.end(); ++it) { |
| 2788 | if ((*it)->attributes.Lookup("id")) num_id_fields++; |
| 2789 | } |
| 2790 | // If any fields have ids.. |
| 2791 | if (num_id_fields || opts.require_explicit_ids) { |
| 2792 | // Then all fields must have them. |
| 2793 | if (num_id_fields != fields.size()) { |
| 2794 | if (opts.require_explicit_ids) { |
| 2795 | return Error( |
| 2796 | "all fields must have an 'id' attribute when " |
| 2797 | "--require-explicit-ids is used"); |
| 2798 | } else { |
| 2799 | return Error( |
| 2800 | "either all fields or no fields must have an 'id' attribute"); |
| 2801 | } |
| 2802 | } |
| 2803 | // Simply sort by id, then the fields are the same as if no ids had |
| 2804 | // been specified. |
| 2805 | std::sort(fields.begin(), fields.end(), compareFieldDefs); |
| 2806 | // Verify we have a contiguous set, and reassign vtable offsets. |
| 2807 | FLATBUFFERS_ASSERT(fields.size() <= |
| 2808 | flatbuffers::numeric_limits<voffset_t>::max()); |
| 2809 | for (voffset_t i = 0; i < static_cast<voffset_t>(fields.size()); i++) { |
nothing calls this directly
no test coverage detected