raise
try:
- import nanopb_pb2
+ import proto.nanopb_pb2 as nanopb_pb2
except:
print
print "***************************************************************"
else:
raise NotImplementedError(desc.label)
+ # Check if the field can be implemented with static allocation
+ # i.e. whether the data size is known.
+ if desc.type == FieldD.TYPE_STRING and self.max_size is None:
+ can_be_static = False
+
+ if desc.type == FieldD.TYPE_BYTES and self.max_size is None:
+ can_be_static = False
+
+ # Decide how the field data will be allocated
+ if field_options.type == nanopb_pb2.FT_DEFAULT:
+ if can_be_static:
+ field_options.type = nanopb_pb2.FT_STATIC
+ else:
+ field_options.type = nanopb_pb2.FT_CALLBACK
+
+ if field_options.type == nanopb_pb2.FT_STATIC and not can_be_static:
+ raise Exception("Field %s is defined as static, but max_size or "
+ "max_count is not given." % self.name)
+
+ if field_options.type == nanopb_pb2.FT_STATIC:
+ self.allocation = 'STATIC'
+ elif field_options.type == nanopb_pb2.FT_POINTER:
+ self.allocation = 'POINTER'
+ elif field_options.type == nanopb_pb2.FT_CALLBACK:
+ self.allocation = 'CALLBACK'
+ else:
+ raise NotImplementedError(field_options.type)
+
# Decide the C data type to use in the struct.
if datatypes.has_key(desc.type):
self.ctype, self.pbtype, self.enc_size = datatypes[desc.type]
self.enc_size = 5 # protoc rejects enum values > 32 bits
elif desc.type == FieldD.TYPE_STRING:
self.pbtype = 'STRING'
- if self.max_size is None:
- can_be_static = False
- else:
+ self.ctype = 'char'
+ if self.allocation == 'STATIC':
self.ctype = 'char'
self.array_decl += '[%d]' % self.max_size
self.enc_size = varint_max_size(self.max_size) + self.max_size
elif desc.type == FieldD.TYPE_BYTES:
self.pbtype = 'BYTES'
- if self.max_size is None:
- can_be_static = False
- else:
+ if self.allocation == 'STATIC':
self.ctype = self.struct_name + self.name + 't'
self.enc_size = varint_max_size(self.max_size) + self.max_size
+ elif self.allocation == 'POINTER':
+ self.ctype = 'pb_bytes_ptr_t'
elif desc.type == FieldD.TYPE_MESSAGE:
self.pbtype = 'MESSAGE'
self.ctype = self.submsgname = names_from_type_name(desc.type_name)
else:
raise NotImplementedError(desc.type)
- if field_options.type == nanopb_pb2.FT_DEFAULT:
- if can_be_static:
- field_options.type = nanopb_pb2.FT_STATIC
- else:
- field_options.type = nanopb_pb2.FT_CALLBACK
-
- if field_options.type == nanopb_pb2.FT_STATIC and not can_be_static:
- raise Exception("Field %s is defined as static, but max_size or max_count is not given." % self.name)
-
- if field_options.type == nanopb_pb2.FT_STATIC:
- self.allocation = 'STATIC'
- elif field_options.type == nanopb_pb2.FT_CALLBACK:
- self.allocation = 'CALLBACK'
- self.ctype = 'pb_callback_t'
- self.array_decl = ''
- else:
- raise NotImplementedError(field_options.type)
-
def __cmp__(self, other):
return cmp(self.tag, other.tag)
def __str__(self):
- if self.rules == 'OPTIONAL' and self.allocation == 'STATIC':
- result = ' bool has_' + self.name + ';\n'
- elif self.rules == 'REPEATED' and self.allocation == 'STATIC':
- result = ' size_t ' + self.name + '_count;\n'
+ result = ''
+ if self.allocation == 'POINTER':
+ if self.rules == 'REPEATED':
+ result += ' size_t ' + self.name + '_count;\n'
+
+ if self.pbtype == 'MESSAGE':
+ # Use struct definition, so recursive submessages are possible
+ result += ' struct _%s *%s;' % (self.ctype, self.name)
+ elif self.rules == 'REPEATED' and self.pbtype == 'STRING':
+ # String arrays need to be defined as pointers to pointers
+ result += ' %s **%s;' % (self.ctype, self.name)
+ else:
+ result += ' %s *%s;' % (self.ctype, self.name)
+ elif self.allocation == 'CALLBACK':
+ result += ' pb_callback_t %s;' % self.name
else:
- result = ''
- result += ' %s %s%s;' % (self.ctype, self.name, self.array_decl)
+ if self.rules == 'OPTIONAL' and self.allocation == 'STATIC':
+ result += ' bool has_' + self.name + ';\n'
+ elif self.rules == 'REPEATED' and self.allocation == 'STATIC':
+ result += ' size_t ' + self.name + '_count;\n'
+ result += ' %s %s%s;' % (self.ctype, self.name, self.array_decl)
return result
def types(self):
result = ' PB_FIELD2(%3d, ' % self.tag
result += '%-8s, ' % self.pbtype
result += '%s, ' % self.rules
- result += '%s, ' % self.allocation
+ result += '%-8s, ' % self.allocation
result += '%s, ' % ("FIRST" if not prev_field_name else "OTHER")
result += '%s, ' % self.struct_name
result += '%s, ' % self.name
def main_plugin():
'''Main function when invoked as a protoc plugin.'''
- import plugin_pb2
+ import proto.plugin_pb2 as plugin_pb2
data = sys.stdin.read()
request = plugin_pb2.CodeGeneratorRequest.FromString(data)