00001
00002 from snippets.generators.elements.structure import Structure
00003 from snippets.generators.elements.variable import Variable
00004 from snippets.generators.elements.function import Function
00005 import xml.etree.ElementTree as ET
00006
00007 class CppGen():
00008 def __init__(self):
00009 self.type_equiv = {
00010 'bool': 'byte',
00011 'int8_t': 'byte',
00012 'uint8_t': 'byte',
00013 'int16_t': 'short',
00014 'uint16_t': 'short',
00015 'int32_t': 'int',
00016 'uint32_t': 'int',
00017 'int64_t': 'long',
00018 'uint64_t': 'long'
00019 }
00020
00021 self.type_size = {
00022 'byte':1,
00023 'short':2,
00024 'int':4,
00025 'long':8,
00026 'float':4,
00027 'double':8}
00028
00029 self.primitive_types = self.type_equiv.keys()
00030 self.packable_types = []
00031 self.special_types = {}
00032 self.array_len_type = 'int'
00033
00034 def gen_variable(self, var, indent = ''):
00035 atype = None
00036 type = var.type
00037 cinit = var.default
00038
00039 if self.is_array_type(var.type):
00040 len = self.get_array_len(var.type)
00041 type = self.get_array_type(var.type)
00042 if len == '':
00043 type = 'std::vector< ' + type + ' >'
00044 else:
00045 atype = '[' + len + ']'
00046
00047 cvar = indent + type + ' ' + var.name
00048
00049 if atype != None:
00050 cvar = cvar + atype
00051
00052 if cinit != None:
00053 cvar = cvar + ' = ' + cinit
00054
00055 return cvar + ';'
00056
00057 def gen_enum(self, enum, indent = ''):
00058 return indent + 'enum { ' + enum.name + ' = ' + enum.value + '};'
00059
00060 def gen_method_def(self, method, indent):
00061 code = indent + method.ret + ' '
00062 code = code + method.name + '('
00063
00064 for arg in method.args:
00065 code = code + arg.type + ' ' + arg.name + ','
00066
00067 if len(method.args): code = code[:-1]
00068 code = code + ')'
00069
00070 if method.qual != None:
00071 code = code + ' ' + method.qual
00072
00073 if method.inline:
00074 code = code + '\n{\n' + indent + method.body + '\n}'
00075
00076 return code + ";"
00077
00078 def gen_method(self, name, method, indent):
00079 if method.inline: return ''
00080
00081 code = indent + method.ret + ' '
00082 code = code + name + '::' + method.name + '('
00083
00084 for arg in method.args:
00085 code = code + arg.type + ' ' + arg.name + ','
00086
00087 if len(method.args): code = code[:-1]
00088 code = code + ')'
00089
00090 if method.qual != None:
00091 code = code + ' ' + method.qual
00092
00093 code = code + '\n{\n' + indent + method.body + '\n}'
00094
00095 return code + ";"
00096
00097 def gen_header(self, struct, includes = [], serialization = True):
00098
00099
00100
00101
00102 code = 'struct ' + struct.name
00103
00104 if struct.inherit != None:
00105 code = code + ' : public ' + struct.inherit
00106 code = code + ' {\n'
00107 code = code + 'public:\n'
00108
00109
00110 for t in struct.typedefs:
00111 code = code + ' typedef ' + t[0] + ' ' + t[1] + ';\n'
00112
00113
00114 for enum in struct.enums:
00115 code = code + self.gen_enum(enum, ' ') + '\n'
00116 code = code + "\n"
00117
00118
00119 if serialization: self.add_serializers(struct, ' ')
00120 for method in struct.methods:
00121 code = code + self.gen_method_def(method, ' ') + '\n\n'
00122
00123 for var in struct.variables:
00124 code = code + self.gen_variable(var, ' ') + '\n'
00125
00126 code = code + "\n"
00127
00128
00129 code = code + '};\n'
00130
00131 return code
00132
00133 def gen_impl(self, struct, includes = [], serialization = True):
00134
00135
00136
00137
00138 if serialization: self.add_serializers(struct, ' ')
00139 code = ''
00140 for method in struct.methods:
00141 code = code + self.gen_method(struct.name, method, ' ') + '\n\n'
00142
00143 code = code + "\n"
00144
00145 return code
00146
00147 def add_serializers(self, struct, indent):
00148
00149 fn = Function()
00150 fn.name = 'pack'
00151 fn.inline = None
00152 fn.ret = 'void'
00153 fn.qual = 'const'
00154 arg = Variable()
00155 arg.name = 'out'
00156 arg.type = 'boost::archive::binary_oarchive&'
00157 fn.args.append(arg)
00158 fn.body = self.gen_serializer_body(struct, indent)
00159 struct.methods.append(fn)
00160
00161 fn = Function()
00162 fn.name = 'unpack'
00163 fn.ret = 'void'
00164 fn.qual = ''
00165 arg = Variable()
00166 arg.name = 'in'
00167 arg.type = 'boost::archive::binary_iarchive&'
00168 fn.args.append(arg)
00169 fn.body = self.gen_deserializer_body(struct, indent)
00170 struct.methods.append(fn)
00171
00172 def gen_bitfield_serializer(self, struct, indent):
00173 store_type = ''
00174 sz = int(struct.assert_size)
00175 if sz == 1:
00176 store_type = 'uint8_t'
00177 if sz == 2:
00178 store_type = 'uint16_t'
00179 elif (sz > 2) and (sz <= 4):
00180 store_type = 'uint32_t'
00181 elif (sz > 4) and (sz <= 8):
00182 store_type = 'uint64_t'
00183 elif sz != 1:
00184 print('Cannot create a serializer for size '+ str(sz))
00185 return ''
00186
00187 code = indent + store_type + ' storage = 0;\n'
00188 shift = 0
00189 for var in struct.variables:
00190 if var.bits == None:
00191 print('All variables need a bit size in a bitfield.')
00192 return ''
00193 code = code + indent + 'storage |= ('
00194 code = code + store_type + '(' + var.name
00195 code = code + ') & ((1<<' + var.bits + ')-1))'
00196 code = code + ' << ' + str(shift) + ';\n'
00197 shift += int(var.bits)
00198
00199
00200 code = code + indent + 'uint8_t* pt(reinterpret_cast<uint8_t*>(&storage));\n'
00201 code = code + indent + 'for(int i=0; i<' + str(sz) + '; ++i,++pt) out << *pt;\n'
00202
00203 return code
00204
00205 def gen_bitfield_deserializer(self, struct, indent):
00206 store_type = ''
00207 sz = int(struct.assert_size)
00208 if sz == 1:
00209 store_type = 'uint8_t'
00210 if sz == 2:
00211 store_type = 'uint16_t'
00212 elif (sz > 2) and (sz <= 4):
00213 store_type = 'uint32_t'
00214 elif (sz > 4) and (sz <= 8):
00215 store_type = 'uint64_t'
00216 elif sz != 1:
00217 print('Cannot create a serializer for size '+ str(sz))
00218 return ''
00219
00220 code = ''
00221 code = code + indent + store_type + ' storage(0);\n'
00222 code = code + indent + 'uint8_t* pt(reinterpret_cast<uint8_t*>(&storage));\n'
00223 code = code + indent + 'for(int i=0; i<' + str(sz) + '; ++i,++pt) in >> *pt;\n'
00224 for var in struct.variables:
00225 if var.bits == None:
00226 print('All variables need a bit size in a bitfield.')
00227 return ''
00228 code = code + indent + var.name + ' = static_cast<'
00229 code = code + var.type + '>'
00230 code = code + '(storage & ((1<<' + var.bits + ')-1));\n'
00231 code = code + indent + 'storage >>= ' + str(var.bits) + ';\n'
00232
00233 return code
00234
00235 def is_array_type(self, type):
00236 return ((type.find('[') != -1) and
00237 (type.find(']') != -1))
00238
00239 def get_array_len(self, type):
00240 sidx = type.find('[')
00241 eidx = type.find(']')
00242 return type[sidx+1:eidx]
00243
00244 def get_array_type(self, type):
00245 sidx = type.find('[')
00246 return type[:sidx]
00247
00248 def gen_array_serializer(self, var, indent):
00249 code = indent
00250 len = self.get_array_len(var.type)
00251
00252 if len == '':
00253 code = code + self.array_len_type + ' ' + var.name + '_len'
00254 code = code + '(' + var.name +'.size());\n'
00255 code = code + indent + 'out << ' + var.name + '_len;\n'
00256 code = code + indent + 'for(int i=0; i<' + var.name + '.size(); ++i) '
00257 else:
00258 code = code + indent + 'for(int i=0; i<' + len + '; ++i) '
00259
00260 code = code + 'out << '
00261 code = code + var.name + '[i];\n'
00262
00263 return code
00264
00265 def gen_array_deserializer(self, var, indent):
00266 code = indent
00267 len = self.get_array_len(var.type)
00268
00269 if len == '':
00270 code = code + self.array_len_type + ' ' + var.name + '_len;\n'
00271 code = code + 'in >> ' + var.name + '_len;\n'
00272 code = code + indent + var.name + '.resize(' + var.name + '_len);\n'
00273 code = code + indent + 'for(int i=0; i<' + var.name + '.size(); ++i) '
00274 else:
00275 code = code + indent + 'for(int i=0; i<' + len + '; ++i) '
00276
00277 code = code + 'in >> '
00278 code = code + var.name + '[i];\n'
00279
00280 return code
00281
00282 def gen_serializer_body(self, struct, indent):
00283
00284 if struct.bitfield: return self.gen_bitfield_serializer(struct, indent)
00285
00286
00287 code = ''
00288 for var in struct.variables:
00289 if var.cond != None:
00290 code = code + indent + 'if (' + var.cond + '){\n'
00291
00292 if self.is_array_type(var.type):
00293 code = code + indent + self.gen_array_serializer(var, indent)
00294 elif var.type in self.primitive_types:
00295 code = code + indent + 'out <<' + var.name + ';\n'
00296 elif var.type in self.packable_types:
00297 code = code + indent + var.name + '.pack(out);\n'
00298 elif var.type in self.special_types.keys():
00299 code = code + indent + self.special_types[var.type](var, "serializer")
00300 else:
00301 print('Cannot create a serializer for type: ' + var.type)
00302
00303 if var.cond != None:
00304 code = code + indent + '}\n'
00305
00306 return code
00307
00308 def gen_deserializer_body(self, struct, indent):
00309
00310 if struct.bitfield: return self.gen_bitfield_deserializer(struct, indent)
00311
00312
00313 code = ''
00314 for var in struct.variables:
00315 if var.cond != None:
00316 code = code + indent + 'if (' + var.cond + '){\n'
00317 if self.is_array_type(var.type):
00318 code = code + indent + self.gen_array_deserializer(var, indent)
00319 elif var.type in self.primitive_types:
00320 code = code + indent + 'in >> ' + var.name + ';\n'
00321 elif var.type in self.packable_types:
00322 code = code + indent + var.name + '.unpack(in);\n'
00323 elif var.type in self.special_types.keys():
00324 code = code + indent + self.special_types[var.type](var, "deserializer")
00325 else:
00326 print('Cannot create a serializer for type: ' + var.type)
00327
00328 if var.cond != None:
00329 code = code + indent + '}\n'
00330 return code