Add enum name lookup method to Java/C# enums
authorGabriel Martinez <gabrielma@google.com>
Thu, 18 Sep 2014 19:28:10 +0000 (12:28 -0700)
committerGabriel Martinez <gabrielma@google.com>
Mon, 22 Sep 2014 22:10:48 +0000 (15:10 -0700)
Tested: on Linux for Java and C#

Bug: 15781151
Change-Id: I7cb97bcc01d986cac2b24aaf7cb29521ddaa2f6b

src/idl_gen_general.cpp
tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
tests/JavaTest.java
tests/MyGame/Example/Any.cs
tests/MyGame/Example/Any.java [changed mode: 0755->0644]
tests/MyGame/Example/Color.cs
tests/MyGame/Example/Color.java [changed mode: 0755->0644]
tests/MyGame/Example/Monster.java [changed mode: 0755->0644]
tests/MyGame/Example/Test.java [changed mode: 0755->0644]
tests/MyGame/Example/Vec3.java [changed mode: 0755->0644]

index 0f3ca9d..4c25740 100644 (file)
@@ -73,7 +73,7 @@ LanguageParameters language_parameters[] = {
     "String",
     "boolean ",
     " {\n",
-    "  public static final ",
+    " final ",
     " extends ",
     "package ",
     ";",
@@ -89,7 +89,7 @@ LanguageParameters language_parameters[] = {
     "string",
     "bool ",
     "\n{\n",
-    "  public static ",
+    " readonly ",
     " : ",
     "namespace ",
     "\n{",
@@ -164,11 +164,45 @@ static void GenEnum(const LanguageParameters &lang, EnumDef &enum_def,
        ++it) {
     auto &ev = **it;
     GenComment(ev.doc_comment, code_ptr, "  ");
+    code += "  public static";
     code += lang.const_decl;
     code += GenTypeBasic(lang, enum_def.underlying_type);
     code += " " + ev.name + " = ";
     code += NumToString(ev.value) + ";\n";
   }
+
+  // Generate a generate string table for enum values.
+  // Problem is, if values are very sparse that could generate really big
+  // tables. Ideally in that case we generate a map lookup instead, but for
+  // the moment we simply don't output a table at all.
+  auto range = enum_def.vals.vec.back()->value -
+               enum_def.vals.vec.front()->value + 1;
+  // Average distance between values above which we consider a table
+  // "too sparse". Change at will.
+  static const int kMaxSparseness = 5;
+  if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) {
+    code += "\n  private static";
+    code += lang.const_decl;
+    code += lang.string_type;
+    code += "[] names = { ";
+    auto val = enum_def.vals.vec.front()->value;
+    for (auto it = enum_def.vals.vec.begin();
+         it != enum_def.vals.vec.end();
+         ++it) {
+      while (val++ != (*it)->value) code += "\"\", ";
+      code += "\"" + (*it)->name + "\", ";
+    }
+    code += "};\n\n";
+    code += "  public static ";
+    code += lang.string_type;
+    code += " " + MakeCamel("name", lang.first_camel_upper);
+    code += "(int e) { return names[e";
+    if (enum_def.vals.vec.front()->value)
+      code += " - " + enum_def.vals.vec.front()->name;
+    code += "]; }\n";
+  }
+
+  // Close the class
   code += "};\n\n";
 }
 
index a084dda..23023bf 100644 (file)
@@ -25,6 +25,7 @@ namespace FlatBuffers.Test
         {
             CanCreateNewFlatBufferFromScratch();
             CanReadCppGeneratedWireFile();
+            TestEnums();
         }
 
         public void CanCreateNewFlatBufferFromScratch()
@@ -141,5 +142,13 @@ namespace FlatBuffers.Test
             var bb = new ByteBuffer(data);
             TestBuffer(bb);
         }
+
+        public void TestEnums()
+        {
+            Assert.AreEqual(Color.Name(Color.Red), "Red");
+            Assert.AreEqual(Color.Name(Color.Blue), "Blue");
+            Assert.AreEqual(Any.Name(Any.NONE), "NONE");
+            Assert.AreEqual(Any.Name(Any.Monster), "Monster");
+        }
     }
 }
index 7fcc937..73db176 100755 (executable)
@@ -106,9 +106,18 @@ class JavaTest {
         // (see Table.__string).
         TestBuffer(fbb.dataBuffer().asReadOnlyBuffer());
 
+        TestEnums();
+
         System.out.println("FlatBuffers test: completed successfully");
     }
 
+    static void TestEnums() {
+      TestEq(Color.name(Color.Red), "Red");
+      TestEq(Color.name(Color.Blue), "Blue");
+      TestEq(Any.name(Any.NONE), "NONE");
+      TestEq(Any.name(Any.Monster), "Monster");
+    }
+
     static void TestBuffer(ByteBuffer bb) {
         TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
 
index 8f88a9d..5223969 100644 (file)
@@ -5,8 +5,12 @@ namespace MyGame.Example
 
 public class Any
 {
-  public static byte NONE = 0;
-  public static byte Monster = 1;
+  public static readonly byte NONE = 0;
+  public static readonly byte Monster = 1;
+
+  private static readonly string[] names = { "NONE", "Monster", };
+
+  public static string Name(int e) { return names[e]; }
 };
 
 
old mode 100755 (executable)
new mode 100644 (file)
index 7d5a1a0..eb7514c
@@ -5,5 +5,9 @@ package MyGame.Example;
 public class Any {
   public static final byte NONE = 0;
   public static final byte Monster = 1;
+
+  private static final String[] names = { "NONE", "Monster", };
+
+  public static String name(int e) { return names[e]; }
 };
 
index 7d9df7b..403b9d9 100644 (file)
@@ -5,9 +5,13 @@ namespace MyGame.Example
 
 public class Color
 {
-  public static sbyte Red = 1;
-  public static sbyte Green = 2;
-  public static sbyte Blue = 8;
+  public static readonly sbyte Red = 1;
+  public static readonly sbyte Green = 2;
+  public static readonly sbyte Blue = 8;
+
+  private static readonly string[] names = { "Red", "Green", "", "", "", "", "", "Blue", };
+
+  public static string Name(int e) { return names[e - Red]; }
 };
 
 
old mode 100755 (executable)
new mode 100644 (file)
index 8144e41..b63493a
@@ -6,5 +6,9 @@ public class Color {
   public static final byte Red = 1;
   public static final byte Green = 2;
   public static final byte Blue = 8;
+
+  private static final String[] names = { "Red", "Green", "", "", "", "", "", "Blue", };
+
+  public static String name(int e) { return names[e - Red]; }
 };
 
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)