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, bool underlying = false) {
     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_VECTOR:
     32         return "[" + GenType(type.VectorType()) + "]";
     33     default:
     34         if (type.enum_def && !underlying) {
     35           return type.enum_def->defined_namespace->GetFullyQualifiedName(
     36                    type.enum_def->name);
     37         } else {
     38           return kTypeNames[type.base_type];
     39         }
     40   }
     41 }
     42 
     43 static void GenNameSpace(const Namespace &name_space, std::string *_schema,
     44                          const Namespace **last_namespace) {
     45   if (*last_namespace == &name_space) return;
     46   *last_namespace = &name_space;
     47   auto &schema = *_schema;
     48   schema += "namespace ";
     49   for (auto it = name_space.components.begin();
     50            it != name_space.components.end(); ++it) {
     51     if (it != name_space.components.begin()) schema += ".";
     52     schema += *it;
     53   }
     54   schema += ";\n\n";
     55 }
     56 
     57 // Generate a flatbuffer schema from the Parser's internal representation.
     58 std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
     59   // Proto namespaces may clash with table names, escape the ones that were
     60   // generated from a table:
     61   for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
     62        ++it) {
     63     auto &ns = **it;
     64     for (size_t i = 0; i < ns.from_table; i++) {
     65       ns.components[ns.components.size() - 1 - i] += "_";
     66     }
     67   }
     68 
     69   std::string schema;
     70   schema += "// Generated from " + file_name + ".proto\n\n";
     71   if (parser.opts.include_dependence_headers) {
     72     #ifdef FBS_GEN_INCLUDES  // TODO: currently all in one file.
     73     int num_includes = 0;
     74     for (auto it = parser.included_files_.begin();
     75          it != parser.included_files_.end(); ++it) {
     76       if (it->second.empty())
     77         continue;
     78       auto basename = flatbuffers::StripPath(
     79                         flatbuffers::StripExtension(it->second));
     80       schema += "include \"" + basename + ".fbs\";\n";
     81       num_includes++;
     82     }
     83     if (num_includes) schema += "\n";
     84     #endif
     85   }
     86   // Generate code for all the enum declarations.
     87   const Namespace *last_namespace = nullptr;
     88   for (auto enum_def_it = parser.enums_.vec.begin();
     89            enum_def_it != parser.enums_.vec.end(); ++enum_def_it) {
     90     EnumDef &enum_def = **enum_def_it;
     91     GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
     92     GenComment(enum_def.doc_comment, &schema, nullptr);
     93     schema += "enum " + enum_def.name + " : ";
     94     schema += GenType(enum_def.underlying_type, true) + " {\n";
     95     for (auto it = enum_def.vals.vec.begin();
     96          it != enum_def.vals.vec.end(); ++it) {
     97       auto &ev = **it;
     98       GenComment(ev.doc_comment, &schema, nullptr, "  ");
     99       schema += "  " + ev.name + " = " + NumToString(ev.value) + ",\n";
    100     }
    101     schema += "}\n\n";
    102   }
    103   // Generate code for all structs/tables.
    104   for (auto it = parser.structs_.vec.begin();
    105            it != parser.structs_.vec.end(); ++it) {
    106     StructDef &struct_def = **it;
    107     GenNameSpace(*struct_def.defined_namespace, &schema, &last_namespace);
    108     GenComment(struct_def.doc_comment, &schema, nullptr);
    109     schema += "table " + struct_def.name + " {\n";
    110     for (auto field_it = struct_def.fields.vec.begin();
    111              field_it != struct_def.fields.vec.end(); ++field_it) {
    112       auto &field = **field_it;
    113       if (field.value.type.base_type != BASE_TYPE_UTYPE) {
    114         GenComment(field.doc_comment, &schema, nullptr, "  ");
    115         schema += "  " + field.name + ":" + GenType(field.value.type);
    116         if (field.value.constant != "0") schema += " = " + field.value.constant;
    117         if (field.required) schema += " (required)";
    118         schema += ";\n";
    119       }
    120     }
    121     schema += "}\n\n";
    122   }
    123   return schema;
    124 }
    125 
    126 bool GenerateFBS(const Parser &parser,
    127                  const std::string &path,
    128                  const std::string &file_name) {
    129   return SaveFile((path + file_name + ".fbs").c_str(),
    130                   GenerateFBS(parser, file_name), false);
    131 }
    132 
    133 }  // namespace flatbuffers
    134 
    135