nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

bfbs2json.c (9710B)


      1 #include "flatcc/support/readfile.h"
      2 #include "flatcc/reflection/reflection_reader.h"
      3 
      4 /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
      5 #ifndef PRId64
      6 #include <inttypes.h>
      7 #endif
      8 
      9 
     10 /*
     11  * Reads a binary schema generated by `flatcc` or Googles `flatc` tool,
     12  * then prints the content out in a custom JSON format.
     13  *
     14  * Note: This is completely unrelated to `flatcc's` JSON support - we
     15  * just needed to do something tangible with the data we read from the
     16  * binary schema and opted to print it as JSON.
     17  *
     18  * The JSON can be pretty printed with an external tool, for example:
     19  *
     20  *     cat monster_test_schema.json | jq '.'
     21  */
     22 
     23 void print_type(reflection_Type_table_t T)
     24 {
     25     int first = 1;
     26     printf("{");
     27     if (reflection_Type_base_type_is_present(T)) {
     28         if (!first) {
     29             printf(",");
     30         }
     31         printf("\"base_type\":\"%s\"", reflection_BaseType_name(reflection_Type_base_type(T)));
     32         first = 0;
     33     }
     34     if (reflection_Type_element_is_present(T)) {
     35         if (!first) {
     36             printf(",");
     37         }
     38         printf("\"element\":\"%s\"", reflection_BaseType_name(reflection_Type_element(T)));
     39         first = 0;
     40     }
     41     if (reflection_Type_index_is_present(T)) {
     42         if (!first) {
     43             printf(",");
     44         }
     45         printf("\"index\":%d", reflection_Type_index(T));
     46         first = 0;
     47     }
     48     if (reflection_Type_fixed_length_is_present(T)) {
     49         if (!first) {
     50             printf(",");
     51         }
     52         printf("\"fixed_length\":%d", reflection_Type_fixed_length(T));
     53         first = 0;
     54     }
     55     printf("}");
     56 }
     57 
     58 void print_attributes(reflection_KeyValue_vec_t KV)
     59 {
     60     size_t i;
     61     reflection_KeyValue_table_t attribute;
     62     const char *key, *value;
     63 
     64     printf("[");
     65     for (i = 0; i < reflection_KeyValue_vec_len(KV); ++i) {
     66         attribute = reflection_KeyValue_vec_at(KV, i);
     67         key = reflection_KeyValue_key(attribute);
     68         value = reflection_KeyValue_value(attribute);
     69         if (i > 0) {
     70             printf(",");
     71         }
     72         printf("{\"key\":\"%s\"", key);
     73         if (value) {
     74             /* TODO: we ought to escape '\"' and other non-string-able characters. */
     75             printf(",\"value\":\"%s\"", value);
     76         }
     77         printf("}");
     78     }
     79     printf("]");
     80 }
     81 
     82 void print_object(reflection_Object_table_t O)
     83 {
     84     reflection_Field_vec_t Flds;
     85     reflection_Field_table_t F;
     86     size_t i;
     87 
     88     Flds = reflection_Object_fields(O);
     89     printf("{\"name\":\"%s\"", reflection_Object_name(O));
     90     printf(",\"fields\":[");
     91     for (i = 0; i < reflection_Field_vec_len(Flds); ++i) {
     92         if (i > 0) {
     93             printf(",");
     94         }
     95         F = reflection_Field_vec_at(Flds, i);
     96         printf("{\"name\":\"%s\",\"type\":", reflection_Field_name(F));
     97         print_type(reflection_Field_type(F));
     98         if (reflection_Field_id_is_present(F)) {
     99             printf(",\"id\":%hu", reflection_Field_id(F));
    100         }
    101         if (reflection_Field_default_integer_is_present(F)) {
    102             printf(",\"default_integer\":%"PRId64"", (int64_t)reflection_Field_default_integer(F));
    103         }
    104         if (reflection_Field_default_real_is_present(F)) {
    105             printf(",\"default_integer\":%lf", reflection_Field_default_real(F));
    106         }
    107         if (reflection_Field_required_is_present(F)) {
    108             printf(",\"required\":%s", reflection_Field_required(F) ? "true" : "false");
    109         }
    110         if (reflection_Field_key_is_present(F)) {
    111             printf(",\"key\":%s", reflection_Field_key(F) ? "true" : "false");
    112         }
    113         if (reflection_Field_attributes_is_present(F)) {
    114             printf(",\"attributes\":");
    115             print_attributes(reflection_Field_attributes(F));
    116         }
    117         printf("}");
    118     }
    119     printf("]");
    120     if (reflection_Object_is_struct_is_present(O)) {
    121         printf(",\"is_struct\":%s", reflection_Object_is_struct(O) ? "true" : "false");
    122     }
    123     if (reflection_Object_minalign_is_present(O)) {
    124         printf(",\"minalign\":%d", reflection_Object_minalign(O));
    125     }
    126     if (reflection_Object_bytesize_is_present(O)) {
    127         printf(",\"bytesize\":%d", reflection_Object_bytesize(O));
    128     }
    129     if (reflection_Object_attributes_is_present(O)) {
    130         printf(",\"attributes\":");
    131         print_attributes(reflection_Object_attributes(O));
    132     }
    133     printf("}");
    134 }
    135 
    136 void print_enum(reflection_Enum_table_t E)
    137 {
    138     reflection_EnumVal_vec_t EnumVals;
    139     reflection_EnumVal_table_t EV;
    140     size_t i;
    141 
    142     printf("{\"name\":\"%s\"", reflection_Enum_name(E));
    143     EnumVals = reflection_Enum_values(E);
    144     printf(",\"values\":[");
    145     for (i = 0; i < reflection_Enum_vec_len(EnumVals); ++i) {
    146         EV = reflection_EnumVal_vec_at(EnumVals, i);
    147         if (i > 0) {
    148             printf(",");
    149         }
    150         printf("{\"name\":\"%s\"", reflection_EnumVal_name(EV));
    151         if (reflection_EnumVal_value_is_present(EV)) {
    152             printf(",\"value\":%"PRId64"", (int64_t)reflection_EnumVal_value(EV));
    153         }
    154         if (reflection_EnumVal_object_is_present(EV)) {
    155             printf(",\"object\":");
    156             print_object(reflection_EnumVal_object(EV));
    157         }
    158         if (reflection_EnumVal_union_type_is_present(EV)) {
    159             printf(",\"union_type\":");
    160             print_type(reflection_EnumVal_union_type(EV));
    161         }
    162         printf("}");
    163     }
    164     printf("]");
    165     if (reflection_Enum_is_union_is_present(E)) {
    166         printf(",\"is_union\":%s", reflection_Enum_is_union(E) ? "true" : "false");
    167     }
    168     printf(",\"underlying_type\":");
    169     print_type(reflection_Enum_underlying_type(E));
    170     if (reflection_Enum_attributes_is_present(E)) {
    171         printf(",\"attributes\":");
    172         print_attributes(reflection_Enum_attributes(E));
    173     }
    174     printf("}");
    175 }
    176 
    177 void print_call(reflection_RPCCall_table_t C)
    178 {
    179     printf("{\"name\":\"%s\"", reflection_RPCCall_name(C));
    180     printf(",\"request\":");
    181     print_object(reflection_RPCCall_request(C));
    182     printf(",\"response\":");
    183     print_object(reflection_RPCCall_response(C));
    184 
    185     if (reflection_RPCCall_attributes_is_present(C)) {
    186         printf(",\"attributes\":");
    187         print_attributes(reflection_RPCCall_attributes(C));
    188     }
    189     printf("}");
    190 }
    191 
    192 void print_service(reflection_Service_table_t S)
    193 {
    194     reflection_RPCCall_vec_t calls;
    195     size_t i;
    196 
    197     printf("{\"name\":\"%s\"", reflection_Service_name(S));
    198 
    199     printf(",\"calls\":[");
    200     calls = reflection_Service_calls(S);
    201     for (i = 0; i < reflection_RPCCall_vec_len(calls); ++i) {
    202         if (i > 0) {
    203             printf(",");
    204         }
    205         print_call(reflection_RPCCall_vec_at(calls, i));
    206     }
    207     printf("]");
    208 
    209     if (reflection_Service_attributes_is_present(S)) {
    210         printf(",\"attributes\":");
    211         print_attributes(reflection_Service_attributes(S));
    212     }
    213     printf("}");
    214 }
    215 
    216 void print_schema(reflection_Schema_table_t S)
    217 {
    218     reflection_Object_vec_t Objs;
    219     reflection_Enum_vec_t Enums;
    220     reflection_Service_vec_t Services;
    221     size_t i;
    222 
    223     Objs = reflection_Schema_objects(S);
    224     printf("{");
    225     printf("\"objects\":[");
    226     for (i = 0; i < reflection_Object_vec_len(Objs); ++i) {
    227         if (i > 0) {
    228             printf(",");
    229         }
    230         print_object(reflection_Object_vec_at(Objs, i));
    231     }
    232     printf("]");
    233     Enums = reflection_Schema_enums(S);
    234     printf(",\"enums\":[");
    235     for (i = 0; i < reflection_Enum_vec_len(Enums); ++i) {
    236         if (i > 0) {
    237             printf(",");
    238         }
    239         print_enum(reflection_Enum_vec_at(Enums, i));
    240     }
    241     printf("]");
    242     if (reflection_Schema_file_ident_is_present(S)) {
    243         printf(",\"file_ident\":\"%s\"", reflection_Schema_file_ident(S));
    244     }
    245     if (reflection_Schema_file_ext_is_present(S)) {
    246         printf(",\"file_ext\":\"%s\"", reflection_Schema_file_ext(S));
    247     }
    248     if (reflection_Schema_root_table_is_present(S)) {
    249         printf(",\"root_table\":");
    250         print_object(reflection_Schema_root_table(S));
    251     }
    252     if (reflection_Schema_services_is_present(S)) {
    253         printf(",\"services\":[");
    254         Services = reflection_Schema_services(S);
    255         for (i = 0; i < reflection_Service_vec_len(Services); ++i) {
    256             if (i > 0) {
    257                 printf(",");
    258             }
    259             print_service(reflection_Service_vec_at(Services, i));
    260         }
    261         printf("]");
    262     }
    263     printf("}\n");
    264 }
    265 
    266 int load_and_dump_schema(const char *filename)
    267 {
    268     void *buffer;
    269     size_t size;
    270     int ret = -1;
    271     reflection_Schema_table_t S;
    272 
    273     buffer = readfile(filename, 100000, &size);
    274     if (!buffer) {
    275         fprintf(stderr, "failed to load binary schema file: '%s'\n", filename);
    276         goto done;
    277     }
    278     if (size < 12) {
    279         fprintf(stderr, "file too small to access: '%s'\n", filename);
    280         goto done;
    281     }
    282     S = reflection_Schema_as_root(buffer);
    283     if (!S) {
    284         S = reflection_Schema_as_root((char*)buffer + 4);
    285         if (S) {
    286             fprintf(stderr, "(skipping length field of input buffer)\n");
    287         }
    288     }
    289     if (!S) {
    290         fprintf(stderr, "input is not a valid schema");
    291         goto done;
    292     }
    293     print_schema(S);
    294     ret = 0;
    295 
    296 done:
    297     if (buffer) {
    298         free(buffer);
    299     }
    300     return ret;
    301 }
    302 
    303 int main(int argc, char *argv[])
    304 {
    305     if (argc != 2) {
    306         fprintf(stderr, "usage: bfbs2json <filename>\n");
    307         fprintf(stderr, "reads a binary flatbuffer schema and prints it to compact json on stdout\n\n");
    308         fprintf(stderr, "pretty print with exernal tool, for example:\n"
    309                "  bfbs2json myschema.bfbs | python -m json.tool > myschema.json\n"
    310                "note: also understands binary schema files with a 4 byte length prefix\n");
    311         exit(-1);
    312     }
    313     return load_and_dump_schema(argv[1]);
    314 }