Skip to content

Commit 56dd165

Browse files
committed
implement unpacking for all the fixtext formats
1 parent 985d4c1 commit 56dd165

File tree

6 files changed

+62
-15
lines changed

6 files changed

+62
-15
lines changed

msgpack/_unpacker.pyx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ cdef extern from "unpack.h":
2525
PyObject* object_hook
2626
bint has_pairs_hook # call object_hook with k-v pairs
2727
PyObject* list_hook
28+
PyObject* ext_type_hook
2829
char *encoding
2930
char *unicode_errors
3031

@@ -46,6 +47,7 @@ cdef extern from "unpack.h":
4647

4748
cdef inline init_ctx(unpack_context *ctx,
4849
object object_hook, object object_pairs_hook, object list_hook,
50+
object ext_type_hook,
4951
bint use_list, char* encoding, char* unicode_errors):
5052
unpack_init(ctx)
5153
ctx.user.use_list = use_list
@@ -72,9 +74,17 @@ cdef inline init_ctx(unpack_context *ctx,
7274
raise TypeError("list_hook must be a callable.")
7375
ctx.user.list_hook = <PyObject*>list_hook
7476

77+
if ext_type_hook is not None:
78+
if not PyCallable_Check(ext_type_hook):
79+
raise TypeError("ext_type_hook must be a callable.")
80+
ctx.user.ext_type_hook = <PyObject*>ext_type_hook
81+
7582
ctx.user.encoding = encoding
7683
ctx.user.unicode_errors = unicode_errors
7784

85+
def default_read_extended_type(typecode, data):
86+
raise NotImplementedError("Cannot decode extended type with typecode=%d" % typecode)
87+
7888
def unpackb(object packed, object object_hook=None, object list_hook=None,
7989
bint use_list=1, encoding=None, unicode_errors="strict",
8090
object_pairs_hook=None,
@@ -107,7 +117,8 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
107117
unicode_errors = unicode_errors.encode('ascii')
108118
cerr = PyBytes_AsString(unicode_errors)
109119

110-
init_ctx(&ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
120+
init_ctx(&ctx, object_hook, object_pairs_hook, list_hook, default_read_extended_type,
121+
use_list, cenc, cerr)
111122
ret = unpack_construct(&ctx, buf, buf_len, &off)
112123
if ret == 1:
113124
obj = unpack_data(&ctx)
@@ -249,7 +260,10 @@ cdef class Unpacker(object):
249260
self.unicode_errors = unicode_errors
250261
cerr = PyBytes_AsString(self.unicode_errors)
251262

252-
init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
263+
ext_type_hook = self.read_extended_type
264+
Py_INCREF(ext_type_hook)
265+
init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook,
266+
ext_type_hook, use_list, cenc, cerr)
253267

254268
def feed(self, object next_bytes):
255269
"""Append `next_bytes` to internal buffer."""
@@ -404,6 +418,9 @@ cdef class Unpacker(object):
404418
"""
405419
return self._unpack(read_map_header, write_bytes)
406420

421+
def read_extended_type(self, typecode, data):
422+
return default_read_extended_type(typecode, data)
423+
407424
def __iter__(self):
408425
return self
409426

msgpack/unpack.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef struct unpack_user {
2424
PyObject *object_hook;
2525
bool has_pairs_hook;
2626
PyObject *list_hook;
27+
PyObject *ext_type_hook;
2728
const char *encoding;
2829
const char *unicode_errors;
2930
} unpack_user;
@@ -226,4 +227,21 @@ static inline int unpack_callback_raw(unpack_user* u, const char* b, const char*
226227
return 0;
227228
}
228229

230+
static inline int unpack_callback_ext(unpack_user* u, const char* base, const char* pos,
231+
unsigned int lenght, msgpack_unpack_object* o)
232+
{
233+
PyObject *py;
234+
int8_t typecode = (int8_t)*pos++;
235+
if (!u->ext_type_hook) {
236+
PyErr_SetString(PyExc_AssertionError, "u->ext_type_hook cannot be NULL");
237+
return -1;
238+
}
239+
// lenght also includes the typecode, so the actual data is lenght-1
240+
py = PyEval_CallFunction(u->ext_type_hook, "(is#)", typecode, pos, lenght-1);
241+
if (!py)
242+
return -1;
243+
*o = py;
244+
return 0;
245+
}
246+
229247
#include "unpack_template.h"

msgpack/unpack_define.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ typedef enum {
5959
CS_INT_32 = 0x12,
6060
CS_INT_64 = 0x13,
6161

62-
//CS_ = 0x14,
63-
//CS_ = 0x15,
64-
//CS_BIG_INT_16 = 0x16,
65-
//CS_BIG_INT_32 = 0x17,
66-
//CS_BIG_FLOAT_16 = 0x18,
67-
//CS_BIG_FLOAT_32 = 0x19,
62+
CS_FIXEXT1 = 0x14,
63+
CS_FIXEXT2 = 0x15,
64+
CS_FIXEXT4 = 0x16,
65+
CS_FIXEXT8 = 0x17,
66+
CS_FIXEXT16 = 0x18,
67+
6868
CS_RAW_16 = 0x1a,
6969
CS_RAW_32 = 0x1b,
7070
CS_ARRAY_16 = 0x1c,
@@ -75,6 +75,8 @@ typedef enum {
7575
//ACS_BIG_INT_VALUE,
7676
//ACS_BIG_FLOAT_VALUE,
7777
ACS_RAW_VALUE,
78+
ACS_EXT_VALUE,
79+
7880
} msgpack_unpack_state;
7981

8082

msgpack/unpack_template.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,16 @@ static inline int unpack_execute(unpack_context* ctx, const char* data, size_t l
202202
case 0xd2: // signed int 32
203203
case 0xd3: // signed int 64
204204
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
205-
//case 0xd4:
206-
//case 0xd5:
207-
//case 0xd6: // big integer 16
208-
//case 0xd7: // big integer 32
209-
//case 0xd8: // big float 16
210-
//case 0xd9: // big float 32
205+
case 0xd4: // fixext 1
206+
case 0xd5: // fixext 2
207+
case 0xd6: // fixext 4
208+
case 0xd7: // fixext 8
209+
again_fixed_trail_if_zero(ACS_EXT_VALUE,
210+
(1 << (((unsigned int)*p) & 0x03))+1,
211+
_ext_zero);
212+
case 0xd8: // fixext 16
213+
again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero);
214+
//case 0xd9:
211215
case 0xda: // raw 16
212216
case 0xdb: // raw 32
213217
case 0xdc: // array 16
@@ -298,6 +302,10 @@ static inline int unpack_execute(unpack_context* ctx, const char* data, size_t l
298302
_raw_zero:
299303
push_variable_value(_raw, data, n, trail);
300304

305+
case ACS_EXT_VALUE:
306+
_ext_zero:
307+
push_variable_value(_ext, data, n, trail);
308+
301309
case CS_ARRAY_16:
302310
start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM);
303311
case CS_ARRAY_32:
@@ -309,7 +317,7 @@ static inline int unpack_execute(unpack_context* ctx, const char* data, size_t l
309317
case CS_MAP_32:
310318
/* FIXME security guard */
311319
start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY);
312-
320+
313321
default:
314322
goto _failed;
315323
}

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def __init__(self, *args, **kwargs):
9292
libraries=libraries,
9393
include_dirs=['.'],
9494
define_macros=macros,
95+
extra_compile_args=['-O0'],
9596
))
9697
del libraries, macros
9798

test/test_extension.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import py
12
import array
23
import struct
34
import msgpack

0 commit comments

Comments
 (0)