Add Packer.buffer() (#320)

This commit is contained in:
INADA Naoki 2018-11-09 20:55:13 +09:00 committed by GitHub
parent a8b3e97fe5
commit 9e210bfc1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 20 deletions

View file

@ -41,6 +41,9 @@ cdef extern from "pack.h":
int msgpack_pack_ext(msgpack_packer* pk, char typecode, size_t l)
int msgpack_pack_unicode(msgpack_packer* pk, object o, long long limit)
cdef extern from "buff_converter.h":
object buff_to_buff(char *, Py_ssize_t)
cdef int DEFAULT_RECURSE_LIMIT=511
cdef long long ITEM_LIMIT = (2**32)-1
@ -349,9 +352,16 @@ cdef class Packer(object):
return buf
def reset(self):
"""Clear internal buffer."""
"""Reset internal buffer.
This method is usaful only when autoreset=False.
"""
self.pk.length = 0
def bytes(self):
"""Return buffer content."""
"""Return internal buffer contents as bytes object"""
return PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
def getbuffer(self):
"""Return view of internal buffer."""
return buff_to_buff(self.pk.buf, self.pk.length)

28
msgpack/buff_converter.h Normal file
View file

@ -0,0 +1,28 @@
#include "Python.h"
/* cython does not support this preprocessor check => write it in raw C */
#if PY_MAJOR_VERSION == 2
static PyObject *
buff_to_buff(char *buff, Py_ssize_t size)
{
return PyBuffer_FromMemory(buff, size);
}
#elif (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION >= 3)
static PyObject *
buff_to_buff(char *buff, Py_ssize_t size)
{
return PyMemoryView_FromMemory(buff, size, PyBUF_READ);
}
#else
static PyObject *
buff_to_buff(char *buff, Py_ssize_t size)
{
Py_buffer pybuf;
if (PyBuffer_FillInfo(&pybuf, NULL, buff, size, 1, PyBUF_FULL_RO) == -1) {
return NULL;
}
return PyMemoryView_FromBuffer(&pybuf);
}
#endif

View file

@ -860,43 +860,35 @@ class Packer(object):
except:
self._buffer = StringIO() # force reset
raise
ret = self._buffer.getvalue()
if self._autoreset:
ret = self._buffer.getvalue()
self._buffer = StringIO()
elif USING_STRINGBUILDER:
self._buffer = StringIO(ret)
return ret
return ret
def pack_map_pairs(self, pairs):
self._pack_map_pairs(len(pairs), pairs)
ret = self._buffer.getvalue()
if self._autoreset:
ret = self._buffer.getvalue()
self._buffer = StringIO()
elif USING_STRINGBUILDER:
self._buffer = StringIO(ret)
return ret
return ret
def pack_array_header(self, n):
if n >= 2**32:
raise PackValueError
self._pack_array_header(n)
ret = self._buffer.getvalue()
if self._autoreset:
ret = self._buffer.getvalue()
self._buffer = StringIO()
elif USING_STRINGBUILDER:
self._buffer = StringIO(ret)
return ret
return ret
def pack_map_header(self, n):
if n >= 2**32:
raise PackValueError
self._pack_map_header(n)
ret = self._buffer.getvalue()
if self._autoreset:
ret = self._buffer.getvalue()
self._buffer = StringIO()
elif USING_STRINGBUILDER:
self._buffer = StringIO(ret)
return ret
return ret
def pack_ext_type(self, typecode, data):
if not isinstance(typecode, int):
@ -976,7 +968,19 @@ class Packer(object):
raise PackValueError('Bin is too large')
def bytes(self):
"""Return internal buffer contents as bytes object"""
return self._buffer.getvalue()
def reset(self):
"""Reset internal buffer.
This method is usaful only when autoreset=False.
"""
self._buffer = StringIO()
def getbuffer(self):
"""Return view of internal buffer."""
if USING_STRINGBUILDER or not PY3:
return memoryview(self.bytes())
else:
return self._buffer.getbuffer()