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