from __future__ import unicode_literals
'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
-nanopb_version = "nanopb-0.3.5-dev"
+nanopb_version = "nanopb-0.3.6-dev"
import sys
import re
'''Class used to represent the encoded size of a field or a message.
Consists of a combination of symbolic sizes and integer sizes.'''
def __init__(self, value = 0, symbols = []):
- if isinstance(value, strtypes + (Names,)):
- symbols = [str(value)]
- value = 0
- self.value = value
- self.symbols = symbols
+ if isinstance(value, EncodedSize):
+ self.value = value.value
+ self.symbols = value.symbols
+ elif isinstance(value, strtypes + (Names,)):
+ self.symbols = [str(value)]
+ self.value = 0
+ else:
+ self.value = value
+ self.symbols = symbols
def __add__(self, other):
if isinstance(other, int):
'''
if self.rules == 'ONEOF':
- result = ' PB_ONEOF_FIELD(%s, ' % self.union_name
+ if self.anonymous:
+ result = ' PB_ANONYMOUS_ONEOF_FIELD(%s, ' % self.union_name
+ else:
+ result = ' PB_ONEOF_FIELD(%s, ' % self.union_name
else:
result = ' PB_FIELD('
return result
+ def get_last_field_name(self):
+ return self.name
+
def largest_field_value(self):
'''Determine if this field needs 16bit or 32bit pb_field_t structure to compile properly.
Returns numeric value or a C-expression for assert.'''
if self.rules == 'REPEATED' and self.allocation == 'STATIC':
check.append('pb_membersize(%s, %s[0])' % (self.struct_name, self.name))
elif self.rules == 'ONEOF':
- check.append('pb_membersize(%s, %s.%s)' % (self.struct_name, self.union_name, self.name))
+ if self.anonymous:
+ check.append('pb_membersize(%s, %s)' % (self.struct_name, self.name))
+ else:
+ 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))
self.allocation = 'ONEOF'
self.default = None
self.rules = 'ONEOF'
+ self.anonymous = False
def add_field(self, field):
if field.allocation == 'CALLBACK':
field.union_name = self.name
field.rules = 'ONEOF'
+ field.anonymous = self.anonymous
self.fields.append(field)
self.fields.sort(key = lambda f: f.tag)
result += ' union {\n'
for f in self.fields:
result += ' ' + str(f).replace('\n', '\n ') + '\n'
- result += ' } ' + self.name + ';'
+ if self.anonymous:
+ result += ' };'
+ else:
+ result += ' } ' + self.name + ';'
return result
def types(self):
return None
def tags(self):
- return '\n'.join([f.tags() for f in self.fields])
+ 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
+ def get_last_field_name(self):
+ if self.anonymous:
+ return self.fields[-1].name
+ else:
+ return self.name + '.' + self.fields[-1].name
+
def largest_field_value(self):
largest = FieldMaxSize()
for f in self.fields:
return largest
def encoded_size(self, dependencies):
+ '''Returns the size of the largest oneof field.'''
largest = EncodedSize(0)
for f in self.fields:
- size = f.encoded_size(dependencies)
- if size is None:
+ size = EncodedSize(f.encoded_size(dependencies))
+ if size.value is None:
return None
elif size.symbols:
return None # Cannot resolve maximum of symbols
pass # No union and skip fields also
else:
oneof = OneOf(self.name, f)
+ if oneof_options.anonymous_oneof:
+ oneof.anonymous = True
self.oneofs[i] = oneof
self.fields.append(oneof)
if not self.ordered_fields:
# Empty structs are not allowed in C standard.
# Therefore add a dummy field if an empty message occurs.
- result += ' uint8_t dummy_field;'
+ result += ' char dummy_field;'
result += '\n'.join([str(f) for f in self.ordered_fields])
+ result += '\n/* @@protoc_insertion_point(struct:%s) */' % self.name
result += '\n}'
if self.packed:
for field in self.ordered_fields:
result += field.pb_field_t(prev)
result += ',\n'
- if isinstance(field, OneOf):
- prev = field.name + '.' + field.fields[-1].name
- else:
- prev = field.name
+ prev = field.get_last_field_name()
result += ' PB_LAST_FIELD\n};'
return result
noext = os.path.splitext(incfile)[0]
yield options.genformat % (noext + options.extension + '.h')
yield '\n'
+
+ yield '/* @@protoc_insertion_point(includes) */\n'
yield '#if PB_PROTO_HEADER_VERSION != 30\n'
yield '#error Regenerate this file with the current version of nanopb generator.\n'
yield '#endif\n'
# End of header
+ yield '/* @@protoc_insertion_point(eof) */\n'
yield '\n#endif\n'
def generate_source(self, headername, options):
yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime())
yield options.genformat % (headername)
yield '\n'
+ yield '/* @@protoc_insertion_point(includes) */\n'
yield '#if PB_PROTO_HEADER_VERSION != 30\n'
yield '#error Regenerate this file with the current version of nanopb generator.\n'
yield 'PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES)\n'
yield '\n'
+ yield '/* @@protoc_insertion_point(eof) */\n'
# ---------------------------------------------------------------------------
# Options parsing for the .proto files