diff --git a/Cython/Compiler/Buffer.py b/Cython/Compiler/Buffer.py index aaf1b6f8bee0b93c69a87228da68d5b4abbc41a0..2cb30279f64d99980943d176c84ba59a383f76a1 100644 --- a/Cython/Compiler/Buffer.py +++ b/Cython/Compiler/Buffer.py @@ -681,7 +681,10 @@ def get_type_information_cname(code, dtype, maxdepth=None): flags = "0" is_unsigned = "0" - if dtype.is_int: + if dtype is PyrexTypes.c_char_type: + is_unsigned = "IS_UNSIGNED(%s)" % declcode + typegroup = "'H'" + elif dtype.is_int: is_unsigned = "IS_UNSIGNED(%s)" % declcode typegroup = "%s ? 'U' : 'I'" % is_unsigned elif complex_possible or dtype.is_complex: @@ -695,7 +698,7 @@ def get_type_information_cname(code, dtype, maxdepth=None): elif dtype.is_pyobject: typegroup = "'O'" else: - assert False + assert False, dtype typeinfo = ('static __Pyx_TypeInfo %s = ' '{ "%s", %s, sizeof(%s), { %s }, %s, %s, %s, %s };') diff --git a/Cython/Utility/Buffer.c b/Cython/Utility/Buffer.c index 008fd95a9059a8d6a2b597364c8da2d8df47231d..8327d407a6bc1dd321ff7038656d23bf3766d847 100644 --- a/Cython/Utility/Buffer.c +++ b/Cython/Utility/Buffer.c @@ -66,7 +66,7 @@ typedef struct { size_t size; /* sizeof(type) */ size_t arraysize[8]; /* length of array in each dimension */ int ndim; - char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */ + char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject, c_H_ar */ char is_unsigned; int flags; } __Pyx_TypeInfo; @@ -290,7 +290,8 @@ static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { switch (ch) { - case 'b': return "'char'"; + case 'c': return "'char'"; + case 'b': return "'signed char'"; case 'B': return "'unsigned char'"; case 'h': return "'short'"; case 'H': return "'unsigned short'"; @@ -417,7 +418,9 @@ static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_compl static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { switch (ch) { - case 'c': case 'b': case 'h': case 'i': + case 'c': + return 'H'; + case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; case 'B': case 'H': case 'I': case 'L': case 'Q': @@ -530,8 +533,12 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { continue; } - __Pyx_BufFmt_RaiseExpected(ctx); - return -1; + if ((type->typegroup == 'H' || group == 'H') && type->size == size) { + /* special case -- chars don't care about sign */ + } else { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } } offset = ctx->head->parent_offset + field->offset; @@ -837,8 +844,14 @@ __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b) return 1; if (a->size != b->size || a->typegroup != b->typegroup || - a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) - return 0; + a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) { + if (a->typegroup == 'H' || b->typegroup == 'H') { + /* Special case for chars */ + return a->size == b->size; + } else { + return 0; + } + } if (a->ndim) { /* Verify multidimensional C arrays */ @@ -893,6 +906,9 @@ static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type) size_t size = type->size; switch (type->typegroup) { + case 'H': + *buf = 'c'; + break; case 'I': case 'U': if (size == 1) diff --git a/tests/buffers/bufaccess.pyx b/tests/buffers/bufaccess.pyx index 4c4ff4d7b0ca1c5607abe3ea37f8b11da1d63707..3418804708d01fd81c64f6df0080184277ccef15 100644 --- a/tests/buffers/bufaccess.pyx +++ b/tests/buffers/bufaccess.pyx @@ -1034,7 +1034,7 @@ def basic_struct(object[MyStruct] buf): >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 - >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="bbqii")) + >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e diff --git a/tests/buffers/buffmt.pyx b/tests/buffers/buffmt.pyx index 8ffaad26d563c8650265df40674f8eb750d97e16..86f31fb782dfe545ba52437718a5412f0a54d7c0 100644 --- a/tests/buffers/buffmt.pyx +++ b/tests/buffers/buffmt.pyx @@ -63,7 +63,7 @@ def _int(fmt): >>> _int("b") Traceback (most recent call last): ... - ValueError: Buffer dtype mismatch, expected 'int' but got 'char' + ValueError: Buffer dtype mismatch, expected 'int' but got 'signed char' >>> _int("if") Traceback (most recent call last): @@ -184,13 +184,13 @@ def char3int(fmt): def unpacked_struct(fmt): """ Native formats: - >>> unpacked_struct("biZffbiii") - >>> unpacked_struct("@bi3fb3i") - >>> unpacked_struct("@biZffbi2i") - >>> unpacked_struct("biZffT{biii}") - >>> unpacked_struct("bT{ifffb2i}i") - >>> unpacked_struct("biZffb3T{i}") - >>> unpacked_struct("T{b}T{T{iZffT{bi}}}2T{T{i}}") + >>> unpacked_struct("ciZffciii") + >>> unpacked_struct("@ci3fc3i") + >>> unpacked_struct("@ciZffci2i") + >>> unpacked_struct("ciZffT{ciii}") + >>> unpacked_struct("cT{ifffc2i}i") + >>> unpacked_struct("ciZffc3T{i}") + >>> unpacked_struct("T{c}T{T{iZffT{ci}}}2T{T{i}}") """ assert (sizeof(UnpackedStruct1) == sizeof(UnpackedStruct2) @@ -303,7 +303,7 @@ def packed_struct(fmt): Assuming int is four bytes: >>> packed_struct("^cici") - >>> packed_struct("=cibi") + >>> packed_struct("=cici") However aligned access won't work: diff --git a/tests/buffers/mockbuffers.pxi b/tests/buffers/mockbuffers.pxi index fcb596262608a082ed2a471e1ca8c00d862fee98..bf145b1504ced838674f1505b6c70bcd14c6f931 100644 --- a/tests/buffers/mockbuffers.pxi +++ b/tests/buffers/mockbuffers.pxi @@ -280,7 +280,7 @@ cdef class MyStructMockBuffer(MockBuffer): return 0 cdef get_itemsize(self): return sizeof(MyStruct) - cdef get_default_format(self): return b"2bq2i" + cdef get_default_format(self): return b"2cq2i" cdef class NestedStructMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: diff --git a/tests/memoryview/memoryview.pyx b/tests/memoryview/memoryview.pyx index db560cd0d98a554d1c620eb20a4a9496e91c4810..00e0427ae31c759ea05c20e91e531b1bf86fa428 100644 --- a/tests/memoryview/memoryview.pyx +++ b/tests/memoryview/memoryview.pyx @@ -237,7 +237,7 @@ def basic_struct(MyStruct[:] mslice): >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] - >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="bbqii")) + >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] """ buf = mslice diff --git a/tests/memoryview/memoryviewattrs.pyx b/tests/memoryview/memoryviewattrs.pyx index 772b23e74bd0d87c2a70d4011b87ec31c2282504..b2ce03a68de7c0fad2abe56e17513d1dc89f450b 100644 --- a/tests/memoryview/memoryviewattrs.pyx +++ b/tests/memoryview/memoryviewattrs.pyx @@ -30,13 +30,13 @@ def test_shape_stride_suboffset(): 77 11 1 -1 -1 -1 ''' - cdef char[:,:,:] larr = array((5,7,11), 1, 'b') + cdef char[:,:,:] larr = array((5,7,11), 1, 'c') print larr.shape[0], larr.shape[1], larr.shape[2] print larr.strides[0], larr.strides[1], larr.strides[2] print larr.suboffsets[0], larr.suboffsets[1], larr.suboffsets[2] print - larr = array((5,7,11), 1, 'b', mode='fortran') + larr = array((5,7,11), 1, 'c', mode='fortran') print larr.shape[0], larr.shape[1], larr.shape[2] print larr.strides[0], larr.strides[1], larr.strides[2] print larr.suboffsets[0], larr.suboffsets[1], larr.suboffsets[2] diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx index a32e63902d916d3d074fdc0c397ad90c906a08f9..e459fdbc9905d8f7691d6c92471403e5c417cb65 100644 --- a/tests/memoryview/memslice.pyx +++ b/tests/memoryview/memslice.pyx @@ -1008,7 +1008,7 @@ def basic_struct(MyStruct[:] buf): >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 - >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="bbqii")) + >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e