cpython/Tools/bgen/bgen/bgenBuffer.py

302 lines
8.5 KiB
Python

"""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 getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
if reference:
raise RuntimeError, "Cannot pass buffer types by reference"
return (self.getBufferDeclarations(name, constmode, outmode) +
self.getSizeDeclarations(name, outmode))
def getBufferDeclarations(self, name, constmode=False, outmode=False):
return self.getInputBufferDeclarations(name, constmode) + \
self.getOutputBufferDeclarations(name, constmode, outmode)
def getInputBufferDeclarations(self, name, constmode=False):
if constmode:
const = "const "
else:
const = ""
return ["%s%s *%s__in__" % (const, self.datatype, name)]
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
if constmode:
raise RuntimeError, "Cannot use const output buffer"
if outmode:
out = "*"
else:
out = ""
return ["%s%s %s__out__[%s]" % (self.datatype, out, name, self.size)]
def getSizeDeclarations(self, name, outmode=False):
if outmode:
out = "*"
else:
out = ""
return ["%s%s %s__len__" %(self.sizetype, out, name)]
def getAuxDeclarations(self, name):
return ["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 getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
return []
class OutputOnlyBufferMixIn(OutputOnlyMixIn):
def getInputBufferDeclarations(self, name, constmode=False):
return []
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 getInputBufferDeclarations(self, name, constmode=False):
if constmode:
const = "const "
else:
const = ""
return ["%s%s *%s__in__" % (const, self.type, name)]
def getSizeDeclarations(self, name, outmode=False):
return []
def getAuxDeclarations(self, name):
return ["int %s__in_len__" % (name)]
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
if constmode:
raise RuntimeError, "Cannot use const output buffer"
if outmode:
out = "*"
else:
out = ""
return ["%s%s %s__out__" % (self.type, out, 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 getSizeDeclarations(self, name, outmode=False):
return []
def getAuxDeclarations(self, name):
return []
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 getSizeDeclarations(self, name, outmode=False):
return []
def getAuxDeclarations(self, name):
return []
def passOutput(self, name):
return "%s__out__" % name