Home | History | Annotate | Download | only in bgen
      1 """Buffers are character arrays that may contain null bytes.
      2 
      3 There are a number of variants depending on:
      4 - how the buffer is allocated (for output buffers), and
      5 - whether and how the size is passed into and/or out of the called function.
      6 """
      7 
      8 
      9 from bgenType import Type, InputOnlyMixIn, OutputOnlyMixIn, InputOnlyType, OutputOnlyType
     10 from bgenOutput import *
     11 
     12 
     13 # Map common types to their format characters

     14 type2format = {
     15     'long': 'l',
     16     'int': 'i',
     17     'short': 'h',
     18     'char': 'b',
     19     'unsigned long': 'l',
     20     'unsigned int': 'i',
     21     'unsigned short': 'h',
     22     'unsigned char': 'b',
     23 }
     24 
     25 
     26 # ----- PART 1: Fixed character buffers -----

     27 
     28 
     29 class FixedInputOutputBufferType(InputOnlyType):
     30 
     31     """Fixed buffer -- passed as (inbuffer, outbuffer)."""
     32 
     33     def __init__(self, size, datatype = 'char', sizetype = 'int', sizeformat = None):
     34         self.typeName = "Buffer"
     35         self.size = str(size)
     36         self.datatype = datatype
     37         self.sizetype = sizetype
     38         self.sizeformat = sizeformat or type2format[sizetype]
     39         self.label_needed = 0
     40 
     41     def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
     42         if reference:
     43             raise RuntimeError, "Cannot pass buffer types by reference"
     44         return (self.getBufferDeclarations(name, constmode, outmode) +
     45                 self.getSizeDeclarations(name, outmode))
     46 
     47     def getBufferDeclarations(self, name, constmode=False, outmode=False):
     48         return self.getInputBufferDeclarations(name, constmode) + \
     49                 self.getOutputBufferDeclarations(name, constmode, outmode)
     50 
     51     def getInputBufferDeclarations(self, name, constmode=False):
     52         if constmode:
     53             const = "const "
     54         else:
     55             const = ""
     56         return ["%s%s *%s__in__" % (const, self.datatype, name)]
     57 
     58     def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
     59         if constmode:
     60             raise RuntimeError, "Cannot use const output buffer"
     61         if outmode:
     62             out = "*"
     63         else:
     64             out = ""
     65         return ["%s%s %s__out__[%s]" % (self.datatype, out, name, self.size)]
     66 
     67     def getSizeDeclarations(self, name, outmode=False):
     68         if outmode:
     69             out = "*"
     70         else:
     71             out = ""
     72         return ["%s%s %s__len__" %(self.sizetype, out, name)]
     73 
     74     def getAuxDeclarations(self, name):
     75         return ["int %s__in_len__" %(name)]
     76 
     77     def getargsFormat(self):
     78         return "s#"
     79 
     80     def getargsArgs(self, name):
     81         return "&%s__in__, &%s__in_len__" % (name, name)
     82 
     83     def getargsCheck(self, name):
     84         Output("if (%s__in_len__ != %s)", name, self.size)
     85         OutLbrace()
     86         Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
     87                self.size)
     88         Output("goto %s__error__;", name)
     89         self.label_needed = 1
     90         OutRbrace()
     91         self.transferSize(name)
     92 
     93     def transferSize(self, name):
     94         Output("%s__len__ = %s__in_len__;", name, name)
     95 
     96     def passOutput(self, name):
     97         return "%s__in__, %s__out__" % (name, name)
     98 
     99     def mkvalueFormat(self):
    100         return "s#"
    101 
    102     def mkvalueArgs(self, name):
    103         return "%s__out__, (int)%s" % (name, self.size)
    104 
    105     def cleanup(self, name):
    106         if self.label_needed:
    107             DedentLevel()
    108             Output(" %s__error__: ;", name)
    109             IndentLevel()
    110 
    111 
    112 class FixedCombinedInputOutputBufferType(FixedInputOutputBufferType):
    113 
    114     """Like fixed buffer -- but same parameter is input and output."""
    115 
    116     def passOutput(self, name):
    117         return "(%s *)memcpy(%s__out__, %s__in__, %s)" % \
    118             (self.datatype, name,   name,     self.size)
    119 
    120 
    121 class InputOnlyBufferMixIn(InputOnlyMixIn):
    122 
    123     def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
    124         return []
    125 
    126 
    127 class OutputOnlyBufferMixIn(OutputOnlyMixIn):
    128 
    129     def getInputBufferDeclarations(self, name, constmode=False):
    130         return []
    131 
    132 class OptionalInputBufferMixIn:
    133 
    134     """Add to input buffers if the buffer may be omitted: pass None in Python
    135     and the C code will get a NULL pointer and zero size"""
    136 
    137     def getargsFormat(self):
    138         return "z#"
    139 
    140 
    141 class FixedInputBufferType(InputOnlyBufferMixIn, FixedInputOutputBufferType):
    142 
    143     """Fixed size input buffer -- passed without size information.
    144 
    145     Instantiate with the size as parameter.
    146     """
    147 
    148     def passInput(self, name):
    149         return "%s__in__" % name
    150 
    151 class OptionalFixedInputBufferType(OptionalInputBufferMixIn, FixedInputBufferType):
    152     pass
    153 
    154 class FixedOutputBufferType(OutputOnlyBufferMixIn, FixedInputOutputBufferType):
    155 
    156     """Fixed size output buffer -- passed without size information.
    157 
    158     Instantiate with the size as parameter.
    159     """
    160 
    161     def passOutput(self, name):
    162         return "%s__out__" % name
    163 
    164 
    165 class VarInputBufferType(FixedInputBufferType):
    166 
    167     """Variable size input buffer -- passed as (buffer, size).
    168 
    169     Instantiate without size parameter.
    170     """
    171 
    172     def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None):
    173         FixedInputBufferType.__init__(self, "0", datatype, sizetype, sizeformat)
    174 
    175     def getargsCheck(self, name):
    176         Output("%s__len__ = %s__in_len__;", name, name)
    177 
    178     def passInput(self, name):
    179         return "%s__in__, %s__len__" % (name, name)
    180 
    181 class ReverseInputBufferMixin:
    182     """ Mixin for input buffers that are passed as (size, buffer) """
    183 
    184     def passInput(self, name):
    185         return "%s__len__, %s__in__" % (name, name)
    186 
    187 class OptionalVarInputBufferType(OptionalInputBufferMixIn, VarInputBufferType):
    188     pass
    189 
    190 # ----- PART 2: Structure buffers -----

    191 
    192 
    193 class StructInputOutputBufferType(FixedInputOutputBufferType):
    194 
    195     """Structure buffer -- passed as a structure pointer.
    196 
    197     Instantiate with the struct type as parameter.
    198     """
    199 
    200     def __init__(self, type):
    201         FixedInputOutputBufferType.__init__(self, "sizeof(%s)" % type)
    202         self.typeName = self.type = type
    203 
    204     def getInputBufferDeclarations(self, name, constmode=False):
    205         if constmode:
    206             const = "const "
    207         else:
    208             const = ""
    209         return ["%s%s *%s__in__" % (const, self.type, name)]
    210 
    211     def getSizeDeclarations(self, name, outmode=False):
    212         return []
    213 
    214     def getAuxDeclarations(self, name):
    215         return ["int %s__in_len__" % (name)]
    216 
    217     def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
    218         if constmode:
    219             raise RuntimeError, "Cannot use const output buffer"
    220         if outmode:
    221             out = "*"
    222         else:
    223             out = ""
    224         return ["%s%s %s__out__" % (self.type, out, name)]
    225 
    226     def getargsArgs(self, name):
    227         return "(char **)&%s__in__, &%s__in_len__" % (name, name)
    228 
    229     def transferSize(self, name):
    230         pass
    231 
    232     def passInput(self, name):
    233         return "%s__in__" % name
    234 
    235     def passOutput(self, name):
    236         return "%s__in__, &%s__out__" % (name, name)
    237 
    238     def mkvalueArgs(self, name):
    239         return "(char *)&%s__out__, (int)%s" % (name, self.size)
    240 
    241 
    242 class StructCombinedInputOutputBufferType(StructInputOutputBufferType):
    243 
    244     """Like structure buffer -- but same parameter is input and output."""
    245 
    246     def passOutput(self, name):
    247         return "(%s *)memcpy((char *)%s__out__, (char *)%s__in__, %s)" % \
    248             (self.type,          name,              name,     self.size)
    249 
    250 
    251 class StructInputBufferType(InputOnlyBufferMixIn, StructInputOutputBufferType):
    252 
    253     """Fixed size input buffer -- passed as a pointer to a structure.
    254 
    255     Instantiate with the struct type as parameter.
    256     """
    257 
    258 
    259 class StructByValueBufferType(StructInputBufferType):
    260 
    261     """Fixed size input buffer -- passed as a structure BY VALUE.
    262 
    263     Instantiate with the struct type as parameter.
    264     """
    265 
    266     def passInput(self, name):
    267         return "*%s__in__" % name
    268 
    269 
    270 class StructOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
    271 
    272     """Fixed size output buffer -- passed as a pointer to a structure.
    273 
    274     Instantiate with the struct type as parameter.
    275     """
    276 
    277     def getSizeDeclarations(self, name, outmode=False):
    278         return []
    279 
    280     def getAuxDeclarations(self, name):
    281         return []
    282 
    283     def passOutput(self, name):
    284         return "&%s__out__" % name
    285 
    286 
    287 class ArrayOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
    288 
    289     """Fixed size output buffer -- declared as a typedef, passed as an array.
    290 
    291     Instantiate with the struct type as parameter.
    292     """
    293 
    294     def getSizeDeclarations(self, name, outmode=False):
    295         return []
    296 
    297     def getAuxDeclarations(self, name):
    298         return []
    299 
    300     def passOutput(self, name):
    301         return "%s__out__" % name
    302