@@ -13,6 +13,7 @@ cdef extern from "Python.h":
1313 int PyMemoryView_Check(object obj)
1414 int PyByteArray_Check(object obj)
1515 int PyByteArray_CheckExact(object obj)
16+ char * PyUnicode_AsUTF8AndSize(object obj, Py_ssize_t * l) except NULL
1617
1718
1819cdef extern from " pack.h" :
@@ -37,6 +38,7 @@ cdef extern from "pack.h":
3738 int msgpack_pack_bin(msgpack_packer* pk, size_t l)
3839 int msgpack_pack_raw_body(msgpack_packer* pk, char * body, size_t l)
3940 int msgpack_pack_ext(msgpack_packer* pk, char typecode, size_t l)
41+ int msgpack_pack_unicode(msgpack_packer* pk, object o, long long limit)
4042
4143cdef int DEFAULT_RECURSE_LIMIT= 511
4244cdef long long ITEM_LIMIT = (2 ** 32 )- 1
@@ -126,8 +128,12 @@ cdef class Packer(object):
126128 raise TypeError (" default must be a callable." )
127129 self ._default = default
128130 if encoding is None :
129- self .encoding = ' utf_8'
130- self .unicode_errors = NULL
131+ if unicode_errors is None :
132+ self .encoding = NULL
133+ self .unicode_errors = NULL
134+ else :
135+ self .encoding = " utf_8"
136+ self .unicode_errors = unicode_errors
131137 else :
132138 if isinstance (encoding, unicode ):
133139 self ._bencoding = encoding.encode(' ascii' )
@@ -140,6 +146,8 @@ cdef class Packer(object):
140146 self ._berrors = unicode_errors
141147 if self ._berrors is not None :
142148 self .unicode_errors = PyBytes_AsString(self ._berrors)
149+ else :
150+ self .unicode_errors = NULL
143151
144152 def __dealloc__ (self ):
145153 PyMem_Free(self .pk.buf)
@@ -206,17 +214,19 @@ cdef class Packer(object):
206214 if ret == 0 :
207215 ret = msgpack_pack_raw_body(& self .pk, rawval, L)
208216 elif PyUnicode_CheckExact(o) if strict_types else PyUnicode_Check(o):
209- if not self .encoding:
210- raise TypeError (" Can't encode unicode string: no encoding is specified" )
211- # TODO: Use faster API for UTF-8
212- o = PyUnicode_AsEncodedString(o, self .encoding, self .unicode_errors)
213- L = len (o)
214- if L > ITEM_LIMIT:
215- raise PackValueError(" unicode string is too large" )
216- rawval = o
217- ret = msgpack_pack_raw(& self .pk, L)
218- if ret == 0 :
219- ret = msgpack_pack_raw_body(& self .pk, rawval, L)
217+ if self .encoding == NULL :
218+ ret = msgpack_pack_unicode(& self .pk, o, ITEM_LIMIT);
219+ if ret == - 2 :
220+ raise PackValueError(" unicode string is too large" )
221+ else :
222+ o = PyUnicode_AsEncodedString(o, self .encoding, self .unicode_errors)
223+ L = len (o)
224+ if L > ITEM_LIMIT:
225+ raise PackValueError(" unicode string is too large" )
226+ ret = msgpack_pack_raw(& self .pk, L)
227+ if ret == 0 :
228+ rawval = o
229+ ret = msgpack_pack_raw_body(& self .pk, rawval, L)
220230 elif PyDict_CheckExact(o):
221231 d = < dict > o
222232 L = len (d)
0 commit comments