Add bin type support to pure Python packer.

This commit is contained in:
INADA Naoki 2013-10-17 08:52:59 +09:00
parent 171c538113
commit 84f6b10019
2 changed files with 25 additions and 9 deletions

View file

@ -429,11 +429,15 @@ class Packer(object):
:param bool autoreset: :param bool autoreset:
Reset buffer after each pack and return it's content as `bytes`. (default: True). Reset buffer after each pack and return it's content as `bytes`. (default: True).
If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.
:param bool use_bin_type:
Use bin type introduced in msgpack spec 2.0 for bytes.
It also enable str8 type for unicode.
""" """
def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
use_single_float=False, autoreset=True): use_single_float=False, autoreset=True, use_bin_type=False):
self._use_float = use_single_float self._use_float = use_single_float
self._autoreset = autoreset self._autoreset = autoreset
self._use_bin_type = use_bin_type
self._encoding = encoding self._encoding = encoding
self._unicode_errors = unicode_errors self._unicode_errors = unicode_errors
self._buffer = StringIO() self._buffer = StringIO()
@ -473,6 +477,17 @@ class Packer(object):
if -0x8000000000000000 <= obj < -0x80000000: if -0x8000000000000000 <= obj < -0x80000000:
return self._buffer.write(struct.pack(">Bq", 0xd3, obj)) return self._buffer.write(struct.pack(">Bq", 0xd3, obj))
raise PackValueError("Integer value out of range") raise PackValueError("Integer value out of range")
if self._use_bin_type and isinstance(obj, bytes):
n = len(obj)
if n <= 0xff:
self._buffer.write(struct.pack('>BB', 0xc4, n))
elif n <= 0xffff:
self._buffer.write(struct.pack(">BH", 0xc5, n))
elif n <= 0xffffffff:
self._buffer.write(struct.pack(">BI", 0xc6, n))
else:
raise PackValueError("Bytes is too large")
return self._buffer.write(obj)
if isinstance(obj, (Unicode, bytes)): if isinstance(obj, (Unicode, bytes)):
if isinstance(obj, Unicode): if isinstance(obj, Unicode):
if self._encoding is None: if self._encoding is None:
@ -483,19 +498,20 @@ class Packer(object):
n = len(obj) n = len(obj)
if n <= 0x1f: if n <= 0x1f:
self._buffer.write(struct.pack('B', 0xa0 + n)) self._buffer.write(struct.pack('B', 0xa0 + n))
return self._buffer.write(obj) elif self._use_bin_type and n <= 0xff:
if n <= 0xffff: self._buffer.write(struct.pack('>BB', 0xd9, n))
elif n <= 0xffff:
self._buffer.write(struct.pack(">BH", 0xda, n)) self._buffer.write(struct.pack(">BH", 0xda, n))
return self._buffer.write(obj) elif n <= 0xffffffff:
if n <= 0xffffffff:
self._buffer.write(struct.pack(">BI", 0xdb, n)) self._buffer.write(struct.pack(">BI", 0xdb, n))
return self._buffer.write(obj) else:
raise PackValueError("String is too large") raise PackValueError("String is too large")
return self._buffer.write(obj)
if isinstance(obj, float): if isinstance(obj, float):
if self._use_float: if self._use_float:
return self._buffer.write(struct.pack(">Bf", 0xca, obj)) return self._buffer.write(struct.pack(">Bf", 0xca, obj))
return self._buffer.write(struct.pack(">Bd", 0xcb, obj)) return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
if isinstance(obj, list) or isinstance(obj, tuple): if isinstance(obj, (list, tuple)):
n = len(obj) n = len(obj)
self._fb_pack_array_header(n) self._fb_pack_array_header(n)
for i in xrange(n): for i in xrange(n):

View file

@ -664,7 +664,7 @@ static inline int msgpack_pack_map(msgpack_packer* x, unsigned int n)
static inline int msgpack_pack_raw(msgpack_packer* x, size_t l) static inline int msgpack_pack_raw(msgpack_packer* x, size_t l)
{ {
if(l < 32) { if (l < 32) {
unsigned char d = 0xa0 | (uint8_t)l; unsigned char d = 0xa0 | (uint8_t)l;
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
} else if (x->use_bin_type && l < 256) { // str8 is new format introduced with bin. } else if (x->use_bin_type && l < 256) { // str8 is new format introduced with bin.