##// END OF EJS Templates
parsers.c: Added support for py3k....
Renato Cunha -
r11361:3de3d670 default
parent child Browse files
Show More
@@ -1,433 +1,455 b''
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <ctype.h>
11 #include <ctype.h>
12 #include <string.h>
12 #include <string.h>
13
13
14 #include "util.h"
15
14 static int hexdigit(char c)
16 static int hexdigit(char c)
15 {
17 {
16 if (c >= '0' && c <= '9')
18 if (c >= '0' && c <= '9')
17 return c - '0';
19 return c - '0';
18 if (c >= 'a' && c <= 'f')
20 if (c >= 'a' && c <= 'f')
19 return c - 'a' + 10;
21 return c - 'a' + 10;
20 if (c >= 'A' && c <= 'F')
22 if (c >= 'A' && c <= 'F')
21 return c - 'A' + 10;
23 return c - 'A' + 10;
22
24
23 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
24 return 0;
26 return 0;
25 }
27 }
26
28
27 /*
29 /*
28 * Turn a hex-encoded string into binary.
30 * Turn a hex-encoded string into binary.
29 */
31 */
30 static PyObject *unhexlify(const char *str, int len)
32 static PyObject *unhexlify(const char *str, int len)
31 {
33 {
32 PyObject *ret;
34 PyObject *ret;
33 const char *c;
35 const char *c;
34 char *d;
36 char *d;
35
37
36 ret = PyString_FromStringAndSize(NULL, len / 2);
38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
39
37 if (!ret)
40 if (!ret)
38 return NULL;
41 return NULL;
39
42
40 d = PyString_AS_STRING(ret);
43 d = PyBytes_AsString(ret);
44
41 for (c = str; c < str + len;) {
45 for (c = str; c < str + len;) {
42 int hi = hexdigit(*c++);
46 int hi = hexdigit(*c++);
43 int lo = hexdigit(*c++);
47 int lo = hexdigit(*c++);
44 *d++ = (hi << 4) | lo;
48 *d++ = (hi << 4) | lo;
45 }
49 }
46
50
47 return ret;
51 return ret;
48 }
52 }
49
53
50 /*
54 /*
51 * This code assumes that a manifest is stitched together with newline
55 * This code assumes that a manifest is stitched together with newline
52 * ('\n') characters.
56 * ('\n') characters.
53 */
57 */
54 static PyObject *parse_manifest(PyObject *self, PyObject *args)
58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
55 {
59 {
56 PyObject *mfdict, *fdict;
60 PyObject *mfdict, *fdict;
57 char *str, *cur, *start, *zero;
61 char *str, *cur, *start, *zero;
58 int len;
62 int len;
59
63
60 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
61 &PyDict_Type, &mfdict,
65 &PyDict_Type, &mfdict,
62 &PyDict_Type, &fdict,
66 &PyDict_Type, &fdict,
63 &str, &len))
67 &str, &len))
64 goto quit;
68 goto quit;
65
69
66 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
67 PyObject *file = NULL, *node = NULL;
71 PyObject *file = NULL, *node = NULL;
68 PyObject *flags = NULL;
72 PyObject *flags = NULL;
69 int nlen;
73 int nlen;
70
74
71 if (!*cur) {
75 if (!*cur) {
72 zero = cur;
76 zero = cur;
73 continue;
77 continue;
74 }
78 }
75 else if (*cur != '\n')
79 else if (*cur != '\n')
76 continue;
80 continue;
77
81
78 if (!zero) {
82 if (!zero) {
79 PyErr_SetString(PyExc_ValueError,
83 PyErr_SetString(PyExc_ValueError,
80 "manifest entry has no separator");
84 "manifest entry has no separator");
81 goto quit;
85 goto quit;
82 }
86 }
83
87
84 file = PyString_FromStringAndSize(start, zero - start);
88 file = PyBytes_FromStringAndSize(start, zero - start);
89
85 if (!file)
90 if (!file)
86 goto bail;
91 goto bail;
87
92
88 nlen = cur - zero - 1;
93 nlen = cur - zero - 1;
89
94
90 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
91 if (!node)
96 if (!node)
92 goto bail;
97 goto bail;
93
98
94 if (nlen > 40) {
99 if (nlen > 40) {
95 flags = PyString_FromStringAndSize(zero + 41,
100 flags = PyBytes_FromStringAndSize(zero + 41,
96 nlen - 40);
101 nlen - 40);
97 if (!flags)
102 if (!flags)
98 goto bail;
103 goto bail;
99
104
100 if (PyDict_SetItem(fdict, file, flags) == -1)
105 if (PyDict_SetItem(fdict, file, flags) == -1)
101 goto bail;
106 goto bail;
102 }
107 }
103
108
104 if (PyDict_SetItem(mfdict, file, node) == -1)
109 if (PyDict_SetItem(mfdict, file, node) == -1)
105 goto bail;
110 goto bail;
106
111
107 start = cur + 1;
112 start = cur + 1;
108 zero = NULL;
113 zero = NULL;
109
114
110 Py_XDECREF(flags);
115 Py_XDECREF(flags);
111 Py_XDECREF(node);
116 Py_XDECREF(node);
112 Py_XDECREF(file);
117 Py_XDECREF(file);
113 continue;
118 continue;
114 bail:
119 bail:
115 Py_XDECREF(flags);
120 Py_XDECREF(flags);
116 Py_XDECREF(node);
121 Py_XDECREF(node);
117 Py_XDECREF(file);
122 Py_XDECREF(file);
118 goto quit;
123 goto quit;
119 }
124 }
120
125
121 if (len > 0 && *(cur - 1) != '\n') {
126 if (len > 0 && *(cur - 1) != '\n') {
122 PyErr_SetString(PyExc_ValueError,
127 PyErr_SetString(PyExc_ValueError,
123 "manifest contains trailing garbage");
128 "manifest contains trailing garbage");
124 goto quit;
129 goto quit;
125 }
130 }
126
131
127 Py_INCREF(Py_None);
132 Py_INCREF(Py_None);
128 return Py_None;
133 return Py_None;
129 quit:
134 quit:
130 return NULL;
135 return NULL;
131 }
136 }
132
137
133 #ifdef _WIN32
138 #ifdef _WIN32
134 #ifdef _MSC_VER
139 #ifdef _MSC_VER
135 /* msvc 6.0 has problems */
140 /* msvc 6.0 has problems */
136 #define inline __inline
141 #define inline __inline
137 typedef unsigned long uint32_t;
142 typedef unsigned long uint32_t;
138 typedef unsigned __int64 uint64_t;
143 typedef unsigned __int64 uint64_t;
139 #else
144 #else
140 #include <stdint.h>
145 #include <stdint.h>
141 #endif
146 #endif
142 static uint32_t ntohl(uint32_t x)
147 static uint32_t ntohl(uint32_t x)
143 {
148 {
144 return ((x & 0x000000ffUL) << 24) |
149 return ((x & 0x000000ffUL) << 24) |
145 ((x & 0x0000ff00UL) << 8) |
150 ((x & 0x0000ff00UL) << 8) |
146 ((x & 0x00ff0000UL) >> 8) |
151 ((x & 0x00ff0000UL) >> 8) |
147 ((x & 0xff000000UL) >> 24);
152 ((x & 0xff000000UL) >> 24);
148 }
153 }
149 #else
154 #else
150 /* not windows */
155 /* not windows */
151 #include <sys/types.h>
156 #include <sys/types.h>
152 #if defined __BEOS__ && !defined __HAIKU__
157 #if defined __BEOS__ && !defined __HAIKU__
153 #include <ByteOrder.h>
158 #include <ByteOrder.h>
154 #else
159 #else
155 #include <arpa/inet.h>
160 #include <arpa/inet.h>
156 #endif
161 #endif
157 #include <inttypes.h>
162 #include <inttypes.h>
158 #endif
163 #endif
159
164
160 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
165 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
161 {
166 {
162 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
167 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
163 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
168 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
164 char *str, *cur, *end, *cpos;
169 char *str, *cur, *end, *cpos;
165 int state, mode, size, mtime;
170 int state, mode, size, mtime;
166 unsigned int flen;
171 unsigned int flen;
167 int len;
172 int len;
168 char decode[16]; /* for alignment */
173 char decode[16]; /* for alignment */
169
174
170 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
175 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
171 &PyDict_Type, &dmap,
176 &PyDict_Type, &dmap,
172 &PyDict_Type, &cmap,
177 &PyDict_Type, &cmap,
173 &str, &len))
178 &str, &len))
174 goto quit;
179 goto quit;
175
180
176 /* read parents */
181 /* read parents */
177 if (len < 40)
182 if (len < 40)
178 goto quit;
183 goto quit;
179
184
180 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
185 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
181 if (!parents)
186 if (!parents)
182 goto quit;
187 goto quit;
183
188
184 /* read filenames */
189 /* read filenames */
185 cur = str + 40;
190 cur = str + 40;
186 end = str + len;
191 end = str + len;
187
192
188 while (cur < end - 17) {
193 while (cur < end - 17) {
189 /* unpack header */
194 /* unpack header */
190 state = *cur;
195 state = *cur;
191 memcpy(decode, cur + 1, 16);
196 memcpy(decode, cur + 1, 16);
192 mode = ntohl(*(uint32_t *)(decode));
197 mode = ntohl(*(uint32_t *)(decode));
193 size = ntohl(*(uint32_t *)(decode + 4));
198 size = ntohl(*(uint32_t *)(decode + 4));
194 mtime = ntohl(*(uint32_t *)(decode + 8));
199 mtime = ntohl(*(uint32_t *)(decode + 8));
195 flen = ntohl(*(uint32_t *)(decode + 12));
200 flen = ntohl(*(uint32_t *)(decode + 12));
196 cur += 17;
201 cur += 17;
197 if (cur + flen > end || cur + flen < cur) {
202 if (cur + flen > end || cur + flen < cur) {
198 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
203 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
199 goto quit;
204 goto quit;
200 }
205 }
201
206
202 entry = Py_BuildValue("ciii", state, mode, size, mtime);
207 entry = Py_BuildValue("ciii", state, mode, size, mtime);
203 if (!entry)
208 if (!entry)
204 goto quit;
209 goto quit;
205 PyObject_GC_UnTrack(entry); /* don't waste time with this */
210 PyObject_GC_UnTrack(entry); /* don't waste time with this */
206
211
207 cpos = memchr(cur, 0, flen);
212 cpos = memchr(cur, 0, flen);
208 if (cpos) {
213 if (cpos) {
209 fname = PyString_FromStringAndSize(cur, cpos - cur);
214 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
210 cname = PyString_FromStringAndSize(cpos + 1,
215 cname = PyBytes_FromStringAndSize(cpos + 1,
211 flen - (cpos - cur) - 1);
216 flen - (cpos - cur) - 1);
212 if (!fname || !cname ||
217 if (!fname || !cname ||
213 PyDict_SetItem(cmap, fname, cname) == -1 ||
218 PyDict_SetItem(cmap, fname, cname) == -1 ||
214 PyDict_SetItem(dmap, fname, entry) == -1)
219 PyDict_SetItem(dmap, fname, entry) == -1)
215 goto quit;
220 goto quit;
216 Py_DECREF(cname);
221 Py_DECREF(cname);
217 } else {
222 } else {
218 fname = PyString_FromStringAndSize(cur, flen);
223 fname = PyBytes_FromStringAndSize(cur, flen);
219 if (!fname ||
224 if (!fname ||
220 PyDict_SetItem(dmap, fname, entry) == -1)
225 PyDict_SetItem(dmap, fname, entry) == -1)
221 goto quit;
226 goto quit;
222 }
227 }
223 cur += flen;
228 cur += flen;
224 Py_DECREF(fname);
229 Py_DECREF(fname);
225 Py_DECREF(entry);
230 Py_DECREF(entry);
226 fname = cname = entry = NULL;
231 fname = cname = entry = NULL;
227 }
232 }
228
233
229 ret = parents;
234 ret = parents;
230 Py_INCREF(ret);
235 Py_INCREF(ret);
231 quit:
236 quit:
232 Py_XDECREF(fname);
237 Py_XDECREF(fname);
233 Py_XDECREF(cname);
238 Py_XDECREF(cname);
234 Py_XDECREF(entry);
239 Py_XDECREF(entry);
235 Py_XDECREF(parents);
240 Py_XDECREF(parents);
236 return ret;
241 return ret;
237 }
242 }
238
243
239 const char nullid[20];
244 const char nullid[20];
240 const int nullrev = -1;
245 const int nullrev = -1;
241
246
242 /* create an index tuple, insert into the nodemap */
247 /* create an index tuple, insert into the nodemap */
243 static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags,
248 static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags,
244 int comp_len, int uncomp_len, int base_rev,
249 int comp_len, int uncomp_len, int base_rev,
245 int link_rev, int parent_1, int parent_2,
250 int link_rev, int parent_1, int parent_2,
246 const char *c_node_id)
251 const char *c_node_id)
247 {
252 {
248 int err;
253 int err;
249 PyObject *entry, *node_id, *n_obj;
254 PyObject *entry, *node_id, *n_obj;
250
255
251 node_id = PyString_FromStringAndSize(c_node_id, 20);
256 node_id = PyBytes_FromStringAndSize(c_node_id, 20);
252 n_obj = PyInt_FromLong(n);
257 n_obj = PyInt_FromLong(n);
258
253 if (!node_id || !n_obj)
259 if (!node_id || !n_obj)
254 err = -1;
260 err = -1;
255 else
261 else
256 err = PyDict_SetItem(nodemap, node_id, n_obj);
262 err = PyDict_SetItem(nodemap, node_id, n_obj);
257
263
258 Py_XDECREF(n_obj);
264 Py_XDECREF(n_obj);
259 if (err)
265 if (err)
260 goto error_dealloc;
266 goto error_dealloc;
261
267
262 entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len,
268 entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len,
263 uncomp_len, base_rev, link_rev,
269 uncomp_len, base_rev, link_rev,
264 parent_1, parent_2, node_id);
270 parent_1, parent_2, node_id);
265 if (!entry)
271 if (!entry)
266 goto error_dealloc;
272 goto error_dealloc;
267 PyObject_GC_UnTrack(entry); /* don't waste time with this */
273 PyObject_GC_UnTrack(entry); /* don't waste time with this */
268
274
269 return entry;
275 return entry;
270
276
271 error_dealloc:
277 error_dealloc:
272 Py_XDECREF(node_id);
278 Py_XDECREF(node_id);
273 return NULL;
279 return NULL;
274 }
280 }
275
281
276 /* RevlogNG format (all in big endian, data may be inlined):
282 /* RevlogNG format (all in big endian, data may be inlined):
277 * 6 bytes: offset
283 * 6 bytes: offset
278 * 2 bytes: flags
284 * 2 bytes: flags
279 * 4 bytes: compressed length
285 * 4 bytes: compressed length
280 * 4 bytes: uncompressed length
286 * 4 bytes: uncompressed length
281 * 4 bytes: base revision
287 * 4 bytes: base revision
282 * 4 bytes: link revision
288 * 4 bytes: link revision
283 * 4 bytes: parent 1 revision
289 * 4 bytes: parent 1 revision
284 * 4 bytes: parent 2 revision
290 * 4 bytes: parent 2 revision
285 * 32 bytes: nodeid (only 20 bytes used)
291 * 32 bytes: nodeid (only 20 bytes used)
286 */
292 */
287 static int _parse_index_ng (const char *data, int size, int inlined,
293 static int _parse_index_ng (const char *data, int size, int inlined,
288 PyObject *index, PyObject *nodemap)
294 PyObject *index, PyObject *nodemap)
289 {
295 {
290 PyObject *entry;
296 PyObject *entry;
291 int n = 0, err;
297 int n = 0, err;
292 uint64_t offset_flags;
298 uint64_t offset_flags;
293 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
299 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
294 const char *c_node_id;
300 const char *c_node_id;
295 const char *end = data + size;
301 const char *end = data + size;
296 char decode[64]; /* to enforce alignment with inline data */
302 char decode[64]; /* to enforce alignment with inline data */
297
303
298 while (data < end) {
304 while (data < end) {
299 unsigned int step;
305 unsigned int step;
300
306
301 memcpy(decode, data, 64);
307 memcpy(decode, data, 64);
302 offset_flags = ntohl(*((uint32_t *) (decode + 4)));
308 offset_flags = ntohl(*((uint32_t *) (decode + 4)));
303 if (n == 0) /* mask out version number for the first entry */
309 if (n == 0) /* mask out version number for the first entry */
304 offset_flags &= 0xFFFF;
310 offset_flags &= 0xFFFF;
305 else {
311 else {
306 uint32_t offset_high = ntohl(*((uint32_t *)decode));
312 uint32_t offset_high = ntohl(*((uint32_t *)decode));
307 offset_flags |= ((uint64_t)offset_high) << 32;
313 offset_flags |= ((uint64_t)offset_high) << 32;
308 }
314 }
309
315
310 comp_len = ntohl(*((uint32_t *)(decode + 8)));
316 comp_len = ntohl(*((uint32_t *)(decode + 8)));
311 uncomp_len = ntohl(*((uint32_t *)(decode + 12)));
317 uncomp_len = ntohl(*((uint32_t *)(decode + 12)));
312 base_rev = ntohl(*((uint32_t *)(decode + 16)));
318 base_rev = ntohl(*((uint32_t *)(decode + 16)));
313 link_rev = ntohl(*((uint32_t *)(decode + 20)));
319 link_rev = ntohl(*((uint32_t *)(decode + 20)));
314 parent_1 = ntohl(*((uint32_t *)(decode + 24)));
320 parent_1 = ntohl(*((uint32_t *)(decode + 24)));
315 parent_2 = ntohl(*((uint32_t *)(decode + 28)));
321 parent_2 = ntohl(*((uint32_t *)(decode + 28)));
316 c_node_id = decode + 32;
322 c_node_id = decode + 32;
317
323
318 entry = _build_idx_entry(nodemap, n, offset_flags,
324 entry = _build_idx_entry(nodemap, n, offset_flags,
319 comp_len, uncomp_len, base_rev,
325 comp_len, uncomp_len, base_rev,
320 link_rev, parent_1, parent_2,
326 link_rev, parent_1, parent_2,
321 c_node_id);
327 c_node_id);
322 if (!entry)
328 if (!entry)
323 return 0;
329 return 0;
324
330
325 if (inlined) {
331 if (inlined) {
326 err = PyList_Append(index, entry);
332 err = PyList_Append(index, entry);
327 Py_DECREF(entry);
333 Py_DECREF(entry);
328 if (err)
334 if (err)
329 return 0;
335 return 0;
330 } else
336 } else
331 PyList_SET_ITEM(index, n, entry); /* steals reference */
337 PyList_SET_ITEM(index, n, entry); /* steals reference */
332
338
333 n++;
339 n++;
334 step = 64 + (inlined ? comp_len : 0);
340 step = 64 + (inlined ? comp_len : 0);
335 if (data + step > end || data + step < data)
341 if (data + step > end || data + step < data)
336 break;
342 break;
337 data += step;
343 data += step;
338 }
344 }
339 if (data != end) {
345 if (data != end) {
340 if (!PyErr_Occurred())
346 if (!PyErr_Occurred())
341 PyErr_SetString(PyExc_ValueError, "corrupt index file");
347 PyErr_SetString(PyExc_ValueError, "corrupt index file");
342 return 0;
348 return 0;
343 }
349 }
344
350
345 /* create the nullid/nullrev entry in the nodemap and the
351 /* create the nullid/nullrev entry in the nodemap and the
346 * magic nullid entry in the index at [-1] */
352 * magic nullid entry in the index at [-1] */
347 entry = _build_idx_entry(nodemap,
353 entry = _build_idx_entry(nodemap,
348 nullrev, 0, 0, 0, -1, -1, -1, -1, nullid);
354 nullrev, 0, 0, 0, -1, -1, -1, -1, nullid);
349 if (!entry)
355 if (!entry)
350 return 0;
356 return 0;
351 if (inlined) {
357 if (inlined) {
352 err = PyList_Append(index, entry);
358 err = PyList_Append(index, entry);
353 Py_DECREF(entry);
359 Py_DECREF(entry);
354 if (err)
360 if (err)
355 return 0;
361 return 0;
356 } else
362 } else
357 PyList_SET_ITEM(index, n, entry); /* steals reference */
363 PyList_SET_ITEM(index, n, entry); /* steals reference */
358
364
359 return 1;
365 return 1;
360 }
366 }
361
367
362 /* This function parses a index file and returns a Python tuple of the
368 /* This function parses a index file and returns a Python tuple of the
363 * following format: (index, nodemap, cache)
369 * following format: (index, nodemap, cache)
364 *
370 *
365 * index: a list of tuples containing the RevlogNG records
371 * index: a list of tuples containing the RevlogNG records
366 * nodemap: a dict mapping node ids to indices in the index list
372 * nodemap: a dict mapping node ids to indices in the index list
367 * cache: if data is inlined, a tuple (index_file_content, 0) else None
373 * cache: if data is inlined, a tuple (index_file_content, 0) else None
368 */
374 */
369 static PyObject *parse_index(PyObject *self, PyObject *args)
375 static PyObject *parse_index(PyObject *self, PyObject *args)
370 {
376 {
371 const char *data;
377 const char *data;
372 int size, inlined;
378 int size, inlined;
373 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
379 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
374 PyObject *data_obj = NULL, *inlined_obj;
380 PyObject *data_obj = NULL, *inlined_obj;
375
381
376 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
382 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
377 return NULL;
383 return NULL;
378 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
384 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
379
385
380 /* If no data is inlined, we know the size of the index list in
386 /* If no data is inlined, we know the size of the index list in
381 * advance: size divided by size of one one revlog record (64 bytes)
387 * advance: size divided by size of one one revlog record (64 bytes)
382 * plus one for the nullid */
388 * plus one for the nullid */
383 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
389 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
384 if (!index)
390 if (!index)
385 goto quit;
391 goto quit;
386
392
387 nodemap = PyDict_New();
393 nodemap = PyDict_New();
388 if (!nodemap)
394 if (!nodemap)
389 goto quit;
395 goto quit;
390
396
391 /* set up the cache return value */
397 /* set up the cache return value */
392 if (inlined) {
398 if (inlined) {
393 /* Note that the reference to data_obj is only borrowed */
399 /* Note that the reference to data_obj is only borrowed */
394 data_obj = PyTuple_GET_ITEM(args, 0);
400 data_obj = PyTuple_GET_ITEM(args, 0);
395 cache = Py_BuildValue("iO", 0, data_obj);
401 cache = Py_BuildValue("iO", 0, data_obj);
396 if (!cache)
402 if (!cache)
397 goto quit;
403 goto quit;
398 } else {
404 } else {
399 cache = Py_None;
405 cache = Py_None;
400 Py_INCREF(Py_None);
406 Py_INCREF(Py_None);
401 }
407 }
402
408
403 /* actually populate the index and the nodemap with data */
409 /* actually populate the index and the nodemap with data */
404 if (!_parse_index_ng (data, size, inlined, index, nodemap))
410 if (!_parse_index_ng (data, size, inlined, index, nodemap))
405 goto quit;
411 goto quit;
406
412
407 rval = Py_BuildValue("NNN", index, nodemap, cache);
413 rval = Py_BuildValue("NNN", index, nodemap, cache);
408 if (!rval)
414 if (!rval)
409 goto quit;
415 goto quit;
410 return rval;
416 return rval;
411
417
412 quit:
418 quit:
413 Py_XDECREF(index);
419 Py_XDECREF(index);
414 Py_XDECREF(nodemap);
420 Py_XDECREF(nodemap);
415 Py_XDECREF(cache);
421 Py_XDECREF(cache);
416 Py_XDECREF(rval);
422 Py_XDECREF(rval);
417 return NULL;
423 return NULL;
418 }
424 }
419
425
420
426
421 static char parsers_doc[] = "Efficient content parsing.";
427 static char parsers_doc[] = "Efficient content parsing.";
422
428
423 static PyMethodDef methods[] = {
429 static PyMethodDef methods[] = {
424 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
430 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
425 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
431 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
426 {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"},
432 {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"},
427 {NULL, NULL}
433 {NULL, NULL}
428 };
434 };
429
435
436 #ifdef IS_PY3K
437 static struct PyModuleDef parsers_module = {
438 PyModuleDef_HEAD_INIT,
439 "parsers",
440 parsers_doc,
441 -1,
442 methods
443 };
444
445 PyMODINIT_FUNC PyInit_parsers(void)
446 {
447 return PyModule_Create(&parsers_module);
448 }
449 #else
430 PyMODINIT_FUNC initparsers(void)
450 PyMODINIT_FUNC initparsers(void)
431 {
451 {
432 Py_InitModule3("parsers", methods, parsers_doc);
452 Py_InitModule3("parsers", methods, parsers_doc);
433 }
453 }
454 #endif
455
General Comments 0
You need to be logged in to leave comments. Login now