flatbuffer force-empty option (#4822)
authorshassani <shassani@soe.ucsc.edu>
Mon, 16 Jul 2018 23:05:06 +0000 (16:05 -0700)
committerWouter van Oortmerssen <aardappel@gmail.com>
Mon, 16 Jul 2018 23:05:06 +0000 (16:05 -0700)
docs/source/Compiler.md
include/flatbuffers/idl.h
src/flatc.cpp
src/idl_gen_cpp.cpp

index 3a6adf8..e7676bf 100644 (file)
@@ -138,5 +138,8 @@ Additional options:
 
 -   `--force-defaults` : Emit default values in binary output from JSON.
 
+-   `--force-empty` : When serializing from object API representation, force
+     strings and vectors to empty rather than null.
+
 NOTE: short-form options for generators are deprecated, use the long form
 whenever possible.
index 55ef89d..9d50a94 100644 (file)
@@ -422,6 +422,10 @@ struct IDLOptions {
   // for code generation.
   unsigned long lang_to_generate;
 
+  // If set (default behavior), empty string and vector fields will be set to
+  // nullptr to make the flatbuffer more compact.
+  bool set_empty_to_null;
+
   IDLOptions()
       : strict_json(false),
         skip_js_exports(false),
@@ -457,7 +461,8 @@ struct IDLOptions {
         force_defaults(false),
         lang(IDLOptions::kJava),
         mini_reflect(IDLOptions::kNone),
-        lang_to_generate(0) {}
+        lang_to_generate(0),
+        set_empty_to_null(true) {}
 };
 
 // This encapsulates where the parser is in the current source file.
index ef91792..bcd5c3b 100644 (file)
@@ -123,6 +123,8 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
     "  --reflect-names    Add minimal type/name reflection.\n"
     "  --root-type T      Select or override the default root_type\n"
     "  --force-defaults   Emit default values in binary output from JSON\n"
+    "  --force-empty      When serializing from object API representation, "
+    "                     force strings and vectors to empty rather than null.\n"
     "FILEs may be schemas (must end in .fbs), or JSON files (conforming to preceding\n"
     "schema). FILEs after the -- must be binary flatbuffer format files.\n"
     "Output files are named using the base file name of the input,\n"
@@ -280,6 +282,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
         opts.root_type = argv[argi];
       } else if (arg == "--force-defaults") {
         opts.force_defaults = true;
+      } else if (arg == "--force-empty") {
+        opts.set_empty_to_null = false;
       } else {
         for (size_t i = 0; i < params_.num_generators; ++i) {
           if (arg == params_.generators[i].generator_opt_long ||
index 1980c16..060f4bc 100644 (file)
@@ -2148,6 +2148,8 @@ class CppGenerator : public BaseGenerator {
   }
 
   std::string GenCreateParam(const FieldDef &field) {
+    const IDLOptions &opts = parser_.opts;
+
     std::string value = "_o->";
     if (field.value.type.base_type == BASE_TYPE_UTYPE) {
       value += StripUnionType(Name(field));
@@ -2172,8 +2174,13 @@ class CppGenerator : public BaseGenerator {
         code += "_fbb.CreateString(" + value + ")";
 
         // For optional fields, check to see if there actually is any data
-        // in _o->field before attempting to access it.
-        if (!field.required) { code = value + ".empty() ? 0 : " + code; }
+        // in _o->field before attempting to access it. If there isn't,
+        // depending on set_empty_to_null either set it to 0 or an empty string.
+        if (!field.required) {
+          auto empty_value =
+              opts.set_empty_to_null ? "0" : "_fbb.CreateSharedString(\"\")";
+          code = value + ".empty() ? " + empty_value + " : " + code;
+        }
         break;
       }
       // Vector fields come in several flavours, of the forms:
@@ -2259,9 +2266,12 @@ class CppGenerator : public BaseGenerator {
           }
         }
 
-        // For optional fields, check to see if there actually is any data
-        // in _o->field before attempting to access it.
-        if (!field.required) { code = value + ".size() ? " + code + " : 0"; }
+        // If set_empty_to_null option is enabled, for optional fields, check to
+        // see if there actually is any data in _o->field before attempting to
+        // access it.
+        if (opts.set_empty_to_null && !field.required) {
+          code = value + ".size() ? " + code + " : 0";
+        }
         break;
       }
       case BASE_TYPE_UNION: {