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