Browse Source

Wip on oneof fields.

Bart Hertog 5 năm trước cách đây
mục cha
commit
6c9a85cb0c

+ 5 - 0
generator/support/Field.py

@@ -106,6 +106,11 @@ class Field:
     def register_template_parameters(self):
         return True
 
+    # Returns true if in oneof.init the new& function needs to be call to initialize already allocated memory.
+    def oneof_allocation_required(self):
+        return (type(self) is FieldMessage) or (type(self) is FieldRepeated) or (type(self) is FieldString) or \
+               (type(self) is FieldBytes)
+
     def render(self, filename, jinja_environment):
         template = jinja_environment.get_template(filename)
         try:

+ 7 - 7
generator/support/Oneof.py

@@ -39,12 +39,12 @@ class Oneof:
         # A reference to the parent message in which this oneof is defined.
         self.parent = parent_msg
 
-        self.fields_array = []
+        self.fields = []
         # Loop over all the fields in this oneof
         for f in msg_descriptor.field:
             if f.HasField('oneof_index') and index == f.oneof_index:
-                new_field = Field.factor(f, self.parent, oneof=self)
-                self.fields_array.append(new_field)
+                new_field = Field.factory(f, self.parent, oneof=self)
+                self.fields.append(new_field)
 
     def get_name(self):
         return self.descriptor.name
@@ -52,15 +52,15 @@ class Oneof:
     def get_which_oneof(self):
         return "which_" + self.get_name() + "_"
 
-    def fields(self):
-        return self.fields_array
+    def get_fields(self):
+        return self.fields
 
     def match_field_with_definitions(self, all_types_definitions):
-        for field in self.fields_array:
+        for field in self.fields:
             field.match_field_with_definitions(all_types_definitions)
 
     def register_template_parameters(self):
         all_parameters_registered = True
-        for field in self.fields_array:
+        for field in self.fields:
             all_parameters_registered = field.register_template_parameters() and all_parameters_registered
         return all_parameters_registered

+ 1 - 1
generator/support/TypeDefinitions.py

@@ -165,7 +165,7 @@ class MessageDefinition(TypeDefinition):
         for index, oneof in enumerate(self.descriptor.oneof_decl):
             new_oneof = Oneof(oneof, index, proto_descriptor, self)
             self.oneofs.append(new_oneof)
-            for oneof_field in oneof.fields():
+            for oneof_field in new_oneof.get_fields():
                 self.field_ids.append((oneof_field.variable_id, oneof_field.variable_id_name))
 
         # Sort the field id's such they will appear in order in the id enum.

+ 24 - 8
generator/templates/TypeDefMsg.h

@@ -40,7 +40,7 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
         {{field.get_variable_name()}}({{field.get_default_value()}}){{"," if not loop.last}}{{"," if loop.last and typedef.oneofs}}
     {% endfor %}
     {% for oneof in typedef.oneofs %}
-        {{oneof.which_oneof}}(id::NOT_SET){{"," if not loop.last}}
+        {{oneof.get_which_oneof()}}(id::NOT_SET){{"," if not loop.last}}
     {% endfor %}
     {
 
@@ -71,7 +71,6 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
       {% for oneof in typedef.oneofs %}
       {{ TypeOneof.assign(oneof)|indent(6) }}
       {% endfor %}
-
       return *this;
     }
 
@@ -89,11 +88,11 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
 
       {% endfor %}
       {% for oneof in typedef.oneofs %}
-      switch({{oneof.which_oneof}})
+      switch({{oneof.get_which_oneof()}})
       {
-        {% for field in oneof.fields() %}
+        {% for field in oneof.get_fields() %}
         case id::{{field.variable_id_name}}:
-          {{ field_serialize_macro(field)|indent(12) }}
+          {{ field.render_serialize(environment)|indent(10) }}
           break;
 
         {% endfor %}
@@ -125,10 +124,10 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
 
           {% endfor %}
           {% for oneof in typedef.oneofs %}
-          {% for field in oneof.fields() %}
+          {% for field in oneof.get_fields() %}
           case static_cast<uint32_t>(id::{{field.get_variable_id_name()}}):
           {
-            {{ field_deserialize_macro(field)|indent(12) }}
+            {{ field.render_deserialize(environment)|indent(12) }}
             break;
           }
 
@@ -162,8 +161,9 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
       clear_{{field.get_name()}}();
       {% endfor %}
       {% for oneof in typedef.oneofs %}
-      clear_{{oneof.name}}();
+      clear_{{oneof.get_name()}}();
       {% endfor %}
+
     }
 
     private:
@@ -171,4 +171,20 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
       {% for field in typedef.fields %}
       {{field.get_type()}} {{field.get_variable_name()}};
       {% endfor %}
+
+      {% for oneof in typedef.oneofs %}
+      id {{oneof.get_which_oneof()}};
+      union {{oneof.get_name()}}
+      {
+        {{oneof.get_name()}}() {}
+        ~{{oneof.get_name()}}() {}
+        {% for field in oneof.fields %}
+        {{field.get_type()}} {{field.get_variable_name()}};
+        {% endfor %}
+      };
+      {{oneof.get_name()}} {{oneof.get_name()}}_;
+
+      {{ TypeOneof.init(oneof)|indent(4) }}
+      {{ TypeOneof.clear(oneof)|indent(4) }}
+      {% endfor %}
 };

+ 57 - 6
generator/templates/TypeOneof.h

@@ -28,20 +28,71 @@ Postal address:
   the Netherlands
 #}
 {% macro assign(_oneof) %}
-if(rhs.get_which_{{_oneof.name}}() != {{_oneof.which_oneof}})
+if(rhs.get_which_{{_oneof.get_name()}}() != {{_oneof.get_which_oneof()}})
 {
   // First delete the old object in the oneof.
-  clear_{{_oneof.name}}();
+  clear_{{_oneof.get_name()}}();
 }
 
-switch(rhs.get_which_{{_oneof.name}}())
+switch(rhs.get_which_{{_oneof.get_name()}}())
 {
-  {% for field in _oneof.fields() %}
-  case id::{{field.variable_id_name}}:
-    set_{{field.name}}(rhs.get_{{field.name}}());
+  {% for field in _oneof.get_fields() %}
+  case id::{{field.get_variable_id_name()}}:
+    set_{{field.get_name()}}(rhs.get_{{field.name}}());
     break;
   {% endfor %}
   default:
     break;
 }
+{% endmacro %}
+{# #}
+{# ------------------------------------------------------------------------------------------------------------------ #}
+{# #}
+{% macro init(_oneof) %}
+void init_{{_oneof.get_name()}}(const id field_id)
+{
+  if(id::NOT_SET != {{_oneof.get_which_oneof()}})
+  {
+    // First delete the old object in the oneof.
+    clear_{{_oneof.get_name()}}();
+  }
+
+  // C++11 unions only support nontrivial members when you explicitly call the placement new statement.
+  switch(field_id)
+  {
+    {% for field in _oneof.get_fields() %}
+    case id::{{field.get_variable_id_name()}}:
+      {% if field.oneof_allocation_required() %}
+      new(&{{field.variable_full_name}}) {{field.type}};
+      {{_oneof.get_which_oneof()}} = id::{{field.get_variable_id_name()}};
+      {% endif %}
+      break;
+    {% endfor %}
+    default:
+      break;
+   }
+}
+{% endmacro %}
+{# #}
+{# ------------------------------------------------------------------------------------------------------------------ #}
+{# #}
+{% macro clear(_oneof) %}
+void clear_{{_oneof.get_name()}}()
+{
+  switch({{_oneof.get_which_oneof()}})
+  {
+    {% for field in _oneof.get_fields() %}
+    case id::{{field.get_variable_id_name()}}:
+      {% if field.oneof_allocation_required() %}
+      {{field.get_variable_name()}}.~{{field.get_short_type()}}();
+      {% else %}
+      {{field.get_variable_name()}}.set(0);
+      {% endif %}
+      break;
+    {% endfor %}
+    default:
+      break;
+  }
+  {{_oneof.get_which_oneof()}} = id::NOT_SET;
+}
 {% endmacro %}