diff options
author | Martin Donath <scifish@gmail.com> | 2013-12-08 23:25:32 +0100 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2013-12-29 18:35:57 +0200 |
commit | 4ae3b2e5661b154cd1f7e545f6052d271306ff25 (patch) | |
tree | 90b8fb3619eedaf9c0f3e8a5ac7ffd494467b99c /generator | |
parent | 4f37c083d532a782e478b2cef6a02d028613564d (diff) |
Generating and encoding messages with dynamic allocaiton
Diffstat (limited to 'generator')
-rw-r--r-- | generator/nanopb.proto | 1 | ||||
-rwxr-xr-x | generator/nanopb_generator.py | 62 | ||||
-rw-r--r-- | generator/nanopb_pb2.py | 13 |
3 files changed, 54 insertions, 22 deletions
diff --git a/generator/nanopb.proto b/generator/nanopb.proto index fe564b5c..2be2f803 100644 --- a/generator/nanopb.proto +++ b/generator/nanopb.proto @@ -12,6 +12,7 @@ option java_package = "fi.kapsi.koti.jpa.nanopb"; enum FieldType { FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible. FT_CALLBACK = 1; // Always generate a callback field. + FT_POINTER = 4; // Always generate a dynamically allocated field. FT_STATIC = 2; // Generate a static field or raise an exception if not possible. FT_IGNORE = 3; // Ignore the field completely. } diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 468c0d2e..69548ad6 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -200,19 +200,27 @@ class Field: 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: + if field_options.type == nanopb_pb2.FT_POINTER: self.ctype = 'char' - self.array_decl += '[%d]' % self.max_size - self.enc_size = varint_max_size(self.max_size) + self.max_size + self.enc_size = None + else: + if self.max_size is None: + can_be_static = False + else: + 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 field_options.type == nanopb_pb2.FT_POINTER: self.ctype = self.struct_name + self.name + 't' - self.enc_size = varint_max_size(self.max_size) + self.max_size + self.enc_size = None + else: + if self.max_size is None: + can_be_static = False + else: + self.ctype = self.struct_name + self.name + 't' + self.enc_size = varint_max_size(self.max_size) + self.max_size elif desc.type == FieldD.TYPE_MESSAGE: self.pbtype = 'MESSAGE' self.ctype = self.submsgname = names_from_type_name(desc.type_name) @@ -231,6 +239,8 @@ class Field: 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' self.ctype = 'pb_callback_t' @@ -242,21 +252,37 @@ class Field: 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' + + # Use struct definition, so recursive submessages are possible + if self.pbtype == 'MESSAGE': + result += ' struct _%s *%s;' % (self.ctype, self.name) + + # String arrays need to be defined as pointers to pointers + elif self.rules == 'REPEATED' and self.pbtype == 'STRING': + result += ' %s **%s;' % (self.ctype, self.name) + else: + result += ' %s *%s;' % (self.ctype, 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): '''Return definitions for any special types this field might need.''' - if self.pbtype == 'BYTES' and self.allocation == 'STATIC': + if self.pbtype == 'BYTES' and (self.allocation == 'STATIC' or self.allocation == 'POINTER'): result = 'typedef struct {\n' result += ' size_t size;\n' - result += ' uint8_t bytes[%d];\n' % self.max_size + if self.allocation == 'POINTER': + result += ' uint8_t *bytes;\n' + else: + result += ' uint8_t bytes[%d];\n' % self.max_size result += '} %s;\n' % self.ctype else: result = None @@ -303,7 +329,7 @@ class Field: 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 diff --git a/generator/nanopb_pb2.py b/generator/nanopb_pb2.py index 4ba18b26..ef1931f2 100644 --- a/generator/nanopb_pb2.py +++ b/generator/nanopb_pb2.py @@ -12,7 +12,7 @@ import google.protobuf.descriptor_pb2 DESCRIPTOR = descriptor.FileDescriptor( name='nanopb.proto', package='', - serialized_pb='\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\x92\x01\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse*J\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions') + serialized_pb='\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\x92\x01\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse*Z\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb') _FIELDTYPE = descriptor.EnumDescriptor( name='FieldType', @@ -29,23 +29,28 @@ _FIELDTYPE = descriptor.EnumDescriptor( options=None, type=None), descriptor.EnumValueDescriptor( - name='FT_STATIC', index=2, number=2, + name='FT_POINTER', index=2, number=4, options=None, type=None), descriptor.EnumValueDescriptor( - name='FT_IGNORE', index=3, number=3, + name='FT_STATIC', index=3, number=2, + options=None, + type=None), + descriptor.EnumValueDescriptor( + name='FT_IGNORE', index=4, number=3, options=None, type=None), ], containing_type=None, options=None, serialized_start=199, - serialized_end=273, + serialized_end=289, ) FT_DEFAULT = 0 FT_CALLBACK = 1 +FT_POINTER = 4 FT_STATIC = 2 FT_IGNORE = 3 |