cython

Форк
0
/
buffmt.pyx 
446 строк · 10.9 Кб
1
from __future__ import unicode_literals
2
import struct
3

4
# Tests buffer format string parsing.
5

6

7
from libc cimport stdlib
8

9
def little_endian():
10
    cdef unsigned int n = 1
11
    return (<unsigned char*>&n)[0] != 0
12

13
if little_endian():
14
    current_endian = '<'
15
    other_endian = '>'
16
else:
17
    current_endian = '>'
18
    other_endian = '<'
19

20
cdef struct align_of_float_helper:
21
    char ch
22
    float d
23
cdef struct align_of_int_helper:
24
    char ch
25
    int i
26
float_align = sizeof(align_of_float_helper) - sizeof(float)
27
int_align = sizeof(align_of_int_helper) - sizeof(int)
28
if float_align != 4 or sizeof(float) != 4:
29
    raise RuntimeError("Alignment or size of float is %d on this system, please report to cython-dev for a testcase fix" % float_align)
30
if int_align != 4 or sizeof(int) != 4:
31
    raise RuntimeError("Alignment or size of int is %d on this system, please report to cython-dev for a testcase fix" % int_align)
32

33

34
cdef class MockBuffer:
35
    cdef Py_ssize_t zero
36
    cdef Py_ssize_t minusone
37
    cdef bytes format
38
    cdef object itemsize
39

40
    def __init__(self, format, itemsize):
41
        self.format = unicode(format).encode(u"ASCII")
42
        self.itemsize = itemsize
43
        self.zero = 0
44
        self.minusone = -1
45

46
    def __getbuffer__(self, Py_buffer* info, int flags):
47
        info.buf = NULL
48
        info.strides = &self.zero
49
        info.suboffsets = &self.minusone
50
        info.shape = &self.zero
51
        info.ndim = 1
52
        info.format = self.format
53
        info.itemsize = self.itemsize
54

55
def _int(fmt):
56
    """
57
    >>> _int("i")
58

59
    >>> _int("b")
60
    Traceback (most recent call last):
61
       ...
62
    ValueError: Buffer dtype mismatch, expected 'int' but got 'signed char'
63

64
    >>> _int("if")
65
    Traceback (most recent call last):
66
       ...
67
    ValueError: Buffer dtype mismatch, expected end but got 'float'
68

69
    >>> _int("$$")
70
    Traceback (most recent call last):
71
       ...
72
    ValueError: Does not understand character buffer dtype format string ('$')
73
    """
74
    cdef object[int] buf = MockBuffer(fmt, sizeof(int))
75

76
def _ulong(fmt):
77
    """
78
    >>> _ulong("L")
79
    """
80
    cdef object[unsigned long] buf = MockBuffer(fmt, sizeof(unsigned long))
81

82
def wrongsize():
83
    """
84
    >>> wrongsize()
85
    Traceback (most recent call last):
86
       ...
87
    ValueError: Item size of buffer (1 byte) does not match size of 'float' (4 bytes)
88

89
    """
90
    cdef object[float] buf = MockBuffer("f", 1)
91

92
def _obj(fmt):
93
    """
94
    >>> _obj("O")
95
    >>> _obj("i")
96
    Traceback (most recent call last):
97
       ...
98
    ValueError: Buffer dtype mismatch, expected 'Python object' but got 'int'
99
    """
100
    cdef object[object] buf = MockBuffer(fmt, sizeof(void*))
101

102

103
cdef struct ComplexFloat:
104
    float real
105
    float imag
106

107
ctypedef struct Char3Int:
108
    char a
109
    int b
110
    int c
111
    int d
112

113
ctypedef struct LongString:
114
    char[90198] c
115

116
cdef struct CharIntCFloat:
117
    char a
118
    int b
119
    ComplexFloat c
120
    float d
121

122
cdef struct UnpackedStruct1:
123
    char a
124
    int b
125
    ComplexFloat c
126
    float c2
127
    Char3Int d
128

129
ctypedef struct UnpackedStruct2:
130
    CharIntCFloat a
131
    Char3Int b
132

133
ctypedef struct UnpackedStruct3:
134
    CharIntCFloat a
135
    char b
136
    int c, d, e
137

138
cdef struct UnpackedStruct4:
139
    char a
140
    int b
141
    ComplexFloat c
142
    float c2
143
    char d
144
    int e, f, g
145

146
def char3int(fmt):
147
    """
148
    >>> char3int("ciii")
149
    >>> char3int("c1i1i1i")
150
    >>> char3int("c3i")
151
    >>> char3int("ci2i")
152

153
    >>> char3int("c@i@2i")
154

155
    Extra pad bytes (assuming int size is 4 or more)
156
    >>> char3int("cxiii")
157
    >>> char3int("c3xiii")
158
    >>> char3int("cxxxiii")
159

160
    Standard alignment (assuming int size is 4)
161
    >>> char3int("=c3xiii")
162
    >>> char3int("=ciii")
163
    Traceback (most recent call last):
164
        ...
165
    ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
166

167
    >>> char3int("=cxxx@iii")
168

169
    Error:
170
    >>> char3int("cii")
171
    Traceback (most recent call last):
172
       ...
173
    ValueError: Buffer dtype mismatch, expected 'int' but got end in 'Char3Int.d'
174
    """
175
    cdef object obj = MockBuffer(fmt, sizeof(Char3Int))
176
    cdef object[Char3Int, ndim=1] buf = obj
177

178

179
def long_string(fmt):
180
    """
181
    >>> long_string("90198s")
182
    """
183
    cdef object obj = MockBuffer(fmt, sizeof(LongString))
184
    cdef object[LongString, ndim=1] buf = obj
185

186

187
def unpacked_struct(fmt):
188
    """
189
    Native formats:
190
    >>> unpacked_struct("ciZffciii")
191
    >>> unpacked_struct("@ci3fc3i")
192
    >>> unpacked_struct("@ciZffci2i")
193
    >>> unpacked_struct("ciZffT{ciii}")
194
    >>> unpacked_struct("cT{ifffc2i}i")
195
    >>> unpacked_struct("ciZffc3T{i}")
196
    >>> unpacked_struct("T{c}T{T{iZffT{ci}}}2T{T{i}}")
197
    """
198

199
    assert (sizeof(UnpackedStruct1) == sizeof(UnpackedStruct2)
200
            == sizeof(UnpackedStruct3) == sizeof(UnpackedStruct4))
201
    cdef object obj = MockBuffer(fmt, sizeof(UnpackedStruct1))
202
    cdef object[UnpackedStruct1, ndim=1] buf1 = obj
203
    cdef object[UnpackedStruct2, ndim=1] buf2 = obj
204
    cdef object[UnpackedStruct3, ndim=1] buf3 = obj
205
    cdef object[UnpackedStruct4, ndim=1] buf4 = obj
206

207
cdef struct ComplexTest:
208
    ComplexFloat a, b, c
209

210
def complex_test(fmt):
211
    """
212
    >>> complex_test("ZfZfZf")
213
    >>> complex_test("3Zf")
214
    >>> complex_test("6f")
215
    >>> complex_test("3T{Zf}")
216

217
    >>> complex_test("fZfZff")
218
    Traceback (most recent call last):
219
       ...
220
    ValueError: Buffer dtype mismatch, expected 'float' but got 'complex float' in 'ComplexFloat.imag'
221

222
    """
223
    cdef object obj = MockBuffer(fmt, sizeof(ComplexTest))
224
    cdef object[ComplexTest] buf1 = obj
225

226

227
def alignment_string(fmt, exc=None):
228
    """
229
    >>> alignment_string("@i")
230
    >>> alignment_string("%si" % current_endian)
231
    >>> alignment_string("%si" % other_endian, "X-endian buffer not supported on X-endian compiler")
232
    >>> alignment_string("=i")
233
    """
234
    cdef object[int] buf
235
    try:
236
        buf = MockBuffer(fmt, sizeof(int))
237
    except ValueError, e:
238
        msg = unicode(e).replace("Big", "X").replace("Little", "X").replace("big", "X").replace("little", "X")
239
        if msg != exc:
240
            print msg
241
            print "  is not equal to"
242
            print exc
243
        return
244
    if exc:
245
        print "fail"
246

247

248
def int_and_long_are_same():
249
    """
250
    >>> int_and_long_are_same()
251
    """
252
    cdef object[int] intarr
253
    cdef object[long] longarr
254
    if sizeof(int) == sizeof(long):
255
        intarr = MockBuffer("l", sizeof(int))
256
        longarr = MockBuffer("i", sizeof(int))
257

258
cdef struct MixedComplex:
259
    double real
260
    float imag
261

262
def mixed_complex_struct():
263
    """
264
    Triggering a specific execution path for this case.
265

266
    >>> mixed_complex_struct()
267
    Traceback (most recent call last):
268
        ...
269
    ValueError: Buffer dtype mismatch, expected 'double' but got 'complex double' in 'MixedComplex.real'
270
    """
271
    cdef object[MixedComplex] buf = MockBuffer("Zd",
272
        sizeof(MixedComplex))
273

274

275
cdef packed struct PackedSubStruct:
276
    char x
277
    int y
278

279
cdef struct UnpackedSubStruct:
280
    char x
281
    int y
282

283
cdef packed struct PackedStruct:
284
    char a
285
    int b
286
    PackedSubStruct sub
287

288
cdef struct PartiallyPackedStruct:
289
    char a
290
    int b
291
    PackedSubStruct sub
292

293
cdef packed struct PartiallyPackedStruct2:
294
    char a
295
    UnpackedSubStruct sub
296
    char b
297
    int c
298

299
def packed_struct(fmt):
300
    """
301
    Assuming int is four bytes:
302

303
    >>> packed_struct("^cici")
304
    >>> packed_struct("=cici")
305

306
    However aligned access won't work:
307

308
    >>> packed_struct("^c@i^ci")
309
    Traceback (most recent call last):
310
        ...
311
    ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected
312

313
    >>> packed_struct("@cici")
314
    Traceback (most recent call last):
315
        ...
316
    ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected
317

318
    """
319
    cdef object[PackedStruct] buf = MockBuffer(fmt, sizeof(PackedStruct))
320

321
def partially_packed_struct(fmt):
322
    """
323
    Assuming int is four bytes:
324

325
    >>> partially_packed_struct("^c@i^ci")
326
    >>> partially_packed_struct("@ci^ci")
327
    >>> partially_packed_struct("^c@i=ci")
328
    >>> partially_packed_struct("@ci=ci")
329
    >>> partially_packed_struct("ci^ci")
330
    >>> partially_packed_struct("ci=ci")
331

332
    Incorrectly aligned accesses won't work:
333

334
    >>> partially_packed_struct("^cici")
335
    Traceback (most recent call last):
336
        ...
337
    ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
338

339
    >>> partially_packed_struct("=cibi")
340
    Traceback (most recent call last):
341
        ...
342
    ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
343

344
    """
345
    cdef object[PartiallyPackedStruct] buf = MockBuffer(
346
        fmt, sizeof(PartiallyPackedStruct))
347

348
def partially_packed_struct_2(fmt):
349
    """
350
    Assuming int is four bytes:
351

352
    >>> partially_packed_struct_2("^ccxxxici")
353
    >>> partially_packed_struct_2("^ccxxxi^ci")
354
    >>> partially_packed_struct_2("c=cxxxi^ci")
355
    >>> partially_packed_struct_2("c^cxxxi^ci")
356
    >>> partially_packed_struct_2("c^cxxxi=ci")
357
    >>> partially_packed_struct_2("ccxxx^i@c^i")
358

359
    Incorrectly aligned accesses won't work:
360

361
    >>> partially_packed_struct_2("ccxxxici")
362
    Traceback (most recent call last):
363
        ...
364
    ValueError: Buffer dtype mismatch; next field is at offset 8 but 5 expected
365

366
    >>> partially_packed_struct_2("ccici")
367
    Traceback (most recent call last):
368
        ...
369
    ValueError: Buffer dtype mismatch; next field is at offset 4 but 5 expected
370

371
    """
372
    cdef object[PartiallyPackedStruct2] buf = MockBuffer(
373
        fmt, sizeof(PartiallyPackedStruct2))
374

375

376
cdef packed struct PackedStructWithCharArrays:
377
    float a
378
    int b
379
    char[5] c
380
    char[3] d
381

382

383
def packed_struct_with_strings(fmt):
384
    """
385
    >>> packed_struct_with_strings("T{f:a:i:b:5s:c:3s:d:}")
386
    """
387
    cdef object[PackedStructWithCharArrays] buf = MockBuffer(
388
        fmt, sizeof(PackedStructWithCharArrays))
389

390

391
ctypedef struct PackedStructWithArrays:
392
    double a[16]
393
    double b[16]
394
    double c
395

396
ctypedef struct UnpackedStructWithArrays:
397
    int a
398
    float b[8]
399
    float c
400
    unsigned long long d
401
    int e[5]
402
    int f
403
    int g
404
    double h[4]
405
    int i
406

407
ctypedef struct PackedStructWithNDArrays:
408
    double a
409
    double b[2][2]
410
    float c
411
    float d
412

413

414
def packed_struct_with_arrays(fmt):
415
    """
416
    >>> packed_struct_with_arrays("T{(16)d:a:(16)d:b:d:c:}")
417
    """
418

419
    cdef object[PackedStructWithArrays] buf = MockBuffer(
420
        fmt, sizeof(PackedStructWithArrays))
421

422

423
def unpacked_struct_with_arrays(fmt):
424
    """
425
    >>> if struct.calcsize('P') == 8:  # 64 bit
426
    ...     unpacked_struct_with_arrays("T{i:a:(8)f:b:f:c:Q:d:(5)i:e:i:f:i:g:xxxx(4)d:h:i:i:}")
427
    ... elif struct.calcsize('P') == 4:  # 32 bit
428
    ...     unpacked_struct_with_arrays("T{i:a:(8)f:b:f:c:Q:d:(5)i:e:i:f:i:g:(4)d:h:i:i:}")
429
    """
430

431
    cdef object[UnpackedStructWithArrays] buf = MockBuffer(
432
        fmt, sizeof(UnpackedStructWithArrays))
433

434

435
def packed_struct_with_ndarrays(fmt):
436
    """
437
    >>> packed_struct_with_ndarrays("T{d:a:(2,2)d:b:f:c:f:d:}")
438
    """
439

440
    cdef object[PackedStructWithNDArrays] buf = MockBuffer(
441
        fmt, sizeof(PackedStructWithNDArrays))
442

443

444
# TODO: empty struct
445
# TODO: Incomplete structs
446
# TODO: mixed structs
447

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.