summaryrefslogtreecommitdiff
path: root/msgpack/_msgpack.pyx
diff options
context:
space:
mode:
authorINADA Naoki <inada-n@klab.com>2012-09-24 03:10:37 +0900
committerINADA Naoki <inada-n@klab.com>2012-09-24 03:10:37 +0900
commit1526316a0803c233a6752aff1bab6e951447d12a (patch)
tree1705ccd3828c981791b2a0ce1debfbcc9f598a82 /msgpack/_msgpack.pyx
parentd13f10c02e06b0f3c138b1726cfa8b1a31529d64 (diff)
parent477d3b152f5d36a48a8083b3720def2dd1f5d1a7 (diff)
downloadmsgpack-python-1526316a0803c233a6752aff1bab6e951447d12a.tar.gz
Merge branch '0.2-maint'
Conflicts: msgpack/_msgpack.pyx
Diffstat (limited to 'msgpack/_msgpack.pyx')
-rw-r--r--msgpack/_msgpack.pyx108
1 files changed, 51 insertions, 57 deletions
diff --git a/msgpack/_msgpack.pyx b/msgpack/_msgpack.pyx
index e932ba9..3fab3cd 100644
--- a/msgpack/_msgpack.pyx
+++ b/msgpack/_msgpack.pyx
@@ -201,6 +201,7 @@ cdef extern from "unpack.h":
ctypedef struct msgpack_user:
bint use_list
PyObject* object_hook
+ bint has_pairs_hook # call object_hook with k-v pairs
PyObject* list_hook
char *encoding
char *unicode_errors
@@ -217,9 +218,50 @@ cdef extern from "unpack.h":
void template_init(template_context* ctx)
object template_data(template_context* ctx)
+cdef inline init_ctx(template_context *ctx, object object_hook, object object_pairs_hook, object list_hook, bint use_list, encoding, unicode_errors):
+ template_init(ctx)
+ ctx.user.use_list = use_list
+ ctx.user.object_hook = ctx.user.list_hook = <PyObject*>NULL
+
+ if object_hook is not None and object_pairs_hook is not None:
+ raise ValueError("object_pairs_hook and object_hook are mutually exclusive.")
+
+ if object_hook is not None:
+ if not PyCallable_Check(object_hook):
+ raise TypeError("object_hook must be a callable.")
+ ctx.user.object_hook = <PyObject*>object_hook
+
+ if object_pairs_hook is None:
+ ctx.user.has_pairs_hook = False
+ else:
+ if not PyCallable_Check(object_pairs_hook):
+ raise TypeError("object_pairs_hook must be a callable.")
+ ctx.user.object_hook = <PyObject*>object_pairs_hook
+ ctx.user.has_pairs_hook = True
+
+ if list_hook is not None:
+ if not PyCallable_Check(list_hook):
+ raise TypeError("list_hook must be a callable.")
+ ctx.user.list_hook = <PyObject*>list_hook
+
+ if encoding is None:
+ ctx.user.encoding = NULL
+ ctx.user.unicode_errors = NULL
+ else:
+ if isinstance(encoding, unicode):
+ _bencoding = encoding.encode('ascii')
+ else:
+ _bencoding = encoding
+ ctx.user.encoding = PyBytes_AsString(_bencoding)
+ if isinstance(unicode_errors, unicode):
+ _berrors = unicode_errors.encode('ascii')
+ else:
+ _berrors = unicode_errors
+ ctx.user.unicode_errors = PyBytes_AsString(_berrors)
def unpackb(object packed, object object_hook=None, object list_hook=None,
bint use_list=1, encoding=None, unicode_errors="strict",
+ object_pairs_hook=None,
):
"""Unpack packed_bytes to object. Returns an unpacked object.
@@ -234,34 +276,7 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
PyObject_AsReadBuffer(packed, <const_void_ptr*>&buf, &buf_len)
- if encoding is None:
- enc = NULL
- err = NULL
- else:
- if isinstance(encoding, unicode):
- bencoding = encoding.encode('ascii')
- else:
- bencoding = encoding
- if isinstance(unicode_errors, unicode):
- berrors = unicode_errors.encode('ascii')
- else:
- berrors = unicode_errors
- enc = PyBytes_AsString(bencoding)
- err = PyBytes_AsString(berrors)
-
- template_init(&ctx)
- ctx.user.use_list = use_list
- ctx.user.object_hook = ctx.user.list_hook = NULL
- ctx.user.encoding = <const_char_ptr>enc
- ctx.user.unicode_errors = <const_char_ptr>err
- if object_hook is not None:
- if not PyCallable_Check(object_hook):
- raise TypeError("object_hook must be a callable.")
- ctx.user.object_hook = <PyObject*>object_hook
- if list_hook is not None:
- if not PyCallable_Check(list_hook):
- raise TypeError("list_hook must be a callable.")
- ctx.user.list_hook = <PyObject*>list_hook
+ init_ctx(&ctx, object_hook, object_pairs_hook, list_hook, use_list, encoding, unicode_errors)
ret = template_execute(&ctx, buf, buf_len, &off, 1)
if ret == 1:
obj = template_data(&ctx)
@@ -274,13 +289,14 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
def unpack(object stream, object object_hook=None, object list_hook=None,
bint use_list=1, encoding=None, unicode_errors="strict",
+ object_pairs_hook=None,
):
"""Unpack an object from `stream`.
Raises `ValueError` when `stream` has extra bytes.
"""
return unpackb(stream.read(), use_list=use_list,
- object_hook=object_hook, list_hook=list_hook,
+ object_hook=object_hook, object_pairs_hook=object_pairs_hook, list_hook=list_hook,
encoding=encoding, unicode_errors=unicode_errors,
)
@@ -300,7 +316,10 @@ cdef class Unpacker(object):
Otherwise, it is deserialized to Python tuple.
`object_hook` is same to simplejson. If it is not None, it should be callable
- and Unpacker calls it when deserializing key-value.
+ and Unpacker calls it with a dict argument after deserializing a map.
+
+ `object_pairs_hook` is same to simplejson. If it is not None, it should be callable
+ and Unpacker calls it with a list of key-value pairs after deserializing a map.
`encoding` is encoding used for decoding msgpack bytes. If it is None (default),
msgpack bytes is deserialized to Python bytes.
@@ -350,9 +369,8 @@ cdef class Unpacker(object):
self.buf = NULL
def __init__(self, file_like=None, Py_ssize_t read_size=0, bint use_list=1,
- object object_hook=None, object list_hook=None,
+ object object_hook=None, object object_pairs_hook=None, object list_hook=None,
encoding=None, unicode_errors='strict', int max_buffer_size=0,
- object object_pairs_hook=None,
):
self.file_like = file_like
if file_like:
@@ -373,31 +391,7 @@ cdef class Unpacker(object):
self.buf_size = read_size
self.buf_head = 0
self.buf_tail = 0
- template_init(&self.ctx)
- self.ctx.user.use_list = use_list
- self.ctx.user.object_hook = self.ctx.user.list_hook = <PyObject*>NULL
- if object_hook is not None:
- if not PyCallable_Check(object_hook):
- raise TypeError("object_hook must be a callable.")
- self.ctx.user.object_hook = <PyObject*>object_hook
- if list_hook is not None:
- if not PyCallable_Check(list_hook):
- raise TypeError("list_hook must be a callable.")
- self.ctx.user.list_hook = <PyObject*>list_hook
- if encoding is None:
- self.ctx.user.encoding = NULL
- self.ctx.user.unicode_errors = NULL
- else:
- if isinstance(encoding, unicode):
- self._bencoding = encoding.encode('ascii')
- else:
- self._bencoding = encoding
- self.ctx.user.encoding = PyBytes_AsString(self._bencoding)
- if isinstance(unicode_errors, unicode):
- self._berrors = unicode_errors.encode('ascii')
- else:
- self._berrors = unicode_errors
- self.ctx.user.unicode_errors = PyBytes_AsString(self._berrors)
+ init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook, use_list, encoding, unicode_errors)
def feed(self, object next_bytes):
cdef char* buf