aboutsummaryrefslogtreecommitdiffstats
path: root/generator
diff options
context:
space:
mode:
authorMartin Donath <scifish@gmail.com>2013-12-08 23:25:32 +0100
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-12-29 18:35:57 +0200
commit4ae3b2e5661b154cd1f7e545f6052d271306ff25 (patch)
tree90b8fb3619eedaf9c0f3e8a5ac7ffd494467b99c /generator
parent4f37c083d532a782e478b2cef6a02d028613564d (diff)
Generating and encoding messages with dynamic allocaiton
Diffstat (limited to 'generator')
-rw-r--r--generator/nanopb.proto1
-rwxr-xr-xgenerator/nanopb_generator.py62
-rw-r--r--generator/nanopb_pb2.py13
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