| """Buffers are character arrays that may contain null bytes. |
| |
| There are a number of variants depending on: |
| - how the buffer is allocated (for output buffers), and |
| - whether and how the size is passed into and/or out of the called function. |
| """ |
| |
| |
| from bgenType import Type, InputOnlyMixIn, OutputOnlyMixIn, InputOnlyType, OutputOnlyType |
| from bgenOutput import * |
| |
| |
| # Map common types to their format characters |
| type2format = { |
| 'long': 'l', |
| 'int': 'i', |
| 'short': 'h', |
| 'char': 'b', |
| 'unsigned long': 'l', |
| 'unsigned int': 'i', |
| 'unsigned short': 'h', |
| 'unsigned char': 'b', |
| } |
| |
| |
| # ----- PART 1: Fixed character buffers ----- |
| |
| |
| class FixedInputOutputBufferType(InputOnlyType): |
| |
| """Fixed buffer -- passed as (inbuffer, outbuffer).""" |
| |
| def __init__(self, size, datatype = 'char', sizetype = 'int', sizeformat = None): |
| self.typeName = "Buffer" |
| self.size = str(size) |
| self.datatype = datatype |
| self.sizetype = sizetype |
| self.sizeformat = sizeformat or type2format[sizetype] |
| self.label_needed = 0 |
| |
| def declare(self, name): |
| self.declareBuffer(name) |
| self.declareSize(name) |
| |
| def declareBuffer(self, name): |
| self.declareInputBuffer(name) |
| self.declareOutputBuffer(name) |
| |
| def declareInputBuffer(self, name): |
| Output("%s *%s__in__;", self.datatype, name) |
| |
| def declareOutputBuffer(self, name): |
| Output("%s %s__out__[%s];", self.datatype, name, self.size) |
| |
| def declareSize(self, name): |
| Output("%s %s__len__;", self.sizetype, name) |
| Output("int %s__in_len__;", name) |
| |
| def getargsFormat(self): |
| return "s#" |
| |
| def getargsArgs(self, name): |
| return "&%s__in__, &%s__in_len__" % (name, name) |
| |
| def getargsCheck(self, name): |
| Output("if (%s__in_len__ != %s)", name, self.size) |
| OutLbrace() |
| Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");', |
| self.size) |
| Output("goto %s__error__;", name) |
| self.label_needed = 1 |
| OutRbrace() |
| self.transferSize(name) |
| |
| def transferSize(self, name): |
| Output("%s__len__ = %s__in_len__;", name, name) |
| |
| def passOutput(self, name): |
| return "%s__in__, %s__out__" % (name, name) |
| |
| def mkvalueFormat(self): |
| return "s#" |
| |
| def mkvalueArgs(self, name): |
| return "%s__out__, (int)%s" % (name, self.size) |
| |
| def cleanup(self, name): |
| if self.label_needed: |
| DedentLevel() |
| Output(" %s__error__: ;", name) |
| IndentLevel() |
| |
| |
| class FixedCombinedInputOutputBufferType(FixedInputOutputBufferType): |
| |
| """Like fixed buffer -- but same parameter is input and output.""" |
| |
| def passOutput(self, name): |
| return "(%s *)memcpy(%s__out__, %s__in__, %s)" % \ |
| (self.datatype, name, name, self.size) |
| |
| |
| class InputOnlyBufferMixIn(InputOnlyMixIn): |
| |
| def declareOutputBuffer(self, name): |
| pass |
| |
| |
| class OutputOnlyBufferMixIn(OutputOnlyMixIn): |
| |
| def declareInputBuffer(self, name): |
| pass |
| |
| class OptionalInputBufferMixIn: |
| |
| """Add to input buffers if the buffer may be omitted: pass None in Python |
| and the C code will get a NULL pointer and zero size""" |
| |
| def getargsFormat(self): |
| return "z#" |
| |
| |
| class FixedInputBufferType(InputOnlyBufferMixIn, FixedInputOutputBufferType): |
| |
| """Fixed size input buffer -- passed without size information. |
| |
| Instantiate with the size as parameter. |
| """ |
| |
| def passInput(self, name): |
| return "%s__in__" % name |
| |
| class OptionalFixedInputBufferType(OptionalInputBufferMixIn, FixedInputBufferType): |
| pass |
| |
| class FixedOutputBufferType(OutputOnlyBufferMixIn, FixedInputOutputBufferType): |
| |
| """Fixed size output buffer -- passed without size information. |
| |
| Instantiate with the size as parameter. |
| """ |
| |
| def passOutput(self, name): |
| return "%s__out__" % name |
| |
| |
| class VarInputBufferType(FixedInputBufferType): |
| |
| """Variable size input buffer -- passed as (buffer, size). |
| |
| Instantiate without size parameter. |
| """ |
| |
| def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None): |
| FixedInputBufferType.__init__(self, "0", datatype, sizetype, sizeformat) |
| |
| def getargsCheck(self, name): |
| Output("%s__len__ = %s__in_len__;", name, name) |
| |
| def passInput(self, name): |
| return "%s__in__, %s__len__" % (name, name) |
| |
| class ReverseInputBufferMixin: |
| """ Mixin for input buffers that are passed as (size, buffer) """ |
| |
| def passInput(self, name): |
| return "%s__len__, %s__in__" % (name, name) |
| |
| class OptionalVarInputBufferType(OptionalInputBufferMixIn, VarInputBufferType): |
| pass |
| |
| # ----- PART 2: Structure buffers ----- |
| |
| |
| class StructInputOutputBufferType(FixedInputOutputBufferType): |
| |
| """Structure buffer -- passed as a structure pointer. |
| |
| Instantiate with the struct type as parameter. |
| """ |
| |
| def __init__(self, type): |
| FixedInputOutputBufferType.__init__(self, "sizeof(%s)" % type) |
| self.typeName = self.type = type |
| |
| def declareInputBuffer(self, name): |
| Output("%s *%s__in__;", self.type, name) |
| |
| def declareSize(self, name): |
| Output("int %s__in_len__;", name) |
| |
| def declareOutputBuffer(self, name): |
| Output("%s %s__out__;", self.type, name) |
| |
| def getargsArgs(self, name): |
| return "(char **)&%s__in__, &%s__in_len__" % (name, name) |
| |
| def transferSize(self, name): |
| pass |
| |
| def passInput(self, name): |
| return "%s__in__" % name |
| |
| def passOutput(self, name): |
| return "%s__in__, &%s__out__" % (name, name) |
| |
| def mkvalueArgs(self, name): |
| return "(char *)&%s__out__, (int)%s" % (name, self.size) |
| |
| |
| class StructCombinedInputOutputBufferType(StructInputOutputBufferType): |
| |
| """Like structure buffer -- but same parameter is input and output.""" |
| |
| def passOutput(self, name): |
| return "(%s *)memcpy((char *)%s__out__, (char *)%s__in__, %s)" % \ |
| (self.type, name, name, self.size) |
| |
| |
| class StructInputBufferType(InputOnlyBufferMixIn, StructInputOutputBufferType): |
| |
| """Fixed size input buffer -- passed as a pointer to a structure. |
| |
| Instantiate with the struct type as parameter. |
| """ |
| |
| |
| class StructByValueBufferType(StructInputBufferType): |
| |
| """Fixed size input buffer -- passed as a structure BY VALUE. |
| |
| Instantiate with the struct type as parameter. |
| """ |
| |
| def passInput(self, name): |
| return "*%s__in__" % name |
| |
| |
| class StructOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType): |
| |
| """Fixed size output buffer -- passed as a pointer to a structure. |
| |
| Instantiate with the struct type as parameter. |
| """ |
| |
| def declareSize(self, name): |
| pass |
| |
| def passOutput(self, name): |
| return "&%s__out__" % name |
| |
| |
| class ArrayOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType): |
| |
| """Fixed size output buffer -- declared as a typedef, passed as an array. |
| |
| Instantiate with the struct type as parameter. |
| """ |
| |
| def declareSize(self, name): |
| pass |
| |
| def passOutput(self, name): |
| return "%s__out__" % name |