##// END OF EJS Templates
cext: mark constant variables
Yuya Nishihara -
r32385:7640584e default
parent child Browse files
Show More
@@ -1,1009 +1,1009 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 <stddef.h>
12 #include <stddef.h>
13 #include <string.h>
13 #include <string.h>
14
14
15 #include "util.h"
15 #include "util.h"
16 #include "bitmanipulation.h"
16 #include "bitmanipulation.h"
17
17
18 #ifdef IS_PY3K
18 #ifdef IS_PY3K
19 /* The mapping of Python types is meant to be temporary to get Python
19 /* The mapping of Python types is meant to be temporary to get Python
20 * 3 to compile. We should remove this once Python 3 support is fully
20 * 3 to compile. We should remove this once Python 3 support is fully
21 * supported and proper types are used in the extensions themselves. */
21 * supported and proper types are used in the extensions themselves. */
22 #define PyInt_Type PyLong_Type
22 #define PyInt_Type PyLong_Type
23 #define PyInt_Check PyLong_Check
23 #define PyInt_Check PyLong_Check
24 #define PyInt_FromLong PyLong_FromLong
24 #define PyInt_FromLong PyLong_FromLong
25 #define PyInt_FromSsize_t PyLong_FromSsize_t
25 #define PyInt_FromSsize_t PyLong_FromSsize_t
26 #define PyInt_AS_LONG PyLong_AS_LONG
26 #define PyInt_AS_LONG PyLong_AS_LONG
27 #define PyInt_AsLong PyLong_AsLong
27 #define PyInt_AsLong PyLong_AsLong
28 #endif
28 #endif
29
29
30 static char *versionerrortext = "Python minor version mismatch";
30 static const char *const versionerrortext = "Python minor version mismatch";
31
31
32 static char lowertable[128] = {
32 static const char lowertable[128] = {
33 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
33 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
34 '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
34 '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
35 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
35 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
36 '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
36 '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
37 '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
37 '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
38 '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
38 '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
39 '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
39 '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
40 '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
40 '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
41 '\x40',
41 '\x40',
42 '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', /* A-G */
42 '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', /* A-G */
43 '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', /* H-O */
43 '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', /* H-O */
44 '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', /* P-W */
44 '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', /* P-W */
45 '\x78', '\x79', '\x7a', /* X-Z */
45 '\x78', '\x79', '\x7a', /* X-Z */
46 '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
46 '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
47 '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
47 '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
48 '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
48 '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
49 '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
49 '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
50 '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f'
50 '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f'
51 };
51 };
52
52
53 static char uppertable[128] = {
53 static const char uppertable[128] = {
54 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
54 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
55 '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
55 '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
56 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
56 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
57 '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
57 '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
58 '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
58 '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
59 '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
59 '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
60 '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
60 '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
61 '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
61 '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
62 '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
62 '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
63 '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
63 '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
64 '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
64 '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
65 '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
65 '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
66 '\x60',
66 '\x60',
67 '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', /* a-g */
67 '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', /* a-g */
68 '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', /* h-o */
68 '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', /* h-o */
69 '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', /* p-w */
69 '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', /* p-w */
70 '\x58', '\x59', '\x5a', /* x-z */
70 '\x58', '\x59', '\x5a', /* x-z */
71 '\x7b', '\x7c', '\x7d', '\x7e', '\x7f'
71 '\x7b', '\x7c', '\x7d', '\x7e', '\x7f'
72 };
72 };
73
73
74 /*
74 /*
75 * Turn a hex-encoded string into binary.
75 * Turn a hex-encoded string into binary.
76 */
76 */
77 PyObject *unhexlify(const char *str, int len)
77 PyObject *unhexlify(const char *str, int len)
78 {
78 {
79 PyObject *ret;
79 PyObject *ret;
80 char *d;
80 char *d;
81 int i;
81 int i;
82
82
83 ret = PyBytes_FromStringAndSize(NULL, len / 2);
83 ret = PyBytes_FromStringAndSize(NULL, len / 2);
84
84
85 if (!ret)
85 if (!ret)
86 return NULL;
86 return NULL;
87
87
88 d = PyBytes_AsString(ret);
88 d = PyBytes_AsString(ret);
89
89
90 for (i = 0; i < len;) {
90 for (i = 0; i < len;) {
91 int hi = hexdigit(str, i++);
91 int hi = hexdigit(str, i++);
92 int lo = hexdigit(str, i++);
92 int lo = hexdigit(str, i++);
93 *d++ = (hi << 4) | lo;
93 *d++ = (hi << 4) | lo;
94 }
94 }
95
95
96 return ret;
96 return ret;
97 }
97 }
98
98
99 static inline PyObject *_asciitransform(PyObject *str_obj,
99 static inline PyObject *_asciitransform(PyObject *str_obj,
100 const char table[128],
100 const char table[128],
101 PyObject *fallback_fn)
101 PyObject *fallback_fn)
102 {
102 {
103 char *str, *newstr;
103 char *str, *newstr;
104 Py_ssize_t i, len;
104 Py_ssize_t i, len;
105 PyObject *newobj = NULL;
105 PyObject *newobj = NULL;
106 PyObject *ret = NULL;
106 PyObject *ret = NULL;
107
107
108 str = PyBytes_AS_STRING(str_obj);
108 str = PyBytes_AS_STRING(str_obj);
109 len = PyBytes_GET_SIZE(str_obj);
109 len = PyBytes_GET_SIZE(str_obj);
110
110
111 newobj = PyBytes_FromStringAndSize(NULL, len);
111 newobj = PyBytes_FromStringAndSize(NULL, len);
112 if (!newobj)
112 if (!newobj)
113 goto quit;
113 goto quit;
114
114
115 newstr = PyBytes_AS_STRING(newobj);
115 newstr = PyBytes_AS_STRING(newobj);
116
116
117 for (i = 0; i < len; i++) {
117 for (i = 0; i < len; i++) {
118 char c = str[i];
118 char c = str[i];
119 if (c & 0x80) {
119 if (c & 0x80) {
120 if (fallback_fn != NULL) {
120 if (fallback_fn != NULL) {
121 ret = PyObject_CallFunctionObjArgs(fallback_fn,
121 ret = PyObject_CallFunctionObjArgs(fallback_fn,
122 str_obj, NULL);
122 str_obj, NULL);
123 } else {
123 } else {
124 PyObject *err = PyUnicodeDecodeError_Create(
124 PyObject *err = PyUnicodeDecodeError_Create(
125 "ascii", str, len, i, (i + 1),
125 "ascii", str, len, i, (i + 1),
126 "unexpected code byte");
126 "unexpected code byte");
127 PyErr_SetObject(PyExc_UnicodeDecodeError, err);
127 PyErr_SetObject(PyExc_UnicodeDecodeError, err);
128 Py_XDECREF(err);
128 Py_XDECREF(err);
129 }
129 }
130 goto quit;
130 goto quit;
131 }
131 }
132 newstr[i] = table[(unsigned char)c];
132 newstr[i] = table[(unsigned char)c];
133 }
133 }
134
134
135 ret = newobj;
135 ret = newobj;
136 Py_INCREF(ret);
136 Py_INCREF(ret);
137 quit:
137 quit:
138 Py_XDECREF(newobj);
138 Py_XDECREF(newobj);
139 return ret;
139 return ret;
140 }
140 }
141
141
142 static PyObject *asciilower(PyObject *self, PyObject *args)
142 static PyObject *asciilower(PyObject *self, PyObject *args)
143 {
143 {
144 PyObject *str_obj;
144 PyObject *str_obj;
145 if (!PyArg_ParseTuple(args, "O!:asciilower", &PyBytes_Type, &str_obj))
145 if (!PyArg_ParseTuple(args, "O!:asciilower", &PyBytes_Type, &str_obj))
146 return NULL;
146 return NULL;
147 return _asciitransform(str_obj, lowertable, NULL);
147 return _asciitransform(str_obj, lowertable, NULL);
148 }
148 }
149
149
150 static PyObject *asciiupper(PyObject *self, PyObject *args)
150 static PyObject *asciiupper(PyObject *self, PyObject *args)
151 {
151 {
152 PyObject *str_obj;
152 PyObject *str_obj;
153 if (!PyArg_ParseTuple(args, "O!:asciiupper", &PyBytes_Type, &str_obj))
153 if (!PyArg_ParseTuple(args, "O!:asciiupper", &PyBytes_Type, &str_obj))
154 return NULL;
154 return NULL;
155 return _asciitransform(str_obj, uppertable, NULL);
155 return _asciitransform(str_obj, uppertable, NULL);
156 }
156 }
157
157
158 static inline PyObject *_dict_new_presized(Py_ssize_t expected_size)
158 static inline PyObject *_dict_new_presized(Py_ssize_t expected_size)
159 {
159 {
160 /* _PyDict_NewPresized expects a minused parameter, but it actually
160 /* _PyDict_NewPresized expects a minused parameter, but it actually
161 creates a dictionary that's the nearest power of two bigger than the
161 creates a dictionary that's the nearest power of two bigger than the
162 parameter. For example, with the initial minused = 1000, the
162 parameter. For example, with the initial minused = 1000, the
163 dictionary created has size 1024. Of course in a lot of cases that
163 dictionary created has size 1024. Of course in a lot of cases that
164 can be greater than the maximum load factor Python's dict object
164 can be greater than the maximum load factor Python's dict object
165 expects (= 2/3), so as soon as we cross the threshold we'll resize
165 expects (= 2/3), so as soon as we cross the threshold we'll resize
166 anyway. So create a dictionary that's at least 3/2 the size. */
166 anyway. So create a dictionary that's at least 3/2 the size. */
167 return _PyDict_NewPresized(((1 + expected_size) / 2) * 3);
167 return _PyDict_NewPresized(((1 + expected_size) / 2) * 3);
168 }
168 }
169
169
170 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
170 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
171 {
171 {
172 Py_ssize_t expected_size;
172 Py_ssize_t expected_size;
173
173
174 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size))
174 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size))
175 return NULL;
175 return NULL;
176
176
177 return _dict_new_presized(expected_size);
177 return _dict_new_presized(expected_size);
178 }
178 }
179
179
180 static PyObject *make_file_foldmap(PyObject *self, PyObject *args)
180 static PyObject *make_file_foldmap(PyObject *self, PyObject *args)
181 {
181 {
182 PyObject *dmap, *spec_obj, *normcase_fallback;
182 PyObject *dmap, *spec_obj, *normcase_fallback;
183 PyObject *file_foldmap = NULL;
183 PyObject *file_foldmap = NULL;
184 enum normcase_spec spec;
184 enum normcase_spec spec;
185 PyObject *k, *v;
185 PyObject *k, *v;
186 dirstateTupleObject *tuple;
186 dirstateTupleObject *tuple;
187 Py_ssize_t pos = 0;
187 Py_ssize_t pos = 0;
188 const char *table;
188 const char *table;
189
189
190 if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap",
190 if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap",
191 &PyDict_Type, &dmap,
191 &PyDict_Type, &dmap,
192 &PyInt_Type, &spec_obj,
192 &PyInt_Type, &spec_obj,
193 &PyFunction_Type, &normcase_fallback))
193 &PyFunction_Type, &normcase_fallback))
194 goto quit;
194 goto quit;
195
195
196 spec = (int)PyInt_AS_LONG(spec_obj);
196 spec = (int)PyInt_AS_LONG(spec_obj);
197 switch (spec) {
197 switch (spec) {
198 case NORMCASE_LOWER:
198 case NORMCASE_LOWER:
199 table = lowertable;
199 table = lowertable;
200 break;
200 break;
201 case NORMCASE_UPPER:
201 case NORMCASE_UPPER:
202 table = uppertable;
202 table = uppertable;
203 break;
203 break;
204 case NORMCASE_OTHER:
204 case NORMCASE_OTHER:
205 table = NULL;
205 table = NULL;
206 break;
206 break;
207 default:
207 default:
208 PyErr_SetString(PyExc_TypeError, "invalid normcasespec");
208 PyErr_SetString(PyExc_TypeError, "invalid normcasespec");
209 goto quit;
209 goto quit;
210 }
210 }
211
211
212 /* Add some more entries to deal with additions outside this
212 /* Add some more entries to deal with additions outside this
213 function. */
213 function. */
214 file_foldmap = _dict_new_presized((PyDict_Size(dmap) / 10) * 11);
214 file_foldmap = _dict_new_presized((PyDict_Size(dmap) / 10) * 11);
215 if (file_foldmap == NULL)
215 if (file_foldmap == NULL)
216 goto quit;
216 goto quit;
217
217
218 while (PyDict_Next(dmap, &pos, &k, &v)) {
218 while (PyDict_Next(dmap, &pos, &k, &v)) {
219 if (!dirstate_tuple_check(v)) {
219 if (!dirstate_tuple_check(v)) {
220 PyErr_SetString(PyExc_TypeError,
220 PyErr_SetString(PyExc_TypeError,
221 "expected a dirstate tuple");
221 "expected a dirstate tuple");
222 goto quit;
222 goto quit;
223 }
223 }
224
224
225 tuple = (dirstateTupleObject *)v;
225 tuple = (dirstateTupleObject *)v;
226 if (tuple->state != 'r') {
226 if (tuple->state != 'r') {
227 PyObject *normed;
227 PyObject *normed;
228 if (table != NULL) {
228 if (table != NULL) {
229 normed = _asciitransform(k, table,
229 normed = _asciitransform(k, table,
230 normcase_fallback);
230 normcase_fallback);
231 } else {
231 } else {
232 normed = PyObject_CallFunctionObjArgs(
232 normed = PyObject_CallFunctionObjArgs(
233 normcase_fallback, k, NULL);
233 normcase_fallback, k, NULL);
234 }
234 }
235
235
236 if (normed == NULL)
236 if (normed == NULL)
237 goto quit;
237 goto quit;
238 if (PyDict_SetItem(file_foldmap, normed, k) == -1) {
238 if (PyDict_SetItem(file_foldmap, normed, k) == -1) {
239 Py_DECREF(normed);
239 Py_DECREF(normed);
240 goto quit;
240 goto quit;
241 }
241 }
242 Py_DECREF(normed);
242 Py_DECREF(normed);
243 }
243 }
244 }
244 }
245 return file_foldmap;
245 return file_foldmap;
246 quit:
246 quit:
247 Py_XDECREF(file_foldmap);
247 Py_XDECREF(file_foldmap);
248 return NULL;
248 return NULL;
249 }
249 }
250
250
251 /*
251 /*
252 * This code assumes that a manifest is stitched together with newline
252 * This code assumes that a manifest is stitched together with newline
253 * ('\n') characters.
253 * ('\n') characters.
254 */
254 */
255 static PyObject *parse_manifest(PyObject *self, PyObject *args)
255 static PyObject *parse_manifest(PyObject *self, PyObject *args)
256 {
256 {
257 PyObject *mfdict, *fdict;
257 PyObject *mfdict, *fdict;
258 char *str, *start, *end;
258 char *str, *start, *end;
259 int len;
259 int len;
260
260
261 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
261 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
262 &PyDict_Type, &mfdict,
262 &PyDict_Type, &mfdict,
263 &PyDict_Type, &fdict,
263 &PyDict_Type, &fdict,
264 &str, &len))
264 &str, &len))
265 goto quit;
265 goto quit;
266
266
267 start = str;
267 start = str;
268 end = str + len;
268 end = str + len;
269 while (start < end) {
269 while (start < end) {
270 PyObject *file = NULL, *node = NULL;
270 PyObject *file = NULL, *node = NULL;
271 PyObject *flags = NULL;
271 PyObject *flags = NULL;
272 char *zero = NULL, *newline = NULL;
272 char *zero = NULL, *newline = NULL;
273 ptrdiff_t nlen;
273 ptrdiff_t nlen;
274
274
275 zero = memchr(start, '\0', end - start);
275 zero = memchr(start, '\0', end - start);
276 if (!zero) {
276 if (!zero) {
277 PyErr_SetString(PyExc_ValueError,
277 PyErr_SetString(PyExc_ValueError,
278 "manifest entry has no separator");
278 "manifest entry has no separator");
279 goto quit;
279 goto quit;
280 }
280 }
281
281
282 newline = memchr(zero + 1, '\n', end - (zero + 1));
282 newline = memchr(zero + 1, '\n', end - (zero + 1));
283 if (!newline) {
283 if (!newline) {
284 PyErr_SetString(PyExc_ValueError,
284 PyErr_SetString(PyExc_ValueError,
285 "manifest contains trailing garbage");
285 "manifest contains trailing garbage");
286 goto quit;
286 goto quit;
287 }
287 }
288
288
289 file = PyBytes_FromStringAndSize(start, zero - start);
289 file = PyBytes_FromStringAndSize(start, zero - start);
290
290
291 if (!file)
291 if (!file)
292 goto bail;
292 goto bail;
293
293
294 nlen = newline - zero - 1;
294 nlen = newline - zero - 1;
295
295
296 node = unhexlify(zero + 1, nlen > 40 ? 40 : (int)nlen);
296 node = unhexlify(zero + 1, nlen > 40 ? 40 : (int)nlen);
297 if (!node)
297 if (!node)
298 goto bail;
298 goto bail;
299
299
300 if (nlen > 40) {
300 if (nlen > 40) {
301 flags = PyBytes_FromStringAndSize(zero + 41,
301 flags = PyBytes_FromStringAndSize(zero + 41,
302 nlen - 40);
302 nlen - 40);
303 if (!flags)
303 if (!flags)
304 goto bail;
304 goto bail;
305
305
306 if (PyDict_SetItem(fdict, file, flags) == -1)
306 if (PyDict_SetItem(fdict, file, flags) == -1)
307 goto bail;
307 goto bail;
308 }
308 }
309
309
310 if (PyDict_SetItem(mfdict, file, node) == -1)
310 if (PyDict_SetItem(mfdict, file, node) == -1)
311 goto bail;
311 goto bail;
312
312
313 start = newline + 1;
313 start = newline + 1;
314
314
315 Py_XDECREF(flags);
315 Py_XDECREF(flags);
316 Py_XDECREF(node);
316 Py_XDECREF(node);
317 Py_XDECREF(file);
317 Py_XDECREF(file);
318 continue;
318 continue;
319 bail:
319 bail:
320 Py_XDECREF(flags);
320 Py_XDECREF(flags);
321 Py_XDECREF(node);
321 Py_XDECREF(node);
322 Py_XDECREF(file);
322 Py_XDECREF(file);
323 goto quit;
323 goto quit;
324 }
324 }
325
325
326 Py_INCREF(Py_None);
326 Py_INCREF(Py_None);
327 return Py_None;
327 return Py_None;
328 quit:
328 quit:
329 return NULL;
329 return NULL;
330 }
330 }
331
331
332 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
332 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
333 int size, int mtime)
333 int size, int mtime)
334 {
334 {
335 dirstateTupleObject *t = PyObject_New(dirstateTupleObject,
335 dirstateTupleObject *t = PyObject_New(dirstateTupleObject,
336 &dirstateTupleType);
336 &dirstateTupleType);
337 if (!t)
337 if (!t)
338 return NULL;
338 return NULL;
339 t->state = state;
339 t->state = state;
340 t->mode = mode;
340 t->mode = mode;
341 t->size = size;
341 t->size = size;
342 t->mtime = mtime;
342 t->mtime = mtime;
343 return t;
343 return t;
344 }
344 }
345
345
346 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
346 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
347 PyObject *kwds)
347 PyObject *kwds)
348 {
348 {
349 /* We do all the initialization here and not a tp_init function because
349 /* We do all the initialization here and not a tp_init function because
350 * dirstate_tuple is immutable. */
350 * dirstate_tuple is immutable. */
351 dirstateTupleObject *t;
351 dirstateTupleObject *t;
352 char state;
352 char state;
353 int size, mode, mtime;
353 int size, mode, mtime;
354 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
354 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime))
355 return NULL;
355 return NULL;
356
356
357 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
357 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
358 if (!t)
358 if (!t)
359 return NULL;
359 return NULL;
360 t->state = state;
360 t->state = state;
361 t->mode = mode;
361 t->mode = mode;
362 t->size = size;
362 t->size = size;
363 t->mtime = mtime;
363 t->mtime = mtime;
364
364
365 return (PyObject *)t;
365 return (PyObject *)t;
366 }
366 }
367
367
368 static void dirstate_tuple_dealloc(PyObject *o)
368 static void dirstate_tuple_dealloc(PyObject *o)
369 {
369 {
370 PyObject_Del(o);
370 PyObject_Del(o);
371 }
371 }
372
372
373 static Py_ssize_t dirstate_tuple_length(PyObject *o)
373 static Py_ssize_t dirstate_tuple_length(PyObject *o)
374 {
374 {
375 return 4;
375 return 4;
376 }
376 }
377
377
378 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
378 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
379 {
379 {
380 dirstateTupleObject *t = (dirstateTupleObject *)o;
380 dirstateTupleObject *t = (dirstateTupleObject *)o;
381 switch (i) {
381 switch (i) {
382 case 0:
382 case 0:
383 return PyBytes_FromStringAndSize(&t->state, 1);
383 return PyBytes_FromStringAndSize(&t->state, 1);
384 case 1:
384 case 1:
385 return PyInt_FromLong(t->mode);
385 return PyInt_FromLong(t->mode);
386 case 2:
386 case 2:
387 return PyInt_FromLong(t->size);
387 return PyInt_FromLong(t->size);
388 case 3:
388 case 3:
389 return PyInt_FromLong(t->mtime);
389 return PyInt_FromLong(t->mtime);
390 default:
390 default:
391 PyErr_SetString(PyExc_IndexError, "index out of range");
391 PyErr_SetString(PyExc_IndexError, "index out of range");
392 return NULL;
392 return NULL;
393 }
393 }
394 }
394 }
395
395
396 static PySequenceMethods dirstate_tuple_sq = {
396 static PySequenceMethods dirstate_tuple_sq = {
397 dirstate_tuple_length, /* sq_length */
397 dirstate_tuple_length, /* sq_length */
398 0, /* sq_concat */
398 0, /* sq_concat */
399 0, /* sq_repeat */
399 0, /* sq_repeat */
400 dirstate_tuple_item, /* sq_item */
400 dirstate_tuple_item, /* sq_item */
401 0, /* sq_ass_item */
401 0, /* sq_ass_item */
402 0, /* sq_contains */
402 0, /* sq_contains */
403 0, /* sq_inplace_concat */
403 0, /* sq_inplace_concat */
404 0 /* sq_inplace_repeat */
404 0 /* sq_inplace_repeat */
405 };
405 };
406
406
407 PyTypeObject dirstateTupleType = {
407 PyTypeObject dirstateTupleType = {
408 PyVarObject_HEAD_INIT(NULL, 0)
408 PyVarObject_HEAD_INIT(NULL, 0)
409 "dirstate_tuple", /* tp_name */
409 "dirstate_tuple", /* tp_name */
410 sizeof(dirstateTupleObject),/* tp_basicsize */
410 sizeof(dirstateTupleObject),/* tp_basicsize */
411 0, /* tp_itemsize */
411 0, /* tp_itemsize */
412 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
412 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
413 0, /* tp_print */
413 0, /* tp_print */
414 0, /* tp_getattr */
414 0, /* tp_getattr */
415 0, /* tp_setattr */
415 0, /* tp_setattr */
416 0, /* tp_compare */
416 0, /* tp_compare */
417 0, /* tp_repr */
417 0, /* tp_repr */
418 0, /* tp_as_number */
418 0, /* tp_as_number */
419 &dirstate_tuple_sq, /* tp_as_sequence */
419 &dirstate_tuple_sq, /* tp_as_sequence */
420 0, /* tp_as_mapping */
420 0, /* tp_as_mapping */
421 0, /* tp_hash */
421 0, /* tp_hash */
422 0, /* tp_call */
422 0, /* tp_call */
423 0, /* tp_str */
423 0, /* tp_str */
424 0, /* tp_getattro */
424 0, /* tp_getattro */
425 0, /* tp_setattro */
425 0, /* tp_setattro */
426 0, /* tp_as_buffer */
426 0, /* tp_as_buffer */
427 Py_TPFLAGS_DEFAULT, /* tp_flags */
427 Py_TPFLAGS_DEFAULT, /* tp_flags */
428 "dirstate tuple", /* tp_doc */
428 "dirstate tuple", /* tp_doc */
429 0, /* tp_traverse */
429 0, /* tp_traverse */
430 0, /* tp_clear */
430 0, /* tp_clear */
431 0, /* tp_richcompare */
431 0, /* tp_richcompare */
432 0, /* tp_weaklistoffset */
432 0, /* tp_weaklistoffset */
433 0, /* tp_iter */
433 0, /* tp_iter */
434 0, /* tp_iternext */
434 0, /* tp_iternext */
435 0, /* tp_methods */
435 0, /* tp_methods */
436 0, /* tp_members */
436 0, /* tp_members */
437 0, /* tp_getset */
437 0, /* tp_getset */
438 0, /* tp_base */
438 0, /* tp_base */
439 0, /* tp_dict */
439 0, /* tp_dict */
440 0, /* tp_descr_get */
440 0, /* tp_descr_get */
441 0, /* tp_descr_set */
441 0, /* tp_descr_set */
442 0, /* tp_dictoffset */
442 0, /* tp_dictoffset */
443 0, /* tp_init */
443 0, /* tp_init */
444 0, /* tp_alloc */
444 0, /* tp_alloc */
445 dirstate_tuple_new, /* tp_new */
445 dirstate_tuple_new, /* tp_new */
446 };
446 };
447
447
448 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
448 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
449 {
449 {
450 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
450 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
451 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
451 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
452 char state, *cur, *str, *cpos;
452 char state, *cur, *str, *cpos;
453 int mode, size, mtime;
453 int mode, size, mtime;
454 unsigned int flen, len, pos = 40;
454 unsigned int flen, len, pos = 40;
455 int readlen;
455 int readlen;
456
456
457 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
457 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
458 &PyDict_Type, &dmap,
458 &PyDict_Type, &dmap,
459 &PyDict_Type, &cmap,
459 &PyDict_Type, &cmap,
460 &str, &readlen))
460 &str, &readlen))
461 goto quit;
461 goto quit;
462
462
463 len = readlen;
463 len = readlen;
464
464
465 /* read parents */
465 /* read parents */
466 if (len < 40) {
466 if (len < 40) {
467 PyErr_SetString(
467 PyErr_SetString(
468 PyExc_ValueError, "too little data for parents");
468 PyExc_ValueError, "too little data for parents");
469 goto quit;
469 goto quit;
470 }
470 }
471
471
472 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
472 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
473 if (!parents)
473 if (!parents)
474 goto quit;
474 goto quit;
475
475
476 /* read filenames */
476 /* read filenames */
477 while (pos >= 40 && pos < len) {
477 while (pos >= 40 && pos < len) {
478 if (pos + 17 > len) {
478 if (pos + 17 > len) {
479 PyErr_SetString(PyExc_ValueError,
479 PyErr_SetString(PyExc_ValueError,
480 "overflow in dirstate");
480 "overflow in dirstate");
481 goto quit;
481 goto quit;
482 }
482 }
483 cur = str + pos;
483 cur = str + pos;
484 /* unpack header */
484 /* unpack header */
485 state = *cur;
485 state = *cur;
486 mode = getbe32(cur + 1);
486 mode = getbe32(cur + 1);
487 size = getbe32(cur + 5);
487 size = getbe32(cur + 5);
488 mtime = getbe32(cur + 9);
488 mtime = getbe32(cur + 9);
489 flen = getbe32(cur + 13);
489 flen = getbe32(cur + 13);
490 pos += 17;
490 pos += 17;
491 cur += 17;
491 cur += 17;
492 if (flen > len - pos) {
492 if (flen > len - pos) {
493 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
493 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
494 goto quit;
494 goto quit;
495 }
495 }
496
496
497 entry = (PyObject *)make_dirstate_tuple(state, mode, size,
497 entry = (PyObject *)make_dirstate_tuple(state, mode, size,
498 mtime);
498 mtime);
499 cpos = memchr(cur, 0, flen);
499 cpos = memchr(cur, 0, flen);
500 if (cpos) {
500 if (cpos) {
501 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
501 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
502 cname = PyBytes_FromStringAndSize(cpos + 1,
502 cname = PyBytes_FromStringAndSize(cpos + 1,
503 flen - (cpos - cur) - 1);
503 flen - (cpos - cur) - 1);
504 if (!fname || !cname ||
504 if (!fname || !cname ||
505 PyDict_SetItem(cmap, fname, cname) == -1 ||
505 PyDict_SetItem(cmap, fname, cname) == -1 ||
506 PyDict_SetItem(dmap, fname, entry) == -1)
506 PyDict_SetItem(dmap, fname, entry) == -1)
507 goto quit;
507 goto quit;
508 Py_DECREF(cname);
508 Py_DECREF(cname);
509 } else {
509 } else {
510 fname = PyBytes_FromStringAndSize(cur, flen);
510 fname = PyBytes_FromStringAndSize(cur, flen);
511 if (!fname ||
511 if (!fname ||
512 PyDict_SetItem(dmap, fname, entry) == -1)
512 PyDict_SetItem(dmap, fname, entry) == -1)
513 goto quit;
513 goto quit;
514 }
514 }
515 Py_DECREF(fname);
515 Py_DECREF(fname);
516 Py_DECREF(entry);
516 Py_DECREF(entry);
517 fname = cname = entry = NULL;
517 fname = cname = entry = NULL;
518 pos += flen;
518 pos += flen;
519 }
519 }
520
520
521 ret = parents;
521 ret = parents;
522 Py_INCREF(ret);
522 Py_INCREF(ret);
523 quit:
523 quit:
524 Py_XDECREF(fname);
524 Py_XDECREF(fname);
525 Py_XDECREF(cname);
525 Py_XDECREF(cname);
526 Py_XDECREF(entry);
526 Py_XDECREF(entry);
527 Py_XDECREF(parents);
527 Py_XDECREF(parents);
528 return ret;
528 return ret;
529 }
529 }
530
530
531 /*
531 /*
532 * Build a set of non-normal and other parent entries from the dirstate dmap
532 * Build a set of non-normal and other parent entries from the dirstate dmap
533 */
533 */
534 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args) {
534 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args) {
535 PyObject *dmap, *fname, *v;
535 PyObject *dmap, *fname, *v;
536 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
536 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
537 Py_ssize_t pos;
537 Py_ssize_t pos;
538
538
539 if (!PyArg_ParseTuple(args, "O!:nonnormalentries",
539 if (!PyArg_ParseTuple(args, "O!:nonnormalentries",
540 &PyDict_Type, &dmap))
540 &PyDict_Type, &dmap))
541 goto bail;
541 goto bail;
542
542
543 nonnset = PySet_New(NULL);
543 nonnset = PySet_New(NULL);
544 if (nonnset == NULL)
544 if (nonnset == NULL)
545 goto bail;
545 goto bail;
546
546
547 otherpset = PySet_New(NULL);
547 otherpset = PySet_New(NULL);
548 if (otherpset == NULL)
548 if (otherpset == NULL)
549 goto bail;
549 goto bail;
550
550
551 pos = 0;
551 pos = 0;
552 while (PyDict_Next(dmap, &pos, &fname, &v)) {
552 while (PyDict_Next(dmap, &pos, &fname, &v)) {
553 dirstateTupleObject *t;
553 dirstateTupleObject *t;
554 if (!dirstate_tuple_check(v)) {
554 if (!dirstate_tuple_check(v)) {
555 PyErr_SetString(PyExc_TypeError,
555 PyErr_SetString(PyExc_TypeError,
556 "expected a dirstate tuple");
556 "expected a dirstate tuple");
557 goto bail;
557 goto bail;
558 }
558 }
559 t = (dirstateTupleObject *)v;
559 t = (dirstateTupleObject *)v;
560
560
561 if (t->state == 'n' && t->size == -2) {
561 if (t->state == 'n' && t->size == -2) {
562 if (PySet_Add(otherpset, fname) == -1) {
562 if (PySet_Add(otherpset, fname) == -1) {
563 goto bail;
563 goto bail;
564 }
564 }
565 }
565 }
566
566
567 if (t->state == 'n' && t->mtime != -1)
567 if (t->state == 'n' && t->mtime != -1)
568 continue;
568 continue;
569 if (PySet_Add(nonnset, fname) == -1)
569 if (PySet_Add(nonnset, fname) == -1)
570 goto bail;
570 goto bail;
571 }
571 }
572
572
573 result = Py_BuildValue("(OO)", nonnset, otherpset);
573 result = Py_BuildValue("(OO)", nonnset, otherpset);
574 if (result == NULL)
574 if (result == NULL)
575 goto bail;
575 goto bail;
576 Py_DECREF(nonnset);
576 Py_DECREF(nonnset);
577 Py_DECREF(otherpset);
577 Py_DECREF(otherpset);
578 return result;
578 return result;
579 bail:
579 bail:
580 Py_XDECREF(nonnset);
580 Py_XDECREF(nonnset);
581 Py_XDECREF(otherpset);
581 Py_XDECREF(otherpset);
582 Py_XDECREF(result);
582 Py_XDECREF(result);
583 return NULL;
583 return NULL;
584 }
584 }
585
585
586 /*
586 /*
587 * Efficiently pack a dirstate object into its on-disk format.
587 * Efficiently pack a dirstate object into its on-disk format.
588 */
588 */
589 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
589 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
590 {
590 {
591 PyObject *packobj = NULL;
591 PyObject *packobj = NULL;
592 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
592 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
593 Py_ssize_t nbytes, pos, l;
593 Py_ssize_t nbytes, pos, l;
594 PyObject *k, *v = NULL, *pn;
594 PyObject *k, *v = NULL, *pn;
595 char *p, *s;
595 char *p, *s;
596 int now;
596 int now;
597
597
598 if (!PyArg_ParseTuple(args, "O!O!Oi:pack_dirstate",
598 if (!PyArg_ParseTuple(args, "O!O!Oi:pack_dirstate",
599 &PyDict_Type, &map, &PyDict_Type, &copymap,
599 &PyDict_Type, &map, &PyDict_Type, &copymap,
600 &pl, &now))
600 &pl, &now))
601 return NULL;
601 return NULL;
602
602
603 if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
603 if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
604 PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
604 PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
605 return NULL;
605 return NULL;
606 }
606 }
607
607
608 /* Figure out how much we need to allocate. */
608 /* Figure out how much we need to allocate. */
609 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
609 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
610 PyObject *c;
610 PyObject *c;
611 if (!PyBytes_Check(k)) {
611 if (!PyBytes_Check(k)) {
612 PyErr_SetString(PyExc_TypeError, "expected string key");
612 PyErr_SetString(PyExc_TypeError, "expected string key");
613 goto bail;
613 goto bail;
614 }
614 }
615 nbytes += PyBytes_GET_SIZE(k) + 17;
615 nbytes += PyBytes_GET_SIZE(k) + 17;
616 c = PyDict_GetItem(copymap, k);
616 c = PyDict_GetItem(copymap, k);
617 if (c) {
617 if (c) {
618 if (!PyBytes_Check(c)) {
618 if (!PyBytes_Check(c)) {
619 PyErr_SetString(PyExc_TypeError,
619 PyErr_SetString(PyExc_TypeError,
620 "expected string key");
620 "expected string key");
621 goto bail;
621 goto bail;
622 }
622 }
623 nbytes += PyBytes_GET_SIZE(c) + 1;
623 nbytes += PyBytes_GET_SIZE(c) + 1;
624 }
624 }
625 }
625 }
626
626
627 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
627 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
628 if (packobj == NULL)
628 if (packobj == NULL)
629 goto bail;
629 goto bail;
630
630
631 p = PyBytes_AS_STRING(packobj);
631 p = PyBytes_AS_STRING(packobj);
632
632
633 pn = PySequence_ITEM(pl, 0);
633 pn = PySequence_ITEM(pl, 0);
634 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
634 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
635 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
635 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
636 goto bail;
636 goto bail;
637 }
637 }
638 memcpy(p, s, l);
638 memcpy(p, s, l);
639 p += 20;
639 p += 20;
640 pn = PySequence_ITEM(pl, 1);
640 pn = PySequence_ITEM(pl, 1);
641 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
641 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
642 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
642 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
643 goto bail;
643 goto bail;
644 }
644 }
645 memcpy(p, s, l);
645 memcpy(p, s, l);
646 p += 20;
646 p += 20;
647
647
648 for (pos = 0; PyDict_Next(map, &pos, &k, &v); ) {
648 for (pos = 0; PyDict_Next(map, &pos, &k, &v); ) {
649 dirstateTupleObject *tuple;
649 dirstateTupleObject *tuple;
650 char state;
650 char state;
651 int mode, size, mtime;
651 int mode, size, mtime;
652 Py_ssize_t len, l;
652 Py_ssize_t len, l;
653 PyObject *o;
653 PyObject *o;
654 char *t;
654 char *t;
655
655
656 if (!dirstate_tuple_check(v)) {
656 if (!dirstate_tuple_check(v)) {
657 PyErr_SetString(PyExc_TypeError,
657 PyErr_SetString(PyExc_TypeError,
658 "expected a dirstate tuple");
658 "expected a dirstate tuple");
659 goto bail;
659 goto bail;
660 }
660 }
661 tuple = (dirstateTupleObject *)v;
661 tuple = (dirstateTupleObject *)v;
662
662
663 state = tuple->state;
663 state = tuple->state;
664 mode = tuple->mode;
664 mode = tuple->mode;
665 size = tuple->size;
665 size = tuple->size;
666 mtime = tuple->mtime;
666 mtime = tuple->mtime;
667 if (state == 'n' && mtime == now) {
667 if (state == 'n' && mtime == now) {
668 /* See pure/parsers.py:pack_dirstate for why we do
668 /* See pure/parsers.py:pack_dirstate for why we do
669 * this. */
669 * this. */
670 mtime = -1;
670 mtime = -1;
671 mtime_unset = (PyObject *)make_dirstate_tuple(
671 mtime_unset = (PyObject *)make_dirstate_tuple(
672 state, mode, size, mtime);
672 state, mode, size, mtime);
673 if (!mtime_unset)
673 if (!mtime_unset)
674 goto bail;
674 goto bail;
675 if (PyDict_SetItem(map, k, mtime_unset) == -1)
675 if (PyDict_SetItem(map, k, mtime_unset) == -1)
676 goto bail;
676 goto bail;
677 Py_DECREF(mtime_unset);
677 Py_DECREF(mtime_unset);
678 mtime_unset = NULL;
678 mtime_unset = NULL;
679 }
679 }
680 *p++ = state;
680 *p++ = state;
681 putbe32((uint32_t)mode, p);
681 putbe32((uint32_t)mode, p);
682 putbe32((uint32_t)size, p + 4);
682 putbe32((uint32_t)size, p + 4);
683 putbe32((uint32_t)mtime, p + 8);
683 putbe32((uint32_t)mtime, p + 8);
684 t = p + 12;
684 t = p + 12;
685 p += 16;
685 p += 16;
686 len = PyBytes_GET_SIZE(k);
686 len = PyBytes_GET_SIZE(k);
687 memcpy(p, PyBytes_AS_STRING(k), len);
687 memcpy(p, PyBytes_AS_STRING(k), len);
688 p += len;
688 p += len;
689 o = PyDict_GetItem(copymap, k);
689 o = PyDict_GetItem(copymap, k);
690 if (o) {
690 if (o) {
691 *p++ = '\0';
691 *p++ = '\0';
692 l = PyBytes_GET_SIZE(o);
692 l = PyBytes_GET_SIZE(o);
693 memcpy(p, PyBytes_AS_STRING(o), l);
693 memcpy(p, PyBytes_AS_STRING(o), l);
694 p += l;
694 p += l;
695 len += l + 1;
695 len += l + 1;
696 }
696 }
697 putbe32((uint32_t)len, t);
697 putbe32((uint32_t)len, t);
698 }
698 }
699
699
700 pos = p - PyBytes_AS_STRING(packobj);
700 pos = p - PyBytes_AS_STRING(packobj);
701 if (pos != nbytes) {
701 if (pos != nbytes) {
702 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
702 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
703 (long)pos, (long)nbytes);
703 (long)pos, (long)nbytes);
704 goto bail;
704 goto bail;
705 }
705 }
706
706
707 return packobj;
707 return packobj;
708 bail:
708 bail:
709 Py_XDECREF(mtime_unset);
709 Py_XDECREF(mtime_unset);
710 Py_XDECREF(packobj);
710 Py_XDECREF(packobj);
711 Py_XDECREF(v);
711 Py_XDECREF(v);
712 return NULL;
712 return NULL;
713 }
713 }
714
714
715 #define BUMPED_FIX 1
715 #define BUMPED_FIX 1
716 #define USING_SHA_256 2
716 #define USING_SHA_256 2
717 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
717 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
718
718
719 static PyObject *readshas(
719 static PyObject *readshas(
720 const char *source, unsigned char num, Py_ssize_t hashwidth)
720 const char *source, unsigned char num, Py_ssize_t hashwidth)
721 {
721 {
722 int i;
722 int i;
723 PyObject *list = PyTuple_New(num);
723 PyObject *list = PyTuple_New(num);
724 if (list == NULL) {
724 if (list == NULL) {
725 return NULL;
725 return NULL;
726 }
726 }
727 for (i = 0; i < num; i++) {
727 for (i = 0; i < num; i++) {
728 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
728 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
729 if (hash == NULL) {
729 if (hash == NULL) {
730 Py_DECREF(list);
730 Py_DECREF(list);
731 return NULL;
731 return NULL;
732 }
732 }
733 PyTuple_SET_ITEM(list, i, hash);
733 PyTuple_SET_ITEM(list, i, hash);
734 source += hashwidth;
734 source += hashwidth;
735 }
735 }
736 return list;
736 return list;
737 }
737 }
738
738
739 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
739 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
740 uint32_t *msize)
740 uint32_t *msize)
741 {
741 {
742 const char *data = databegin;
742 const char *data = databegin;
743 const char *meta;
743 const char *meta;
744
744
745 double mtime;
745 double mtime;
746 int16_t tz;
746 int16_t tz;
747 uint16_t flags;
747 uint16_t flags;
748 unsigned char nsuccs, nparents, nmetadata;
748 unsigned char nsuccs, nparents, nmetadata;
749 Py_ssize_t hashwidth = 20;
749 Py_ssize_t hashwidth = 20;
750
750
751 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
751 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
752 PyObject *metadata = NULL, *ret = NULL;
752 PyObject *metadata = NULL, *ret = NULL;
753 int i;
753 int i;
754
754
755 if (data + FM1_HEADER_SIZE > dataend) {
755 if (data + FM1_HEADER_SIZE > dataend) {
756 goto overflow;
756 goto overflow;
757 }
757 }
758
758
759 *msize = getbe32(data);
759 *msize = getbe32(data);
760 data += 4;
760 data += 4;
761 mtime = getbefloat64(data);
761 mtime = getbefloat64(data);
762 data += 8;
762 data += 8;
763 tz = getbeint16(data);
763 tz = getbeint16(data);
764 data += 2;
764 data += 2;
765 flags = getbeuint16(data);
765 flags = getbeuint16(data);
766 data += 2;
766 data += 2;
767
767
768 if (flags & USING_SHA_256) {
768 if (flags & USING_SHA_256) {
769 hashwidth = 32;
769 hashwidth = 32;
770 }
770 }
771
771
772 nsuccs = (unsigned char)(*data++);
772 nsuccs = (unsigned char)(*data++);
773 nparents = (unsigned char)(*data++);
773 nparents = (unsigned char)(*data++);
774 nmetadata = (unsigned char)(*data++);
774 nmetadata = (unsigned char)(*data++);
775
775
776 if (databegin + *msize > dataend) {
776 if (databegin + *msize > dataend) {
777 goto overflow;
777 goto overflow;
778 }
778 }
779 dataend = databegin + *msize; /* narrow down to marker size */
779 dataend = databegin + *msize; /* narrow down to marker size */
780
780
781 if (data + hashwidth > dataend) {
781 if (data + hashwidth > dataend) {
782 goto overflow;
782 goto overflow;
783 }
783 }
784 prec = PyBytes_FromStringAndSize(data, hashwidth);
784 prec = PyBytes_FromStringAndSize(data, hashwidth);
785 data += hashwidth;
785 data += hashwidth;
786 if (prec == NULL) {
786 if (prec == NULL) {
787 goto bail;
787 goto bail;
788 }
788 }
789
789
790 if (data + nsuccs * hashwidth > dataend) {
790 if (data + nsuccs * hashwidth > dataend) {
791 goto overflow;
791 goto overflow;
792 }
792 }
793 succs = readshas(data, nsuccs, hashwidth);
793 succs = readshas(data, nsuccs, hashwidth);
794 if (succs == NULL) {
794 if (succs == NULL) {
795 goto bail;
795 goto bail;
796 }
796 }
797 data += nsuccs * hashwidth;
797 data += nsuccs * hashwidth;
798
798
799 if (nparents == 1 || nparents == 2) {
799 if (nparents == 1 || nparents == 2) {
800 if (data + nparents * hashwidth > dataend) {
800 if (data + nparents * hashwidth > dataend) {
801 goto overflow;
801 goto overflow;
802 }
802 }
803 parents = readshas(data, nparents, hashwidth);
803 parents = readshas(data, nparents, hashwidth);
804 if (parents == NULL) {
804 if (parents == NULL) {
805 goto bail;
805 goto bail;
806 }
806 }
807 data += nparents * hashwidth;
807 data += nparents * hashwidth;
808 } else {
808 } else {
809 parents = Py_None;
809 parents = Py_None;
810 Py_INCREF(parents);
810 Py_INCREF(parents);
811 }
811 }
812
812
813 if (data + 2 * nmetadata > dataend) {
813 if (data + 2 * nmetadata > dataend) {
814 goto overflow;
814 goto overflow;
815 }
815 }
816 meta = data + (2 * nmetadata);
816 meta = data + (2 * nmetadata);
817 metadata = PyTuple_New(nmetadata);
817 metadata = PyTuple_New(nmetadata);
818 if (metadata == NULL) {
818 if (metadata == NULL) {
819 goto bail;
819 goto bail;
820 }
820 }
821 for (i = 0; i < nmetadata; i++) {
821 for (i = 0; i < nmetadata; i++) {
822 PyObject *tmp, *left = NULL, *right = NULL;
822 PyObject *tmp, *left = NULL, *right = NULL;
823 Py_ssize_t leftsize = (unsigned char)(*data++);
823 Py_ssize_t leftsize = (unsigned char)(*data++);
824 Py_ssize_t rightsize = (unsigned char)(*data++);
824 Py_ssize_t rightsize = (unsigned char)(*data++);
825 if (meta + leftsize + rightsize > dataend) {
825 if (meta + leftsize + rightsize > dataend) {
826 goto overflow;
826 goto overflow;
827 }
827 }
828 left = PyBytes_FromStringAndSize(meta, leftsize);
828 left = PyBytes_FromStringAndSize(meta, leftsize);
829 meta += leftsize;
829 meta += leftsize;
830 right = PyBytes_FromStringAndSize(meta, rightsize);
830 right = PyBytes_FromStringAndSize(meta, rightsize);
831 meta += rightsize;
831 meta += rightsize;
832 tmp = PyTuple_New(2);
832 tmp = PyTuple_New(2);
833 if (!left || !right || !tmp) {
833 if (!left || !right || !tmp) {
834 Py_XDECREF(left);
834 Py_XDECREF(left);
835 Py_XDECREF(right);
835 Py_XDECREF(right);
836 Py_XDECREF(tmp);
836 Py_XDECREF(tmp);
837 goto bail;
837 goto bail;
838 }
838 }
839 PyTuple_SET_ITEM(tmp, 0, left);
839 PyTuple_SET_ITEM(tmp, 0, left);
840 PyTuple_SET_ITEM(tmp, 1, right);
840 PyTuple_SET_ITEM(tmp, 1, right);
841 PyTuple_SET_ITEM(metadata, i, tmp);
841 PyTuple_SET_ITEM(metadata, i, tmp);
842 }
842 }
843 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags,
843 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags,
844 metadata, mtime, (int)tz * 60, parents);
844 metadata, mtime, (int)tz * 60, parents);
845 goto bail; /* return successfully */
845 goto bail; /* return successfully */
846
846
847 overflow:
847 overflow:
848 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
848 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
849 bail:
849 bail:
850 Py_XDECREF(prec);
850 Py_XDECREF(prec);
851 Py_XDECREF(succs);
851 Py_XDECREF(succs);
852 Py_XDECREF(metadata);
852 Py_XDECREF(metadata);
853 Py_XDECREF(parents);
853 Py_XDECREF(parents);
854 return ret;
854 return ret;
855 }
855 }
856
856
857
857
858 static PyObject *fm1readmarkers(PyObject *self, PyObject *args) {
858 static PyObject *fm1readmarkers(PyObject *self, PyObject *args) {
859 const char *data, *dataend;
859 const char *data, *dataend;
860 int datalen;
860 int datalen;
861 Py_ssize_t offset, stop;
861 Py_ssize_t offset, stop;
862 PyObject *markers = NULL;
862 PyObject *markers = NULL;
863
863
864 if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
864 if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
865 return NULL;
865 return NULL;
866 }
866 }
867 dataend = data + datalen;
867 dataend = data + datalen;
868 data += offset;
868 data += offset;
869 markers = PyList_New(0);
869 markers = PyList_New(0);
870 if (!markers) {
870 if (!markers) {
871 return NULL;
871 return NULL;
872 }
872 }
873 while (offset < stop) {
873 while (offset < stop) {
874 uint32_t msize;
874 uint32_t msize;
875 int error;
875 int error;
876 PyObject *record = fm1readmarker(data, dataend, &msize);
876 PyObject *record = fm1readmarker(data, dataend, &msize);
877 if (!record) {
877 if (!record) {
878 goto bail;
878 goto bail;
879 }
879 }
880 error = PyList_Append(markers, record);
880 error = PyList_Append(markers, record);
881 Py_DECREF(record);
881 Py_DECREF(record);
882 if (error) {
882 if (error) {
883 goto bail;
883 goto bail;
884 }
884 }
885 data += msize;
885 data += msize;
886 offset += msize;
886 offset += msize;
887 }
887 }
888 return markers;
888 return markers;
889 bail:
889 bail:
890 Py_DECREF(markers);
890 Py_DECREF(markers);
891 return NULL;
891 return NULL;
892 }
892 }
893
893
894 static char parsers_doc[] = "Efficient content parsing.";
894 static char parsers_doc[] = "Efficient content parsing.";
895
895
896 PyObject *encodedir(PyObject *self, PyObject *args);
896 PyObject *encodedir(PyObject *self, PyObject *args);
897 PyObject *pathencode(PyObject *self, PyObject *args);
897 PyObject *pathencode(PyObject *self, PyObject *args);
898 PyObject *lowerencode(PyObject *self, PyObject *args);
898 PyObject *lowerencode(PyObject *self, PyObject *args);
899 PyObject *parse_index2(PyObject *self, PyObject *args);
899 PyObject *parse_index2(PyObject *self, PyObject *args);
900
900
901 static PyMethodDef methods[] = {
901 static PyMethodDef methods[] = {
902 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
902 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
903 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
903 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
904 "create a set containing non-normal and other parent entries of given "
904 "create a set containing non-normal and other parent entries of given "
905 "dirstate\n"},
905 "dirstate\n"},
906 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
906 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
907 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
907 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
908 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
908 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
909 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
909 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
910 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
910 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
911 {"dict_new_presized", dict_new_presized, METH_VARARGS,
911 {"dict_new_presized", dict_new_presized, METH_VARARGS,
912 "construct a dict with an expected size\n"},
912 "construct a dict with an expected size\n"},
913 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
913 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
914 "make file foldmap\n"},
914 "make file foldmap\n"},
915 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
915 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
916 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
916 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
917 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
917 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
918 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
918 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
919 "parse v1 obsolete markers\n"},
919 "parse v1 obsolete markers\n"},
920 {NULL, NULL}
920 {NULL, NULL}
921 };
921 };
922
922
923 void dirs_module_init(PyObject *mod);
923 void dirs_module_init(PyObject *mod);
924 void manifest_module_init(PyObject *mod);
924 void manifest_module_init(PyObject *mod);
925 void revlog_module_init(PyObject *mod);
925 void revlog_module_init(PyObject *mod);
926
926
927 static const int version = 1;
927 static const int version = 1;
928
928
929 static void module_init(PyObject *mod)
929 static void module_init(PyObject *mod)
930 {
930 {
931 PyModule_AddIntConstant(mod, "version", version);
931 PyModule_AddIntConstant(mod, "version", version);
932
932
933 /* This module constant has two purposes. First, it lets us unit test
933 /* This module constant has two purposes. First, it lets us unit test
934 * the ImportError raised without hard-coding any error text. This
934 * the ImportError raised without hard-coding any error text. This
935 * means we can change the text in the future without breaking tests,
935 * means we can change the text in the future without breaking tests,
936 * even across changesets without a recompile. Second, its presence
936 * even across changesets without a recompile. Second, its presence
937 * can be used to determine whether the version-checking logic is
937 * can be used to determine whether the version-checking logic is
938 * present, which also helps in testing across changesets without a
938 * present, which also helps in testing across changesets without a
939 * recompile. Note that this means the pure-Python version of parsers
939 * recompile. Note that this means the pure-Python version of parsers
940 * should not have this module constant. */
940 * should not have this module constant. */
941 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
941 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
942
942
943 dirs_module_init(mod);
943 dirs_module_init(mod);
944 manifest_module_init(mod);
944 manifest_module_init(mod);
945 revlog_module_init(mod);
945 revlog_module_init(mod);
946
946
947 if (PyType_Ready(&dirstateTupleType) < 0)
947 if (PyType_Ready(&dirstateTupleType) < 0)
948 return;
948 return;
949 Py_INCREF(&dirstateTupleType);
949 Py_INCREF(&dirstateTupleType);
950 PyModule_AddObject(mod, "dirstatetuple",
950 PyModule_AddObject(mod, "dirstatetuple",
951 (PyObject *)&dirstateTupleType);
951 (PyObject *)&dirstateTupleType);
952 }
952 }
953
953
954 static int check_python_version(void)
954 static int check_python_version(void)
955 {
955 {
956 PyObject *sys = PyImport_ImportModule("sys"), *ver;
956 PyObject *sys = PyImport_ImportModule("sys"), *ver;
957 long hexversion;
957 long hexversion;
958 if (!sys)
958 if (!sys)
959 return -1;
959 return -1;
960 ver = PyObject_GetAttrString(sys, "hexversion");
960 ver = PyObject_GetAttrString(sys, "hexversion");
961 Py_DECREF(sys);
961 Py_DECREF(sys);
962 if (!ver)
962 if (!ver)
963 return -1;
963 return -1;
964 hexversion = PyInt_AsLong(ver);
964 hexversion = PyInt_AsLong(ver);
965 Py_DECREF(ver);
965 Py_DECREF(ver);
966 /* sys.hexversion is a 32-bit number by default, so the -1 case
966 /* sys.hexversion is a 32-bit number by default, so the -1 case
967 * should only occur in unusual circumstances (e.g. if sys.hexversion
967 * should only occur in unusual circumstances (e.g. if sys.hexversion
968 * is manually set to an invalid value). */
968 * is manually set to an invalid value). */
969 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
969 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
970 PyErr_Format(PyExc_ImportError, "%s: The Mercurial extension "
970 PyErr_Format(PyExc_ImportError, "%s: The Mercurial extension "
971 "modules were compiled with Python " PY_VERSION ", but "
971 "modules were compiled with Python " PY_VERSION ", but "
972 "Mercurial is currently using Python with sys.hexversion=%ld: "
972 "Mercurial is currently using Python with sys.hexversion=%ld: "
973 "Python %s\n at: %s", versionerrortext, hexversion,
973 "Python %s\n at: %s", versionerrortext, hexversion,
974 Py_GetVersion(), Py_GetProgramFullPath());
974 Py_GetVersion(), Py_GetProgramFullPath());
975 return -1;
975 return -1;
976 }
976 }
977 return 0;
977 return 0;
978 }
978 }
979
979
980 #ifdef IS_PY3K
980 #ifdef IS_PY3K
981 static struct PyModuleDef parsers_module = {
981 static struct PyModuleDef parsers_module = {
982 PyModuleDef_HEAD_INIT,
982 PyModuleDef_HEAD_INIT,
983 "parsers",
983 "parsers",
984 parsers_doc,
984 parsers_doc,
985 -1,
985 -1,
986 methods
986 methods
987 };
987 };
988
988
989 PyMODINIT_FUNC PyInit_parsers(void)
989 PyMODINIT_FUNC PyInit_parsers(void)
990 {
990 {
991 PyObject *mod;
991 PyObject *mod;
992
992
993 if (check_python_version() == -1)
993 if (check_python_version() == -1)
994 return NULL;
994 return NULL;
995 mod = PyModule_Create(&parsers_module);
995 mod = PyModule_Create(&parsers_module);
996 module_init(mod);
996 module_init(mod);
997 return mod;
997 return mod;
998 }
998 }
999 #else
999 #else
1000 PyMODINIT_FUNC initparsers(void)
1000 PyMODINIT_FUNC initparsers(void)
1001 {
1001 {
1002 PyObject *mod;
1002 PyObject *mod;
1003
1003
1004 if (check_python_version() == -1)
1004 if (check_python_version() == -1)
1005 return;
1005 return;
1006 mod = Py_InitModule3("parsers", methods, parsers_doc);
1006 mod = Py_InitModule3("parsers", methods, parsers_doc);
1007 module_init(mod);
1007 module_init(mod);
1008 }
1008 }
1009 #endif
1009 #endif
@@ -1,76 +1,76 b''
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 #include "compat.h"
11 #include "compat.h"
12
12
13 #if PY_MAJOR_VERSION >= 3
13 #if PY_MAJOR_VERSION >= 3
14 #define IS_PY3K
14 #define IS_PY3K
15 #endif
15 #endif
16
16
17 typedef struct {
17 typedef struct {
18 PyObject_HEAD
18 PyObject_HEAD
19 char state;
19 char state;
20 int mode;
20 int mode;
21 int size;
21 int size;
22 int mtime;
22 int mtime;
23 } dirstateTupleObject;
23 } dirstateTupleObject;
24
24
25 extern PyTypeObject dirstateTupleType;
25 extern PyTypeObject dirstateTupleType;
26 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateTupleType)
26 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateTupleType)
27
27
28 /* This should be kept in sync with normcasespecs in encoding.py. */
28 /* This should be kept in sync with normcasespecs in encoding.py. */
29 enum normcase_spec {
29 enum normcase_spec {
30 NORMCASE_LOWER = -1,
30 NORMCASE_LOWER = -1,
31 NORMCASE_UPPER = 1,
31 NORMCASE_UPPER = 1,
32 NORMCASE_OTHER = 0
32 NORMCASE_OTHER = 0
33 };
33 };
34
34
35 #define MIN(a, b) (((a)<(b))?(a):(b))
35 #define MIN(a, b) (((a)<(b))?(a):(b))
36 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */
36 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */
37 #if defined(_MSC_VER) || __STDC_VERSION__ < 199901L
37 #if defined(_MSC_VER) || __STDC_VERSION__ < 199901L
38 #define true 1
38 #define true 1
39 #define false 0
39 #define false 0
40 typedef unsigned char bool;
40 typedef unsigned char bool;
41 #else
41 #else
42 #include <stdbool.h>
42 #include <stdbool.h>
43 #endif
43 #endif
44
44
45 static int8_t hextable[256] = {
45 static const int8_t hextable[256] = {
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
48 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
48 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
49 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0-9 */
49 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0-9 */
50 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
50 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
52 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
62 };
62 };
63
63
64 static inline int hexdigit(const char *p, Py_ssize_t off)
64 static inline int hexdigit(const char *p, Py_ssize_t off)
65 {
65 {
66 int8_t val = hextable[(unsigned char)p[off]];
66 int8_t val = hextable[(unsigned char)p[off]];
67
67
68 if (val >= 0) {
68 if (val >= 0) {
69 return val;
69 return val;
70 }
70 }
71
71
72 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
72 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
73 return 0;
73 return 0;
74 }
74 }
75
75
76 #endif /* _HG_UTIL_H_ */
76 #endif /* _HG_UTIL_H_ */
General Comments 0
You need to be logged in to leave comments. Login now