from __future__ import unicode_literals
'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
-nanopb_version = "nanopb-0.3.7-dev"
+nanopb_version = "nanopb-0.3.8-dev"
import sys
import re
for i, x in enumerate(self.values):
result += '\n#define %s %s' % (self.value_longnames[i], x[0])
+ if self.options.enum_to_string:
+ result += '\nconst char *%s_name(%s v);\n' % (self.names, self.names)
+
+ return result
+
+ def enum_to_string_definition(self):
+ if not self.options.enum_to_string:
+ return ""
+
+ result = 'const char *%s_name(%s v) {\n' % (self.names, self.names)
+ result += ' switch (v) {\n'
+
+ for ((enumname, _), strname) in zip(self.values, self.value_longnames):
+ # Strip off the leading type name from the string value.
+ strval = str(strname)[len(str(self.names)) + 1:]
+ result += ' case %s: return "%s";\n' % (enumname, strval)
+
+ result += ' }\n'
+ result += ' return "unknown";\n'
+ result += '}\n'
+
return result
class FieldMaxSize:
# Parse field options
if field_options.HasField("max_size"):
self.max_size = field_options.max_size
+
+ if desc.type == FieldD.TYPE_STRING and field_options.HasField("max_length"):
+ # max_length overrides max_size for strings
+ self.max_size = field_options.max_length + 1
if field_options.HasField("max_count"):
self.max_count = field_options.max_count
can_be_static = False
else:
self.array_decl = '[%d]' % self.max_count
- elif field_options.HasField("proto3"):
+ elif field_options.proto3:
self.rules = 'SINGULAR'
elif desc.label == FieldD.LABEL_REQUIRED:
self.rules = 'REQUIRED'
identifier = '%s_%s_tag' % (self.struct_name, self.name)
return '#define %-40s %d\n' % (identifier, self.tag)
- def pb_field_t(self, prev_field_name):
+ def pb_field_t(self, prev_field_name, union_index = None):
'''Return the pb_field_t initializer to use in the constant array.
- prev_field_name is the name of the previous field or None.
+ prev_field_name is the name of the previous field or None. For OneOf
+ unions, union_index is the index of this field inside the OneOf.
'''
if self.rules == 'ONEOF':
result += '%-8s, ' % self.pbtype
result += '%s, ' % self.rules
result += '%-8s, ' % (self.allocation if not self.inline else "INLINE")
- result += '%s, ' % ("FIRST" if not prev_field_name else "OTHER")
+
+ if union_index is not None and union_index > 0:
+ result += 'UNION, '
+ elif prev_field_name is None:
+ result += 'FIRST, '
+ else:
+ result += 'OTHER, '
+
result += '%s, ' % self.struct_name
result += '%s, ' % self.name
result += '%s, ' % (prev_field_name or self.name)
'''Determine if this field needs 16bit or 32bit pb_field_t structure to compile properly.
Returns numeric value or a C-expression for assert.'''
check = []
- if self.pbtype == 'MESSAGE':
- if self.rules == 'REPEATED' and self.allocation == 'STATIC':
+ if self.pbtype == 'MESSAGE' and self.allocation == 'STATIC':
+ if self.rules == 'REPEATED':
check.append('pb_membersize(%s, %s[0])' % (self.struct_name, self.name))
elif self.rules == 'ONEOF':
if self.anonymous:
check.append('pb_membersize(%s, %s.%s)' % (self.struct_name, self.union_name, self.name))
else:
check.append('pb_membersize(%s, %s)' % (self.struct_name, self.name))
+ elif self.pbtype == 'BYTES' and self.allocation == 'STATIC':
+ if self.max_size > 251:
+ check.append('pb_membersize(%s, %s)' % (self.struct_name, self.name))
return FieldMaxSize([self.tag, self.max_size, self.max_count],
check,
return ''.join([f.tags() for f in self.fields])
def pb_field_t(self, prev_field_name):
- result = ',\n'.join([f.pb_field_t(prev_field_name) for f in self.fields])
- return result
+ parts = []
+ for union_index, field in enumerate(self.fields):
+ parts.append(field.pb_field_t(prev_field_name, union_index))
+ return ',\n'.join(parts)
def get_last_field_name(self):
if self.anonymous:
for ext in self.extensions:
yield ext.extension_def() + '\n'
+ for enum in self.enums:
+ yield enum.enum_to_string_definition() + '\n'
+
# Add checks for numeric limits
if self.messages:
largest_msg = max(self.messages, key = lambda m: m.count_required_fields())
new_options = nanopb_pb2.NanoPBOptions()
new_options.CopyFrom(options)
+ if hasattr(subdesc, 'syntax') and subdesc.syntax == "proto3":
+ new_options.proto3 = True
+
# Handle options defined in a separate file
dotname = '.'.join(name.parts)
for namemask, options in Globals.separate_options: