##// END OF EJS Templates
fsmonitor: handle unicode keys in tuples...
Gregory Szorc -
r43712:d359dfc1 stable
parent child Browse files
Show More
@@ -1,1252 +1,1267 b''
1 /*
1 /*
2 Copyright (c) 2013-2015, Facebook, Inc.
2 Copyright (c) 2013-2015, Facebook, Inc.
3 All rights reserved.
3 All rights reserved.
4
4
5 Redistribution and use in source and binary forms, with or without
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
6 modification, are permitted provided that the following conditions are met:
7
7
8 * Redistributions of source code must retain the above copyright notice,
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
9 this list of conditions and the following disclaimer.
10
10
11 * Redistributions in binary form must reproduce the above copyright notice,
11 * Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
13 and/or other materials provided with the distribution.
14
14
15 * Neither the name Facebook nor the names of its contributors may be used to
15 * Neither the name Facebook nor the names of its contributors may be used to
16 endorse or promote products derived from this software without specific
16 endorse or promote products derived from this software without specific
17 prior written permission.
17 prior written permission.
18
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
29 */
30
30
31 #include <Python.h>
31 #include <Python.h>
32 #include <bytesobject.h>
32 #include <bytesobject.h>
33 #ifdef _MSC_VER
33 #ifdef _MSC_VER
34 #define inline __inline
34 #define inline __inline
35 #if _MSC_VER >= 1800
35 #if _MSC_VER >= 1800
36 #include <stdint.h>
36 #include <stdint.h>
37 #else
37 #else
38 // The compiler associated with Python 2.7 on Windows doesn't ship
38 // The compiler associated with Python 2.7 on Windows doesn't ship
39 // with stdint.h, so define the small subset that we use here.
39 // with stdint.h, so define the small subset that we use here.
40 typedef __int8 int8_t;
40 typedef __int8 int8_t;
41 typedef __int16 int16_t;
41 typedef __int16 int16_t;
42 typedef __int32 int32_t;
42 typedef __int32 int32_t;
43 typedef __int64 int64_t;
43 typedef __int64 int64_t;
44 typedef unsigned __int8 uint8_t;
44 typedef unsigned __int8 uint8_t;
45 typedef unsigned __int16 uint16_t;
45 typedef unsigned __int16 uint16_t;
46 typedef unsigned __int32 uint32_t;
46 typedef unsigned __int32 uint32_t;
47 typedef unsigned __int64 uint64_t;
47 typedef unsigned __int64 uint64_t;
48 #define UINT32_MAX 4294967295U
48 #define UINT32_MAX 4294967295U
49 #endif
49 #endif
50 #endif
50 #endif
51
51
52 // clang-format off
52 // clang-format off
53 /* Return the smallest size int that can store the value */
53 /* Return the smallest size int that can store the value */
54 #define INT_SIZE(x) (((x) == ((int8_t)x)) ? 1 : \
54 #define INT_SIZE(x) (((x) == ((int8_t)x)) ? 1 : \
55 ((x) == ((int16_t)x)) ? 2 : \
55 ((x) == ((int16_t)x)) ? 2 : \
56 ((x) == ((int32_t)x)) ? 4 : 8)
56 ((x) == ((int32_t)x)) ? 4 : 8)
57
57
58 #define BSER_ARRAY 0x00
58 #define BSER_ARRAY 0x00
59 #define BSER_OBJECT 0x01
59 #define BSER_OBJECT 0x01
60 #define BSER_BYTESTRING 0x02
60 #define BSER_BYTESTRING 0x02
61 #define BSER_INT8 0x03
61 #define BSER_INT8 0x03
62 #define BSER_INT16 0x04
62 #define BSER_INT16 0x04
63 #define BSER_INT32 0x05
63 #define BSER_INT32 0x05
64 #define BSER_INT64 0x06
64 #define BSER_INT64 0x06
65 #define BSER_REAL 0x07
65 #define BSER_REAL 0x07
66 #define BSER_TRUE 0x08
66 #define BSER_TRUE 0x08
67 #define BSER_FALSE 0x09
67 #define BSER_FALSE 0x09
68 #define BSER_NULL 0x0a
68 #define BSER_NULL 0x0a
69 #define BSER_TEMPLATE 0x0b
69 #define BSER_TEMPLATE 0x0b
70 #define BSER_SKIP 0x0c
70 #define BSER_SKIP 0x0c
71 #define BSER_UTF8STRING 0x0d
71 #define BSER_UTF8STRING 0x0d
72 // clang-format on
72 // clang-format on
73
73
74 // An immutable object representation of BSER_OBJECT.
74 // An immutable object representation of BSER_OBJECT.
75 // Rather than build a hash table, key -> value are obtained
75 // Rather than build a hash table, key -> value are obtained
76 // by walking the list of keys to determine the offset into
76 // by walking the list of keys to determine the offset into
77 // the values array. The assumption is that the number of
77 // the values array. The assumption is that the number of
78 // array elements will be typically small (~6 for the top
78 // array elements will be typically small (~6 for the top
79 // level query result and typically 3-5 for the file entries)
79 // level query result and typically 3-5 for the file entries)
80 // so that the time overhead for this is small compared to
80 // so that the time overhead for this is small compared to
81 // using a proper hash table. Even with this simplistic
81 // using a proper hash table. Even with this simplistic
82 // approach, this is still faster for the mercurial use case
82 // approach, this is still faster for the mercurial use case
83 // as it helps to eliminate creating N other objects to
83 // as it helps to eliminate creating N other objects to
84 // represent the stat information in the hgwatchman extension
84 // represent the stat information in the hgwatchman extension
85 // clang-format off
85 // clang-format off
86 typedef struct {
86 typedef struct {
87 PyObject_HEAD
87 PyObject_HEAD
88 PyObject *keys; // tuple of field names
88 PyObject *keys; // tuple of field names
89 PyObject *values; // tuple of values
89 PyObject *values; // tuple of values
90 } bserObject;
90 } bserObject;
91 // clang-format on
91 // clang-format on
92
92
93 static Py_ssize_t bserobj_tuple_length(PyObject* o) {
93 static Py_ssize_t bserobj_tuple_length(PyObject* o) {
94 bserObject* obj = (bserObject*)o;
94 bserObject* obj = (bserObject*)o;
95
95
96 return PySequence_Length(obj->keys);
96 return PySequence_Length(obj->keys);
97 }
97 }
98
98
99 static PyObject* bserobj_tuple_item(PyObject* o, Py_ssize_t i) {
99 static PyObject* bserobj_tuple_item(PyObject* o, Py_ssize_t i) {
100 bserObject* obj = (bserObject*)o;
100 bserObject* obj = (bserObject*)o;
101
101
102 return PySequence_GetItem(obj->values, i);
102 return PySequence_GetItem(obj->values, i);
103 }
103 }
104
104
105 // clang-format off
105 // clang-format off
106 static PySequenceMethods bserobj_sq = {
106 static PySequenceMethods bserobj_sq = {
107 bserobj_tuple_length, /* sq_length */
107 bserobj_tuple_length, /* sq_length */
108 0, /* sq_concat */
108 0, /* sq_concat */
109 0, /* sq_repeat */
109 0, /* sq_repeat */
110 bserobj_tuple_item, /* sq_item */
110 bserobj_tuple_item, /* sq_item */
111 0, /* sq_ass_item */
111 0, /* sq_ass_item */
112 0, /* sq_contains */
112 0, /* sq_contains */
113 0, /* sq_inplace_concat */
113 0, /* sq_inplace_concat */
114 0 /* sq_inplace_repeat */
114 0 /* sq_inplace_repeat */
115 };
115 };
116 // clang-format on
116 // clang-format on
117
117
118 static void bserobj_dealloc(PyObject* o) {
118 static void bserobj_dealloc(PyObject* o) {
119 bserObject* obj = (bserObject*)o;
119 bserObject* obj = (bserObject*)o;
120
120
121 Py_CLEAR(obj->keys);
121 Py_CLEAR(obj->keys);
122 Py_CLEAR(obj->values);
122 Py_CLEAR(obj->values);
123 PyObject_Del(o);
123 PyObject_Del(o);
124 }
124 }
125
125
126 static PyObject* bserobj_getattrro(PyObject* o, PyObject* name) {
126 static PyObject* bserobj_getattrro(PyObject* o, PyObject* name) {
127 bserObject* obj = (bserObject*)o;
127 bserObject* obj = (bserObject*)o;
128 Py_ssize_t i, n;
128 Py_ssize_t i, n;
129 PyObject* name_bytes = NULL;
129 PyObject* name_bytes = NULL;
130 PyObject* ret = NULL;
130 PyObject* ret = NULL;
131 const char* namestr = NULL;
131 const char* namestr = NULL;
132
132
133 if (PyIndex_Check(name)) {
133 if (PyIndex_Check(name)) {
134 i = PyNumber_AsSsize_t(name, PyExc_IndexError);
134 i = PyNumber_AsSsize_t(name, PyExc_IndexError);
135 if (i == -1 && PyErr_Occurred()) {
135 if (i == -1 && PyErr_Occurred()) {
136 goto bail;
136 goto bail;
137 }
137 }
138
138
139 if (i == 8 && PySequence_Size(obj->values) < 9) {
139 if (i == 8 && PySequence_Size(obj->values) < 9) {
140 // Hack alert: Python 3 removed support for os.stat().st_mtime
140 // Hack alert: Python 3 removed support for os.stat().st_mtime
141 // being an integer.Instead, if you need an integer, you have to
141 // being an integer.Instead, if you need an integer, you have to
142 // use os.stat()[stat.ST_MTIME] instead. stat.ST_MTIME is 8, and
142 // use os.stat()[stat.ST_MTIME] instead. stat.ST_MTIME is 8, and
143 // our stat tuples are shorter than that, so we can detect
143 // our stat tuples are shorter than that, so we can detect
144 // requests for index 8 on tuples shorter than that and return
144 // requests for index 8 on tuples shorter than that and return
145 // st_mtime instead.
145 // st_mtime instead.
146 namestr = "st_mtime";
146 namestr = "st_mtime";
147 } else {
147 } else {
148 ret = PySequence_GetItem(obj->values, i);
148 ret = PySequence_GetItem(obj->values, i);
149 goto bail;
149 goto bail;
150 }
150 }
151 } else {
151 } else {
152 // We can be passed in Unicode objects here -- we don't support anything other
152 // We can be passed in Unicode objects here -- we don't support anything other
153 // than UTF-8 for keys.
153 // than UTF-8 for keys.
154 if (PyUnicode_Check(name)) {
154 if (PyUnicode_Check(name)) {
155 name_bytes = PyUnicode_AsUTF8String(name);
155 name_bytes = PyUnicode_AsUTF8String(name);
156 if (name_bytes == NULL) {
156 if (name_bytes == NULL) {
157 goto bail;
157 goto bail;
158 }
158 }
159 namestr = PyBytes_AsString(name_bytes);
159 namestr = PyBytes_AsString(name_bytes);
160 } else {
160 } else {
161 namestr = PyBytes_AsString(name);
161 namestr = PyBytes_AsString(name);
162 }
162 }
163 }
163 }
164
164
165 if (namestr == NULL) {
165 if (namestr == NULL) {
166 goto bail;
166 goto bail;
167 }
167 }
168 // hack^Wfeature to allow mercurial to use "st_size" to reference "size"
168 // hack^Wfeature to allow mercurial to use "st_size" to reference "size"
169 if (!strncmp(namestr, "st_", 3)) {
169 if (!strncmp(namestr, "st_", 3)) {
170 namestr += 3;
170 namestr += 3;
171 }
171 }
172
172
173 n = PyTuple_GET_SIZE(obj->keys);
173 n = PyTuple_GET_SIZE(obj->keys);
174 for (i = 0; i < n; i++) {
174 for (i = 0; i < n; i++) {
175 const char* item_name = NULL;
175 const char* item_name = NULL;
176 PyObject* key = PyTuple_GET_ITEM(obj->keys, i);
176 PyObject* key = PyTuple_GET_ITEM(obj->keys, i);
177
177
178 if (PyUnicode_Check(key)) {
179 #if PY_MAJOR_VERSION >= 3
180 item_name = PyUnicode_AsUTF8(key);
181 #else
182 PyObject* utf = PyUnicode_AsEncodedString(key, "utf-8", "ignore");
183 if (utf == NULL) {
184 goto bail;
185 }
186 item_name = PyBytes_AsString(utf);
187 #endif
188 } else {
178 item_name = PyBytes_AsString(key);
189 item_name = PyBytes_AsString(key);
190 }
191 if (item_name == NULL) {
192 goto bail;
193 }
179 if (!strcmp(item_name, namestr)) {
194 if (!strcmp(item_name, namestr)) {
180 ret = PySequence_GetItem(obj->values, i);
195 ret = PySequence_GetItem(obj->values, i);
181 goto bail;
196 goto bail;
182 }
197 }
183 }
198 }
184
199
185 PyErr_Format(
200 PyErr_Format(
186 PyExc_AttributeError, "bserobject has no attribute '%.400s'", namestr);
201 PyExc_AttributeError, "bserobject has no attribute '%.400s'", namestr);
187 bail:
202 bail:
188 Py_XDECREF(name_bytes);
203 Py_XDECREF(name_bytes);
189 return ret;
204 return ret;
190 }
205 }
191
206
192 // clang-format off
207 // clang-format off
193 static PyMappingMethods bserobj_map = {
208 static PyMappingMethods bserobj_map = {
194 bserobj_tuple_length, /* mp_length */
209 bserobj_tuple_length, /* mp_length */
195 bserobj_getattrro, /* mp_subscript */
210 bserobj_getattrro, /* mp_subscript */
196 0 /* mp_ass_subscript */
211 0 /* mp_ass_subscript */
197 };
212 };
198
213
199 PyTypeObject bserObjectType = {
214 PyTypeObject bserObjectType = {
200 PyVarObject_HEAD_INIT(NULL, 0)
215 PyVarObject_HEAD_INIT(NULL, 0)
201 "bserobj_tuple", /* tp_name */
216 "bserobj_tuple", /* tp_name */
202 sizeof(bserObject), /* tp_basicsize */
217 sizeof(bserObject), /* tp_basicsize */
203 0, /* tp_itemsize */
218 0, /* tp_itemsize */
204 bserobj_dealloc, /* tp_dealloc */
219 bserobj_dealloc, /* tp_dealloc */
205 0, /* tp_print */
220 0, /* tp_print */
206 0, /* tp_getattr */
221 0, /* tp_getattr */
207 0, /* tp_setattr */
222 0, /* tp_setattr */
208 0, /* tp_compare */
223 0, /* tp_compare */
209 0, /* tp_repr */
224 0, /* tp_repr */
210 0, /* tp_as_number */
225 0, /* tp_as_number */
211 &bserobj_sq, /* tp_as_sequence */
226 &bserobj_sq, /* tp_as_sequence */
212 &bserobj_map, /* tp_as_mapping */
227 &bserobj_map, /* tp_as_mapping */
213 0, /* tp_hash */
228 0, /* tp_hash */
214 0, /* tp_call */
229 0, /* tp_call */
215 0, /* tp_str */
230 0, /* tp_str */
216 bserobj_getattrro, /* tp_getattro */
231 bserobj_getattrro, /* tp_getattro */
217 0, /* tp_setattro */
232 0, /* tp_setattro */
218 0, /* tp_as_buffer */
233 0, /* tp_as_buffer */
219 Py_TPFLAGS_DEFAULT, /* tp_flags */
234 Py_TPFLAGS_DEFAULT, /* tp_flags */
220 "bserobj tuple", /* tp_doc */
235 "bserobj tuple", /* tp_doc */
221 0, /* tp_traverse */
236 0, /* tp_traverse */
222 0, /* tp_clear */
237 0, /* tp_clear */
223 0, /* tp_richcompare */
238 0, /* tp_richcompare */
224 0, /* tp_weaklistoffset */
239 0, /* tp_weaklistoffset */
225 0, /* tp_iter */
240 0, /* tp_iter */
226 0, /* tp_iternext */
241 0, /* tp_iternext */
227 0, /* tp_methods */
242 0, /* tp_methods */
228 0, /* tp_members */
243 0, /* tp_members */
229 0, /* tp_getset */
244 0, /* tp_getset */
230 0, /* tp_base */
245 0, /* tp_base */
231 0, /* tp_dict */
246 0, /* tp_dict */
232 0, /* tp_descr_get */
247 0, /* tp_descr_get */
233 0, /* tp_descr_set */
248 0, /* tp_descr_set */
234 0, /* tp_dictoffset */
249 0, /* tp_dictoffset */
235 0, /* tp_init */
250 0, /* tp_init */
236 0, /* tp_alloc */
251 0, /* tp_alloc */
237 0, /* tp_new */
252 0, /* tp_new */
238 };
253 };
239 // clang-format on
254 // clang-format on
240
255
241 typedef struct loads_ctx {
256 typedef struct loads_ctx {
242 int mutable;
257 int mutable;
243 const char* value_encoding;
258 const char* value_encoding;
244 const char* value_errors;
259 const char* value_errors;
245 uint32_t bser_version;
260 uint32_t bser_version;
246 uint32_t bser_capabilities;
261 uint32_t bser_capabilities;
247 } unser_ctx_t;
262 } unser_ctx_t;
248
263
249 static PyObject*
264 static PyObject*
250 bser_loads_recursive(const char** ptr, const char* end, const unser_ctx_t* ctx);
265 bser_loads_recursive(const char** ptr, const char* end, const unser_ctx_t* ctx);
251
266
252 static const char bser_true = BSER_TRUE;
267 static const char bser_true = BSER_TRUE;
253 static const char bser_false = BSER_FALSE;
268 static const char bser_false = BSER_FALSE;
254 static const char bser_null = BSER_NULL;
269 static const char bser_null = BSER_NULL;
255 static const char bser_bytestring_hdr = BSER_BYTESTRING;
270 static const char bser_bytestring_hdr = BSER_BYTESTRING;
256 static const char bser_array_hdr = BSER_ARRAY;
271 static const char bser_array_hdr = BSER_ARRAY;
257 static const char bser_object_hdr = BSER_OBJECT;
272 static const char bser_object_hdr = BSER_OBJECT;
258
273
259 static inline uint32_t next_power_2(uint32_t n) {
274 static inline uint32_t next_power_2(uint32_t n) {
260 n |= (n >> 16);
275 n |= (n >> 16);
261 n |= (n >> 8);
276 n |= (n >> 8);
262 n |= (n >> 4);
277 n |= (n >> 4);
263 n |= (n >> 2);
278 n |= (n >> 2);
264 n |= (n >> 1);
279 n |= (n >> 1);
265 return n + 1;
280 return n + 1;
266 }
281 }
267
282
268 // A buffer we use for building up the serialized result
283 // A buffer we use for building up the serialized result
269 struct bser_buffer {
284 struct bser_buffer {
270 char* buf;
285 char* buf;
271 int wpos, allocd;
286 int wpos, allocd;
272 uint32_t bser_version;
287 uint32_t bser_version;
273 uint32_t capabilities;
288 uint32_t capabilities;
274 };
289 };
275 typedef struct bser_buffer bser_t;
290 typedef struct bser_buffer bser_t;
276
291
277 static int bser_append(bser_t* bser, const char* data, uint32_t len) {
292 static int bser_append(bser_t* bser, const char* data, uint32_t len) {
278 int newlen = next_power_2(bser->wpos + len);
293 int newlen = next_power_2(bser->wpos + len);
279 if (newlen > bser->allocd) {
294 if (newlen > bser->allocd) {
280 char* nbuf = realloc(bser->buf, newlen);
295 char* nbuf = realloc(bser->buf, newlen);
281 if (!nbuf) {
296 if (!nbuf) {
282 return 0;
297 return 0;
283 }
298 }
284
299
285 bser->buf = nbuf;
300 bser->buf = nbuf;
286 bser->allocd = newlen;
301 bser->allocd = newlen;
287 }
302 }
288
303
289 memcpy(bser->buf + bser->wpos, data, len);
304 memcpy(bser->buf + bser->wpos, data, len);
290 bser->wpos += len;
305 bser->wpos += len;
291 return 1;
306 return 1;
292 }
307 }
293
308
294 static int bser_init(bser_t* bser, uint32_t version, uint32_t capabilities) {
309 static int bser_init(bser_t* bser, uint32_t version, uint32_t capabilities) {
295 bser->allocd = 8192;
310 bser->allocd = 8192;
296 bser->wpos = 0;
311 bser->wpos = 0;
297 bser->buf = malloc(bser->allocd);
312 bser->buf = malloc(bser->allocd);
298 bser->bser_version = version;
313 bser->bser_version = version;
299 bser->capabilities = capabilities;
314 bser->capabilities = capabilities;
300 if (!bser->buf) {
315 if (!bser->buf) {
301 return 0;
316 return 0;
302 }
317 }
303
318
304 // Leave room for the serialization header, which includes
319 // Leave room for the serialization header, which includes
305 // our overall length. To make things simpler, we'll use an
320 // our overall length. To make things simpler, we'll use an
306 // int32 for the header
321 // int32 for the header
307 #define EMPTY_HEADER "\x00\x01\x05\x00\x00\x00\x00"
322 #define EMPTY_HEADER "\x00\x01\x05\x00\x00\x00\x00"
308
323
309 // Version 2 also carries an integer indicating the capabilities. The
324 // Version 2 also carries an integer indicating the capabilities. The
310 // capabilities integer comes before the PDU size.
325 // capabilities integer comes before the PDU size.
311 #define EMPTY_HEADER_V2 "\x00\x02\x00\x00\x00\x00\x05\x00\x00\x00\x00"
326 #define EMPTY_HEADER_V2 "\x00\x02\x00\x00\x00\x00\x05\x00\x00\x00\x00"
312 if (version == 2) {
327 if (version == 2) {
313 bser_append(bser, EMPTY_HEADER_V2, sizeof(EMPTY_HEADER_V2) - 1);
328 bser_append(bser, EMPTY_HEADER_V2, sizeof(EMPTY_HEADER_V2) - 1);
314 } else {
329 } else {
315 bser_append(bser, EMPTY_HEADER, sizeof(EMPTY_HEADER) - 1);
330 bser_append(bser, EMPTY_HEADER, sizeof(EMPTY_HEADER) - 1);
316 }
331 }
317
332
318 return 1;
333 return 1;
319 }
334 }
320
335
321 static void bser_dtor(bser_t* bser) {
336 static void bser_dtor(bser_t* bser) {
322 free(bser->buf);
337 free(bser->buf);
323 bser->buf = NULL;
338 bser->buf = NULL;
324 }
339 }
325
340
326 static int bser_long(bser_t* bser, int64_t val) {
341 static int bser_long(bser_t* bser, int64_t val) {
327 int8_t i8;
342 int8_t i8;
328 int16_t i16;
343 int16_t i16;
329 int32_t i32;
344 int32_t i32;
330 int64_t i64;
345 int64_t i64;
331 char sz;
346 char sz;
332 int size = INT_SIZE(val);
347 int size = INT_SIZE(val);
333 char* iptr;
348 char* iptr;
334
349
335 switch (size) {
350 switch (size) {
336 case 1:
351 case 1:
337 sz = BSER_INT8;
352 sz = BSER_INT8;
338 i8 = (int8_t)val;
353 i8 = (int8_t)val;
339 iptr = (char*)&i8;
354 iptr = (char*)&i8;
340 break;
355 break;
341 case 2:
356 case 2:
342 sz = BSER_INT16;
357 sz = BSER_INT16;
343 i16 = (int16_t)val;
358 i16 = (int16_t)val;
344 iptr = (char*)&i16;
359 iptr = (char*)&i16;
345 break;
360 break;
346 case 4:
361 case 4:
347 sz = BSER_INT32;
362 sz = BSER_INT32;
348 i32 = (int32_t)val;
363 i32 = (int32_t)val;
349 iptr = (char*)&i32;
364 iptr = (char*)&i32;
350 break;
365 break;
351 case 8:
366 case 8:
352 sz = BSER_INT64;
367 sz = BSER_INT64;
353 i64 = (int64_t)val;
368 i64 = (int64_t)val;
354 iptr = (char*)&i64;
369 iptr = (char*)&i64;
355 break;
370 break;
356 default:
371 default:
357 PyErr_SetString(PyExc_RuntimeError, "Cannot represent this long value!?");
372 PyErr_SetString(PyExc_RuntimeError, "Cannot represent this long value!?");
358 return 0;
373 return 0;
359 }
374 }
360
375
361 if (!bser_append(bser, &sz, sizeof(sz))) {
376 if (!bser_append(bser, &sz, sizeof(sz))) {
362 return 0;
377 return 0;
363 }
378 }
364
379
365 return bser_append(bser, iptr, size);
380 return bser_append(bser, iptr, size);
366 }
381 }
367
382
368 static int bser_bytestring(bser_t* bser, PyObject* sval) {
383 static int bser_bytestring(bser_t* bser, PyObject* sval) {
369 char* buf = NULL;
384 char* buf = NULL;
370 Py_ssize_t len;
385 Py_ssize_t len;
371 int res;
386 int res;
372 PyObject* utf = NULL;
387 PyObject* utf = NULL;
373
388
374 if (PyUnicode_Check(sval)) {
389 if (PyUnicode_Check(sval)) {
375 utf = PyUnicode_AsEncodedString(sval, "utf-8", "ignore");
390 utf = PyUnicode_AsEncodedString(sval, "utf-8", "ignore");
376 sval = utf;
391 sval = utf;
377 }
392 }
378
393
379 res = PyBytes_AsStringAndSize(sval, &buf, &len);
394 res = PyBytes_AsStringAndSize(sval, &buf, &len);
380 if (res == -1) {
395 if (res == -1) {
381 res = 0;
396 res = 0;
382 goto out;
397 goto out;
383 }
398 }
384
399
385 if (!bser_append(bser, &bser_bytestring_hdr, sizeof(bser_bytestring_hdr))) {
400 if (!bser_append(bser, &bser_bytestring_hdr, sizeof(bser_bytestring_hdr))) {
386 res = 0;
401 res = 0;
387 goto out;
402 goto out;
388 }
403 }
389
404
390 if (!bser_long(bser, len)) {
405 if (!bser_long(bser, len)) {
391 res = 0;
406 res = 0;
392 goto out;
407 goto out;
393 }
408 }
394
409
395 if (len > UINT32_MAX) {
410 if (len > UINT32_MAX) {
396 PyErr_Format(PyExc_ValueError, "string too big");
411 PyErr_Format(PyExc_ValueError, "string too big");
397 res = 0;
412 res = 0;
398 goto out;
413 goto out;
399 }
414 }
400
415
401 res = bser_append(bser, buf, (uint32_t)len);
416 res = bser_append(bser, buf, (uint32_t)len);
402
417
403 out:
418 out:
404 if (utf) {
419 if (utf) {
405 Py_DECREF(utf);
420 Py_DECREF(utf);
406 }
421 }
407
422
408 return res;
423 return res;
409 }
424 }
410
425
411 static int bser_recursive(bser_t* bser, PyObject* val) {
426 static int bser_recursive(bser_t* bser, PyObject* val) {
412 if (PyBool_Check(val)) {
427 if (PyBool_Check(val)) {
413 if (val == Py_True) {
428 if (val == Py_True) {
414 return bser_append(bser, &bser_true, sizeof(bser_true));
429 return bser_append(bser, &bser_true, sizeof(bser_true));
415 }
430 }
416 return bser_append(bser, &bser_false, sizeof(bser_false));
431 return bser_append(bser, &bser_false, sizeof(bser_false));
417 }
432 }
418
433
419 if (val == Py_None) {
434 if (val == Py_None) {
420 return bser_append(bser, &bser_null, sizeof(bser_null));
435 return bser_append(bser, &bser_null, sizeof(bser_null));
421 }
436 }
422
437
423 // Python 3 has one integer type.
438 // Python 3 has one integer type.
424 #if PY_MAJOR_VERSION < 3
439 #if PY_MAJOR_VERSION < 3
425 if (PyInt_Check(val)) {
440 if (PyInt_Check(val)) {
426 return bser_long(bser, PyInt_AS_LONG(val));
441 return bser_long(bser, PyInt_AS_LONG(val));
427 }
442 }
428 #endif // PY_MAJOR_VERSION < 3
443 #endif // PY_MAJOR_VERSION < 3
429
444
430 if (PyLong_Check(val)) {
445 if (PyLong_Check(val)) {
431 return bser_long(bser, PyLong_AsLongLong(val));
446 return bser_long(bser, PyLong_AsLongLong(val));
432 }
447 }
433
448
434 if (PyBytes_Check(val) || PyUnicode_Check(val)) {
449 if (PyBytes_Check(val) || PyUnicode_Check(val)) {
435 return bser_bytestring(bser, val);
450 return bser_bytestring(bser, val);
436 }
451 }
437
452
438 if (PyFloat_Check(val)) {
453 if (PyFloat_Check(val)) {
439 double dval = PyFloat_AS_DOUBLE(val);
454 double dval = PyFloat_AS_DOUBLE(val);
440 char sz = BSER_REAL;
455 char sz = BSER_REAL;
441
456
442 if (!bser_append(bser, &sz, sizeof(sz))) {
457 if (!bser_append(bser, &sz, sizeof(sz))) {
443 return 0;
458 return 0;
444 }
459 }
445
460
446 return bser_append(bser, (char*)&dval, sizeof(dval));
461 return bser_append(bser, (char*)&dval, sizeof(dval));
447 }
462 }
448
463
449 if (PyList_Check(val)) {
464 if (PyList_Check(val)) {
450 Py_ssize_t i, len = PyList_GET_SIZE(val);
465 Py_ssize_t i, len = PyList_GET_SIZE(val);
451
466
452 if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
467 if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
453 return 0;
468 return 0;
454 }
469 }
455
470
456 if (!bser_long(bser, len)) {
471 if (!bser_long(bser, len)) {
457 return 0;
472 return 0;
458 }
473 }
459
474
460 for (i = 0; i < len; i++) {
475 for (i = 0; i < len; i++) {
461 PyObject* ele = PyList_GET_ITEM(val, i);
476 PyObject* ele = PyList_GET_ITEM(val, i);
462
477
463 if (!bser_recursive(bser, ele)) {
478 if (!bser_recursive(bser, ele)) {
464 return 0;
479 return 0;
465 }
480 }
466 }
481 }
467
482
468 return 1;
483 return 1;
469 }
484 }
470
485
471 if (PyTuple_Check(val)) {
486 if (PyTuple_Check(val)) {
472 Py_ssize_t i, len = PyTuple_GET_SIZE(val);
487 Py_ssize_t i, len = PyTuple_GET_SIZE(val);
473
488
474 if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
489 if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
475 return 0;
490 return 0;
476 }
491 }
477
492
478 if (!bser_long(bser, len)) {
493 if (!bser_long(bser, len)) {
479 return 0;
494 return 0;
480 }
495 }
481
496
482 for (i = 0; i < len; i++) {
497 for (i = 0; i < len; i++) {
483 PyObject* ele = PyTuple_GET_ITEM(val, i);
498 PyObject* ele = PyTuple_GET_ITEM(val, i);
484
499
485 if (!bser_recursive(bser, ele)) {
500 if (!bser_recursive(bser, ele)) {
486 return 0;
501 return 0;
487 }
502 }
488 }
503 }
489
504
490 return 1;
505 return 1;
491 }
506 }
492
507
493 if (PyMapping_Check(val)) {
508 if (PyMapping_Check(val)) {
494 Py_ssize_t len = PyMapping_Length(val);
509 Py_ssize_t len = PyMapping_Length(val);
495 Py_ssize_t pos = 0;
510 Py_ssize_t pos = 0;
496 PyObject *key, *ele;
511 PyObject *key, *ele;
497
512
498 if (!bser_append(bser, &bser_object_hdr, sizeof(bser_object_hdr))) {
513 if (!bser_append(bser, &bser_object_hdr, sizeof(bser_object_hdr))) {
499 return 0;
514 return 0;
500 }
515 }
501
516
502 if (!bser_long(bser, len)) {
517 if (!bser_long(bser, len)) {
503 return 0;
518 return 0;
504 }
519 }
505
520
506 while (PyDict_Next(val, &pos, &key, &ele)) {
521 while (PyDict_Next(val, &pos, &key, &ele)) {
507 if (!bser_bytestring(bser, key)) {
522 if (!bser_bytestring(bser, key)) {
508 return 0;
523 return 0;
509 }
524 }
510 if (!bser_recursive(bser, ele)) {
525 if (!bser_recursive(bser, ele)) {
511 return 0;
526 return 0;
512 }
527 }
513 }
528 }
514
529
515 return 1;
530 return 1;
516 }
531 }
517
532
518 PyErr_SetString(PyExc_ValueError, "Unsupported value type");
533 PyErr_SetString(PyExc_ValueError, "Unsupported value type");
519 return 0;
534 return 0;
520 }
535 }
521
536
522 static PyObject* bser_dumps(PyObject* self, PyObject* args, PyObject* kw) {
537 static PyObject* bser_dumps(PyObject* self, PyObject* args, PyObject* kw) {
523 PyObject *val = NULL, *res;
538 PyObject *val = NULL, *res;
524 bser_t bser;
539 bser_t bser;
525 uint32_t len, bser_version = 1, bser_capabilities = 0;
540 uint32_t len, bser_version = 1, bser_capabilities = 0;
526
541
527 static char* kw_list[] = {"val", "version", "capabilities", NULL};
542 static char* kw_list[] = {"val", "version", "capabilities", NULL};
528
543
529 if (!PyArg_ParseTupleAndKeywords(
544 if (!PyArg_ParseTupleAndKeywords(
530 args,
545 args,
531 kw,
546 kw,
532 "O|ii:dumps",
547 "O|ii:dumps",
533 kw_list,
548 kw_list,
534 &val,
549 &val,
535 &bser_version,
550 &bser_version,
536 &bser_capabilities)) {
551 &bser_capabilities)) {
537 return NULL;
552 return NULL;
538 }
553 }
539
554
540 if (!bser_init(&bser, bser_version, bser_capabilities)) {
555 if (!bser_init(&bser, bser_version, bser_capabilities)) {
541 return PyErr_NoMemory();
556 return PyErr_NoMemory();
542 }
557 }
543
558
544 if (!bser_recursive(&bser, val)) {
559 if (!bser_recursive(&bser, val)) {
545 bser_dtor(&bser);
560 bser_dtor(&bser);
546 if (errno == ENOMEM) {
561 if (errno == ENOMEM) {
547 return PyErr_NoMemory();
562 return PyErr_NoMemory();
548 }
563 }
549 // otherwise, we've already set the error to something reasonable
564 // otherwise, we've already set the error to something reasonable
550 return NULL;
565 return NULL;
551 }
566 }
552
567
553 // Now fill in the overall length
568 // Now fill in the overall length
554 if (bser_version == 1) {
569 if (bser_version == 1) {
555 len = bser.wpos - (sizeof(EMPTY_HEADER) - 1);
570 len = bser.wpos - (sizeof(EMPTY_HEADER) - 1);
556 memcpy(bser.buf + 3, &len, sizeof(len));
571 memcpy(bser.buf + 3, &len, sizeof(len));
557 } else {
572 } else {
558 len = bser.wpos - (sizeof(EMPTY_HEADER_V2) - 1);
573 len = bser.wpos - (sizeof(EMPTY_HEADER_V2) - 1);
559 // The BSER capabilities block comes before the PDU length
574 // The BSER capabilities block comes before the PDU length
560 memcpy(bser.buf + 2, &bser_capabilities, sizeof(bser_capabilities));
575 memcpy(bser.buf + 2, &bser_capabilities, sizeof(bser_capabilities));
561 memcpy(bser.buf + 7, &len, sizeof(len));
576 memcpy(bser.buf + 7, &len, sizeof(len));
562 }
577 }
563
578
564 res = PyBytes_FromStringAndSize(bser.buf, bser.wpos);
579 res = PyBytes_FromStringAndSize(bser.buf, bser.wpos);
565 bser_dtor(&bser);
580 bser_dtor(&bser);
566
581
567 return res;
582 return res;
568 }
583 }
569
584
570 int bunser_int(const char** ptr, const char* end, int64_t* val) {
585 int bunser_int(const char** ptr, const char* end, int64_t* val) {
571 int needed;
586 int needed;
572 const char* buf = *ptr;
587 const char* buf = *ptr;
573 int8_t i8;
588 int8_t i8;
574 int16_t i16;
589 int16_t i16;
575 int32_t i32;
590 int32_t i32;
576 int64_t i64;
591 int64_t i64;
577
592
578 switch (buf[0]) {
593 switch (buf[0]) {
579 case BSER_INT8:
594 case BSER_INT8:
580 needed = 2;
595 needed = 2;
581 break;
596 break;
582 case BSER_INT16:
597 case BSER_INT16:
583 needed = 3;
598 needed = 3;
584 break;
599 break;
585 case BSER_INT32:
600 case BSER_INT32:
586 needed = 5;
601 needed = 5;
587 break;
602 break;
588 case BSER_INT64:
603 case BSER_INT64:
589 needed = 9;
604 needed = 9;
590 break;
605 break;
591 default:
606 default:
592 PyErr_Format(
607 PyErr_Format(
593 PyExc_ValueError, "invalid bser int encoding 0x%02x", buf[0]);
608 PyExc_ValueError, "invalid bser int encoding 0x%02x", buf[0]);
594 return 0;
609 return 0;
595 }
610 }
596 if (end - buf < needed) {
611 if (end - buf < needed) {
597 PyErr_SetString(PyExc_ValueError, "input buffer to small for int encoding");
612 PyErr_SetString(PyExc_ValueError, "input buffer to small for int encoding");
598 return 0;
613 return 0;
599 }
614 }
600 *ptr = buf + needed;
615 *ptr = buf + needed;
601 switch (buf[0]) {
616 switch (buf[0]) {
602 case BSER_INT8:
617 case BSER_INT8:
603 memcpy(&i8, buf + 1, sizeof(i8));
618 memcpy(&i8, buf + 1, sizeof(i8));
604 *val = i8;
619 *val = i8;
605 return 1;
620 return 1;
606 case BSER_INT16:
621 case BSER_INT16:
607 memcpy(&i16, buf + 1, sizeof(i16));
622 memcpy(&i16, buf + 1, sizeof(i16));
608 *val = i16;
623 *val = i16;
609 return 1;
624 return 1;
610 case BSER_INT32:
625 case BSER_INT32:
611 memcpy(&i32, buf + 1, sizeof(i32));
626 memcpy(&i32, buf + 1, sizeof(i32));
612 *val = i32;
627 *val = i32;
613 return 1;
628 return 1;
614 case BSER_INT64:
629 case BSER_INT64:
615 memcpy(&i64, buf + 1, sizeof(i64));
630 memcpy(&i64, buf + 1, sizeof(i64));
616 *val = i64;
631 *val = i64;
617 return 1;
632 return 1;
618 default:
633 default:
619 return 0;
634 return 0;
620 }
635 }
621 }
636 }
622
637
623 static int bunser_bytestring(
638 static int bunser_bytestring(
624 const char** ptr,
639 const char** ptr,
625 const char* end,
640 const char* end,
626 const char** start,
641 const char** start,
627 int64_t* len) {
642 int64_t* len) {
628 const char* buf = *ptr;
643 const char* buf = *ptr;
629
644
630 // skip string marker
645 // skip string marker
631 buf++;
646 buf++;
632 if (!bunser_int(&buf, end, len)) {
647 if (!bunser_int(&buf, end, len)) {
633 return 0;
648 return 0;
634 }
649 }
635
650
636 if (buf + *len > end) {
651 if (buf + *len > end) {
637 PyErr_Format(PyExc_ValueError, "invalid string length in bser data");
652 PyErr_Format(PyExc_ValueError, "invalid string length in bser data");
638 return 0;
653 return 0;
639 }
654 }
640
655
641 *ptr = buf + *len;
656 *ptr = buf + *len;
642 *start = buf;
657 *start = buf;
643 return 1;
658 return 1;
644 }
659 }
645
660
646 static PyObject*
661 static PyObject*
647 bunser_array(const char** ptr, const char* end, const unser_ctx_t* ctx) {
662 bunser_array(const char** ptr, const char* end, const unser_ctx_t* ctx) {
648 const char* buf = *ptr;
663 const char* buf = *ptr;
649 int64_t nitems, i;
664 int64_t nitems, i;
650 int mutable = ctx->mutable;
665 int mutable = ctx->mutable;
651 PyObject* res;
666 PyObject* res;
652
667
653 // skip array header
668 // skip array header
654 buf++;
669 buf++;
655 if (!bunser_int(&buf, end, &nitems)) {
670 if (!bunser_int(&buf, end, &nitems)) {
656 return 0;
671 return 0;
657 }
672 }
658 *ptr = buf;
673 *ptr = buf;
659
674
660 if (nitems > LONG_MAX) {
675 if (nitems > LONG_MAX) {
661 PyErr_Format(PyExc_ValueError, "too many items for python array");
676 PyErr_Format(PyExc_ValueError, "too many items for python array");
662 return NULL;
677 return NULL;
663 }
678 }
664
679
665 if (mutable) {
680 if (mutable) {
666 res = PyList_New((Py_ssize_t)nitems);
681 res = PyList_New((Py_ssize_t)nitems);
667 } else {
682 } else {
668 res = PyTuple_New((Py_ssize_t)nitems);
683 res = PyTuple_New((Py_ssize_t)nitems);
669 }
684 }
670
685
671 for (i = 0; i < nitems; i++) {
686 for (i = 0; i < nitems; i++) {
672 PyObject* ele = bser_loads_recursive(ptr, end, ctx);
687 PyObject* ele = bser_loads_recursive(ptr, end, ctx);
673
688
674 if (!ele) {
689 if (!ele) {
675 Py_DECREF(res);
690 Py_DECREF(res);
676 return NULL;
691 return NULL;
677 }
692 }
678
693
679 if (mutable) {
694 if (mutable) {
680 PyList_SET_ITEM(res, i, ele);
695 PyList_SET_ITEM(res, i, ele);
681 } else {
696 } else {
682 PyTuple_SET_ITEM(res, i, ele);
697 PyTuple_SET_ITEM(res, i, ele);
683 }
698 }
684 // DECREF(ele) not required as SET_ITEM steals the ref
699 // DECREF(ele) not required as SET_ITEM steals the ref
685 }
700 }
686
701
687 return res;
702 return res;
688 }
703 }
689
704
690 static PyObject*
705 static PyObject*
691 bunser_object(const char** ptr, const char* end, const unser_ctx_t* ctx) {
706 bunser_object(const char** ptr, const char* end, const unser_ctx_t* ctx) {
692 const char* buf = *ptr;
707 const char* buf = *ptr;
693 int64_t nitems, i;
708 int64_t nitems, i;
694 int mutable = ctx->mutable;
709 int mutable = ctx->mutable;
695 PyObject* res;
710 PyObject* res;
696 bserObject* obj;
711 bserObject* obj;
697
712
698 // skip array header
713 // skip array header
699 buf++;
714 buf++;
700 if (!bunser_int(&buf, end, &nitems)) {
715 if (!bunser_int(&buf, end, &nitems)) {
701 return 0;
716 return 0;
702 }
717 }
703 *ptr = buf;
718 *ptr = buf;
704
719
705 if (mutable) {
720 if (mutable) {
706 res = PyDict_New();
721 res = PyDict_New();
707 } else {
722 } else {
708 obj = PyObject_New(bserObject, &bserObjectType);
723 obj = PyObject_New(bserObject, &bserObjectType);
709 obj->keys = PyTuple_New((Py_ssize_t)nitems);
724 obj->keys = PyTuple_New((Py_ssize_t)nitems);
710 obj->values = PyTuple_New((Py_ssize_t)nitems);
725 obj->values = PyTuple_New((Py_ssize_t)nitems);
711 res = (PyObject*)obj;
726 res = (PyObject*)obj;
712 }
727 }
713
728
714 for (i = 0; i < nitems; i++) {
729 for (i = 0; i < nitems; i++) {
715 const char* keystr;
730 const char* keystr;
716 int64_t keylen;
731 int64_t keylen;
717 PyObject* key;
732 PyObject* key;
718 PyObject* ele;
733 PyObject* ele;
719
734
720 if (!bunser_bytestring(ptr, end, &keystr, &keylen)) {
735 if (!bunser_bytestring(ptr, end, &keystr, &keylen)) {
721 Py_DECREF(res);
736 Py_DECREF(res);
722 return NULL;
737 return NULL;
723 }
738 }
724
739
725 if (keylen > LONG_MAX) {
740 if (keylen > LONG_MAX) {
726 PyErr_Format(PyExc_ValueError, "string too big for python");
741 PyErr_Format(PyExc_ValueError, "string too big for python");
727 Py_DECREF(res);
742 Py_DECREF(res);
728 return NULL;
743 return NULL;
729 }
744 }
730
745
731 if (mutable) {
746 if (mutable) {
732 // This will interpret the key as UTF-8.
747 // This will interpret the key as UTF-8.
733 key = PyUnicode_FromStringAndSize(keystr, (Py_ssize_t)keylen);
748 key = PyUnicode_FromStringAndSize(keystr, (Py_ssize_t)keylen);
734 } else {
749 } else {
735 // For immutable objects we'll manage key lookups, so we can avoid going
750 // For immutable objects we'll manage key lookups, so we can avoid going
736 // through the Unicode APIs. This avoids a potentially expensive and
751 // through the Unicode APIs. This avoids a potentially expensive and
737 // definitely unnecessary conversion to UTF-16 and back for Python 2.
752 // definitely unnecessary conversion to UTF-16 and back for Python 2.
738 // TODO: On Python 3 the Unicode APIs are smarter: we might be able to use
753 // TODO: On Python 3 the Unicode APIs are smarter: we might be able to use
739 // Unicode keys there without an appreciable performance loss.
754 // Unicode keys there without an appreciable performance loss.
740 key = PyBytes_FromStringAndSize(keystr, (Py_ssize_t)keylen);
755 key = PyBytes_FromStringAndSize(keystr, (Py_ssize_t)keylen);
741 }
756 }
742
757
743 if (!key) {
758 if (!key) {
744 Py_DECREF(res);
759 Py_DECREF(res);
745 return NULL;
760 return NULL;
746 }
761 }
747
762
748 ele = bser_loads_recursive(ptr, end, ctx);
763 ele = bser_loads_recursive(ptr, end, ctx);
749
764
750 if (!ele) {
765 if (!ele) {
751 Py_DECREF(key);
766 Py_DECREF(key);
752 Py_DECREF(res);
767 Py_DECREF(res);
753 return NULL;
768 return NULL;
754 }
769 }
755
770
756 if (mutable) {
771 if (mutable) {
757 PyDict_SetItem(res, key, ele);
772 PyDict_SetItem(res, key, ele);
758 Py_DECREF(key);
773 Py_DECREF(key);
759 Py_DECREF(ele);
774 Py_DECREF(ele);
760 } else {
775 } else {
761 /* PyTuple_SET_ITEM steals ele, key */
776 /* PyTuple_SET_ITEM steals ele, key */
762 PyTuple_SET_ITEM(obj->values, i, ele);
777 PyTuple_SET_ITEM(obj->values, i, ele);
763 PyTuple_SET_ITEM(obj->keys, i, key);
778 PyTuple_SET_ITEM(obj->keys, i, key);
764 }
779 }
765 }
780 }
766
781
767 return res;
782 return res;
768 }
783 }
769
784
770 static PyObject*
785 static PyObject*
771 bunser_template(const char** ptr, const char* end, const unser_ctx_t* ctx) {
786 bunser_template(const char** ptr, const char* end, const unser_ctx_t* ctx) {
772 const char* buf = *ptr;
787 const char* buf = *ptr;
773 int64_t nitems, i;
788 int64_t nitems, i;
774 int mutable = ctx->mutable;
789 int mutable = ctx->mutable;
775 PyObject* arrval;
790 PyObject* arrval;
776 PyObject* keys;
791 PyObject* keys;
777 Py_ssize_t numkeys, keyidx;
792 Py_ssize_t numkeys, keyidx;
778 unser_ctx_t keys_ctx = {0};
793 unser_ctx_t keys_ctx = {0};
779 if (mutable) {
794 if (mutable) {
780 keys_ctx.mutable = 1;
795 keys_ctx.mutable = 1;
781 // Decode keys as UTF-8 in this case.
796 // Decode keys as UTF-8 in this case.
782 keys_ctx.value_encoding = "utf-8";
797 keys_ctx.value_encoding = "utf-8";
783 keys_ctx.value_errors = "strict";
798 keys_ctx.value_errors = "strict";
784 } else {
799 } else {
785 // Treat keys as bytestrings in this case -- we'll do Unicode conversions at
800 // Treat keys as bytestrings in this case -- we'll do Unicode conversions at
786 // lookup time.
801 // lookup time.
787 }
802 }
788
803
789 if (buf[1] != BSER_ARRAY) {
804 if (buf[1] != BSER_ARRAY) {
790 PyErr_Format(PyExc_ValueError, "Expect ARRAY to follow TEMPLATE");
805 PyErr_Format(PyExc_ValueError, "Expect ARRAY to follow TEMPLATE");
791 return NULL;
806 return NULL;
792 }
807 }
793
808
794 // skip header
809 // skip header
795 buf++;
810 buf++;
796 *ptr = buf;
811 *ptr = buf;
797
812
798 // Load template keys.
813 // Load template keys.
799 // For keys we don't want to do any decoding right now.
814 // For keys we don't want to do any decoding right now.
800 keys = bunser_array(ptr, end, &keys_ctx);
815 keys = bunser_array(ptr, end, &keys_ctx);
801 if (!keys) {
816 if (!keys) {
802 return NULL;
817 return NULL;
803 }
818 }
804
819
805 numkeys = PySequence_Length(keys);
820 numkeys = PySequence_Length(keys);
806
821
807 // Load number of array elements
822 // Load number of array elements
808 if (!bunser_int(ptr, end, &nitems)) {
823 if (!bunser_int(ptr, end, &nitems)) {
809 Py_DECREF(keys);
824 Py_DECREF(keys);
810 return 0;
825 return 0;
811 }
826 }
812
827
813 if (nitems > LONG_MAX) {
828 if (nitems > LONG_MAX) {
814 PyErr_Format(PyExc_ValueError, "Too many items for python");
829 PyErr_Format(PyExc_ValueError, "Too many items for python");
815 Py_DECREF(keys);
830 Py_DECREF(keys);
816 return NULL;
831 return NULL;
817 }
832 }
818
833
819 arrval = PyList_New((Py_ssize_t)nitems);
834 arrval = PyList_New((Py_ssize_t)nitems);
820 if (!arrval) {
835 if (!arrval) {
821 Py_DECREF(keys);
836 Py_DECREF(keys);
822 return NULL;
837 return NULL;
823 }
838 }
824
839
825 for (i = 0; i < nitems; i++) {
840 for (i = 0; i < nitems; i++) {
826 PyObject* dict = NULL;
841 PyObject* dict = NULL;
827 bserObject* obj = NULL;
842 bserObject* obj = NULL;
828
843
829 if (mutable) {
844 if (mutable) {
830 dict = PyDict_New();
845 dict = PyDict_New();
831 } else {
846 } else {
832 obj = PyObject_New(bserObject, &bserObjectType);
847 obj = PyObject_New(bserObject, &bserObjectType);
833 if (obj) {
848 if (obj) {
834 obj->keys = keys;
849 obj->keys = keys;
835 Py_INCREF(obj->keys);
850 Py_INCREF(obj->keys);
836 obj->values = PyTuple_New(numkeys);
851 obj->values = PyTuple_New(numkeys);
837 }
852 }
838 dict = (PyObject*)obj;
853 dict = (PyObject*)obj;
839 }
854 }
840 if (!dict) {
855 if (!dict) {
841 fail:
856 fail:
842 Py_DECREF(keys);
857 Py_DECREF(keys);
843 Py_DECREF(arrval);
858 Py_DECREF(arrval);
844 return NULL;
859 return NULL;
845 }
860 }
846
861
847 for (keyidx = 0; keyidx < numkeys; keyidx++) {
862 for (keyidx = 0; keyidx < numkeys; keyidx++) {
848 PyObject* key;
863 PyObject* key;
849 PyObject* ele;
864 PyObject* ele;
850
865
851 if (**ptr == BSER_SKIP) {
866 if (**ptr == BSER_SKIP) {
852 *ptr = *ptr + 1;
867 *ptr = *ptr + 1;
853 ele = Py_None;
868 ele = Py_None;
854 Py_INCREF(ele);
869 Py_INCREF(ele);
855 } else {
870 } else {
856 ele = bser_loads_recursive(ptr, end, ctx);
871 ele = bser_loads_recursive(ptr, end, ctx);
857 }
872 }
858
873
859 if (!ele) {
874 if (!ele) {
860 goto fail;
875 goto fail;
861 }
876 }
862
877
863 if (mutable) {
878 if (mutable) {
864 key = PyList_GET_ITEM(keys, keyidx);
879 key = PyList_GET_ITEM(keys, keyidx);
865 PyDict_SetItem(dict, key, ele);
880 PyDict_SetItem(dict, key, ele);
866 Py_DECREF(ele);
881 Py_DECREF(ele);
867 } else {
882 } else {
868 PyTuple_SET_ITEM(obj->values, keyidx, ele);
883 PyTuple_SET_ITEM(obj->values, keyidx, ele);
869 // DECREF(ele) not required as SET_ITEM steals the ref
884 // DECREF(ele) not required as SET_ITEM steals the ref
870 }
885 }
871 }
886 }
872
887
873 PyList_SET_ITEM(arrval, i, dict);
888 PyList_SET_ITEM(arrval, i, dict);
874 // DECREF(obj) not required as SET_ITEM steals the ref
889 // DECREF(obj) not required as SET_ITEM steals the ref
875 }
890 }
876
891
877 Py_DECREF(keys);
892 Py_DECREF(keys);
878
893
879 return arrval;
894 return arrval;
880 }
895 }
881
896
882 static PyObject* bser_loads_recursive(
897 static PyObject* bser_loads_recursive(
883 const char** ptr,
898 const char** ptr,
884 const char* end,
899 const char* end,
885 const unser_ctx_t* ctx) {
900 const unser_ctx_t* ctx) {
886 const char* buf = *ptr;
901 const char* buf = *ptr;
887
902
888 switch (buf[0]) {
903 switch (buf[0]) {
889 case BSER_INT8:
904 case BSER_INT8:
890 case BSER_INT16:
905 case BSER_INT16:
891 case BSER_INT32:
906 case BSER_INT32:
892 case BSER_INT64: {
907 case BSER_INT64: {
893 int64_t ival;
908 int64_t ival;
894 if (!bunser_int(ptr, end, &ival)) {
909 if (!bunser_int(ptr, end, &ival)) {
895 return NULL;
910 return NULL;
896 }
911 }
897 // Python 3 has one integer type.
912 // Python 3 has one integer type.
898 #if PY_MAJOR_VERSION >= 3
913 #if PY_MAJOR_VERSION >= 3
899 return PyLong_FromLongLong(ival);
914 return PyLong_FromLongLong(ival);
900 #else
915 #else
901 if (ival < LONG_MIN || ival > LONG_MAX) {
916 if (ival < LONG_MIN || ival > LONG_MAX) {
902 return PyLong_FromLongLong(ival);
917 return PyLong_FromLongLong(ival);
903 }
918 }
904 return PyInt_FromSsize_t(Py_SAFE_DOWNCAST(ival, int64_t, Py_ssize_t));
919 return PyInt_FromSsize_t(Py_SAFE_DOWNCAST(ival, int64_t, Py_ssize_t));
905 #endif // PY_MAJOR_VERSION >= 3
920 #endif // PY_MAJOR_VERSION >= 3
906 }
921 }
907
922
908 case BSER_REAL: {
923 case BSER_REAL: {
909 double dval;
924 double dval;
910 memcpy(&dval, buf + 1, sizeof(dval));
925 memcpy(&dval, buf + 1, sizeof(dval));
911 *ptr = buf + 1 + sizeof(double);
926 *ptr = buf + 1 + sizeof(double);
912 return PyFloat_FromDouble(dval);
927 return PyFloat_FromDouble(dval);
913 }
928 }
914
929
915 case BSER_TRUE:
930 case BSER_TRUE:
916 *ptr = buf + 1;
931 *ptr = buf + 1;
917 Py_INCREF(Py_True);
932 Py_INCREF(Py_True);
918 return Py_True;
933 return Py_True;
919
934
920 case BSER_FALSE:
935 case BSER_FALSE:
921 *ptr = buf + 1;
936 *ptr = buf + 1;
922 Py_INCREF(Py_False);
937 Py_INCREF(Py_False);
923 return Py_False;
938 return Py_False;
924
939
925 case BSER_NULL:
940 case BSER_NULL:
926 *ptr = buf + 1;
941 *ptr = buf + 1;
927 Py_INCREF(Py_None);
942 Py_INCREF(Py_None);
928 return Py_None;
943 return Py_None;
929
944
930 case BSER_BYTESTRING: {
945 case BSER_BYTESTRING: {
931 const char* start;
946 const char* start;
932 int64_t len;
947 int64_t len;
933
948
934 if (!bunser_bytestring(ptr, end, &start, &len)) {
949 if (!bunser_bytestring(ptr, end, &start, &len)) {
935 return NULL;
950 return NULL;
936 }
951 }
937
952
938 if (len > LONG_MAX) {
953 if (len > LONG_MAX) {
939 PyErr_Format(PyExc_ValueError, "string too long for python");
954 PyErr_Format(PyExc_ValueError, "string too long for python");
940 return NULL;
955 return NULL;
941 }
956 }
942
957
943 if (ctx->value_encoding != NULL) {
958 if (ctx->value_encoding != NULL) {
944 return PyUnicode_Decode(
959 return PyUnicode_Decode(
945 start, (long)len, ctx->value_encoding, ctx->value_errors);
960 start, (long)len, ctx->value_encoding, ctx->value_errors);
946 } else {
961 } else {
947 return PyBytes_FromStringAndSize(start, (long)len);
962 return PyBytes_FromStringAndSize(start, (long)len);
948 }
963 }
949 }
964 }
950
965
951 case BSER_UTF8STRING: {
966 case BSER_UTF8STRING: {
952 const char* start;
967 const char* start;
953 int64_t len;
968 int64_t len;
954
969
955 if (!bunser_bytestring(ptr, end, &start, &len)) {
970 if (!bunser_bytestring(ptr, end, &start, &len)) {
956 return NULL;
971 return NULL;
957 }
972 }
958
973
959 if (len > LONG_MAX) {
974 if (len > LONG_MAX) {
960 PyErr_Format(PyExc_ValueError, "string too long for python");
975 PyErr_Format(PyExc_ValueError, "string too long for python");
961 return NULL;
976 return NULL;
962 }
977 }
963
978
964 return PyUnicode_Decode(start, (long)len, "utf-8", "strict");
979 return PyUnicode_Decode(start, (long)len, "utf-8", "strict");
965 }
980 }
966
981
967 case BSER_ARRAY:
982 case BSER_ARRAY:
968 return bunser_array(ptr, end, ctx);
983 return bunser_array(ptr, end, ctx);
969
984
970 case BSER_OBJECT:
985 case BSER_OBJECT:
971 return bunser_object(ptr, end, ctx);
986 return bunser_object(ptr, end, ctx);
972
987
973 case BSER_TEMPLATE:
988 case BSER_TEMPLATE:
974 return bunser_template(ptr, end, ctx);
989 return bunser_template(ptr, end, ctx);
975
990
976 default:
991 default:
977 PyErr_Format(PyExc_ValueError, "unhandled bser opcode 0x%02x", buf[0]);
992 PyErr_Format(PyExc_ValueError, "unhandled bser opcode 0x%02x", buf[0]);
978 }
993 }
979
994
980 return NULL;
995 return NULL;
981 }
996 }
982
997
983 static int _pdu_info_helper(
998 static int _pdu_info_helper(
984 const char* data,
999 const char* data,
985 const char* end,
1000 const char* end,
986 uint32_t* bser_version_out,
1001 uint32_t* bser_version_out,
987 uint32_t* bser_capabilities_out,
1002 uint32_t* bser_capabilities_out,
988 int64_t* expected_len_out,
1003 int64_t* expected_len_out,
989 off_t* position_out) {
1004 off_t* position_out) {
990 uint32_t bser_version;
1005 uint32_t bser_version;
991 uint32_t bser_capabilities = 0;
1006 uint32_t bser_capabilities = 0;
992 int64_t expected_len;
1007 int64_t expected_len;
993
1008
994 const char* start;
1009 const char* start;
995 start = data;
1010 start = data;
996 // Validate the header and length
1011 // Validate the header and length
997 if (memcmp(data, EMPTY_HEADER, 2) == 0) {
1012 if (memcmp(data, EMPTY_HEADER, 2) == 0) {
998 bser_version = 1;
1013 bser_version = 1;
999 } else if (memcmp(data, EMPTY_HEADER_V2, 2) == 0) {
1014 } else if (memcmp(data, EMPTY_HEADER_V2, 2) == 0) {
1000 bser_version = 2;
1015 bser_version = 2;
1001 } else {
1016 } else {
1002 PyErr_SetString(PyExc_ValueError, "invalid bser header");
1017 PyErr_SetString(PyExc_ValueError, "invalid bser header");
1003 return 0;
1018 return 0;
1004 }
1019 }
1005
1020
1006 data += 2;
1021 data += 2;
1007
1022
1008 if (bser_version == 2) {
1023 if (bser_version == 2) {
1009 // Expect an integer telling us what capabilities are supported by the
1024 // Expect an integer telling us what capabilities are supported by the
1010 // remote server (currently unused).
1025 // remote server (currently unused).
1011 if (!memcpy(&bser_capabilities, &data, sizeof(bser_capabilities))) {
1026 if (!memcpy(&bser_capabilities, &data, sizeof(bser_capabilities))) {
1012 return 0;
1027 return 0;
1013 }
1028 }
1014 data += sizeof(bser_capabilities);
1029 data += sizeof(bser_capabilities);
1015 }
1030 }
1016
1031
1017 // Expect an integer telling us how big the rest of the data
1032 // Expect an integer telling us how big the rest of the data
1018 // should be
1033 // should be
1019 if (!bunser_int(&data, end, &expected_len)) {
1034 if (!bunser_int(&data, end, &expected_len)) {
1020 return 0;
1035 return 0;
1021 }
1036 }
1022
1037
1023 *bser_version_out = bser_version;
1038 *bser_version_out = bser_version;
1024 *bser_capabilities_out = (uint32_t)bser_capabilities;
1039 *bser_capabilities_out = (uint32_t)bser_capabilities;
1025 *expected_len_out = expected_len;
1040 *expected_len_out = expected_len;
1026 *position_out = (off_t)(data - start);
1041 *position_out = (off_t)(data - start);
1027 return 1;
1042 return 1;
1028 }
1043 }
1029
1044
1030 // This function parses the PDU header and provides info about the packet
1045 // This function parses the PDU header and provides info about the packet
1031 // Returns false if unsuccessful
1046 // Returns false if unsuccessful
1032 static int pdu_info_helper(
1047 static int pdu_info_helper(
1033 PyObject* self,
1048 PyObject* self,
1034 PyObject* args,
1049 PyObject* args,
1035 uint32_t* bser_version_out,
1050 uint32_t* bser_version_out,
1036 uint32_t* bser_capabilities_out,
1051 uint32_t* bser_capabilities_out,
1037 int64_t* total_len_out) {
1052 int64_t* total_len_out) {
1038 const char* start = NULL;
1053 const char* start = NULL;
1039 const char* data = NULL;
1054 const char* data = NULL;
1040 int datalen = 0;
1055 int datalen = 0;
1041 const char* end;
1056 const char* end;
1042 int64_t expected_len;
1057 int64_t expected_len;
1043 off_t position;
1058 off_t position;
1044
1059
1045 if (!PyArg_ParseTuple(args, "s#", &start, &datalen)) {
1060 if (!PyArg_ParseTuple(args, "s#", &start, &datalen)) {
1046 return 0;
1061 return 0;
1047 }
1062 }
1048 data = start;
1063 data = start;
1049 end = data + datalen;
1064 end = data + datalen;
1050
1065
1051 if (!_pdu_info_helper(
1066 if (!_pdu_info_helper(
1052 data,
1067 data,
1053 end,
1068 end,
1054 bser_version_out,
1069 bser_version_out,
1055 bser_capabilities_out,
1070 bser_capabilities_out,
1056 &expected_len,
1071 &expected_len,
1057 &position)) {
1072 &position)) {
1058 return 0;
1073 return 0;
1059 }
1074 }
1060 *total_len_out = (int64_t)(expected_len + position);
1075 *total_len_out = (int64_t)(expected_len + position);
1061 return 1;
1076 return 1;
1062 }
1077 }
1063
1078
1064 // Expected use case is to read a packet from the socket and then call
1079 // Expected use case is to read a packet from the socket and then call
1065 // bser.pdu_info on the packet. It returns the BSER version, BSER capabilities,
1080 // bser.pdu_info on the packet. It returns the BSER version, BSER capabilities,
1066 // and the total length of the entire response that the peer is sending,
1081 // and the total length of the entire response that the peer is sending,
1067 // including the bytes already received. This allows the client to compute the
1082 // including the bytes already received. This allows the client to compute the
1068 // data size it needs to read before it can decode the data.
1083 // data size it needs to read before it can decode the data.
1069 static PyObject* bser_pdu_info(PyObject* self, PyObject* args) {
1084 static PyObject* bser_pdu_info(PyObject* self, PyObject* args) {
1070 uint32_t version, capabilities;
1085 uint32_t version, capabilities;
1071 int64_t total_len;
1086 int64_t total_len;
1072 if (!pdu_info_helper(self, args, &version, &capabilities, &total_len)) {
1087 if (!pdu_info_helper(self, args, &version, &capabilities, &total_len)) {
1073 return NULL;
1088 return NULL;
1074 }
1089 }
1075 return Py_BuildValue("kkL", version, capabilities, total_len);
1090 return Py_BuildValue("kkL", version, capabilities, total_len);
1076 }
1091 }
1077
1092
1078 static PyObject* bser_pdu_len(PyObject* self, PyObject* args) {
1093 static PyObject* bser_pdu_len(PyObject* self, PyObject* args) {
1079 uint32_t version, capabilities;
1094 uint32_t version, capabilities;
1080 int64_t total_len;
1095 int64_t total_len;
1081 if (!pdu_info_helper(self, args, &version, &capabilities, &total_len)) {
1096 if (!pdu_info_helper(self, args, &version, &capabilities, &total_len)) {
1082 return NULL;
1097 return NULL;
1083 }
1098 }
1084 return Py_BuildValue("L", total_len);
1099 return Py_BuildValue("L", total_len);
1085 }
1100 }
1086
1101
1087 static PyObject* bser_loads(PyObject* self, PyObject* args, PyObject* kw) {
1102 static PyObject* bser_loads(PyObject* self, PyObject* args, PyObject* kw) {
1088 const char* data = NULL;
1103 const char* data = NULL;
1089 int datalen = 0;
1104 int datalen = 0;
1090 const char* start;
1105 const char* start;
1091 const char* end;
1106 const char* end;
1092 int64_t expected_len;
1107 int64_t expected_len;
1093 off_t position;
1108 off_t position;
1094 PyObject* mutable_obj = NULL;
1109 PyObject* mutable_obj = NULL;
1095 const char* value_encoding = NULL;
1110 const char* value_encoding = NULL;
1096 const char* value_errors = NULL;
1111 const char* value_errors = NULL;
1097 unser_ctx_t ctx = {1, 0};
1112 unser_ctx_t ctx = {1, 0};
1098
1113
1099 static char* kw_list[] = {
1114 static char* kw_list[] = {
1100 "buf", "mutable", "value_encoding", "value_errors", NULL};
1115 "buf", "mutable", "value_encoding", "value_errors", NULL};
1101
1116
1102 if (!PyArg_ParseTupleAndKeywords(
1117 if (!PyArg_ParseTupleAndKeywords(
1103 args,
1118 args,
1104 kw,
1119 kw,
1105 "s#|Ozz:loads",
1120 "s#|Ozz:loads",
1106 kw_list,
1121 kw_list,
1107 &start,
1122 &start,
1108 &datalen,
1123 &datalen,
1109 &mutable_obj,
1124 &mutable_obj,
1110 &value_encoding,
1125 &value_encoding,
1111 &value_errors)) {
1126 &value_errors)) {
1112 return NULL;
1127 return NULL;
1113 }
1128 }
1114
1129
1115 if (mutable_obj) {
1130 if (mutable_obj) {
1116 ctx.mutable = PyObject_IsTrue(mutable_obj) > 0 ? 1 : 0;
1131 ctx.mutable = PyObject_IsTrue(mutable_obj) > 0 ? 1 : 0;
1117 }
1132 }
1118 ctx.value_encoding = value_encoding;
1133 ctx.value_encoding = value_encoding;
1119 if (value_encoding == NULL) {
1134 if (value_encoding == NULL) {
1120 ctx.value_errors = NULL;
1135 ctx.value_errors = NULL;
1121 } else if (value_errors == NULL) {
1136 } else if (value_errors == NULL) {
1122 ctx.value_errors = "strict";
1137 ctx.value_errors = "strict";
1123 } else {
1138 } else {
1124 ctx.value_errors = value_errors;
1139 ctx.value_errors = value_errors;
1125 }
1140 }
1126 data = start;
1141 data = start;
1127 end = data + datalen;
1142 end = data + datalen;
1128
1143
1129 if (!_pdu_info_helper(
1144 if (!_pdu_info_helper(
1130 data,
1145 data,
1131 end,
1146 end,
1132 &ctx.bser_version,
1147 &ctx.bser_version,
1133 &ctx.bser_capabilities,
1148 &ctx.bser_capabilities,
1134 &expected_len,
1149 &expected_len,
1135 &position)) {
1150 &position)) {
1136 return NULL;
1151 return NULL;
1137 }
1152 }
1138
1153
1139 data = start + position;
1154 data = start + position;
1140 // Verify
1155 // Verify
1141 if (expected_len + data != end) {
1156 if (expected_len + data != end) {
1142 PyErr_SetString(PyExc_ValueError, "bser data len != header len");
1157 PyErr_SetString(PyExc_ValueError, "bser data len != header len");
1143 return NULL;
1158 return NULL;
1144 }
1159 }
1145
1160
1146 return bser_loads_recursive(&data, end, &ctx);
1161 return bser_loads_recursive(&data, end, &ctx);
1147 }
1162 }
1148
1163
1149 static PyObject* bser_load(PyObject* self, PyObject* args, PyObject* kw) {
1164 static PyObject* bser_load(PyObject* self, PyObject* args, PyObject* kw) {
1150 PyObject* load;
1165 PyObject* load;
1151 PyObject* load_method;
1166 PyObject* load_method;
1152 PyObject* string;
1167 PyObject* string;
1153 PyObject* load_method_args;
1168 PyObject* load_method_args;
1154 PyObject* load_method_kwargs;
1169 PyObject* load_method_kwargs;
1155 PyObject* fp = NULL;
1170 PyObject* fp = NULL;
1156 PyObject* mutable_obj = NULL;
1171 PyObject* mutable_obj = NULL;
1157 PyObject* value_encoding = NULL;
1172 PyObject* value_encoding = NULL;
1158 PyObject* value_errors = NULL;
1173 PyObject* value_errors = NULL;
1159
1174
1160 static char* kw_list[] = {
1175 static char* kw_list[] = {
1161 "fp", "mutable", "value_encoding", "value_errors", NULL};
1176 "fp", "mutable", "value_encoding", "value_errors", NULL};
1162
1177
1163 if (!PyArg_ParseTupleAndKeywords(
1178 if (!PyArg_ParseTupleAndKeywords(
1164 args,
1179 args,
1165 kw,
1180 kw,
1166 "O|OOO:load",
1181 "O|OOO:load",
1167 kw_list,
1182 kw_list,
1168 &fp,
1183 &fp,
1169 &mutable_obj,
1184 &mutable_obj,
1170 &value_encoding,
1185 &value_encoding,
1171 &value_errors)) {
1186 &value_errors)) {
1172 return NULL;
1187 return NULL;
1173 }
1188 }
1174
1189
1175 load = PyImport_ImportModule("pywatchman.load");
1190 load = PyImport_ImportModule("pywatchman.load");
1176 if (load == NULL) {
1191 if (load == NULL) {
1177 return NULL;
1192 return NULL;
1178 }
1193 }
1179 load_method = PyObject_GetAttrString(load, "load");
1194 load_method = PyObject_GetAttrString(load, "load");
1180 if (load_method == NULL) {
1195 if (load_method == NULL) {
1181 return NULL;
1196 return NULL;
1182 }
1197 }
1183 // Mandatory method arguments
1198 // Mandatory method arguments
1184 load_method_args = Py_BuildValue("(O)", fp);
1199 load_method_args = Py_BuildValue("(O)", fp);
1185 if (load_method_args == NULL) {
1200 if (load_method_args == NULL) {
1186 return NULL;
1201 return NULL;
1187 }
1202 }
1188 // Optional method arguments
1203 // Optional method arguments
1189 load_method_kwargs = PyDict_New();
1204 load_method_kwargs = PyDict_New();
1190 if (load_method_kwargs == NULL) {
1205 if (load_method_kwargs == NULL) {
1191 return NULL;
1206 return NULL;
1192 }
1207 }
1193 if (mutable_obj) {
1208 if (mutable_obj) {
1194 PyDict_SetItemString(load_method_kwargs, "mutable", mutable_obj);
1209 PyDict_SetItemString(load_method_kwargs, "mutable", mutable_obj);
1195 }
1210 }
1196 if (value_encoding) {
1211 if (value_encoding) {
1197 PyDict_SetItemString(load_method_kwargs, "value_encoding", value_encoding);
1212 PyDict_SetItemString(load_method_kwargs, "value_encoding", value_encoding);
1198 }
1213 }
1199 if (value_errors) {
1214 if (value_errors) {
1200 PyDict_SetItemString(load_method_kwargs, "value_errors", value_errors);
1215 PyDict_SetItemString(load_method_kwargs, "value_errors", value_errors);
1201 }
1216 }
1202 string = PyObject_Call(load_method, load_method_args, load_method_kwargs);
1217 string = PyObject_Call(load_method, load_method_args, load_method_kwargs);
1203 Py_DECREF(load_method_kwargs);
1218 Py_DECREF(load_method_kwargs);
1204 Py_DECREF(load_method_args);
1219 Py_DECREF(load_method_args);
1205 Py_DECREF(load_method);
1220 Py_DECREF(load_method);
1206 Py_DECREF(load);
1221 Py_DECREF(load);
1207 return string;
1222 return string;
1208 }
1223 }
1209
1224
1210 // clang-format off
1225 // clang-format off
1211 static PyMethodDef bser_methods[] = {
1226 static PyMethodDef bser_methods[] = {
1212 {"loads", (PyCFunction)bser_loads, METH_VARARGS | METH_KEYWORDS,
1227 {"loads", (PyCFunction)bser_loads, METH_VARARGS | METH_KEYWORDS,
1213 "Deserialize string."},
1228 "Deserialize string."},
1214 {"load", (PyCFunction)bser_load, METH_VARARGS | METH_KEYWORDS,
1229 {"load", (PyCFunction)bser_load, METH_VARARGS | METH_KEYWORDS,
1215 "Deserialize a file object"},
1230 "Deserialize a file object"},
1216 {"pdu_info", (PyCFunction)bser_pdu_info, METH_VARARGS,
1231 {"pdu_info", (PyCFunction)bser_pdu_info, METH_VARARGS,
1217 "Extract PDU information."},
1232 "Extract PDU information."},
1218 {"pdu_len", (PyCFunction)bser_pdu_len, METH_VARARGS,
1233 {"pdu_len", (PyCFunction)bser_pdu_len, METH_VARARGS,
1219 "Extract total PDU length."},
1234 "Extract total PDU length."},
1220 {"dumps", (PyCFunction)bser_dumps, METH_VARARGS | METH_KEYWORDS,
1235 {"dumps", (PyCFunction)bser_dumps, METH_VARARGS | METH_KEYWORDS,
1221 "Serialize string."},
1236 "Serialize string."},
1222 {NULL, NULL, 0, NULL}
1237 {NULL, NULL, 0, NULL}
1223 };
1238 };
1224
1239
1225 #if PY_MAJOR_VERSION >= 3
1240 #if PY_MAJOR_VERSION >= 3
1226 static struct PyModuleDef bser_module = {
1241 static struct PyModuleDef bser_module = {
1227 PyModuleDef_HEAD_INIT,
1242 PyModuleDef_HEAD_INIT,
1228 "bser",
1243 "bser",
1229 "Efficient encoding and decoding of BSER.",
1244 "Efficient encoding and decoding of BSER.",
1230 -1,
1245 -1,
1231 bser_methods
1246 bser_methods
1232 };
1247 };
1233 // clang-format on
1248 // clang-format on
1234
1249
1235 PyMODINIT_FUNC PyInit_bser(void) {
1250 PyMODINIT_FUNC PyInit_bser(void) {
1236 PyObject* mod;
1251 PyObject* mod;
1237
1252
1238 mod = PyModule_Create(&bser_module);
1253 mod = PyModule_Create(&bser_module);
1239 PyType_Ready(&bserObjectType);
1254 PyType_Ready(&bserObjectType);
1240
1255
1241 return mod;
1256 return mod;
1242 }
1257 }
1243 #else
1258 #else
1244
1259
1245 PyMODINIT_FUNC initbser(void) {
1260 PyMODINIT_FUNC initbser(void) {
1246 (void)Py_InitModule("bser", bser_methods);
1261 (void)Py_InitModule("bser", bser_methods);
1247 PyType_Ready(&bserObjectType);
1262 PyType_Ready(&bserObjectType);
1248 }
1263 }
1249 #endif // PY_MAJOR_VERSION >= 3
1264 #endif // PY_MAJOR_VERSION >= 3
1250
1265
1251 /* vim:ts=2:sw=2:et:
1266 /* vim:ts=2:sw=2:et:
1252 */
1267 */
General Comments 0
You need to be logged in to leave comments. Login now