cppgen.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
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         #Header guard
00099         #Includes
00100                             
00101         #Class definition
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         #Generate typedefs
00110         for t in struct.typedefs:
00111             code = code + '  typedef ' + t[0] + ' ' + t[1] + ';\n'
00112                 
00113         #Generate enums as final static int
00114         for enum in struct.enums:
00115             code = code + self.gen_enum(enum, '  ') + '\n'
00116         code = code + "\n"
00117         
00118         #Methods
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         #End class definition
00129         code = code + '};\n' 
00130     
00131         return code
00132     
00133     def gen_impl(self, struct, includes = [], serialization = True):
00134         #Includes
00135                             
00136         #Class implementation                
00137         #Methods
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         # Adhers to the packer interface
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         #Minimum byte rounding to avoid having zeros
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         # Specially handle bitfields          
00284         if struct.bitfield: return self.gen_bitfield_serializer(struct, indent)
00285                         
00286         # Serialize each memeber variable
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         # Specially handle bitfields          
00310         if struct.bitfield: return self.gen_bitfield_deserializer(struct, indent)
00311                         
00312                 # Serialize each memeber variable
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


snippets
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:22:33