/* Flatbuffers parser attributes and symbols. */ #ifndef SYMBOLS_H #define SYMBOLS_H #include #include "config.h" #include "lex/tokens.h" #include "hash/hash_table.h" #include "hash/ptr_set.h" typedef struct fb_token fb_token_t; typedef struct fb_string fb_string_t; typedef struct fb_value fb_value_t; typedef struct fb_symbol fb_symbol_t; typedef struct fb_metadata fb_metadata_t; typedef struct fb_name fb_name_t; typedef fb_symbol_t fb_namespace_t; typedef fb_symbol_t fb_ref_t; /* Doc is not strictly a symbol, just a chained token list, but close enough. */ typedef fb_symbol_t fb_doc_t; typedef fb_name_t fb_include_t; typedef struct fb_attribute fb_attribute_t; typedef struct fb_member fb_member_t; typedef struct fb_compound_type fb_compound_type_t; typedef struct fb_scope fb_scope_t; typedef struct fb_root_schema fb_root_schema_t; typedef struct fb_root_type fb_root_type_t; typedef struct fb_schema fb_schema_t; enum { tok_kw_base = LEX_TOK_KW_BASE, tok_kw_bool, tok_kw_byte, tok_kw_char, tok_kw_enum, tok_kw_float32, tok_kw_float64, tok_kw_int, tok_kw_int8, tok_kw_int16, tok_kw_int32, tok_kw_int64, tok_kw_long, tok_kw_null, tok_kw_true, tok_kw_uint, tok_kw_false, tok_kw_float, tok_kw_short, tok_kw_table, tok_kw_ubyte, tok_kw_uint8, tok_kw_uint16, tok_kw_uint32, tok_kw_uint64, tok_kw_ulong, tok_kw_union, tok_kw_double, tok_kw_string, tok_kw_struct, tok_kw_ushort, tok_kw_include, tok_kw_attribute, tok_kw_namespace, tok_kw_root_type, tok_kw_rpc_service, tok_kw_file_extension, tok_kw_file_identifier, LEX_TOK_KW_END, /* Pseudo keywords. */ tok_kw_doc_comment }; struct fb_token { const char *text; long len; long linenum; long pos; long id; }; enum fb_scalar_type { fb_missing_type = 0, fb_ulong, fb_uint, fb_ushort, fb_ubyte, fb_bool, fb_long, fb_int, fb_short, fb_byte, fb_double, fb_float, fb_char, }; typedef enum fb_scalar_type fb_scalar_type_t; static inline size_t sizeof_scalar_type(fb_scalar_type_t st) { static const size_t scalar_type_size[] = { 0, 8, 4, 2, 1, 1, 8, 4, 2, 1, 8, 4, 1 }; return scalar_type_size[st]; } enum fb_value_type { vt_missing = 0, vt_invalid = 1, vt_null, vt_string, vt_float, vt_int, vt_uint, vt_bool, vt_vector_type, vt_scalar_type, vt_vector_string_type, vt_string_type, vt_vector_type_ref, vt_type_ref, vt_name_ref, vt_compound_type_ref, vt_vector_compound_type_ref, vt_fixed_array_type, vt_fixed_array_type_ref, vt_fixed_array_string_type, vt_fixed_array_compound_type_ref }; struct fb_string { char *s; /* printf statements relies on this being int. */ int len; }; struct fb_value { union { fb_string_t s; double f; int64_t i; uint64_t u; uint8_t b; fb_token_t *t; fb_compound_type_t *ct; fb_scalar_type_t st; fb_ref_t *ref; }; unsigned short type; uint32_t len; }; enum fb_kind { fb_is_table, fb_is_struct, fb_is_rpc_service, fb_is_enum, fb_is_union, fb_is_member }; /* * Used for white, gray, black graph coloring while detecting circular * references. */ enum fb_symbol_flags { fb_circular_open = 1, fb_circular_closed = 2, fb_duplicate = 4, fb_indexed = 8, }; enum fb_member_flags { fb_fm_optional = 1 }; /* * We keep the link first in all structs so that we can use a * generic list reverse function after all symbols have been pushed * within a scope. */ struct fb_symbol { fb_symbol_t *link; fb_token_t *ident; uint16_t kind; uint16_t flags; }; struct fb_name { fb_name_t *link; fb_value_t name; }; #define fb_name_table __flatcc_fb_name_table #define fb_value_set __flatcc_fb_value_set #define fb_symbol_table __flatcc_fb_symbol_table #define fb_scope_table __flatcc_fb_scope_table DECLARE_HASH_TABLE(fb_name_table, fb_name_t *) DECLARE_HASH_TABLE(fb_schema_table, fb_schema_t *) DECLARE_HASH_TABLE(fb_value_set, fb_value_t *) DECLARE_HASH_TABLE(fb_symbol_table, fb_symbol_t *) DECLARE_HASH_TABLE(fb_scope_table, fb_scope_t *) struct fb_member { fb_symbol_t symbol; /* Struct or table field type, or method response type. */ fb_value_t type; /* Method request type only used for methods. */ fb_value_t req_type; fb_value_t value; fb_metadata_t *metadata; fb_doc_t *doc; uint16_t metadata_flags; /* * `align`, `offset` are for structs only. 64-bit allows for * dynamically configured 64-bit file offsets. Align is restricted to * at most 256 and must be a power of 2. */ uint16_t align; uint16_t flags; uint64_t offset; uint64_t size; /* `id` is for table fields only. */ uint64_t id; /* * Resolved `nested_flatbuffer` attribute type. Always a table if * set, and only on struct and table fields. */ fb_compound_type_t *nest; /* Used to generate table fields in sorted order. */ fb_member_t *order; /* * Use by code generators. Only valid during export and may hold * garbage from a prevous export. */ size_t export_index; }; struct fb_metadata { fb_metadata_t *link; fb_token_t *ident; fb_value_t value; }; struct fb_compound_type { fb_symbol_t symbol; /* `scope` may span multiple input files, but has a unique namespace. */ fb_scope_t *scope; /* Identifies the the schema the symbol belongs. */ fb_schema_t *schema; fb_symbol_t *members; fb_member_t *ordered_members; fb_member_t *primary_key; fb_metadata_t *metadata; fb_doc_t *doc; fb_value_t type; fb_symbol_table_t index; /* Only for enums. */ fb_value_set_t value_set; /* FNV-1a 32 bit hash of fully qualified name, accidental 0 maps to hash(""). */ uint32_t type_hash; uint16_t metadata_flags; /* `count` is for tables only. */ uint64_t count; /* `align`, `size` is for structs only. */ uint16_t align; uint64_t size; /* Sort structs with forward references. */ fb_compound_type_t *order; /* * Use by code generators. Only valid during export and may hold * garbage from a previous export. */ size_t export_index; }; enum fb_known_attributes { fb_attr_unknown = 0, fb_attr_id = 1, fb_attr_deprecated = 2, fb_attr_original_order = 3, fb_attr_force_align = 4, fb_attr_bit_flags = 5, fb_attr_nested_flatbuffer = 6, fb_attr_key = 7, fb_attr_required = 8, fb_attr_hash = 9, fb_attr_base64 = 10, fb_attr_base64url = 11, fb_attr_primary_key = 12, fb_attr_sorted = 13, KNOWN_ATTR_COUNT }; enum fb_known_attribute_flags { fb_f_unknown = 1 << fb_attr_unknown, fb_f_id = 1 << fb_attr_id, fb_f_deprecated = 1 << fb_attr_deprecated, fb_f_original_order = 1 << fb_attr_original_order, fb_f_force_align = 1 << fb_attr_force_align, fb_f_bit_flags = 1 << fb_attr_bit_flags, fb_f_nested_flatbuffer = 1 << fb_attr_nested_flatbuffer, fb_f_key = 1 << fb_attr_key, fb_f_required = 1 << fb_attr_required, fb_f_hash = 1 << fb_attr_hash, fb_f_base64 = 1 << fb_attr_base64, fb_f_base64url = 1 << fb_attr_base64url, fb_f_primary_key = 1 << fb_attr_primary_key, fb_f_sorted = 1 << fb_attr_sorted, }; struct fb_attribute { fb_name_t name; unsigned int known; }; struct fb_scope { fb_ref_t *name; fb_symbol_table_t symbol_index; fb_string_t prefix; }; struct fb_root_schema { fb_scope_table_t scope_index; fb_name_table_t attribute_index; fb_schema_table_t include_index; int include_count; int include_depth; size_t total_source_size; }; struct fb_root_type { /* Root decl. before symbol is visible. */ fb_ref_t *name; /* Resolved symbol. */ fb_symbol_t *type; fb_scope_t *scope; }; /* * We store the parsed structure as token references. Tokens are stored * in a single array pointing into the source buffer. * * Strings may contain multiple tokens when holding control characters * and line breaks, but for our purposes the first string part is * sufficient. */ struct fb_schema { fb_include_t *includes; fb_name_t *attributes; fb_value_t file_identifier; fb_value_t file_extension; fb_symbol_t *symbols; /* Topologically sorted structs. */ fb_compound_type_t *ordered_structs; fb_root_type_t root_type; fb_root_schema_t *root_schema; /* Only used if schema is root. */ fb_root_schema_t root_schema_instance; /* An optional scope prefix for generated code. */ fb_string_t prefix; /* The basenameup in a format that can be index. */ fb_name_t name; /* These are allocated strings that must be freed. */ /* Name of schema being processed without path or default extension. */ char *basename; /* Uppercase basename for codegen and for case insenstive file inclusion check. */ char *basenameup; /* Basename with extension. */ char *errorname; /* * The dependency schemas visible to this schema (includes self). * Compound symbols have a link to schema which can be checked * against this set to see if the symbol is visible in this * conctext. */ ptr_set_t visible_schema; }; /* * Helpers to ensure a symbol is actually visible because a scope * (namespace) may be extended when a parent inlcudes another file * first. */ static inline fb_compound_type_t *get_enum_if_visible(fb_schema_t *schema, fb_symbol_t *sym) { fb_compound_type_t *ct = 0; switch (sym->kind) { case fb_is_union: /* Fall through. */ case fb_is_enum: ct = (fb_compound_type_t *)sym; if (!ptr_set_exists(&schema->visible_schema, ct->schema)) { ct = 0; } break; default: break; } return ct; } static inline fb_compound_type_t *get_compound_if_visible(fb_schema_t *schema, fb_symbol_t *sym) { fb_compound_type_t *ct = 0; switch (sym->kind) { case fb_is_struct: case fb_is_table: case fb_is_rpc_service: case fb_is_union: case fb_is_enum: ct = (fb_compound_type_t *)sym; if (!ptr_set_exists(&schema->visible_schema, ct->schema)) { ct = 0; } break; default: break; } return ct; } /* Constants are specific to 32-bit FNV-1a hash. It is important to use unsigned integers. */ static inline uint32_t fb_hash_fnv1a_32_init(void) { return 2166136261UL; } static inline uint32_t fb_hash_fnv1a_32_append(uint32_t hash, const char *data, size_t len) { while (len--) { hash ^= *(uint8_t *)data++; hash = hash * 16777619UL; } return hash; } #endif /* SYMBOLS_H */