Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2014 Google Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // independent from idl_parser, since this code is not needed for most clients
     18 
     19 #include "flatbuffers/flatbuffers.h"
     20 #include "flatbuffers/idl.h"
     21 #include "flatbuffers/util.h"
     22 #include "flatbuffers/code_generators.h"
     23 
     24 namespace flatbuffers {
     25 
     26 static std::string GenType(const Type &type) {
     27   switch (type.base_type) {
     28     case BASE_TYPE_STRUCT:
     29       return type.struct_def->defined_namespace->GetFullyQualifiedName(
     30                type.struct_def->name);
     31     case BASE_TYPE_UNION:
     32       return type.enum_def->defined_namespace->GetFullyQualifiedName(
     33                type.enum_def->name);
     34     case BASE_TYPE_VECTOR:
     35         return "[" + GenType(type.VectorType()) + "]";
     36     default:
     37         return kTypeNames[type.base_type];
     38   }
     39 }
     40 
     41 static void GenNameSpace(const Namespace &name_space, std::string *_schema,
     42                          const Namespace **last_namespace) {
     43   if (*last_namespace == &name_space) return;
     44   *last_namespace = &name_space;
     45   auto &schema = *_schema;
     46   schema += "namespace ";
     47   for (auto it = name_space.components.begin();
     48            it != name_space.components.end(); ++it) {
     49     if (it != name_space.components.begin()) schema += ".";
     50     schema += *it;
     51   }
     52   schema += ";\n\n";
     53 }
     54 
     55 // Generate a flatbuffer schema from the Parser's internal representation.
     56 std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
     57  // Proto namespaces may clash with table names, so we have to prefix all:
     58   if (!parser.opts.escape_proto_identifiers) {
     59     for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
     60          ++it) {
     61       for (auto comp = (*it)->components.begin(); comp != (*it)->components.end();
     62            ++comp) {
     63         (*comp) = "_" + (*comp);
     64       }
     65     }
     66   }
     67 
     68   std::string schema;
     69   schema += "// Generated from " + file_name + ".proto\n\n";
     70   if (parser.opts.include_dependence_headers) {
     71     #ifdef FBS_GEN_INCLUDES  // TODO: currently all in one file.
     72     int num_includes = 0;
     73     for (auto it = parser.included_files_.begin();
     74          it != parser.included_files_.end(); ++it) {
     75       auto basename = flatbuffers::StripPath(
     76                         flatbuffers::StripExtension(it->first));
     77       if (basename != file_name) {
     78         schema += "include \"" + basename + ".fbs\";\n";
     79         num_includes++;
     80       }
     81     }
     82     if (num_includes) schema += "\n";
     83     #endif
     84   }
     85   // Generate code for all the enum declarations.
     86   const Namespace *last_namespace = nullptr;
     87   for (auto enum_def_it = parser.enums_.vec.begin();
     88            enum_def_it != parser.enums_.vec.end(); ++enum_def_it) {
     89     EnumDef &enum_def = **enum_def_it;
     90     GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
     91     GenComment(enum_def.doc_comment, &schema, nullptr);
     92     schema += "enum " + enum_def.name + " : ";
     93     schema += GenType(enum_def.underlying_type) + " {\n";
     94     for (auto it = enum_def.vals.vec.begin();
     95          it != enum_def.vals.vec.end(); ++it) {
     96       auto &ev = **it;
     97       GenComment(ev.doc_comment, &schema, nullptr, "  ");
     98       schema += "  " + ev.name + " = " + NumToString(ev.value) + ",\n";
     99     }
    100     schema += "}\n\n";
    101   }
    102   // Generate code for all structs/tables.
    103   for (auto it = parser.structs_.vec.begin();
    104            it != parser.structs_.vec.end(); ++it) {
    105     StructDef &struct_def = **it;
    106     GenNameSpace(*struct_def.defined_namespace, &schema, &last_namespace);
    107     GenComment(struct_def.doc_comment, &schema, nullptr);
    108     schema += "table " + struct_def.name + " {\n";
    109     for (auto field_it = struct_def.fields.vec.begin();
    110              field_it != struct_def.fields.vec.end(); ++field_it) {
    111       auto &field = **field_it;
    112       GenComment(field.doc_comment, &schema, nullptr, "  ");
    113       schema += "  " + field.name + ":" + GenType(field.value.type);
    114       if (field.value.constant != "0") schema += " = " + field.value.constant;
    115       if (field.required) schema += " (required)";
    116       schema += ";\n";
    117     }
    118     schema += "}\n\n";
    119   }
    120   return schema;
    121 }
    122 
    123 bool GenerateFBS(const Parser &parser,
    124                  const std::string &path,
    125                  const std::string &file_name) {
    126   return SaveFile((path + file_name + ".fbs").c_str(),
    127                   GenerateFBS(parser, file_name), false);
    128 }
    129 
    130 }  // namespace flatbuffers
    131 
    132