##// END OF EJS Templates
parser: use PyInt_FromSsize_t in index_stats...
Adrian Buehlmann -
r16629:1435866c default
parent child Browse files
Show More
@@ -1,1207 +1,1207
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"
14 #include "util.h"
15
15
16 static inline int hexdigit(const char *p, Py_ssize_t off)
16 static inline int hexdigit(const char *p, Py_ssize_t off)
17 {
17 {
18 char c = p[off];
18 char c = p[off];
19
19
20 if (c >= '0' && c <= '9')
20 if (c >= '0' && c <= '9')
21 return c - '0';
21 return c - '0';
22 if (c >= 'a' && c <= 'f')
22 if (c >= 'a' && c <= 'f')
23 return c - 'a' + 10;
23 return c - 'a' + 10;
24 if (c >= 'A' && c <= 'F')
24 if (c >= 'A' && c <= 'F')
25 return c - 'A' + 10;
25 return c - 'A' + 10;
26
26
27 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
27 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
28 return 0;
28 return 0;
29 }
29 }
30
30
31 /*
31 /*
32 * Turn a hex-encoded string into binary.
32 * Turn a hex-encoded string into binary.
33 */
33 */
34 static PyObject *unhexlify(const char *str, int len)
34 static PyObject *unhexlify(const char *str, int len)
35 {
35 {
36 PyObject *ret;
36 PyObject *ret;
37 char *d;
37 char *d;
38 int i;
38 int i;
39
39
40 ret = PyBytes_FromStringAndSize(NULL, len / 2);
40 ret = PyBytes_FromStringAndSize(NULL, len / 2);
41
41
42 if (!ret)
42 if (!ret)
43 return NULL;
43 return NULL;
44
44
45 d = PyBytes_AsString(ret);
45 d = PyBytes_AsString(ret);
46
46
47 for (i = 0; i < len;) {
47 for (i = 0; i < len;) {
48 int hi = hexdigit(str, i++);
48 int hi = hexdigit(str, i++);
49 int lo = hexdigit(str, i++);
49 int lo = hexdigit(str, i++);
50 *d++ = (hi << 4) | lo;
50 *d++ = (hi << 4) | lo;
51 }
51 }
52
52
53 return ret;
53 return ret;
54 }
54 }
55
55
56 /*
56 /*
57 * This code assumes that a manifest is stitched together with newline
57 * This code assumes that a manifest is stitched together with newline
58 * ('\n') characters.
58 * ('\n') characters.
59 */
59 */
60 static PyObject *parse_manifest(PyObject *self, PyObject *args)
60 static PyObject *parse_manifest(PyObject *self, PyObject *args)
61 {
61 {
62 PyObject *mfdict, *fdict;
62 PyObject *mfdict, *fdict;
63 char *str, *cur, *start, *zero;
63 char *str, *cur, *start, *zero;
64 int len;
64 int len;
65
65
66 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
66 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
67 &PyDict_Type, &mfdict,
67 &PyDict_Type, &mfdict,
68 &PyDict_Type, &fdict,
68 &PyDict_Type, &fdict,
69 &str, &len))
69 &str, &len))
70 goto quit;
70 goto quit;
71
71
72 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
72 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
73 PyObject *file = NULL, *node = NULL;
73 PyObject *file = NULL, *node = NULL;
74 PyObject *flags = NULL;
74 PyObject *flags = NULL;
75 int nlen;
75 int nlen;
76
76
77 if (!*cur) {
77 if (!*cur) {
78 zero = cur;
78 zero = cur;
79 continue;
79 continue;
80 }
80 }
81 else if (*cur != '\n')
81 else if (*cur != '\n')
82 continue;
82 continue;
83
83
84 if (!zero) {
84 if (!zero) {
85 PyErr_SetString(PyExc_ValueError,
85 PyErr_SetString(PyExc_ValueError,
86 "manifest entry has no separator");
86 "manifest entry has no separator");
87 goto quit;
87 goto quit;
88 }
88 }
89
89
90 file = PyBytes_FromStringAndSize(start, zero - start);
90 file = PyBytes_FromStringAndSize(start, zero - start);
91
91
92 if (!file)
92 if (!file)
93 goto bail;
93 goto bail;
94
94
95 nlen = cur - zero - 1;
95 nlen = cur - zero - 1;
96
96
97 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
97 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
98 if (!node)
98 if (!node)
99 goto bail;
99 goto bail;
100
100
101 if (nlen > 40) {
101 if (nlen > 40) {
102 flags = PyBytes_FromStringAndSize(zero + 41,
102 flags = PyBytes_FromStringAndSize(zero + 41,
103 nlen - 40);
103 nlen - 40);
104 if (!flags)
104 if (!flags)
105 goto bail;
105 goto bail;
106
106
107 if (PyDict_SetItem(fdict, file, flags) == -1)
107 if (PyDict_SetItem(fdict, file, flags) == -1)
108 goto bail;
108 goto bail;
109 }
109 }
110
110
111 if (PyDict_SetItem(mfdict, file, node) == -1)
111 if (PyDict_SetItem(mfdict, file, node) == -1)
112 goto bail;
112 goto bail;
113
113
114 start = cur + 1;
114 start = cur + 1;
115 zero = NULL;
115 zero = NULL;
116
116
117 Py_XDECREF(flags);
117 Py_XDECREF(flags);
118 Py_XDECREF(node);
118 Py_XDECREF(node);
119 Py_XDECREF(file);
119 Py_XDECREF(file);
120 continue;
120 continue;
121 bail:
121 bail:
122 Py_XDECREF(flags);
122 Py_XDECREF(flags);
123 Py_XDECREF(node);
123 Py_XDECREF(node);
124 Py_XDECREF(file);
124 Py_XDECREF(file);
125 goto quit;
125 goto quit;
126 }
126 }
127
127
128 if (len > 0 && *(cur - 1) != '\n') {
128 if (len > 0 && *(cur - 1) != '\n') {
129 PyErr_SetString(PyExc_ValueError,
129 PyErr_SetString(PyExc_ValueError,
130 "manifest contains trailing garbage");
130 "manifest contains trailing garbage");
131 goto quit;
131 goto quit;
132 }
132 }
133
133
134 Py_INCREF(Py_None);
134 Py_INCREF(Py_None);
135 return Py_None;
135 return Py_None;
136 quit:
136 quit:
137 return NULL;
137 return NULL;
138 }
138 }
139
139
140 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
140 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
141 {
141 {
142 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
142 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
143 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
143 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
144 char *str, *cur, *end, *cpos;
144 char *str, *cur, *end, *cpos;
145 int state, mode, size, mtime;
145 int state, mode, size, mtime;
146 unsigned int flen;
146 unsigned int flen;
147 int len;
147 int len;
148
148
149 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
149 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
150 &PyDict_Type, &dmap,
150 &PyDict_Type, &dmap,
151 &PyDict_Type, &cmap,
151 &PyDict_Type, &cmap,
152 &str, &len))
152 &str, &len))
153 goto quit;
153 goto quit;
154
154
155 /* read parents */
155 /* read parents */
156 if (len < 40)
156 if (len < 40)
157 goto quit;
157 goto quit;
158
158
159 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
159 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
160 if (!parents)
160 if (!parents)
161 goto quit;
161 goto quit;
162
162
163 /* read filenames */
163 /* read filenames */
164 cur = str + 40;
164 cur = str + 40;
165 end = str + len;
165 end = str + len;
166
166
167 while (cur < end - 17) {
167 while (cur < end - 17) {
168 /* unpack header */
168 /* unpack header */
169 state = *cur;
169 state = *cur;
170 mode = getbe32(cur + 1);
170 mode = getbe32(cur + 1);
171 size = getbe32(cur + 5);
171 size = getbe32(cur + 5);
172 mtime = getbe32(cur + 9);
172 mtime = getbe32(cur + 9);
173 flen = getbe32(cur + 13);
173 flen = getbe32(cur + 13);
174 cur += 17;
174 cur += 17;
175 if (cur + flen > end || cur + flen < cur) {
175 if (cur + flen > end || cur + flen < cur) {
176 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
176 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
177 goto quit;
177 goto quit;
178 }
178 }
179
179
180 entry = Py_BuildValue("ciii", state, mode, size, mtime);
180 entry = Py_BuildValue("ciii", state, mode, size, mtime);
181 if (!entry)
181 if (!entry)
182 goto quit;
182 goto quit;
183 PyObject_GC_UnTrack(entry); /* don't waste time with this */
183 PyObject_GC_UnTrack(entry); /* don't waste time with this */
184
184
185 cpos = memchr(cur, 0, flen);
185 cpos = memchr(cur, 0, flen);
186 if (cpos) {
186 if (cpos) {
187 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
187 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
188 cname = PyBytes_FromStringAndSize(cpos + 1,
188 cname = PyBytes_FromStringAndSize(cpos + 1,
189 flen - (cpos - cur) - 1);
189 flen - (cpos - cur) - 1);
190 if (!fname || !cname ||
190 if (!fname || !cname ||
191 PyDict_SetItem(cmap, fname, cname) == -1 ||
191 PyDict_SetItem(cmap, fname, cname) == -1 ||
192 PyDict_SetItem(dmap, fname, entry) == -1)
192 PyDict_SetItem(dmap, fname, entry) == -1)
193 goto quit;
193 goto quit;
194 Py_DECREF(cname);
194 Py_DECREF(cname);
195 } else {
195 } else {
196 fname = PyBytes_FromStringAndSize(cur, flen);
196 fname = PyBytes_FromStringAndSize(cur, flen);
197 if (!fname ||
197 if (!fname ||
198 PyDict_SetItem(dmap, fname, entry) == -1)
198 PyDict_SetItem(dmap, fname, entry) == -1)
199 goto quit;
199 goto quit;
200 }
200 }
201 cur += flen;
201 cur += flen;
202 Py_DECREF(fname);
202 Py_DECREF(fname);
203 Py_DECREF(entry);
203 Py_DECREF(entry);
204 fname = cname = entry = NULL;
204 fname = cname = entry = NULL;
205 }
205 }
206
206
207 ret = parents;
207 ret = parents;
208 Py_INCREF(ret);
208 Py_INCREF(ret);
209 quit:
209 quit:
210 Py_XDECREF(fname);
210 Py_XDECREF(fname);
211 Py_XDECREF(cname);
211 Py_XDECREF(cname);
212 Py_XDECREF(entry);
212 Py_XDECREF(entry);
213 Py_XDECREF(parents);
213 Py_XDECREF(parents);
214 return ret;
214 return ret;
215 }
215 }
216
216
217 /*
217 /*
218 * A base-16 trie for fast node->rev mapping.
218 * A base-16 trie for fast node->rev mapping.
219 *
219 *
220 * Positive value is index of the next node in the trie
220 * Positive value is index of the next node in the trie
221 * Negative value is a leaf: -(rev + 1)
221 * Negative value is a leaf: -(rev + 1)
222 * Zero is empty
222 * Zero is empty
223 */
223 */
224 typedef struct {
224 typedef struct {
225 int children[16];
225 int children[16];
226 } nodetree;
226 } nodetree;
227
227
228 /*
228 /*
229 * This class has two behaviours.
229 * This class has two behaviours.
230 *
230 *
231 * When used in a list-like way (with integer keys), we decode an
231 * When used in a list-like way (with integer keys), we decode an
232 * entry in a RevlogNG index file on demand. Our last entry is a
232 * entry in a RevlogNG index file on demand. Our last entry is a
233 * sentinel, always a nullid. We have limited support for
233 * sentinel, always a nullid. We have limited support for
234 * integer-keyed insert and delete, only at elements right before the
234 * integer-keyed insert and delete, only at elements right before the
235 * sentinel.
235 * sentinel.
236 *
236 *
237 * With string keys, we lazily perform a reverse mapping from node to
237 * With string keys, we lazily perform a reverse mapping from node to
238 * rev, using a base-16 trie.
238 * rev, using a base-16 trie.
239 */
239 */
240 typedef struct {
240 typedef struct {
241 PyObject_HEAD
241 PyObject_HEAD
242 /* Type-specific fields go here. */
242 /* Type-specific fields go here. */
243 PyObject *data; /* raw bytes of index */
243 PyObject *data; /* raw bytes of index */
244 PyObject **cache; /* cached tuples */
244 PyObject **cache; /* cached tuples */
245 const char **offsets; /* populated on demand */
245 const char **offsets; /* populated on demand */
246 Py_ssize_t raw_length; /* original number of elements */
246 Py_ssize_t raw_length; /* original number of elements */
247 Py_ssize_t length; /* current number of elements */
247 Py_ssize_t length; /* current number of elements */
248 PyObject *added; /* populated on demand */
248 PyObject *added; /* populated on demand */
249 nodetree *nt; /* base-16 trie */
249 nodetree *nt; /* base-16 trie */
250 int ntlength; /* # nodes in use */
250 int ntlength; /* # nodes in use */
251 int ntcapacity; /* # nodes allocated */
251 int ntcapacity; /* # nodes allocated */
252 int ntdepth; /* maximum depth of tree */
252 int ntdepth; /* maximum depth of tree */
253 int ntsplits; /* # splits performed */
253 int ntsplits; /* # splits performed */
254 int ntrev; /* last rev scanned */
254 int ntrev; /* last rev scanned */
255 int ntlookups; /* # lookups */
255 int ntlookups; /* # lookups */
256 int ntmisses; /* # lookups that miss the cache */
256 int ntmisses; /* # lookups that miss the cache */
257 int inlined;
257 int inlined;
258 } indexObject;
258 } indexObject;
259
259
260 static Py_ssize_t index_length(const indexObject *self)
260 static Py_ssize_t index_length(const indexObject *self)
261 {
261 {
262 if (self->added == NULL)
262 if (self->added == NULL)
263 return self->length;
263 return self->length;
264 return self->length + PyList_GET_SIZE(self->added);
264 return self->length + PyList_GET_SIZE(self->added);
265 }
265 }
266
266
267 static PyObject *nullentry;
267 static PyObject *nullentry;
268 static const char nullid[20];
268 static const char nullid[20];
269
269
270 static long inline_scan(indexObject *self, const char **offsets);
270 static long inline_scan(indexObject *self, const char **offsets);
271
271
272 #if LONG_MAX == 0x7fffffffL
272 #if LONG_MAX == 0x7fffffffL
273 static char *tuple_format = "Kiiiiiis#";
273 static char *tuple_format = "Kiiiiiis#";
274 #else
274 #else
275 static char *tuple_format = "kiiiiiis#";
275 static char *tuple_format = "kiiiiiis#";
276 #endif
276 #endif
277
277
278 /*
278 /*
279 * Return a pointer to the beginning of a RevlogNG record.
279 * Return a pointer to the beginning of a RevlogNG record.
280 */
280 */
281 static const char *index_deref(indexObject *self, Py_ssize_t pos)
281 static const char *index_deref(indexObject *self, Py_ssize_t pos)
282 {
282 {
283 if (self->inlined && pos > 0) {
283 if (self->inlined && pos > 0) {
284 if (self->offsets == NULL) {
284 if (self->offsets == NULL) {
285 self->offsets = malloc(self->raw_length *
285 self->offsets = malloc(self->raw_length *
286 sizeof(*self->offsets));
286 sizeof(*self->offsets));
287 if (self->offsets == NULL)
287 if (self->offsets == NULL)
288 return (const char *)PyErr_NoMemory();
288 return (const char *)PyErr_NoMemory();
289 inline_scan(self, self->offsets);
289 inline_scan(self, self->offsets);
290 }
290 }
291 return self->offsets[pos];
291 return self->offsets[pos];
292 }
292 }
293
293
294 return PyString_AS_STRING(self->data) + pos * 64;
294 return PyString_AS_STRING(self->data) + pos * 64;
295 }
295 }
296
296
297 /*
297 /*
298 * RevlogNG format (all in big endian, data may be inlined):
298 * RevlogNG format (all in big endian, data may be inlined):
299 * 6 bytes: offset
299 * 6 bytes: offset
300 * 2 bytes: flags
300 * 2 bytes: flags
301 * 4 bytes: compressed length
301 * 4 bytes: compressed length
302 * 4 bytes: uncompressed length
302 * 4 bytes: uncompressed length
303 * 4 bytes: base revision
303 * 4 bytes: base revision
304 * 4 bytes: link revision
304 * 4 bytes: link revision
305 * 4 bytes: parent 1 revision
305 * 4 bytes: parent 1 revision
306 * 4 bytes: parent 2 revision
306 * 4 bytes: parent 2 revision
307 * 32 bytes: nodeid (only 20 bytes used)
307 * 32 bytes: nodeid (only 20 bytes used)
308 */
308 */
309 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
309 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
310 {
310 {
311 uint64_t offset_flags;
311 uint64_t offset_flags;
312 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
312 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
313 const char *c_node_id;
313 const char *c_node_id;
314 const char *data;
314 const char *data;
315 Py_ssize_t length = index_length(self);
315 Py_ssize_t length = index_length(self);
316 PyObject *entry;
316 PyObject *entry;
317
317
318 if (pos < 0)
318 if (pos < 0)
319 pos += length;
319 pos += length;
320
320
321 if (pos < 0 || pos >= length) {
321 if (pos < 0 || pos >= length) {
322 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
322 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
323 return NULL;
323 return NULL;
324 }
324 }
325
325
326 if (pos == length - 1) {
326 if (pos == length - 1) {
327 Py_INCREF(nullentry);
327 Py_INCREF(nullentry);
328 return nullentry;
328 return nullentry;
329 }
329 }
330
330
331 if (pos >= self->length - 1) {
331 if (pos >= self->length - 1) {
332 PyObject *obj;
332 PyObject *obj;
333 obj = PyList_GET_ITEM(self->added, pos - self->length + 1);
333 obj = PyList_GET_ITEM(self->added, pos - self->length + 1);
334 Py_INCREF(obj);
334 Py_INCREF(obj);
335 return obj;
335 return obj;
336 }
336 }
337
337
338 if (self->cache) {
338 if (self->cache) {
339 if (self->cache[pos]) {
339 if (self->cache[pos]) {
340 Py_INCREF(self->cache[pos]);
340 Py_INCREF(self->cache[pos]);
341 return self->cache[pos];
341 return self->cache[pos];
342 }
342 }
343 } else {
343 } else {
344 self->cache = calloc(self->raw_length, sizeof(PyObject *));
344 self->cache = calloc(self->raw_length, sizeof(PyObject *));
345 if (self->cache == NULL)
345 if (self->cache == NULL)
346 return PyErr_NoMemory();
346 return PyErr_NoMemory();
347 }
347 }
348
348
349 data = index_deref(self, pos);
349 data = index_deref(self, pos);
350 if (data == NULL)
350 if (data == NULL)
351 return NULL;
351 return NULL;
352
352
353 offset_flags = getbe32(data + 4);
353 offset_flags = getbe32(data + 4);
354 if (pos == 0) /* mask out version number for the first entry */
354 if (pos == 0) /* mask out version number for the first entry */
355 offset_flags &= 0xFFFF;
355 offset_flags &= 0xFFFF;
356 else {
356 else {
357 uint32_t offset_high = getbe32(data);
357 uint32_t offset_high = getbe32(data);
358 offset_flags |= ((uint64_t)offset_high) << 32;
358 offset_flags |= ((uint64_t)offset_high) << 32;
359 }
359 }
360
360
361 comp_len = getbe32(data + 8);
361 comp_len = getbe32(data + 8);
362 uncomp_len = getbe32(data + 12);
362 uncomp_len = getbe32(data + 12);
363 base_rev = getbe32(data + 16);
363 base_rev = getbe32(data + 16);
364 link_rev = getbe32(data + 20);
364 link_rev = getbe32(data + 20);
365 parent_1 = getbe32(data + 24);
365 parent_1 = getbe32(data + 24);
366 parent_2 = getbe32(data + 28);
366 parent_2 = getbe32(data + 28);
367 c_node_id = data + 32;
367 c_node_id = data + 32;
368
368
369 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
369 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
370 uncomp_len, base_rev, link_rev,
370 uncomp_len, base_rev, link_rev,
371 parent_1, parent_2, c_node_id, 20);
371 parent_1, parent_2, c_node_id, 20);
372
372
373 if (entry)
373 if (entry)
374 PyObject_GC_UnTrack(entry);
374 PyObject_GC_UnTrack(entry);
375
375
376 self->cache[pos] = entry;
376 self->cache[pos] = entry;
377 Py_INCREF(entry);
377 Py_INCREF(entry);
378
378
379 return entry;
379 return entry;
380 }
380 }
381
381
382 /*
382 /*
383 * Return the 20-byte SHA of the node corresponding to the given rev.
383 * Return the 20-byte SHA of the node corresponding to the given rev.
384 */
384 */
385 static const char *index_node(indexObject *self, Py_ssize_t pos)
385 static const char *index_node(indexObject *self, Py_ssize_t pos)
386 {
386 {
387 Py_ssize_t length = index_length(self);
387 Py_ssize_t length = index_length(self);
388 const char *data;
388 const char *data;
389
389
390 if (pos == length - 1)
390 if (pos == length - 1)
391 return nullid;
391 return nullid;
392
392
393 if (pos >= length)
393 if (pos >= length)
394 return NULL;
394 return NULL;
395
395
396 if (pos >= self->length - 1) {
396 if (pos >= self->length - 1) {
397 PyObject *tuple, *str;
397 PyObject *tuple, *str;
398 tuple = PyList_GET_ITEM(self->added, pos - self->length + 1);
398 tuple = PyList_GET_ITEM(self->added, pos - self->length + 1);
399 str = PyTuple_GetItem(tuple, 7);
399 str = PyTuple_GetItem(tuple, 7);
400 return str ? PyString_AS_STRING(str) : NULL;
400 return str ? PyString_AS_STRING(str) : NULL;
401 }
401 }
402
402
403 data = index_deref(self, pos);
403 data = index_deref(self, pos);
404 return data ? data + 32 : NULL;
404 return data ? data + 32 : NULL;
405 }
405 }
406
406
407 static int nt_insert(indexObject *self, const char *node, int rev);
407 static int nt_insert(indexObject *self, const char *node, int rev);
408
408
409 static int node_check(PyObject *obj, char **node, Py_ssize_t *nodelen)
409 static int node_check(PyObject *obj, char **node, Py_ssize_t *nodelen)
410 {
410 {
411 if (PyString_AsStringAndSize(obj, node, nodelen) == -1)
411 if (PyString_AsStringAndSize(obj, node, nodelen) == -1)
412 return -1;
412 return -1;
413 if (*nodelen == 20)
413 if (*nodelen == 20)
414 return 0;
414 return 0;
415 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
415 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
416 return -1;
416 return -1;
417 }
417 }
418
418
419 static PyObject *index_insert(indexObject *self, PyObject *args)
419 static PyObject *index_insert(indexObject *self, PyObject *args)
420 {
420 {
421 PyObject *obj;
421 PyObject *obj;
422 char *node;
422 char *node;
423 long offset;
423 long offset;
424 Py_ssize_t len, nodelen;
424 Py_ssize_t len, nodelen;
425
425
426 if (!PyArg_ParseTuple(args, "lO", &offset, &obj))
426 if (!PyArg_ParseTuple(args, "lO", &offset, &obj))
427 return NULL;
427 return NULL;
428
428
429 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
429 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
430 PyErr_SetString(PyExc_TypeError, "8-tuple required");
430 PyErr_SetString(PyExc_TypeError, "8-tuple required");
431 return NULL;
431 return NULL;
432 }
432 }
433
433
434 if (node_check(PyTuple_GET_ITEM(obj, 7), &node, &nodelen) == -1)
434 if (node_check(PyTuple_GET_ITEM(obj, 7), &node, &nodelen) == -1)
435 return NULL;
435 return NULL;
436
436
437 len = index_length(self);
437 len = index_length(self);
438
438
439 if (offset < 0)
439 if (offset < 0)
440 offset += len;
440 offset += len;
441
441
442 if (offset != len - 1) {
442 if (offset != len - 1) {
443 PyErr_SetString(PyExc_IndexError,
443 PyErr_SetString(PyExc_IndexError,
444 "insert only supported at index -1");
444 "insert only supported at index -1");
445 return NULL;
445 return NULL;
446 }
446 }
447
447
448 if (offset > INT_MAX) {
448 if (offset > INT_MAX) {
449 PyErr_SetString(PyExc_ValueError,
449 PyErr_SetString(PyExc_ValueError,
450 "currently only 2**31 revs supported");
450 "currently only 2**31 revs supported");
451 return NULL;
451 return NULL;
452 }
452 }
453
453
454 if (self->added == NULL) {
454 if (self->added == NULL) {
455 self->added = PyList_New(0);
455 self->added = PyList_New(0);
456 if (self->added == NULL)
456 if (self->added == NULL)
457 return NULL;
457 return NULL;
458 }
458 }
459
459
460 if (PyList_Append(self->added, obj) == -1)
460 if (PyList_Append(self->added, obj) == -1)
461 return NULL;
461 return NULL;
462
462
463 if (self->nt)
463 if (self->nt)
464 nt_insert(self, node, (int)offset);
464 nt_insert(self, node, (int)offset);
465
465
466 Py_RETURN_NONE;
466 Py_RETURN_NONE;
467 }
467 }
468
468
469 static void _index_clearcaches(indexObject *self)
469 static void _index_clearcaches(indexObject *self)
470 {
470 {
471 if (self->cache) {
471 if (self->cache) {
472 Py_ssize_t i;
472 Py_ssize_t i;
473
473
474 for (i = 0; i < self->raw_length; i++) {
474 for (i = 0; i < self->raw_length; i++) {
475 if (self->cache[i]) {
475 if (self->cache[i]) {
476 Py_DECREF(self->cache[i]);
476 Py_DECREF(self->cache[i]);
477 self->cache[i] = NULL;
477 self->cache[i] = NULL;
478 }
478 }
479 }
479 }
480 free(self->cache);
480 free(self->cache);
481 self->cache = NULL;
481 self->cache = NULL;
482 }
482 }
483 if (self->offsets) {
483 if (self->offsets) {
484 free(self->offsets);
484 free(self->offsets);
485 self->offsets = NULL;
485 self->offsets = NULL;
486 }
486 }
487 if (self->nt) {
487 if (self->nt) {
488 free(self->nt);
488 free(self->nt);
489 self->nt = NULL;
489 self->nt = NULL;
490 }
490 }
491 }
491 }
492
492
493 static PyObject *index_clearcaches(indexObject *self)
493 static PyObject *index_clearcaches(indexObject *self)
494 {
494 {
495 _index_clearcaches(self);
495 _index_clearcaches(self);
496 self->ntlength = self->ntcapacity = 0;
496 self->ntlength = self->ntcapacity = 0;
497 self->ntdepth = self->ntsplits = 0;
497 self->ntdepth = self->ntsplits = 0;
498 self->ntrev = -1;
498 self->ntrev = -1;
499 self->ntlookups = self->ntmisses = 0;
499 self->ntlookups = self->ntmisses = 0;
500 Py_RETURN_NONE;
500 Py_RETURN_NONE;
501 }
501 }
502
502
503 static PyObject *index_stats(indexObject *self)
503 static PyObject *index_stats(indexObject *self)
504 {
504 {
505 PyObject *obj = PyDict_New();
505 PyObject *obj = PyDict_New();
506
506
507 if (obj == NULL)
507 if (obj == NULL)
508 return NULL;
508 return NULL;
509
509
510 #define istat(__n, __d) \
510 #define istat(__n, __d) \
511 if (PyDict_SetItemString(obj, __d, PyInt_FromLong(self->__n)) == -1) \
511 if (PyDict_SetItemString(obj, __d, PyInt_FromSsize_t(self->__n)) == -1) \
512 goto bail;
512 goto bail;
513
513
514 if (self->added) {
514 if (self->added) {
515 Py_ssize_t len = PyList_GET_SIZE(self->added);
515 Py_ssize_t len = PyList_GET_SIZE(self->added);
516 if (PyDict_SetItemString(obj, "index entries added",
516 if (PyDict_SetItemString(obj, "index entries added",
517 PyInt_FromLong(len)) == -1)
517 PyInt_FromSsize_t(len)) == -1)
518 goto bail;
518 goto bail;
519 }
519 }
520
520
521 if (self->raw_length != self->length - 1)
521 if (self->raw_length != self->length - 1)
522 istat(raw_length, "revs on disk");
522 istat(raw_length, "revs on disk");
523 istat(length, "revs in memory");
523 istat(length, "revs in memory");
524 istat(ntcapacity, "node trie capacity");
524 istat(ntcapacity, "node trie capacity");
525 istat(ntdepth, "node trie depth");
525 istat(ntdepth, "node trie depth");
526 istat(ntlength, "node trie count");
526 istat(ntlength, "node trie count");
527 istat(ntlookups, "node trie lookups");
527 istat(ntlookups, "node trie lookups");
528 istat(ntmisses, "node trie misses");
528 istat(ntmisses, "node trie misses");
529 istat(ntrev, "node trie last rev scanned");
529 istat(ntrev, "node trie last rev scanned");
530 istat(ntsplits, "node trie splits");
530 istat(ntsplits, "node trie splits");
531
531
532 #undef istat
532 #undef istat
533
533
534 return obj;
534 return obj;
535
535
536 bail:
536 bail:
537 Py_XDECREF(obj);
537 Py_XDECREF(obj);
538 return NULL;
538 return NULL;
539 }
539 }
540
540
541 static inline int nt_level(const char *node, Py_ssize_t level)
541 static inline int nt_level(const char *node, Py_ssize_t level)
542 {
542 {
543 int v = node[level>>1];
543 int v = node[level>>1];
544 if (!(level & 1))
544 if (!(level & 1))
545 v >>= 4;
545 v >>= 4;
546 return v & 0xf;
546 return v & 0xf;
547 }
547 }
548
548
549 /*
549 /*
550 * Return values:
550 * Return values:
551 *
551 *
552 * -4: match is ambiguous (multiple candidates)
552 * -4: match is ambiguous (multiple candidates)
553 * -2: not found
553 * -2: not found
554 * rest: valid rev
554 * rest: valid rev
555 */
555 */
556 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen)
556 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen)
557 {
557 {
558 int level, off;
558 int level, off;
559
559
560 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
560 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
561 return -1;
561 return -1;
562
562
563 if (self->nt == NULL)
563 if (self->nt == NULL)
564 return -2;
564 return -2;
565
565
566 for (level = off = 0; level < nodelen; level++) {
566 for (level = off = 0; level < nodelen; level++) {
567 int k = nt_level(node, level);
567 int k = nt_level(node, level);
568 nodetree *n = &self->nt[off];
568 nodetree *n = &self->nt[off];
569 int v = n->children[k];
569 int v = n->children[k];
570
570
571 if (v < 0) {
571 if (v < 0) {
572 const char *n;
572 const char *n;
573 v = -v - 1;
573 v = -v - 1;
574 n = index_node(self, v);
574 n = index_node(self, v);
575 if (n == NULL)
575 if (n == NULL)
576 return -2;
576 return -2;
577 return memcmp(node, n, nodelen > 20 ? 20 : nodelen)
577 return memcmp(node, n, nodelen > 20 ? 20 : nodelen)
578 ? -2 : v;
578 ? -2 : v;
579 }
579 }
580 if (v == 0)
580 if (v == 0)
581 return -2;
581 return -2;
582 off = v;
582 off = v;
583 }
583 }
584 /* multiple matches against an ambiguous prefix */
584 /* multiple matches against an ambiguous prefix */
585 return -4;
585 return -4;
586 }
586 }
587
587
588 static int nt_new(indexObject *self)
588 static int nt_new(indexObject *self)
589 {
589 {
590 if (self->ntlength == self->ntcapacity) {
590 if (self->ntlength == self->ntcapacity) {
591 self->ntcapacity *= 2;
591 self->ntcapacity *= 2;
592 self->nt = realloc(self->nt,
592 self->nt = realloc(self->nt,
593 self->ntcapacity * sizeof(nodetree));
593 self->ntcapacity * sizeof(nodetree));
594 if (self->nt == NULL) {
594 if (self->nt == NULL) {
595 PyErr_SetString(PyExc_MemoryError, "out of memory");
595 PyErr_SetString(PyExc_MemoryError, "out of memory");
596 return -1;
596 return -1;
597 }
597 }
598 memset(&self->nt[self->ntlength], 0,
598 memset(&self->nt[self->ntlength], 0,
599 sizeof(nodetree) * (self->ntcapacity - self->ntlength));
599 sizeof(nodetree) * (self->ntcapacity - self->ntlength));
600 }
600 }
601 return self->ntlength++;
601 return self->ntlength++;
602 }
602 }
603
603
604 static int nt_insert(indexObject *self, const char *node, int rev)
604 static int nt_insert(indexObject *self, const char *node, int rev)
605 {
605 {
606 int level = 0;
606 int level = 0;
607 int off = 0;
607 int off = 0;
608
608
609 while (level < 20) {
609 while (level < 20) {
610 int k = nt_level(node, level);
610 int k = nt_level(node, level);
611 nodetree *n;
611 nodetree *n;
612 int v;
612 int v;
613
613
614 n = &self->nt[off];
614 n = &self->nt[off];
615 v = n->children[k];
615 v = n->children[k];
616
616
617 if (v == 0) {
617 if (v == 0) {
618 n->children[k] = -rev - 1;
618 n->children[k] = -rev - 1;
619 return 0;
619 return 0;
620 }
620 }
621 if (v < 0) {
621 if (v < 0) {
622 const char *oldnode = index_node(self, -v - 1);
622 const char *oldnode = index_node(self, -v - 1);
623 int noff;
623 int noff;
624
624
625 if (!oldnode || !memcmp(oldnode, node, 20)) {
625 if (!oldnode || !memcmp(oldnode, node, 20)) {
626 n->children[k] = -rev - 1;
626 n->children[k] = -rev - 1;
627 return 0;
627 return 0;
628 }
628 }
629 noff = nt_new(self);
629 noff = nt_new(self);
630 if (noff == -1)
630 if (noff == -1)
631 return -1;
631 return -1;
632 /* self->nt may have been changed by realloc */
632 /* self->nt may have been changed by realloc */
633 self->nt[off].children[k] = noff;
633 self->nt[off].children[k] = noff;
634 off = noff;
634 off = noff;
635 n = &self->nt[off];
635 n = &self->nt[off];
636 n->children[nt_level(oldnode, ++level)] = v;
636 n->children[nt_level(oldnode, ++level)] = v;
637 if (level > self->ntdepth)
637 if (level > self->ntdepth)
638 self->ntdepth = level;
638 self->ntdepth = level;
639 self->ntsplits += 1;
639 self->ntsplits += 1;
640 } else {
640 } else {
641 level += 1;
641 level += 1;
642 off = v;
642 off = v;
643 }
643 }
644 }
644 }
645
645
646 return -1;
646 return -1;
647 }
647 }
648
648
649 static int nt_init(indexObject *self)
649 static int nt_init(indexObject *self)
650 {
650 {
651 if (self->nt == NULL) {
651 if (self->nt == NULL) {
652 self->ntcapacity = self->raw_length < 4
652 self->ntcapacity = self->raw_length < 4
653 ? 4 : self->raw_length / 2;
653 ? 4 : self->raw_length / 2;
654 self->nt = calloc(self->ntcapacity, sizeof(nodetree));
654 self->nt = calloc(self->ntcapacity, sizeof(nodetree));
655 if (self->nt == NULL) {
655 if (self->nt == NULL) {
656 PyErr_NoMemory();
656 PyErr_NoMemory();
657 return -1;
657 return -1;
658 }
658 }
659 self->ntlength = 1;
659 self->ntlength = 1;
660 self->ntrev = (int)index_length(self) - 1;
660 self->ntrev = (int)index_length(self) - 1;
661 self->ntlookups = 1;
661 self->ntlookups = 1;
662 self->ntmisses = 0;
662 self->ntmisses = 0;
663 }
663 }
664 return 0;
664 return 0;
665 }
665 }
666
666
667 /*
667 /*
668 * Return values:
668 * Return values:
669 *
669 *
670 * -3: error (exception set)
670 * -3: error (exception set)
671 * -2: not found (no exception set)
671 * -2: not found (no exception set)
672 * rest: valid rev
672 * rest: valid rev
673 */
673 */
674 static int index_find_node(indexObject *self,
674 static int index_find_node(indexObject *self,
675 const char *node, Py_ssize_t nodelen)
675 const char *node, Py_ssize_t nodelen)
676 {
676 {
677 int rev;
677 int rev;
678
678
679 self->ntlookups++;
679 self->ntlookups++;
680 rev = nt_find(self, node, nodelen);
680 rev = nt_find(self, node, nodelen);
681 if (rev >= -1)
681 if (rev >= -1)
682 return rev;
682 return rev;
683
683
684 if (nt_init(self) == -1)
684 if (nt_init(self) == -1)
685 return -3;
685 return -3;
686
686
687 /*
687 /*
688 * For the first handful of lookups, we scan the entire index,
688 * For the first handful of lookups, we scan the entire index,
689 * and cache only the matching nodes. This optimizes for cases
689 * and cache only the matching nodes. This optimizes for cases
690 * like "hg tip", where only a few nodes are accessed.
690 * like "hg tip", where only a few nodes are accessed.
691 *
691 *
692 * After that, we cache every node we visit, using a single
692 * After that, we cache every node we visit, using a single
693 * scan amortized over multiple lookups. This gives the best
693 * scan amortized over multiple lookups. This gives the best
694 * bulk performance, e.g. for "hg log".
694 * bulk performance, e.g. for "hg log".
695 */
695 */
696 if (self->ntmisses++ < 4) {
696 if (self->ntmisses++ < 4) {
697 for (rev = self->ntrev - 1; rev >= 0; rev--) {
697 for (rev = self->ntrev - 1; rev >= 0; rev--) {
698 const char *n = index_node(self, rev);
698 const char *n = index_node(self, rev);
699 if (n == NULL)
699 if (n == NULL)
700 return -2;
700 return -2;
701 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
701 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
702 if (nt_insert(self, n, rev) == -1)
702 if (nt_insert(self, n, rev) == -1)
703 return -3;
703 return -3;
704 break;
704 break;
705 }
705 }
706 }
706 }
707 } else {
707 } else {
708 for (rev = self->ntrev - 1; rev >= 0; rev--) {
708 for (rev = self->ntrev - 1; rev >= 0; rev--) {
709 const char *n = index_node(self, rev);
709 const char *n = index_node(self, rev);
710 if (n == NULL) {
710 if (n == NULL) {
711 self->ntrev = rev + 1;
711 self->ntrev = rev + 1;
712 return -2;
712 return -2;
713 }
713 }
714 if (nt_insert(self, n, rev) == -1) {
714 if (nt_insert(self, n, rev) == -1) {
715 self->ntrev = rev + 1;
715 self->ntrev = rev + 1;
716 return -3;
716 return -3;
717 }
717 }
718 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
718 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
719 break;
719 break;
720 }
720 }
721 }
721 }
722 self->ntrev = rev;
722 self->ntrev = rev;
723 }
723 }
724
724
725 if (rev >= 0)
725 if (rev >= 0)
726 return rev;
726 return rev;
727 return -2;
727 return -2;
728 }
728 }
729
729
730 static PyObject *raise_revlog_error(void)
730 static PyObject *raise_revlog_error(void)
731 {
731 {
732 static PyObject *errclass;
732 static PyObject *errclass;
733 PyObject *mod = NULL, *errobj;
733 PyObject *mod = NULL, *errobj;
734
734
735 if (errclass == NULL) {
735 if (errclass == NULL) {
736 PyObject *dict;
736 PyObject *dict;
737
737
738 mod = PyImport_ImportModule("mercurial.error");
738 mod = PyImport_ImportModule("mercurial.error");
739 if (mod == NULL)
739 if (mod == NULL)
740 goto classfail;
740 goto classfail;
741
741
742 dict = PyModule_GetDict(mod);
742 dict = PyModule_GetDict(mod);
743 if (dict == NULL)
743 if (dict == NULL)
744 goto classfail;
744 goto classfail;
745
745
746 errclass = PyDict_GetItemString(dict, "RevlogError");
746 errclass = PyDict_GetItemString(dict, "RevlogError");
747 if (errclass == NULL) {
747 if (errclass == NULL) {
748 PyErr_SetString(PyExc_SystemError,
748 PyErr_SetString(PyExc_SystemError,
749 "could not find RevlogError");
749 "could not find RevlogError");
750 goto classfail;
750 goto classfail;
751 }
751 }
752 Py_INCREF(errclass);
752 Py_INCREF(errclass);
753 }
753 }
754
754
755 errobj = PyObject_CallFunction(errclass, NULL);
755 errobj = PyObject_CallFunction(errclass, NULL);
756 if (errobj == NULL)
756 if (errobj == NULL)
757 return NULL;
757 return NULL;
758 PyErr_SetObject(errclass, errobj);
758 PyErr_SetObject(errclass, errobj);
759 return errobj;
759 return errobj;
760
760
761 classfail:
761 classfail:
762 Py_XDECREF(mod);
762 Py_XDECREF(mod);
763 return NULL;
763 return NULL;
764 }
764 }
765
765
766 static PyObject *index_getitem(indexObject *self, PyObject *value)
766 static PyObject *index_getitem(indexObject *self, PyObject *value)
767 {
767 {
768 char *node;
768 char *node;
769 Py_ssize_t nodelen;
769 Py_ssize_t nodelen;
770 int rev;
770 int rev;
771
771
772 if (PyInt_Check(value))
772 if (PyInt_Check(value))
773 return index_get(self, PyInt_AS_LONG(value));
773 return index_get(self, PyInt_AS_LONG(value));
774
774
775 if (PyString_AsStringAndSize(value, &node, &nodelen) == -1)
775 if (PyString_AsStringAndSize(value, &node, &nodelen) == -1)
776 return NULL;
776 return NULL;
777 rev = index_find_node(self, node, nodelen);
777 rev = index_find_node(self, node, nodelen);
778 if (rev >= -1)
778 if (rev >= -1)
779 return PyInt_FromLong(rev);
779 return PyInt_FromLong(rev);
780 if (rev == -2)
780 if (rev == -2)
781 raise_revlog_error();
781 raise_revlog_error();
782 return NULL;
782 return NULL;
783 }
783 }
784
784
785 static PyObject *index_m_get(indexObject *self, PyObject *args)
785 static PyObject *index_m_get(indexObject *self, PyObject *args)
786 {
786 {
787 char *node;
787 char *node;
788 int nodelen, rev;
788 int nodelen, rev;
789
789
790 if (!PyArg_ParseTuple(args, "s#", &node, &nodelen))
790 if (!PyArg_ParseTuple(args, "s#", &node, &nodelen))
791 return NULL;
791 return NULL;
792
792
793 rev = index_find_node(self, node, nodelen);
793 rev = index_find_node(self, node, nodelen);
794 if (rev == -3)
794 if (rev == -3)
795 return NULL;
795 return NULL;
796 if (rev == -2)
796 if (rev == -2)
797 Py_RETURN_NONE;
797 Py_RETURN_NONE;
798 return PyInt_FromLong(rev);
798 return PyInt_FromLong(rev);
799 }
799 }
800
800
801 static int index_contains(indexObject *self, PyObject *value)
801 static int index_contains(indexObject *self, PyObject *value)
802 {
802 {
803 char *node;
803 char *node;
804 Py_ssize_t nodelen;
804 Py_ssize_t nodelen;
805
805
806 if (PyInt_Check(value)) {
806 if (PyInt_Check(value)) {
807 long rev = PyInt_AS_LONG(value);
807 long rev = PyInt_AS_LONG(value);
808 return rev >= -1 && rev < index_length(self);
808 return rev >= -1 && rev < index_length(self);
809 }
809 }
810
810
811 if (!PyString_Check(value))
811 if (!PyString_Check(value))
812 return 0;
812 return 0;
813
813
814 node = PyString_AS_STRING(value);
814 node = PyString_AS_STRING(value);
815 nodelen = PyString_GET_SIZE(value);
815 nodelen = PyString_GET_SIZE(value);
816
816
817 switch (index_find_node(self, node, nodelen)) {
817 switch (index_find_node(self, node, nodelen)) {
818 case -3:
818 case -3:
819 return -1;
819 return -1;
820 case -2:
820 case -2:
821 return 0;
821 return 0;
822 default:
822 default:
823 return 1;
823 return 1;
824 }
824 }
825 }
825 }
826
826
827 /*
827 /*
828 * Invalidate any trie entries introduced by added revs.
828 * Invalidate any trie entries introduced by added revs.
829 */
829 */
830 static void nt_invalidate_added(indexObject *self, Py_ssize_t start)
830 static void nt_invalidate_added(indexObject *self, Py_ssize_t start)
831 {
831 {
832 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
832 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
833
833
834 for (i = start; i < len; i++) {
834 for (i = start; i < len; i++) {
835 PyObject *tuple = PyList_GET_ITEM(self->added, i);
835 PyObject *tuple = PyList_GET_ITEM(self->added, i);
836 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
836 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
837
837
838 nt_insert(self, PyString_AS_STRING(node), -1);
838 nt_insert(self, PyString_AS_STRING(node), -1);
839 }
839 }
840
840
841 if (start == 0) {
841 if (start == 0) {
842 Py_DECREF(self->added);
842 Py_DECREF(self->added);
843 self->added = NULL;
843 self->added = NULL;
844 }
844 }
845 }
845 }
846
846
847 /*
847 /*
848 * Delete a numeric range of revs, which must be at the end of the
848 * Delete a numeric range of revs, which must be at the end of the
849 * range, but exclude the sentinel nullid entry.
849 * range, but exclude the sentinel nullid entry.
850 */
850 */
851 static int index_slice_del(indexObject *self, PyObject *item)
851 static int index_slice_del(indexObject *self, PyObject *item)
852 {
852 {
853 Py_ssize_t start, stop, step, slicelength;
853 Py_ssize_t start, stop, step, slicelength;
854 Py_ssize_t length = index_length(self);
854 Py_ssize_t length = index_length(self);
855
855
856 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
856 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
857 &start, &stop, &step, &slicelength) < 0)
857 &start, &stop, &step, &slicelength) < 0)
858 return -1;
858 return -1;
859
859
860 if (slicelength <= 0)
860 if (slicelength <= 0)
861 return 0;
861 return 0;
862
862
863 if ((step < 0 && start < stop) || (step > 0 && start > stop))
863 if ((step < 0 && start < stop) || (step > 0 && start > stop))
864 stop = start;
864 stop = start;
865
865
866 if (step < 0) {
866 if (step < 0) {
867 stop = start + 1;
867 stop = start + 1;
868 start = stop + step*(slicelength - 1) - 1;
868 start = stop + step*(slicelength - 1) - 1;
869 step = -step;
869 step = -step;
870 }
870 }
871
871
872 if (step != 1) {
872 if (step != 1) {
873 PyErr_SetString(PyExc_ValueError,
873 PyErr_SetString(PyExc_ValueError,
874 "revlog index delete requires step size of 1");
874 "revlog index delete requires step size of 1");
875 return -1;
875 return -1;
876 }
876 }
877
877
878 if (stop != length - 1) {
878 if (stop != length - 1) {
879 PyErr_SetString(PyExc_IndexError,
879 PyErr_SetString(PyExc_IndexError,
880 "revlog index deletion indices are invalid");
880 "revlog index deletion indices are invalid");
881 return -1;
881 return -1;
882 }
882 }
883
883
884 if (start < self->length - 1) {
884 if (start < self->length - 1) {
885 if (self->nt) {
885 if (self->nt) {
886 Py_ssize_t i;
886 Py_ssize_t i;
887
887
888 for (i = start + 1; i < self->length - 1; i++) {
888 for (i = start + 1; i < self->length - 1; i++) {
889 const char *node = index_node(self, i);
889 const char *node = index_node(self, i);
890
890
891 if (node)
891 if (node)
892 nt_insert(self, node, -1);
892 nt_insert(self, node, -1);
893 }
893 }
894 if (self->added)
894 if (self->added)
895 nt_invalidate_added(self, 0);
895 nt_invalidate_added(self, 0);
896 if (self->ntrev > start)
896 if (self->ntrev > start)
897 self->ntrev = (int)start;
897 self->ntrev = (int)start;
898 }
898 }
899 self->length = start + 1;
899 self->length = start + 1;
900 return 0;
900 return 0;
901 }
901 }
902
902
903 if (self->nt) {
903 if (self->nt) {
904 nt_invalidate_added(self, start - self->length + 1);
904 nt_invalidate_added(self, start - self->length + 1);
905 if (self->ntrev > start)
905 if (self->ntrev > start)
906 self->ntrev = (int)start;
906 self->ntrev = (int)start;
907 }
907 }
908 return self->added
908 return self->added
909 ? PyList_SetSlice(self->added, start - self->length + 1,
909 ? PyList_SetSlice(self->added, start - self->length + 1,
910 PyList_GET_SIZE(self->added), NULL)
910 PyList_GET_SIZE(self->added), NULL)
911 : 0;
911 : 0;
912 }
912 }
913
913
914 /*
914 /*
915 * Supported ops:
915 * Supported ops:
916 *
916 *
917 * slice deletion
917 * slice deletion
918 * string assignment (extend node->rev mapping)
918 * string assignment (extend node->rev mapping)
919 * string deletion (shrink node->rev mapping)
919 * string deletion (shrink node->rev mapping)
920 */
920 */
921 static int index_assign_subscript(indexObject *self, PyObject *item,
921 static int index_assign_subscript(indexObject *self, PyObject *item,
922 PyObject *value)
922 PyObject *value)
923 {
923 {
924 char *node;
924 char *node;
925 Py_ssize_t nodelen;
925 Py_ssize_t nodelen;
926 long rev;
926 long rev;
927
927
928 if (PySlice_Check(item) && value == NULL)
928 if (PySlice_Check(item) && value == NULL)
929 return index_slice_del(self, item);
929 return index_slice_del(self, item);
930
930
931 if (node_check(item, &node, &nodelen) == -1)
931 if (node_check(item, &node, &nodelen) == -1)
932 return -1;
932 return -1;
933
933
934 if (value == NULL)
934 if (value == NULL)
935 return self->nt ? nt_insert(self, node, -1) : 0;
935 return self->nt ? nt_insert(self, node, -1) : 0;
936 rev = PyInt_AsLong(value);
936 rev = PyInt_AsLong(value);
937 if (rev > INT_MAX || rev < 0) {
937 if (rev > INT_MAX || rev < 0) {
938 if (!PyErr_Occurred())
938 if (!PyErr_Occurred())
939 PyErr_SetString(PyExc_ValueError, "rev out of range");
939 PyErr_SetString(PyExc_ValueError, "rev out of range");
940 return -1;
940 return -1;
941 }
941 }
942 return nt_insert(self, node, (int)rev);
942 return nt_insert(self, node, (int)rev);
943 }
943 }
944
944
945 /*
945 /*
946 * Find all RevlogNG entries in an index that has inline data. Update
946 * Find all RevlogNG entries in an index that has inline data. Update
947 * the optional "offsets" table with those entries.
947 * the optional "offsets" table with those entries.
948 */
948 */
949 static long inline_scan(indexObject *self, const char **offsets)
949 static long inline_scan(indexObject *self, const char **offsets)
950 {
950 {
951 const char *data = PyString_AS_STRING(self->data);
951 const char *data = PyString_AS_STRING(self->data);
952 const char *end = data + PyString_GET_SIZE(self->data);
952 const char *end = data + PyString_GET_SIZE(self->data);
953 const long hdrsize = 64;
953 const long hdrsize = 64;
954 long incr = hdrsize;
954 long incr = hdrsize;
955 Py_ssize_t len = 0;
955 Py_ssize_t len = 0;
956
956
957 while (data + hdrsize <= end) {
957 while (data + hdrsize <= end) {
958 uint32_t comp_len;
958 uint32_t comp_len;
959 const char *old_data;
959 const char *old_data;
960 /* 3rd element of header is length of compressed inline data */
960 /* 3rd element of header is length of compressed inline data */
961 comp_len = getbe32(data + 8);
961 comp_len = getbe32(data + 8);
962 incr = hdrsize + comp_len;
962 incr = hdrsize + comp_len;
963 if (incr < hdrsize)
963 if (incr < hdrsize)
964 break;
964 break;
965 if (offsets)
965 if (offsets)
966 offsets[len] = data;
966 offsets[len] = data;
967 len++;
967 len++;
968 old_data = data;
968 old_data = data;
969 data += incr;
969 data += incr;
970 if (data <= old_data)
970 if (data <= old_data)
971 break;
971 break;
972 }
972 }
973
973
974 if (data != end && data + hdrsize != end) {
974 if (data != end && data + hdrsize != end) {
975 if (!PyErr_Occurred())
975 if (!PyErr_Occurred())
976 PyErr_SetString(PyExc_ValueError, "corrupt index file");
976 PyErr_SetString(PyExc_ValueError, "corrupt index file");
977 return -1;
977 return -1;
978 }
978 }
979
979
980 return len;
980 return len;
981 }
981 }
982
982
983 static int index_init(indexObject *self, PyObject *args)
983 static int index_init(indexObject *self, PyObject *args)
984 {
984 {
985 PyObject *data_obj, *inlined_obj;
985 PyObject *data_obj, *inlined_obj;
986 Py_ssize_t size;
986 Py_ssize_t size;
987
987
988 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
988 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
989 return -1;
989 return -1;
990 if (!PyString_Check(data_obj)) {
990 if (!PyString_Check(data_obj)) {
991 PyErr_SetString(PyExc_TypeError, "data is not a string");
991 PyErr_SetString(PyExc_TypeError, "data is not a string");
992 return -1;
992 return -1;
993 }
993 }
994 size = PyString_GET_SIZE(data_obj);
994 size = PyString_GET_SIZE(data_obj);
995
995
996 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
996 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
997 self->data = data_obj;
997 self->data = data_obj;
998 self->cache = NULL;
998 self->cache = NULL;
999
999
1000 self->added = NULL;
1000 self->added = NULL;
1001 self->offsets = NULL;
1001 self->offsets = NULL;
1002 self->nt = NULL;
1002 self->nt = NULL;
1003 self->ntlength = self->ntcapacity = 0;
1003 self->ntlength = self->ntcapacity = 0;
1004 self->ntdepth = self->ntsplits = 0;
1004 self->ntdepth = self->ntsplits = 0;
1005 self->ntlookups = self->ntmisses = 0;
1005 self->ntlookups = self->ntmisses = 0;
1006 self->ntrev = -1;
1006 self->ntrev = -1;
1007 Py_INCREF(self->data);
1007 Py_INCREF(self->data);
1008
1008
1009 if (self->inlined) {
1009 if (self->inlined) {
1010 long len = inline_scan(self, NULL);
1010 long len = inline_scan(self, NULL);
1011 if (len == -1)
1011 if (len == -1)
1012 goto bail;
1012 goto bail;
1013 self->raw_length = len;
1013 self->raw_length = len;
1014 self->length = len + 1;
1014 self->length = len + 1;
1015 } else {
1015 } else {
1016 if (size % 64) {
1016 if (size % 64) {
1017 PyErr_SetString(PyExc_ValueError, "corrupt index file");
1017 PyErr_SetString(PyExc_ValueError, "corrupt index file");
1018 goto bail;
1018 goto bail;
1019 }
1019 }
1020 self->raw_length = size / 64;
1020 self->raw_length = size / 64;
1021 self->length = self->raw_length + 1;
1021 self->length = self->raw_length + 1;
1022 }
1022 }
1023
1023
1024 return 0;
1024 return 0;
1025 bail:
1025 bail:
1026 return -1;
1026 return -1;
1027 }
1027 }
1028
1028
1029 static PyObject *index_nodemap(indexObject *self)
1029 static PyObject *index_nodemap(indexObject *self)
1030 {
1030 {
1031 Py_INCREF(self);
1031 Py_INCREF(self);
1032 return (PyObject *)self;
1032 return (PyObject *)self;
1033 }
1033 }
1034
1034
1035 static void index_dealloc(indexObject *self)
1035 static void index_dealloc(indexObject *self)
1036 {
1036 {
1037 _index_clearcaches(self);
1037 _index_clearcaches(self);
1038 Py_DECREF(self->data);
1038 Py_DECREF(self->data);
1039 Py_XDECREF(self->added);
1039 Py_XDECREF(self->added);
1040 PyObject_Del(self);
1040 PyObject_Del(self);
1041 }
1041 }
1042
1042
1043 static PySequenceMethods index_sequence_methods = {
1043 static PySequenceMethods index_sequence_methods = {
1044 (lenfunc)index_length, /* sq_length */
1044 (lenfunc)index_length, /* sq_length */
1045 0, /* sq_concat */
1045 0, /* sq_concat */
1046 0, /* sq_repeat */
1046 0, /* sq_repeat */
1047 (ssizeargfunc)index_get, /* sq_item */
1047 (ssizeargfunc)index_get, /* sq_item */
1048 0, /* sq_slice */
1048 0, /* sq_slice */
1049 0, /* sq_ass_item */
1049 0, /* sq_ass_item */
1050 0, /* sq_ass_slice */
1050 0, /* sq_ass_slice */
1051 (objobjproc)index_contains, /* sq_contains */
1051 (objobjproc)index_contains, /* sq_contains */
1052 };
1052 };
1053
1053
1054 static PyMappingMethods index_mapping_methods = {
1054 static PyMappingMethods index_mapping_methods = {
1055 (lenfunc)index_length, /* mp_length */
1055 (lenfunc)index_length, /* mp_length */
1056 (binaryfunc)index_getitem, /* mp_subscript */
1056 (binaryfunc)index_getitem, /* mp_subscript */
1057 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
1057 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
1058 };
1058 };
1059
1059
1060 static PyMethodDef index_methods[] = {
1060 static PyMethodDef index_methods[] = {
1061 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
1061 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
1062 "clear the index caches"},
1062 "clear the index caches"},
1063 {"get", (PyCFunction)index_m_get, METH_VARARGS,
1063 {"get", (PyCFunction)index_m_get, METH_VARARGS,
1064 "get an index entry"},
1064 "get an index entry"},
1065 {"insert", (PyCFunction)index_insert, METH_VARARGS,
1065 {"insert", (PyCFunction)index_insert, METH_VARARGS,
1066 "insert an index entry"},
1066 "insert an index entry"},
1067 {"stats", (PyCFunction)index_stats, METH_NOARGS,
1067 {"stats", (PyCFunction)index_stats, METH_NOARGS,
1068 "stats for the index"},
1068 "stats for the index"},
1069 {NULL} /* Sentinel */
1069 {NULL} /* Sentinel */
1070 };
1070 };
1071
1071
1072 static PyGetSetDef index_getset[] = {
1072 static PyGetSetDef index_getset[] = {
1073 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
1073 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
1074 {NULL} /* Sentinel */
1074 {NULL} /* Sentinel */
1075 };
1075 };
1076
1076
1077 static PyTypeObject indexType = {
1077 static PyTypeObject indexType = {
1078 PyObject_HEAD_INIT(NULL)
1078 PyObject_HEAD_INIT(NULL)
1079 0, /* ob_size */
1079 0, /* ob_size */
1080 "parsers.index", /* tp_name */
1080 "parsers.index", /* tp_name */
1081 sizeof(indexObject), /* tp_basicsize */
1081 sizeof(indexObject), /* tp_basicsize */
1082 0, /* tp_itemsize */
1082 0, /* tp_itemsize */
1083 (destructor)index_dealloc, /* tp_dealloc */
1083 (destructor)index_dealloc, /* tp_dealloc */
1084 0, /* tp_print */
1084 0, /* tp_print */
1085 0, /* tp_getattr */
1085 0, /* tp_getattr */
1086 0, /* tp_setattr */
1086 0, /* tp_setattr */
1087 0, /* tp_compare */
1087 0, /* tp_compare */
1088 0, /* tp_repr */
1088 0, /* tp_repr */
1089 0, /* tp_as_number */
1089 0, /* tp_as_number */
1090 &index_sequence_methods, /* tp_as_sequence */
1090 &index_sequence_methods, /* tp_as_sequence */
1091 &index_mapping_methods, /* tp_as_mapping */
1091 &index_mapping_methods, /* tp_as_mapping */
1092 0, /* tp_hash */
1092 0, /* tp_hash */
1093 0, /* tp_call */
1093 0, /* tp_call */
1094 0, /* tp_str */
1094 0, /* tp_str */
1095 0, /* tp_getattro */
1095 0, /* tp_getattro */
1096 0, /* tp_setattro */
1096 0, /* tp_setattro */
1097 0, /* tp_as_buffer */
1097 0, /* tp_as_buffer */
1098 Py_TPFLAGS_DEFAULT, /* tp_flags */
1098 Py_TPFLAGS_DEFAULT, /* tp_flags */
1099 "revlog index", /* tp_doc */
1099 "revlog index", /* tp_doc */
1100 0, /* tp_traverse */
1100 0, /* tp_traverse */
1101 0, /* tp_clear */
1101 0, /* tp_clear */
1102 0, /* tp_richcompare */
1102 0, /* tp_richcompare */
1103 0, /* tp_weaklistoffset */
1103 0, /* tp_weaklistoffset */
1104 0, /* tp_iter */
1104 0, /* tp_iter */
1105 0, /* tp_iternext */
1105 0, /* tp_iternext */
1106 index_methods, /* tp_methods */
1106 index_methods, /* tp_methods */
1107 0, /* tp_members */
1107 0, /* tp_members */
1108 index_getset, /* tp_getset */
1108 index_getset, /* tp_getset */
1109 0, /* tp_base */
1109 0, /* tp_base */
1110 0, /* tp_dict */
1110 0, /* tp_dict */
1111 0, /* tp_descr_get */
1111 0, /* tp_descr_get */
1112 0, /* tp_descr_set */
1112 0, /* tp_descr_set */
1113 0, /* tp_dictoffset */
1113 0, /* tp_dictoffset */
1114 (initproc)index_init, /* tp_init */
1114 (initproc)index_init, /* tp_init */
1115 0, /* tp_alloc */
1115 0, /* tp_alloc */
1116 };
1116 };
1117
1117
1118 /*
1118 /*
1119 * returns a tuple of the form (index, index, cache) with elements as
1119 * returns a tuple of the form (index, index, cache) with elements as
1120 * follows:
1120 * follows:
1121 *
1121 *
1122 * index: an index object that lazily parses RevlogNG records
1122 * index: an index object that lazily parses RevlogNG records
1123 * cache: if data is inlined, a tuple (index_file_content, 0), else None
1123 * cache: if data is inlined, a tuple (index_file_content, 0), else None
1124 *
1124 *
1125 * added complications are for backwards compatibility
1125 * added complications are for backwards compatibility
1126 */
1126 */
1127 static PyObject *parse_index2(PyObject *self, PyObject *args)
1127 static PyObject *parse_index2(PyObject *self, PyObject *args)
1128 {
1128 {
1129 PyObject *tuple = NULL, *cache = NULL;
1129 PyObject *tuple = NULL, *cache = NULL;
1130 indexObject *idx;
1130 indexObject *idx;
1131 int ret;
1131 int ret;
1132
1132
1133 idx = PyObject_New(indexObject, &indexType);
1133 idx = PyObject_New(indexObject, &indexType);
1134 if (idx == NULL)
1134 if (idx == NULL)
1135 goto bail;
1135 goto bail;
1136
1136
1137 ret = index_init(idx, args);
1137 ret = index_init(idx, args);
1138 if (ret == -1)
1138 if (ret == -1)
1139 goto bail;
1139 goto bail;
1140
1140
1141 if (idx->inlined) {
1141 if (idx->inlined) {
1142 cache = Py_BuildValue("iO", 0, idx->data);
1142 cache = Py_BuildValue("iO", 0, idx->data);
1143 if (cache == NULL)
1143 if (cache == NULL)
1144 goto bail;
1144 goto bail;
1145 } else {
1145 } else {
1146 cache = Py_None;
1146 cache = Py_None;
1147 Py_INCREF(cache);
1147 Py_INCREF(cache);
1148 }
1148 }
1149
1149
1150 tuple = Py_BuildValue("NN", idx, cache);
1150 tuple = Py_BuildValue("NN", idx, cache);
1151 if (!tuple)
1151 if (!tuple)
1152 goto bail;
1152 goto bail;
1153 return tuple;
1153 return tuple;
1154
1154
1155 bail:
1155 bail:
1156 Py_XDECREF(idx);
1156 Py_XDECREF(idx);
1157 Py_XDECREF(cache);
1157 Py_XDECREF(cache);
1158 Py_XDECREF(tuple);
1158 Py_XDECREF(tuple);
1159 return NULL;
1159 return NULL;
1160 }
1160 }
1161
1161
1162 static char parsers_doc[] = "Efficient content parsing.";
1162 static char parsers_doc[] = "Efficient content parsing.";
1163
1163
1164 static PyMethodDef methods[] = {
1164 static PyMethodDef methods[] = {
1165 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
1165 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
1166 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
1166 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
1167 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
1167 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
1168 {NULL, NULL}
1168 {NULL, NULL}
1169 };
1169 };
1170
1170
1171 static void module_init(PyObject *mod)
1171 static void module_init(PyObject *mod)
1172 {
1172 {
1173 indexType.tp_new = PyType_GenericNew;
1173 indexType.tp_new = PyType_GenericNew;
1174 if (PyType_Ready(&indexType) < 0)
1174 if (PyType_Ready(&indexType) < 0)
1175 return;
1175 return;
1176 Py_INCREF(&indexType);
1176 Py_INCREF(&indexType);
1177
1177
1178 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
1178 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
1179
1179
1180 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
1180 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
1181 -1, -1, -1, -1, nullid, 20);
1181 -1, -1, -1, -1, nullid, 20);
1182 if (nullentry)
1182 if (nullentry)
1183 PyObject_GC_UnTrack(nullentry);
1183 PyObject_GC_UnTrack(nullentry);
1184 }
1184 }
1185
1185
1186 #ifdef IS_PY3K
1186 #ifdef IS_PY3K
1187 static struct PyModuleDef parsers_module = {
1187 static struct PyModuleDef parsers_module = {
1188 PyModuleDef_HEAD_INIT,
1188 PyModuleDef_HEAD_INIT,
1189 "parsers",
1189 "parsers",
1190 parsers_doc,
1190 parsers_doc,
1191 -1,
1191 -1,
1192 methods
1192 methods
1193 };
1193 };
1194
1194
1195 PyMODINIT_FUNC PyInit_parsers(void)
1195 PyMODINIT_FUNC PyInit_parsers(void)
1196 {
1196 {
1197 PyObject *mod = PyModule_Create(&parsers_module);
1197 PyObject *mod = PyModule_Create(&parsers_module);
1198 module_init(mod);
1198 module_init(mod);
1199 return mod;
1199 return mod;
1200 }
1200 }
1201 #else
1201 #else
1202 PyMODINIT_FUNC initparsers(void)
1202 PyMODINIT_FUNC initparsers(void)
1203 {
1203 {
1204 PyObject *mod = Py_InitModule3("parsers", methods, parsers_doc);
1204 PyObject *mod = Py_InitModule3("parsers", methods, parsers_doc);
1205 module_init(mod);
1205 module_init(mod);
1206 }
1206 }
1207 #endif
1207 #endif
@@ -1,165 +1,166
1 /*
1 /*
2 util.h - utility functions for interfacing with the various python APIs.
2 util.h - utility functions for interfacing with the various python APIs.
3
3
4 This software may be used and distributed according to the terms of
4 This software may be used and distributed according to the terms of
5 the GNU General Public License, incorporated herein by reference.
5 the GNU General Public License, incorporated herein by reference.
6 */
6 */
7
7
8 #ifndef _HG_UTIL_H_
8 #ifndef _HG_UTIL_H_
9 #define _HG_UTIL_H_
9 #define _HG_UTIL_H_
10
10
11 #if PY_MAJOR_VERSION >= 3
11 #if PY_MAJOR_VERSION >= 3
12
12
13 #define IS_PY3K
13 #define IS_PY3K
14 #define PyInt_FromLong PyLong_FromLong
14 #define PyInt_FromLong PyLong_FromLong
15 #define PyInt_AsLong PyLong_AsLong
15 #define PyInt_AsLong PyLong_AsLong
16
16
17 /*
17 /*
18 Mapping of some of the python < 2.x PyString* functions to py3k's PyUnicode.
18 Mapping of some of the python < 2.x PyString* functions to py3k's PyUnicode.
19
19
20 The commented names below represent those that are present in the PyBytes
20 The commented names below represent those that are present in the PyBytes
21 definitions for python < 2.6 (below in this file) that don't have a direct
21 definitions for python < 2.6 (below in this file) that don't have a direct
22 implementation.
22 implementation.
23 */
23 */
24
24
25 #define PyStringObject PyUnicodeObject
25 #define PyStringObject PyUnicodeObject
26 #define PyString_Type PyUnicode_Type
26 #define PyString_Type PyUnicode_Type
27
27
28 #define PyString_Check PyUnicode_Check
28 #define PyString_Check PyUnicode_Check
29 #define PyString_CheckExact PyUnicode_CheckExact
29 #define PyString_CheckExact PyUnicode_CheckExact
30 #define PyString_CHECK_INTERNED PyUnicode_CHECK_INTERNED
30 #define PyString_CHECK_INTERNED PyUnicode_CHECK_INTERNED
31 #define PyString_AS_STRING PyUnicode_AsLatin1String
31 #define PyString_AS_STRING PyUnicode_AsLatin1String
32 #define PyString_GET_SIZE PyUnicode_GET_SIZE
32 #define PyString_GET_SIZE PyUnicode_GET_SIZE
33
33
34 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
34 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
35 #define PyString_FromString PyUnicode_FromString
35 #define PyString_FromString PyUnicode_FromString
36 #define PyString_FromFormatV PyUnicode_FromFormatV
36 #define PyString_FromFormatV PyUnicode_FromFormatV
37 #define PyString_FromFormat PyUnicode_FromFormat
37 #define PyString_FromFormat PyUnicode_FromFormat
38 /* #define PyString_Size PyUnicode_GET_SIZE */
38 /* #define PyString_Size PyUnicode_GET_SIZE */
39 /* #define PyString_AsString */
39 /* #define PyString_AsString */
40 /* #define PyString_Repr */
40 /* #define PyString_Repr */
41 #define PyString_Concat PyUnicode_Concat
41 #define PyString_Concat PyUnicode_Concat
42 #define PyString_ConcatAndDel PyUnicode_AppendAndDel
42 #define PyString_ConcatAndDel PyUnicode_AppendAndDel
43 #define _PyString_Resize PyUnicode_Resize
43 #define _PyString_Resize PyUnicode_Resize
44 /* #define _PyString_Eq */
44 /* #define _PyString_Eq */
45 #define PyString_Format PyUnicode_Format
45 #define PyString_Format PyUnicode_Format
46 /* #define _PyString_FormatLong */
46 /* #define _PyString_FormatLong */
47 /* #define PyString_DecodeEscape */
47 /* #define PyString_DecodeEscape */
48 #define _PyString_Join PyUnicode_Join
48 #define _PyString_Join PyUnicode_Join
49 #define PyString_Decode PyUnicode_Decode
49 #define PyString_Decode PyUnicode_Decode
50 #define PyString_Encode PyUnicode_Encode
50 #define PyString_Encode PyUnicode_Encode
51 #define PyString_AsEncodedObject PyUnicode_AsEncodedObject
51 #define PyString_AsEncodedObject PyUnicode_AsEncodedObject
52 #define PyString_AsEncodedString PyUnicode_AsEncodedString
52 #define PyString_AsEncodedString PyUnicode_AsEncodedString
53 #define PyString_AsDecodedObject PyUnicode_AsDecodedObject
53 #define PyString_AsDecodedObject PyUnicode_AsDecodedObject
54 #define PyString_AsDecodedString PyUnicode_AsDecodedUnicode
54 #define PyString_AsDecodedString PyUnicode_AsDecodedUnicode
55 /* #define PyString_AsStringAndSize */
55 /* #define PyString_AsStringAndSize */
56 #define _PyString_InsertThousandsGrouping _PyUnicode_InsertThousandsGrouping
56 #define _PyString_InsertThousandsGrouping _PyUnicode_InsertThousandsGrouping
57
57
58 #endif /* PY_MAJOR_VERSION */
58 #endif /* PY_MAJOR_VERSION */
59
59
60 /* Backports from 2.6 */
60 /* Backports from 2.6 */
61 #if PY_VERSION_HEX < 0x02060000
61 #if PY_VERSION_HEX < 0x02060000
62
62
63 #define Py_TYPE(ob) (ob)->ob_type
63 #define Py_TYPE(ob) (ob)->ob_type
64 #define Py_SIZE(ob) (ob)->ob_size
64 #define Py_SIZE(ob) (ob)->ob_size
65 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
65 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
66
66
67 /* Shamelessly stolen from bytesobject.h */
67 /* Shamelessly stolen from bytesobject.h */
68 #define PyBytesObject PyStringObject
68 #define PyBytesObject PyStringObject
69 #define PyBytes_Type PyString_Type
69 #define PyBytes_Type PyString_Type
70
70
71 #define PyBytes_Check PyString_Check
71 #define PyBytes_Check PyString_Check
72 #define PyBytes_CheckExact PyString_CheckExact
72 #define PyBytes_CheckExact PyString_CheckExact
73 #define PyBytes_CHECK_INTERNED PyString_CHECK_INTERNED
73 #define PyBytes_CHECK_INTERNED PyString_CHECK_INTERNED
74 #define PyBytes_AS_STRING PyString_AS_STRING
74 #define PyBytes_AS_STRING PyString_AS_STRING
75 #define PyBytes_GET_SIZE PyString_GET_SIZE
75 #define PyBytes_GET_SIZE PyString_GET_SIZE
76 #define Py_TPFLAGS_BYTES_SUBCLASS Py_TPFLAGS_STRING_SUBCLASS
76 #define Py_TPFLAGS_BYTES_SUBCLASS Py_TPFLAGS_STRING_SUBCLASS
77
77
78 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
78 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
79 #define PyBytes_FromString PyString_FromString
79 #define PyBytes_FromString PyString_FromString
80 #define PyBytes_FromFormatV PyString_FromFormatV
80 #define PyBytes_FromFormatV PyString_FromFormatV
81 #define PyBytes_FromFormat PyString_FromFormat
81 #define PyBytes_FromFormat PyString_FromFormat
82 #define PyBytes_Size PyString_Size
82 #define PyBytes_Size PyString_Size
83 #define PyBytes_AsString PyString_AsString
83 #define PyBytes_AsString PyString_AsString
84 #define PyBytes_Repr PyString_Repr
84 #define PyBytes_Repr PyString_Repr
85 #define PyBytes_Concat PyString_Concat
85 #define PyBytes_Concat PyString_Concat
86 #define PyBytes_ConcatAndDel PyString_ConcatAndDel
86 #define PyBytes_ConcatAndDel PyString_ConcatAndDel
87 #define _PyBytes_Resize _PyString_Resize
87 #define _PyBytes_Resize _PyString_Resize
88 #define _PyBytes_Eq _PyString_Eq
88 #define _PyBytes_Eq _PyString_Eq
89 #define PyBytes_Format PyString_Format
89 #define PyBytes_Format PyString_Format
90 #define _PyBytes_FormatLong _PyString_FormatLong
90 #define _PyBytes_FormatLong _PyString_FormatLong
91 #define PyBytes_DecodeEscape PyString_DecodeEscape
91 #define PyBytes_DecodeEscape PyString_DecodeEscape
92 #define _PyBytes_Join _PyString_Join
92 #define _PyBytes_Join _PyString_Join
93 #define PyBytes_Decode PyString_Decode
93 #define PyBytes_Decode PyString_Decode
94 #define PyBytes_Encode PyString_Encode
94 #define PyBytes_Encode PyString_Encode
95 #define PyBytes_AsEncodedObject PyString_AsEncodedObject
95 #define PyBytes_AsEncodedObject PyString_AsEncodedObject
96 #define PyBytes_AsEncodedString PyString_AsEncodedString
96 #define PyBytes_AsEncodedString PyString_AsEncodedString
97 #define PyBytes_AsDecodedObject PyString_AsDecodedObject
97 #define PyBytes_AsDecodedObject PyString_AsDecodedObject
98 #define PyBytes_AsDecodedString PyString_AsDecodedString
98 #define PyBytes_AsDecodedString PyString_AsDecodedString
99 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
99 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
100 #define _PyBytes_InsertThousandsGrouping _PyString_InsertThousandsGrouping
100 #define _PyBytes_InsertThousandsGrouping _PyString_InsertThousandsGrouping
101
101
102 #endif /* PY_VERSION_HEX */
102 #endif /* PY_VERSION_HEX */
103
103
104 #if (PY_VERSION_HEX < 0x02050000)
104 #if (PY_VERSION_HEX < 0x02050000)
105 /* Definitions to get compatibility with python 2.4 and earlier which
105 /* Definitions to get compatibility with python 2.4 and earlier which
106 does not have Py_ssize_t. See also PEP 353.
106 does not have Py_ssize_t. See also PEP 353.
107 Note: msvc (8 or earlier) does not have ssize_t, so we use Py_ssize_t.
107 Note: msvc (8 or earlier) does not have ssize_t, so we use Py_ssize_t.
108 */
108 */
109 typedef int Py_ssize_t;
109 typedef int Py_ssize_t;
110 typedef Py_ssize_t (*lenfunc)(PyObject *);
110 typedef Py_ssize_t (*lenfunc)(PyObject *);
111 typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
111 typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
112 #define PyInt_FromSsize_t PyInt_FromLong
112
113
113 #if !defined(PY_SSIZE_T_MIN)
114 #if !defined(PY_SSIZE_T_MIN)
114 #define PY_SSIZE_T_MAX INT_MAX
115 #define PY_SSIZE_T_MAX INT_MAX
115 #define PY_SSIZE_T_MIN INT_MIN
116 #define PY_SSIZE_T_MIN INT_MIN
116 #endif
117 #endif
117 #endif
118 #endif
118
119
119 #ifdef _WIN32
120 #ifdef _WIN32
120 #ifdef _MSC_VER
121 #ifdef _MSC_VER
121 /* msvc 6.0 has problems */
122 /* msvc 6.0 has problems */
122 #define inline __inline
123 #define inline __inline
123 typedef unsigned long uint32_t;
124 typedef unsigned long uint32_t;
124 typedef unsigned __int64 uint64_t;
125 typedef unsigned __int64 uint64_t;
125 #else
126 #else
126 #include <stdint.h>
127 #include <stdint.h>
127 #endif
128 #endif
128 #else
129 #else
129 /* not windows */
130 /* not windows */
130 #include <sys/types.h>
131 #include <sys/types.h>
131 #if defined __BEOS__ && !defined __HAIKU__
132 #if defined __BEOS__ && !defined __HAIKU__
132 #include <ByteOrder.h>
133 #include <ByteOrder.h>
133 #else
134 #else
134 #include <arpa/inet.h>
135 #include <arpa/inet.h>
135 #endif
136 #endif
136 #include <inttypes.h>
137 #include <inttypes.h>
137 #endif
138 #endif
138
139
139 #if defined __hpux || defined __SUNPRO_C || defined _AIX
140 #if defined __hpux || defined __SUNPRO_C || defined _AIX
140 #define inline
141 #define inline
141 #endif
142 #endif
142
143
143 #ifdef __linux
144 #ifdef __linux
144 #define inline __inline
145 #define inline __inline
145 #endif
146 #endif
146
147
147 static inline uint32_t getbe32(const char *c)
148 static inline uint32_t getbe32(const char *c)
148 {
149 {
149 const unsigned char *d = (const unsigned char *)c;
150 const unsigned char *d = (const unsigned char *)c;
150
151
151 return ((d[0] << 24) |
152 return ((d[0] << 24) |
152 (d[1] << 16) |
153 (d[1] << 16) |
153 (d[2] << 8) |
154 (d[2] << 8) |
154 (d[3]));
155 (d[3]));
155 }
156 }
156
157
157 static inline void putbe32(uint32_t x, char *c)
158 static inline void putbe32(uint32_t x, char *c)
158 {
159 {
159 c[0] = (x >> 24) & 0xff;
160 c[0] = (x >> 24) & 0xff;
160 c[1] = (x >> 16) & 0xff;
161 c[1] = (x >> 16) & 0xff;
161 c[2] = (x >> 8) & 0xff;
162 c[2] = (x >> 8) & 0xff;
162 c[3] = (x) & 0xff;
163 c[3] = (x) & 0xff;
163 }
164 }
164
165
165 #endif /* _HG_UTIL_H_ */
166 #endif /* _HG_UTIL_H_ */
General Comments 0
You need to be logged in to leave comments. Login now