javagen.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 JavaGen():
00008     def __init__(self):
00009         
00010         self.storage_equiv = {
00011         'bool': 'byte',
00012         'int8_t': 'byte',
00013         'uint8_t': 'int',
00014         'int16_t': 'short',
00015         'uint16_t': 'int',
00016         'int32_t': 'int',
00017         'uint32_t': 'long',
00018         'int64_t': 'long',
00019         'uint64_t': 'float'
00020         }
00021         
00022         self.type_unsigned_corr = {
00023          'uint8_t': ' & 0xFF',
00024          'uint16_t': ' & 0xFFFF',
00025          'uint32_t': ' & 0xFFFFFFFFL'
00026         }
00027         
00028         self.type_equiv = {
00029         'bool': 'byte',
00030         'int8_t': 'byte',
00031         'uint8_t': 'byte',
00032         'int16_t': 'short',
00033         'uint16_t': 'short',
00034         'int32_t': 'int',
00035         'uint32_t': 'int',
00036         'int64_t': 'long',
00037         'uint64_t': 'long'
00038         }
00039         
00040         self.type_size = {
00041          'byte':1,
00042          'short':2,
00043          'int':4,
00044          'long':8,
00045          'float':4,
00046          'double':8}
00047                
00048         self.primitive_types = self.type_equiv.keys()
00049         self.packable_types = []
00050         self.special_types = {}
00051         self.array_len_type = 'int'
00052     
00053     def gen_variable(self, var, indent = ''):
00054         '''All variables default to a public specifier'''
00055         etype =  self.type_equiv.get(var.type,var.type)
00056         type = self.storage_equiv.get(var.type,etype)
00057         cinit = var.default
00058         if cinit == None:
00059             if self.is_array_type(var.type):
00060                 len = self.get_array_len(var.type)
00061                 etype = self.type_equiv.get(var.type,var.type)
00062                 if len == '':
00063                     cinit = 'new ' + etype + '[0]'
00064                 else:
00065                     cinit = 'new ' + etype + '[' + len + ']'
00066                 type = etype + '[]'
00067             elif var.type not in self.primitive_types:
00068                 cinit = 'new ' + type + '()'
00069                                  
00070         cvar = indent + 'public ' + type + ' ' + var.name
00071                 
00072         if cinit != None:
00073             cvar = cvar + ' = ' + cinit
00074         
00075         return cvar + ';'
00076     
00077     def gen_enum(self, enum, indent = ''):
00078         return indent + 'public final static int ' + enum.name + ' = ' + enum.value + ';'
00079     
00080     def gen_method(self, method, indent):
00081         rtype = self.storage_equiv.get(method.ret,method.ret)
00082         code = indent;
00083         if method.static:
00084             code = code + 'static '
00085         code = code + 'public ' + rtype + ' '
00086         code = code +  method.name + '('
00087     
00088         for arg in method.args:
00089             type = self.type_equiv.get(arg.type,arg.type)
00090             code = code + type + ' ' + arg.name + ','
00091         
00092         if len(method.args): code = code[:-1]
00093             
00094         code = code + ')'
00095         if method.qual != None:
00096             code = code + ' ' + method.qual + ' '
00097             
00098         code = code + '{\n' 
00099         code = code + indent + '  ' + method.body + '\n'
00100         code = code + indent + '}'
00101         
00102         return code
00103     
00104     def gen_class(self, struct, package, imports = [], serialization = True):
00105         code = 'package ' + package + ';\n'
00106         code = code + "\n"
00107     
00108         #Imports
00109         if serialization:
00110             imports_ser = [
00111                 'com.google.common.io.LittleEndianDataInputStream',
00112                 'com.google.common.io.LittleEndianDataOutputStream',
00113                 'java.io.IOException']
00114         
00115             for im in imports_ser:
00116                 code = code + 'import ' + im + ';\n'
00117              
00118         for im in imports:
00119             code = code + 'import ' + im + ';\n' 
00120     
00121         code = code + '\n'
00122     
00123         #Class definition
00124         code = code + 'public class ' + struct.name
00125             
00126         if struct.inherit != None:
00127             code = code + ' implements ' + struct.inherit 
00128         code = code + ' {\n'
00129     
00130         #Skip typedefs
00131     
00132         #Generate enums as final static int
00133         for enum in struct.enums:
00134             code = code + self.gen_enum(enum, '  ') + '\n'
00135         code = code + "\n"
00136         
00137         for var in struct.variables:
00138             code = code + self.gen_variable(var, '  ') + '\n'
00139         
00140         code = code + "\n"
00141                     
00142         #Methods
00143         if serialization: self.add_serializers(struct, '  ')          
00144         for method in struct.methods:
00145             code = code + self.gen_method(method, '  ') + '\n\n'
00146             
00147         #End class definition
00148         code = code + '}\n' 
00149     
00150         return code
00151     
00152     def add_serializers(self, struct, indent):
00153         # Adhers to the packer interface
00154         fn = Function()
00155         fn.name = 'pack' 
00156         fn.ret = 'void'
00157         fn.qual = 'throws IOException'
00158         arg = Variable()
00159         arg.name = 'out'
00160         arg.type = 'LittleEndianDataOutputStream'
00161         fn.args.append(arg)
00162         fn.body = self.gen_serializer_body(struct, indent)
00163         struct.methods.append(fn)
00164         
00165         fn = Function()
00166         fn.name = 'unpack' 
00167         fn.ret = 'void'
00168         fn.qual = 'throws IOException'
00169         arg = Variable()
00170         arg.name = 'in'
00171         arg.type = 'LittleEndianDataInputStream'
00172         fn.args.append(arg)
00173         fn.body = self.gen_deserializer_body(struct, indent)
00174         struct.methods.append(fn)
00175         
00176 
00177     def gen_bitfield_serializer(self, struct, indent):
00178         store_type = ''
00179         sz = int(struct.assert_size)
00180         if sz == 1:
00181             store_type = 'byte'
00182         if sz == 2:
00183             store_type = 'short'
00184         elif (sz > 2) and (sz <= 4):
00185             store_type = 'int'
00186         elif (sz > 4) and (sz <= 8):
00187             store_type = 'long'
00188         elif sz != 1:
00189             print('Cannot create a serializer for size '+ str(sz))
00190             return '' 
00191         
00192         code = indent + store_type + ' storage = 0;\n'
00193         shift = 0  
00194         for var in struct.variables:
00195             if var.bits == None: 
00196                 print('All variables need a bit size in a bitfield.')
00197                 return ''
00198             code = code + indent + 'storage |= ( (' 
00199             code = code + store_type + ')(' + var.name
00200             code = code + ' & ((1<<' + var.bits + ')-1))'
00201             code = code + ' << ' + str(shift) + ');\n'
00202             shift += int(var.bits)
00203             
00204         # Write minimal byte count
00205         code = code + indent + 'ByteArrayOutputStream baos = new ByteArrayOutputStream(); \n'
00206         code = code + indent + 'LittleEndianDataOutputStream dos = new LittleEndianDataOutputStream(baos);\n'
00207         code = code + indent + 'dos.write' + store_type.title() + '(storage);\n'
00208         code = code + 'dos.close();\n'
00209         code = code + 'byte[] bb = baos.toByteArray();\n'
00210         code = code + 'for(int i=0; i<' + str(sz) + ';++i) out.writeByte(bb[i]);\n'
00211         
00212         return code
00213     
00214     def gen_bitfield_deserializer(self, struct, indent):
00215         store_type = ''
00216         sz = int(struct.assert_size)
00217         ssz = 1
00218         if sz == 1:
00219             store_type = 'byte'
00220         if sz == 2:
00221             ssz = 2
00222             store_type = 'short'
00223         elif (sz > 2) and (sz <= 4):
00224             ssz = 4
00225             store_type = 'int'
00226         elif (sz > 4) and (sz <= 8):
00227             ssz = 8
00228             store_type = 'long'
00229         elif sz != 1:
00230             print('Cannot create a serializer for size '+ str(sz))
00231             return '' 
00232         
00233         code = indent + 'byte[] buffer = new byte[' + str(ssz) + '];\n'
00234         code = code + indent + 'for(int i=0; i<' + str(sz) + ';++i) buffer[i] = in.readByte();\n'
00235         code = code + indent + 'ByteArrayInputStream bais = new ByteArrayInputStream(buffer); \n'
00236         code = code + indent + 'LittleEndianDataInputStream dis = new LittleEndianDataInputStream(bais);\n'
00237         code = code + indent + store_type + ' storage ='        
00238         code = code + indent + 'dis.read' + store_type.title() + '();\n'
00239         code = code + 'dis.close();\n'
00240 
00241         for var in struct.variables:
00242             if var.bits == None: 
00243                 print('All variables need a bit size in a bitfield.')
00244                 return ''
00245             code = code + indent + var.name + ' = ('
00246             code = code + self.type_equiv.get(var.type, var.type) + ') '
00247             code = code + '(storage & ((1<<' + var.bits + ')-1));\n' 
00248             code = code + indent + 'storage >>>= ' + str(var.bits) + ';\n'
00249         
00250         return code
00251         
00252     def is_array_type(self, type):
00253         return ((type.find('[') != -1) and
00254             (type.find(']') != -1))
00255     
00256     def get_array_len(self, type):
00257         sidx = type.find('[')
00258         eidx = type.find(']')
00259         return type[sidx+1:eidx]
00260     
00261     def get_array_type(self, type):
00262         sidx = type.find('[')
00263         return type[:sidx]
00264             
00265     def gen_array_serializer(self, var, indent):
00266         code = indent
00267         type = self.get_array_type(var.type)
00268         type = self.type_equiv.get(type,type)
00269         len = self.get_array_len(var.type)
00270                
00271         if len == '':
00272             code = code + indent + 'out.write' + self.array_len_type.title()
00273             code = code + '(' + var.name +'.length);\n'
00274         
00275         if type == 'byte':
00276             code = code + indent + 'out.write(' + var.name + ');'
00277         else:
00278             code = code + indent + 'for(int i=0; i<' + var.name + '.length; ++i) '
00279             code = code + 'out.write' + type.title() + '('
00280             code = code + var.name + '[i]);\n'
00281             
00282         return code
00283     
00284     def gen_array_deserializer(self, var, indent):
00285         code = indent
00286         type = self.get_array_type(var.type)
00287         type = self.type_equiv.get(type,type)
00288         len = self.get_array_len(var.type)
00289                
00290         if len == '':
00291             code = code + indent + var.name + ' = new ' + type
00292             code = code + '[' + 'in.read' + self.array_len_type.title() + '()];\n'
00293         
00294         if type == 'byte':
00295             code = code + indent + 'in.read(' + var.name + ');'
00296         else:
00297             code = code + indent + 'for(int i=0; i<' + var.name + '.length; ++i) '
00298             code = code + var.name + '[i] = ' + 'in.read' + type.title() + '();\n'
00299             
00300         return code
00301             
00302     def gen_serializer_body(self, struct, indent):
00303         # Specially handle bitfields          
00304         if struct.bitfield: return self.gen_bitfield_serializer(struct, indent)
00305                         
00306         # Serialize each memeber variable
00307         code = ''
00308         for var in struct.variables:  
00309             if var.cond != None:
00310                 code = code + indent + 'if (' + var.cond + ' == 1){\n'
00311                           
00312             if self.is_array_type(var.type):
00313                 code = code + indent + self.gen_array_serializer(var, indent)
00314             elif var.type in self.primitive_types:
00315                 type = self.type_equiv.get(var.type,var.type)
00316                 code = code + indent + 'out.write'
00317                 code = code + type.title() + '( (' + type + ')'
00318                 code = code + var.name + ');\n'
00319             elif var.type in self.packable_types:
00320                 code = code + indent + var.name + '.pack(out);\n'
00321             elif var.type in self.special_types.keys():
00322                 code = code + indent + self.special_types[var.type](var, "serializer")
00323             else:
00324                 print('Cannot create a serializer for type: ' + var.type)
00325                 
00326             if var.cond != None:
00327                 code = code + indent + '}\n'
00328             
00329         
00330         return code
00331     
00332     def gen_deserializer_body(self, struct, indent):
00333         # Specially handle bitfields          
00334         if struct.bitfield: return self.gen_bitfield_deserializer(struct, indent)
00335                         
00336                 # Serialize each memeber variable
00337         code = ''
00338         for var in struct.variables:            
00339             if var.cond != None:
00340                 code = code + indent + 'if (' + var.cond + ' == 1){\n'
00341                 
00342             if self.is_array_type(var.type):
00343                 code = code + indent + self.gen_array_deserializer(var, indent)
00344             elif var.type in self.primitive_types:
00345                 code = code + indent + var.name + ' = ('
00346                 code = code + self.storage_equiv.get(var.type, var.type) + ') in.read'
00347                 code = code + self.type_equiv.get(var.type,var.type).title()
00348                 code = code + '()' + self.type_unsigned_corr.get(var.type, '') + ';\n'
00349             elif var.type in self.packable_types:
00350                 code = code + indent + var.name + '.unpack(in);\n'
00351             elif var.type in self.special_types.keys():
00352                 code = code + indent + self.special_types[var.type](var, "deserializer")
00353             else:
00354                 print('Cannot create a serializer for type: ' + var.type)
00355             
00356             if var.cond != None:
00357                 code = code + indent + '}\n'
00358         return code


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