Skip to content

Commit a3b3700

Browse files
committed
support var length list encoding.
1 parent 8a23157 commit a3b3700

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

c/cbormodule.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ static Reader* NewObjectReader(PyObject* ob);
6060
static Reader* NewFileReader(PyObject* ob);
6161
#endif
6262

63+
// cache global VarList class object.
64+
static PyObject* g_varlist_class = NULL;
6365

6466
static PyObject* loads_tag(Reader* rin, uint64_t aux);
6567
static int loads_kv(PyObject* out, Reader* rin);
@@ -368,7 +370,7 @@ PyObject* inner_loads_c(Reader* rin, uint8_t c) {
368370
case CBOR_ARRAY:
369371
if (cbor_info == CBOR_VAR_FOLLOWS) {
370372
uint8_t sc;
371-
out = PyList_New(0);
373+
out = PyObject_CallObject(g_varlist_class, NULL);
372374
if (rin->read1(rin, &sc)) { logprintf("r1 fail in var array tag\n"); return NULL; }
373375
while (sc != CBOR_BREAK) {
374376
PyObject* subitem = inner_loads_c(rin, sc);
@@ -520,6 +522,21 @@ static PyObject* getCborTagClass(void) {
520522
return tag_class;
521523
}
522524

525+
// returns a PyObject for cbor.cbor.VarList
526+
// Returned PyObject* is a BORROWED reference from the module dict
527+
static PyObject* getCborVarListClass(void) {
528+
PyObject* cbor_module = PyImport_ImportModule("cbor.cbor");
529+
PyObject* moddict = PyModule_GetDict(cbor_module);
530+
PyObject* tag_class = PyDict_GetItemString(moddict, "VarList");
531+
// moddict and tag_class are 'borrowed reference'
532+
Py_DECREF(cbor_module);
533+
534+
return tag_class;
535+
}
536+
537+
static int VarList_Check(PyObject* o) {
538+
return PyObject_IsInstance(o, g_varlist_class);
539+
}
523540

524541
static PyObject* loads_tag(Reader* rin, uint64_t aux) {
525542
PyObject* out = NULL;
@@ -1180,6 +1197,18 @@ static int inner_dumps(EncodeOptions *optp, PyObject* ob, uint8_t* out, uintptr_
11801197
} else if (PyDict_Check(ob)) {
11811198
int err = dumps_dict(optp, ob, out, &pos);
11821199
if (err != 0) { return err; }
1200+
} else if (VarList_Check(ob)) {
1201+
Py_ssize_t i;
1202+
if (out != NULL) {
1203+
out[pos] = CBOR_ARRAY | CBOR_VAR_FOLLOWS;
1204+
}
1205+
pos++;
1206+
Py_ssize_t listlen = PyList_Size(ob);
1207+
for (i = 0; i < listlen; i++) {
1208+
int err = inner_dumps(optp, PyList_GetItem(ob, i), out, &pos);
1209+
if (err != 0) { return err; }
1210+
}
1211+
tag_aux_out(CBOR_BREAK, 0, out, &pos);
11831212
} else if (PyList_Check(ob)) {
11841213
Py_ssize_t i;
11851214
Py_ssize_t listlen = PyList_Size(ob);
@@ -1462,13 +1491,17 @@ static PyMethodDef CborMethods[] = {
14621491
PyMODINIT_FUNC
14631492
init_cbor(void)
14641493
{
1494+
g_varlist_class = getCborVarListClass();
1495+
14651496
(void) Py_InitModule("cbor._cbor", CborMethods);
14661497
}
14671498
#else
14681499
// Python 3
14691500
PyMODINIT_FUNC
14701501
PyInit__cbor(void)
14711502
{
1503+
g_varlist_class = getCborVarListClass();
1504+
14721505
static PyModuleDef modef = {
14731506
PyModuleDef_HEAD_INIT,
14741507
};

cbor/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# fall back to 100% python implementation
88
from .cbor import loads, dumps, load, dump
99

10-
from .cbor import Tag
10+
from .cbor import Tag, VarList
1111
from .tagmap import TagMapper, ClassTag, UnknownTagException
1212
from .VERSION import __doc__ as __version__
1313

cbor/cbor.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ def dumps_array(arr, sort_keys=False):
155155
return head + b''.join(parts)
156156

157157

158+
def dumps_var_array(arr, sort_keys=False):
159+
head = struct.pack('B', CBOR_ARRAY | CBOR_VAR_FOLLOWS)
160+
parts = [dumps(x, sort_keys=sort_keys) for x in arr]
161+
return head + b''.join(parts) + bytes([CBOR_BREAK])
162+
163+
158164
if _IS_PY3:
159165
def dumps_dict(d, sort_keys=False):
160166
head = _encode_type_num(CBOR_MAP, len(d))
@@ -207,13 +213,19 @@ def _is_intish(x):
207213
return isinstance(x, (int, long))
208214

209215

216+
class VarList(list):
217+
pass
218+
219+
210220
def dumps(ob, sort_keys=False):
211221
if ob is None:
212222
return struct.pack('B', CBOR_NULL)
213223
if isinstance(ob, bool):
214224
return dumps_bool(ob)
215225
if _is_stringish(ob):
216226
return dumps_string(ob)
227+
if isinstance(ob, VarList):
228+
return dumps_var_array(ob, sort_keys=sort_keys)
217229
if isinstance(ob, (list, tuple)):
218230
return dumps_array(ob, sort_keys=sort_keys)
219231
# TODO: accept other enumerables and emit a variable length array
@@ -312,7 +324,7 @@ def _read_byte(fp):
312324

313325

314326
def _loads_var_array(fp, limit, depth, returntags, bytes_read):
315-
ob = []
327+
ob = VarList()
316328
tb = _read_byte(fp)
317329
while tb != CBOR_BREAK:
318330
(subob, sub_len) = _loads_tb(fp, tb, limit, depth, returntags)

0 commit comments

Comments
 (0)