1"""Buffers are character arrays that may contain null bytes. 2 3There 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 9from bgenType import Type, InputOnlyMixIn, OutputOnlyMixIn, InputOnlyType, OutputOnlyType 10from bgenOutput import * 11 12 13# Map common types to their format characters 14type2format = { 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 29class 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 112class 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 121class InputOnlyBufferMixIn(InputOnlyMixIn): 122 123 def getOutputBufferDeclarations(self, name, constmode=False, outmode=False): 124 return [] 125 126 127class OutputOnlyBufferMixIn(OutputOnlyMixIn): 128 129 def getInputBufferDeclarations(self, name, constmode=False): 130 return [] 131 132class 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 141class 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 151class OptionalFixedInputBufferType(OptionalInputBufferMixIn, FixedInputBufferType): 152 pass 153 154class 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 165class 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 181class 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 187class OptionalVarInputBufferType(OptionalInputBufferMixIn, VarInputBufferType): 188 pass 189 190# ----- PART 2: Structure buffers ----- 191 192 193class 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 242class 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 251class 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 259class 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 270class 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 287class 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