##// END OF EJS Templates
manifest: move C bool polyfill into util.h
Matt Mackall -
r24442:98042b0e default
parent child Browse files
Show More
@@ -1,928 +1,919
1 /*
1 /*
2 * manifest.c - manifest type that does on-demand parsing.
2 * manifest.c - manifest type that does on-demand parsing.
3 *
3 *
4 * Copyright 2015, Google Inc.
4 * Copyright 2015, Google Inc.
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 #include <Python.h>
9 #include <Python.h>
10
10
11 #include <assert.h>
11 #include <assert.h>
12 #include <string.h>
12 #include <string.h>
13 #include <stdlib.h>
13 #include <stdlib.h>
14
14
15 #include "util.h"
15 #include "util.h"
16
16
17 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */
18 #ifdef _MSC_VER
19 #define true 1
20 #define false 0
21 typedef unsigned char bool;
22 #else
23 #include <stdbool.h>
24 #endif
25
26 #define DEFAULT_LINES 100000
17 #define DEFAULT_LINES 100000
27
18
28 typedef struct {
19 typedef struct {
29 char *start;
20 char *start;
30 Py_ssize_t len; /* length of line including terminal newline */
21 Py_ssize_t len; /* length of line including terminal newline */
31 char hash_suffix;
22 char hash_suffix;
32 bool from_malloc;
23 bool from_malloc;
33 bool deleted;
24 bool deleted;
34 } line;
25 } line;
35
26
36 typedef struct {
27 typedef struct {
37 PyObject_HEAD
28 PyObject_HEAD
38 PyObject *pydata;
29 PyObject *pydata;
39 line *lines;
30 line *lines;
40 int numlines; /* number of line entries */
31 int numlines; /* number of line entries */
41 int livelines; /* number of non-deleted lines */
32 int livelines; /* number of non-deleted lines */
42 int maxlines; /* allocated number of lines */
33 int maxlines; /* allocated number of lines */
43 bool dirty;
34 bool dirty;
44 } lazymanifest;
35 } lazymanifest;
45
36
46 #define MANIFEST_OOM -1
37 #define MANIFEST_OOM -1
47 #define MANIFEST_NOT_SORTED -2
38 #define MANIFEST_NOT_SORTED -2
48 #define MANIFEST_MALFORMED -3
39 #define MANIFEST_MALFORMED -3
49
40
50 /* defined in parsers.c */
41 /* defined in parsers.c */
51 PyObject *unhexlify(const char *str, int len);
42 PyObject *unhexlify(const char *str, int len);
52
43
53 /* get the length of the path for a line */
44 /* get the length of the path for a line */
54 static size_t pathlen(line *l) {
45 static size_t pathlen(line *l) {
55 return strlen(l->start);
46 return strlen(l->start);
56 }
47 }
57
48
58 /* get the node value of a single line */
49 /* get the node value of a single line */
59 static PyObject *nodeof(line *l) {
50 static PyObject *nodeof(line *l) {
60 char *s = l->start;
51 char *s = l->start;
61 ssize_t llen = pathlen(l);
52 ssize_t llen = pathlen(l);
62 PyObject *hash = unhexlify(s + llen + 1, 40);
53 PyObject *hash = unhexlify(s + llen + 1, 40);
63 if (!hash) {
54 if (!hash) {
64 return NULL;
55 return NULL;
65 }
56 }
66 if (l->hash_suffix != '\0') {
57 if (l->hash_suffix != '\0') {
67 char newhash[21];
58 char newhash[21];
68 memcpy(newhash, PyString_AsString(hash), 20);
59 memcpy(newhash, PyString_AsString(hash), 20);
69 Py_DECREF(hash);
60 Py_DECREF(hash);
70 newhash[20] = l->hash_suffix;
61 newhash[20] = l->hash_suffix;
71 hash = PyString_FromStringAndSize(newhash, 21);
62 hash = PyString_FromStringAndSize(newhash, 21);
72 }
63 }
73 return hash;
64 return hash;
74 }
65 }
75
66
76 /* get the node hash and flags of a line as a tuple */
67 /* get the node hash and flags of a line as a tuple */
77 static PyObject *hashflags(line *l)
68 static PyObject *hashflags(line *l)
78 {
69 {
79 char *s = l->start;
70 char *s = l->start;
80 size_t plen = pathlen(l);
71 size_t plen = pathlen(l);
81 PyObject *hash = nodeof(l);
72 PyObject *hash = nodeof(l);
82
73
83 /* 40 for hash, 1 for null byte, 1 for newline */
74 /* 40 for hash, 1 for null byte, 1 for newline */
84 size_t hplen = plen + 42;
75 size_t hplen = plen + 42;
85 Py_ssize_t flen = l->len - hplen;
76 Py_ssize_t flen = l->len - hplen;
86 PyObject *flags;
77 PyObject *flags;
87 PyObject *tup;
78 PyObject *tup;
88
79
89 if (!hash)
80 if (!hash)
90 return NULL;
81 return NULL;
91 flags = PyString_FromStringAndSize(s + hplen - 1, flen);
82 flags = PyString_FromStringAndSize(s + hplen - 1, flen);
92 if (!flags) {
83 if (!flags) {
93 Py_DECREF(hash);
84 Py_DECREF(hash);
94 return NULL;
85 return NULL;
95 }
86 }
96 tup = PyTuple_Pack(2, hash, flags);
87 tup = PyTuple_Pack(2, hash, flags);
97 Py_DECREF(flags);
88 Py_DECREF(flags);
98 Py_DECREF(hash);
89 Py_DECREF(hash);
99 return tup;
90 return tup;
100 }
91 }
101
92
102 /* if we're about to run out of space in the line index, add more */
93 /* if we're about to run out of space in the line index, add more */
103 static bool realloc_if_full(lazymanifest *self)
94 static bool realloc_if_full(lazymanifest *self)
104 {
95 {
105 if (self->numlines == self->maxlines) {
96 if (self->numlines == self->maxlines) {
106 self->maxlines *= 2;
97 self->maxlines *= 2;
107 self->lines = realloc(self->lines, self->maxlines * sizeof(line));
98 self->lines = realloc(self->lines, self->maxlines * sizeof(line));
108 }
99 }
109 return !!self->lines;
100 return !!self->lines;
110 }
101 }
111
102
112 /*
103 /*
113 * Find the line boundaries in the manifest that 'data' points to and store
104 * Find the line boundaries in the manifest that 'data' points to and store
114 * information about each line in 'self'.
105 * information about each line in 'self'.
115 */
106 */
116 static int find_lines(lazymanifest *self, char *data, Py_ssize_t len)
107 static int find_lines(lazymanifest *self, char *data, Py_ssize_t len)
117 {
108 {
118 char *prev = NULL;
109 char *prev = NULL;
119 while (len > 0) {
110 while (len > 0) {
120 line *l;
111 line *l;
121 char *next = memchr(data, '\n', len);
112 char *next = memchr(data, '\n', len);
122 if (!next) {
113 if (!next) {
123 return MANIFEST_MALFORMED;
114 return MANIFEST_MALFORMED;
124 }
115 }
125 next++; /* advance past newline */
116 next++; /* advance past newline */
126 if (!realloc_if_full(self)) {
117 if (!realloc_if_full(self)) {
127 return MANIFEST_OOM; /* no memory */
118 return MANIFEST_OOM; /* no memory */
128 }
119 }
129 if (prev && strcmp(prev, data) > -1) {
120 if (prev && strcmp(prev, data) > -1) {
130 /* This data isn't sorted, so we have to abort. */
121 /* This data isn't sorted, so we have to abort. */
131 return MANIFEST_NOT_SORTED;
122 return MANIFEST_NOT_SORTED;
132 }
123 }
133 l = self->lines + ((self->numlines)++);
124 l = self->lines + ((self->numlines)++);
134 l->start = data;
125 l->start = data;
135 l->len = next - data;
126 l->len = next - data;
136 l->hash_suffix = '\0';
127 l->hash_suffix = '\0';
137 l->from_malloc = false;
128 l->from_malloc = false;
138 l->deleted = false;
129 l->deleted = false;
139 len = len - l->len;
130 len = len - l->len;
140 prev = data;
131 prev = data;
141 data = next;
132 data = next;
142 }
133 }
143 self->livelines = self->numlines;
134 self->livelines = self->numlines;
144 return 0;
135 return 0;
145 }
136 }
146
137
147 static int lazymanifest_init(lazymanifest *self, PyObject *args)
138 static int lazymanifest_init(lazymanifest *self, PyObject *args)
148 {
139 {
149 char *data;
140 char *data;
150 Py_ssize_t len;
141 Py_ssize_t len;
151 int err, ret;
142 int err, ret;
152 PyObject *pydata;
143 PyObject *pydata;
153 if (!PyArg_ParseTuple(args, "S", &pydata)) {
144 if (!PyArg_ParseTuple(args, "S", &pydata)) {
154 return -1;
145 return -1;
155 }
146 }
156 err = PyString_AsStringAndSize(pydata, &data, &len);
147 err = PyString_AsStringAndSize(pydata, &data, &len);
157
148
158 self->dirty = false;
149 self->dirty = false;
159 if (err == -1)
150 if (err == -1)
160 return -1;
151 return -1;
161 self->pydata = pydata;
152 self->pydata = pydata;
162 Py_INCREF(self->pydata);
153 Py_INCREF(self->pydata);
163 Py_BEGIN_ALLOW_THREADS
154 Py_BEGIN_ALLOW_THREADS
164 self->lines = malloc(DEFAULT_LINES * sizeof(line));
155 self->lines = malloc(DEFAULT_LINES * sizeof(line));
165 self->maxlines = DEFAULT_LINES;
156 self->maxlines = DEFAULT_LINES;
166 self->numlines = 0;
157 self->numlines = 0;
167 if (!self->lines)
158 if (!self->lines)
168 ret = MANIFEST_OOM;
159 ret = MANIFEST_OOM;
169 else
160 else
170 ret = find_lines(self, data, len);
161 ret = find_lines(self, data, len);
171 Py_END_ALLOW_THREADS
162 Py_END_ALLOW_THREADS
172 switch (ret) {
163 switch (ret) {
173 case 0:
164 case 0:
174 break;
165 break;
175 case MANIFEST_OOM:
166 case MANIFEST_OOM:
176 PyErr_NoMemory();
167 PyErr_NoMemory();
177 break;
168 break;
178 case MANIFEST_NOT_SORTED:
169 case MANIFEST_NOT_SORTED:
179 PyErr_Format(PyExc_ValueError,
170 PyErr_Format(PyExc_ValueError,
180 "Manifest lines not in sorted order.");
171 "Manifest lines not in sorted order.");
181 break;
172 break;
182 case MANIFEST_MALFORMED:
173 case MANIFEST_MALFORMED:
183 PyErr_Format(PyExc_ValueError,
174 PyErr_Format(PyExc_ValueError,
184 "Manifest did not end in a newline.");
175 "Manifest did not end in a newline.");
185 break;
176 break;
186 default:
177 default:
187 PyErr_Format(PyExc_ValueError,
178 PyErr_Format(PyExc_ValueError,
188 "Unknown problem parsing manifest.");
179 "Unknown problem parsing manifest.");
189 }
180 }
190 return ret == 0 ? 0 : -1;
181 return ret == 0 ? 0 : -1;
191 }
182 }
192
183
193 static void lazymanifest_dealloc(lazymanifest *self)
184 static void lazymanifest_dealloc(lazymanifest *self)
194 {
185 {
195 /* free any extra lines we had to allocate */
186 /* free any extra lines we had to allocate */
196 int i;
187 int i;
197 for (i = 0; i < self->numlines; i++) {
188 for (i = 0; i < self->numlines; i++) {
198 if (self->lines[i].from_malloc) {
189 if (self->lines[i].from_malloc) {
199 free(self->lines[i].start);
190 free(self->lines[i].start);
200 }
191 }
201 }
192 }
202 if (self->lines) {
193 if (self->lines) {
203 free(self->lines);
194 free(self->lines);
204 self->lines = NULL;
195 self->lines = NULL;
205 }
196 }
206 if (self->pydata) {
197 if (self->pydata) {
207 Py_DECREF(self->pydata);
198 Py_DECREF(self->pydata);
208 self->pydata = NULL;
199 self->pydata = NULL;
209 }
200 }
210 PyObject_Del(self);
201 PyObject_Del(self);
211 }
202 }
212
203
213 /* iteration support */
204 /* iteration support */
214
205
215 typedef struct {
206 typedef struct {
216 PyObject_HEAD lazymanifest *m;
207 PyObject_HEAD lazymanifest *m;
217 Py_ssize_t pos;
208 Py_ssize_t pos;
218 } lmIter;
209 } lmIter;
219
210
220 static void lmiter_dealloc(PyObject *o)
211 static void lmiter_dealloc(PyObject *o)
221 {
212 {
222 lmIter *self = (lmIter *)o;
213 lmIter *self = (lmIter *)o;
223 Py_DECREF(self->m);
214 Py_DECREF(self->m);
224 PyObject_Del(self);
215 PyObject_Del(self);
225 }
216 }
226
217
227 static line *lmiter_nextline(lmIter *self)
218 static line *lmiter_nextline(lmIter *self)
228 {
219 {
229 do {
220 do {
230 self->pos++;
221 self->pos++;
231 if (self->pos >= self->m->numlines) {
222 if (self->pos >= self->m->numlines) {
232 return NULL;
223 return NULL;
233 }
224 }
234 /* skip over deleted manifest entries */
225 /* skip over deleted manifest entries */
235 } while (self->m->lines[self->pos].deleted);
226 } while (self->m->lines[self->pos].deleted);
236 return self->m->lines + self->pos;
227 return self->m->lines + self->pos;
237 }
228 }
238
229
239 static PyObject *lmiter_iterentriesnext(PyObject *o)
230 static PyObject *lmiter_iterentriesnext(PyObject *o)
240 {
231 {
241 size_t pl;
232 size_t pl;
242 line *l;
233 line *l;
243 Py_ssize_t consumed;
234 Py_ssize_t consumed;
244 PyObject *path = NULL, *hash = NULL, *flags = NULL;
235 PyObject *path = NULL, *hash = NULL, *flags = NULL;
245 l = lmiter_nextline((lmIter *)o);
236 l = lmiter_nextline((lmIter *)o);
246 if (!l) {
237 if (!l) {
247 goto bail;
238 goto bail;
248 }
239 }
249 pl = pathlen(l);
240 pl = pathlen(l);
250 path = PyString_FromStringAndSize(l->start, pl);
241 path = PyString_FromStringAndSize(l->start, pl);
251 hash = nodeof(l);
242 hash = nodeof(l);
252 consumed = pl + 41;
243 consumed = pl + 41;
253 flags = PyString_FromStringAndSize(l->start + consumed,
244 flags = PyString_FromStringAndSize(l->start + consumed,
254 l->len - consumed - 1);
245 l->len - consumed - 1);
255 if (!path || !hash || !flags) {
246 if (!path || !hash || !flags) {
256 goto bail;
247 goto bail;
257 }
248 }
258 return PyTuple_Pack(3, path, hash, flags);
249 return PyTuple_Pack(3, path, hash, flags);
259 bail:
250 bail:
260 Py_XDECREF(path);
251 Py_XDECREF(path);
261 Py_XDECREF(hash);
252 Py_XDECREF(hash);
262 Py_XDECREF(flags);
253 Py_XDECREF(flags);
263 return NULL;
254 return NULL;
264 }
255 }
265
256
266 static PyTypeObject lazymanifestEntriesIterator = {
257 static PyTypeObject lazymanifestEntriesIterator = {
267 PyObject_HEAD_INIT(NULL)
258 PyObject_HEAD_INIT(NULL)
268 0, /*ob_size */
259 0, /*ob_size */
269 "parsers.lazymanifest.entriesiterator", /*tp_name */
260 "parsers.lazymanifest.entriesiterator", /*tp_name */
270 sizeof(lmIter), /*tp_basicsize */
261 sizeof(lmIter), /*tp_basicsize */
271 0, /*tp_itemsize */
262 0, /*tp_itemsize */
272 lmiter_dealloc, /*tp_dealloc */
263 lmiter_dealloc, /*tp_dealloc */
273 0, /*tp_print */
264 0, /*tp_print */
274 0, /*tp_getattr */
265 0, /*tp_getattr */
275 0, /*tp_setattr */
266 0, /*tp_setattr */
276 0, /*tp_compare */
267 0, /*tp_compare */
277 0, /*tp_repr */
268 0, /*tp_repr */
278 0, /*tp_as_number */
269 0, /*tp_as_number */
279 0, /*tp_as_sequence */
270 0, /*tp_as_sequence */
280 0, /*tp_as_mapping */
271 0, /*tp_as_mapping */
281 0, /*tp_hash */
272 0, /*tp_hash */
282 0, /*tp_call */
273 0, /*tp_call */
283 0, /*tp_str */
274 0, /*tp_str */
284 0, /*tp_getattro */
275 0, /*tp_getattro */
285 0, /*tp_setattro */
276 0, /*tp_setattro */
286 0, /*tp_as_buffer */
277 0, /*tp_as_buffer */
287 /* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
278 /* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
288 use tp_iter and tp_iternext fields. */
279 use tp_iter and tp_iternext fields. */
289 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
280 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
290 "Iterator for 3-tuples in a lazymanifest.", /* tp_doc */
281 "Iterator for 3-tuples in a lazymanifest.", /* tp_doc */
291 0, /* tp_traverse */
282 0, /* tp_traverse */
292 0, /* tp_clear */
283 0, /* tp_clear */
293 0, /* tp_richcompare */
284 0, /* tp_richcompare */
294 0, /* tp_weaklistoffset */
285 0, /* tp_weaklistoffset */
295 PyObject_SelfIter, /* tp_iter: __iter__() method */
286 PyObject_SelfIter, /* tp_iter: __iter__() method */
296 lmiter_iterentriesnext, /* tp_iternext: next() method */
287 lmiter_iterentriesnext, /* tp_iternext: next() method */
297 };
288 };
298
289
299 static PyObject *lmiter_iterkeysnext(PyObject *o)
290 static PyObject *lmiter_iterkeysnext(PyObject *o)
300 {
291 {
301 size_t pl;
292 size_t pl;
302 line *l = lmiter_nextline((lmIter *)o);
293 line *l = lmiter_nextline((lmIter *)o);
303 if (!l) {
294 if (!l) {
304 return NULL;
295 return NULL;
305 }
296 }
306 pl = pathlen(l);
297 pl = pathlen(l);
307 return PyString_FromStringAndSize(l->start, pl);
298 return PyString_FromStringAndSize(l->start, pl);
308 }
299 }
309
300
310 static PyTypeObject lazymanifestKeysIterator = {
301 static PyTypeObject lazymanifestKeysIterator = {
311 PyObject_HEAD_INIT(NULL)
302 PyObject_HEAD_INIT(NULL)
312 0, /*ob_size */
303 0, /*ob_size */
313 "parsers.lazymanifest.keysiterator", /*tp_name */
304 "parsers.lazymanifest.keysiterator", /*tp_name */
314 sizeof(lmIter), /*tp_basicsize */
305 sizeof(lmIter), /*tp_basicsize */
315 0, /*tp_itemsize */
306 0, /*tp_itemsize */
316 lmiter_dealloc, /*tp_dealloc */
307 lmiter_dealloc, /*tp_dealloc */
317 0, /*tp_print */
308 0, /*tp_print */
318 0, /*tp_getattr */
309 0, /*tp_getattr */
319 0, /*tp_setattr */
310 0, /*tp_setattr */
320 0, /*tp_compare */
311 0, /*tp_compare */
321 0, /*tp_repr */
312 0, /*tp_repr */
322 0, /*tp_as_number */
313 0, /*tp_as_number */
323 0, /*tp_as_sequence */
314 0, /*tp_as_sequence */
324 0, /*tp_as_mapping */
315 0, /*tp_as_mapping */
325 0, /*tp_hash */
316 0, /*tp_hash */
326 0, /*tp_call */
317 0, /*tp_call */
327 0, /*tp_str */
318 0, /*tp_str */
328 0, /*tp_getattro */
319 0, /*tp_getattro */
329 0, /*tp_setattro */
320 0, /*tp_setattro */
330 0, /*tp_as_buffer */
321 0, /*tp_as_buffer */
331 /* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
322 /* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
332 use tp_iter and tp_iternext fields. */
323 use tp_iter and tp_iternext fields. */
333 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
324 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
334 "Keys iterator for a lazymanifest.", /* tp_doc */
325 "Keys iterator for a lazymanifest.", /* tp_doc */
335 0, /* tp_traverse */
326 0, /* tp_traverse */
336 0, /* tp_clear */
327 0, /* tp_clear */
337 0, /* tp_richcompare */
328 0, /* tp_richcompare */
338 0, /* tp_weaklistoffset */
329 0, /* tp_weaklistoffset */
339 PyObject_SelfIter, /* tp_iter: __iter__() method */
330 PyObject_SelfIter, /* tp_iter: __iter__() method */
340 lmiter_iterkeysnext, /* tp_iternext: next() method */
331 lmiter_iterkeysnext, /* tp_iternext: next() method */
341 };
332 };
342
333
343 static lazymanifest *lazymanifest_copy(lazymanifest *self);
334 static lazymanifest *lazymanifest_copy(lazymanifest *self);
344
335
345 static PyObject *lazymanifest_getentriesiter(lazymanifest *self)
336 static PyObject *lazymanifest_getentriesiter(lazymanifest *self)
346 {
337 {
347 lmIter *i = NULL;
338 lmIter *i = NULL;
348 lazymanifest *t = lazymanifest_copy(self);
339 lazymanifest *t = lazymanifest_copy(self);
349 if (!t) {
340 if (!t) {
350 PyErr_NoMemory();
341 PyErr_NoMemory();
351 return NULL;
342 return NULL;
352 }
343 }
353 i = PyObject_New(lmIter, &lazymanifestEntriesIterator);
344 i = PyObject_New(lmIter, &lazymanifestEntriesIterator);
354 if (i) {
345 if (i) {
355 i->m = t;
346 i->m = t;
356 i->pos = -1;
347 i->pos = -1;
357 } else {
348 } else {
358 Py_DECREF(t);
349 Py_DECREF(t);
359 PyErr_NoMemory();
350 PyErr_NoMemory();
360 }
351 }
361 return (PyObject *)i;
352 return (PyObject *)i;
362 }
353 }
363
354
364 static PyObject *lazymanifest_getkeysiter(lazymanifest *self)
355 static PyObject *lazymanifest_getkeysiter(lazymanifest *self)
365 {
356 {
366 lmIter *i = NULL;
357 lmIter *i = NULL;
367 lazymanifest *t = lazymanifest_copy(self);
358 lazymanifest *t = lazymanifest_copy(self);
368 if (!t) {
359 if (!t) {
369 PyErr_NoMemory();
360 PyErr_NoMemory();
370 return NULL;
361 return NULL;
371 }
362 }
372 i = PyObject_New(lmIter, &lazymanifestKeysIterator);
363 i = PyObject_New(lmIter, &lazymanifestKeysIterator);
373 if (i) {
364 if (i) {
374 i->m = t;
365 i->m = t;
375 i->pos = -1;
366 i->pos = -1;
376 } else {
367 } else {
377 Py_DECREF(t);
368 Py_DECREF(t);
378 PyErr_NoMemory();
369 PyErr_NoMemory();
379 }
370 }
380 return (PyObject *)i;
371 return (PyObject *)i;
381 }
372 }
382
373
383 /* __getitem__ and __setitem__ support */
374 /* __getitem__ and __setitem__ support */
384
375
385 static Py_ssize_t lazymanifest_size(lazymanifest *self)
376 static Py_ssize_t lazymanifest_size(lazymanifest *self)
386 {
377 {
387 return self->livelines;
378 return self->livelines;
388 }
379 }
389
380
390 static int linecmp(const void *left, const void *right)
381 static int linecmp(const void *left, const void *right)
391 {
382 {
392 return strcmp(((const line *)left)->start,
383 return strcmp(((const line *)left)->start,
393 ((const line *)right)->start);
384 ((const line *)right)->start);
394 }
385 }
395
386
396 static PyObject *lazymanifest_getitem(lazymanifest *self, PyObject *key)
387 static PyObject *lazymanifest_getitem(lazymanifest *self, PyObject *key)
397 {
388 {
398 line needle;
389 line needle;
399 line *hit;
390 line *hit;
400 if (!PyString_Check(key)) {
391 if (!PyString_Check(key)) {
401 PyErr_Format(PyExc_TypeError,
392 PyErr_Format(PyExc_TypeError,
402 "getitem: manifest keys must be a string.");
393 "getitem: manifest keys must be a string.");
403 return NULL;
394 return NULL;
404 }
395 }
405 needle.start = PyString_AsString(key);
396 needle.start = PyString_AsString(key);
406 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
397 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
407 &linecmp);
398 &linecmp);
408 if (!hit || hit->deleted) {
399 if (!hit || hit->deleted) {
409 PyErr_Format(PyExc_KeyError, "No such manifest entry.");
400 PyErr_Format(PyExc_KeyError, "No such manifest entry.");
410 return NULL;
401 return NULL;
411 }
402 }
412 return hashflags(hit);
403 return hashflags(hit);
413 }
404 }
414
405
415 static int lazymanifest_delitem(lazymanifest *self, PyObject *key)
406 static int lazymanifest_delitem(lazymanifest *self, PyObject *key)
416 {
407 {
417 line needle;
408 line needle;
418 line *hit;
409 line *hit;
419 if (!PyString_Check(key)) {
410 if (!PyString_Check(key)) {
420 PyErr_Format(PyExc_TypeError,
411 PyErr_Format(PyExc_TypeError,
421 "delitem: manifest keys must be a string.");
412 "delitem: manifest keys must be a string.");
422 return -1;
413 return -1;
423 }
414 }
424 needle.start = PyString_AsString(key);
415 needle.start = PyString_AsString(key);
425 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
416 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
426 &linecmp);
417 &linecmp);
427 if (!hit || hit->deleted) {
418 if (!hit || hit->deleted) {
428 PyErr_Format(PyExc_KeyError,
419 PyErr_Format(PyExc_KeyError,
429 "Tried to delete nonexistent manifest entry.");
420 "Tried to delete nonexistent manifest entry.");
430 return -1;
421 return -1;
431 }
422 }
432 self->dirty = true;
423 self->dirty = true;
433 hit->deleted = true;
424 hit->deleted = true;
434 self->livelines--;
425 self->livelines--;
435 return 0;
426 return 0;
436 }
427 }
437
428
438 /* Do a binary search for the insertion point for new, creating the
429 /* Do a binary search for the insertion point for new, creating the
439 * new entry if needed. */
430 * new entry if needed. */
440 static int internalsetitem(lazymanifest *self, line *new) {
431 static int internalsetitem(lazymanifest *self, line *new) {
441 int start = 0, end = self->numlines;
432 int start = 0, end = self->numlines;
442 while (start < end) {
433 while (start < end) {
443 int pos = start + (end - start) / 2;
434 int pos = start + (end - start) / 2;
444 int c = linecmp(new, self->lines + pos);
435 int c = linecmp(new, self->lines + pos);
445 if (c < 0)
436 if (c < 0)
446 end = pos;
437 end = pos;
447 else if (c > 0)
438 else if (c > 0)
448 start = pos + 1;
439 start = pos + 1;
449 else {
440 else {
450 if (self->lines[pos].deleted)
441 if (self->lines[pos].deleted)
451 self->livelines++;
442 self->livelines++;
452 start = pos;
443 start = pos;
453 goto finish;
444 goto finish;
454 }
445 }
455 }
446 }
456 /* being here means we need to do an insert */
447 /* being here means we need to do an insert */
457 if (!realloc_if_full(self)) {
448 if (!realloc_if_full(self)) {
458 PyErr_NoMemory();
449 PyErr_NoMemory();
459 return -1;
450 return -1;
460 }
451 }
461 memmove(self->lines + start + 1, self->lines + start,
452 memmove(self->lines + start + 1, self->lines + start,
462 (self->numlines - start) * sizeof(line));
453 (self->numlines - start) * sizeof(line));
463 self->numlines++;
454 self->numlines++;
464 self->livelines++;
455 self->livelines++;
465 finish:
456 finish:
466 self->lines[start] = *new;
457 self->lines[start] = *new;
467 self->dirty = true;
458 self->dirty = true;
468 return 0;
459 return 0;
469 }
460 }
470
461
471 static int lazymanifest_setitem(
462 static int lazymanifest_setitem(
472 lazymanifest *self, PyObject *key, PyObject *value)
463 lazymanifest *self, PyObject *key, PyObject *value)
473 {
464 {
474 char *path;
465 char *path;
475 Py_ssize_t plen;
466 Py_ssize_t plen;
476 PyObject *pyhash;
467 PyObject *pyhash;
477 Py_ssize_t hlen;
468 Py_ssize_t hlen;
478 char *hash;
469 char *hash;
479 PyObject *pyflags;
470 PyObject *pyflags;
480 char *flags;
471 char *flags;
481 Py_ssize_t flen;
472 Py_ssize_t flen;
482 size_t dlen;
473 size_t dlen;
483 char *dest;
474 char *dest;
484 int i;
475 int i;
485 line new;
476 line new;
486 if (!PyString_Check(key)) {
477 if (!PyString_Check(key)) {
487 PyErr_Format(PyExc_TypeError,
478 PyErr_Format(PyExc_TypeError,
488 "setitem: manifest keys must be a string.");
479 "setitem: manifest keys must be a string.");
489 return -1;
480 return -1;
490 }
481 }
491 if (!value) {
482 if (!value) {
492 return lazymanifest_delitem(self, key);
483 return lazymanifest_delitem(self, key);
493 }
484 }
494 if (!PyTuple_Check(value) || PyTuple_Size(value) != 2) {
485 if (!PyTuple_Check(value) || PyTuple_Size(value) != 2) {
495 PyErr_Format(PyExc_TypeError,
486 PyErr_Format(PyExc_TypeError,
496 "Manifest values must be a tuple of (node, flags).");
487 "Manifest values must be a tuple of (node, flags).");
497 return -1;
488 return -1;
498 }
489 }
499 if (PyString_AsStringAndSize(key, &path, &plen) == -1) {
490 if (PyString_AsStringAndSize(key, &path, &plen) == -1) {
500 return -1;
491 return -1;
501 }
492 }
502
493
503 pyhash = PyTuple_GetItem(value, 0);
494 pyhash = PyTuple_GetItem(value, 0);
504 if (!PyString_Check(pyhash)) {
495 if (!PyString_Check(pyhash)) {
505 PyErr_Format(PyExc_TypeError,
496 PyErr_Format(PyExc_TypeError,
506 "node must be a 20-byte string");
497 "node must be a 20-byte string");
507 return -1;
498 return -1;
508 }
499 }
509 hlen = PyString_Size(pyhash);
500 hlen = PyString_Size(pyhash);
510 /* Some parts of the codebase try and set 21 or 22
501 /* Some parts of the codebase try and set 21 or 22
511 * byte "hash" values in order to perturb things for
502 * byte "hash" values in order to perturb things for
512 * status. We have to preserve at least the 21st
503 * status. We have to preserve at least the 21st
513 * byte. Sigh. If there's a 22nd byte, we drop it on
504 * byte. Sigh. If there's a 22nd byte, we drop it on
514 * the floor, which works fine.
505 * the floor, which works fine.
515 */
506 */
516 if (hlen != 20 && hlen != 21 && hlen != 22) {
507 if (hlen != 20 && hlen != 21 && hlen != 22) {
517 PyErr_Format(PyExc_TypeError,
508 PyErr_Format(PyExc_TypeError,
518 "node must be a 20-byte string");
509 "node must be a 20-byte string");
519 return -1;
510 return -1;
520 }
511 }
521 hash = PyString_AsString(pyhash);
512 hash = PyString_AsString(pyhash);
522
513
523 pyflags = PyTuple_GetItem(value, 1);
514 pyflags = PyTuple_GetItem(value, 1);
524 if (!PyString_Check(pyflags) || PyString_Size(pyflags) > 1) {
515 if (!PyString_Check(pyflags) || PyString_Size(pyflags) > 1) {
525 PyErr_Format(PyExc_TypeError,
516 PyErr_Format(PyExc_TypeError,
526 "flags must a 0 or 1 byte string");
517 "flags must a 0 or 1 byte string");
527 return -1;
518 return -1;
528 }
519 }
529 if (PyString_AsStringAndSize(pyflags, &flags, &flen) == -1) {
520 if (PyString_AsStringAndSize(pyflags, &flags, &flen) == -1) {
530 return -1;
521 return -1;
531 }
522 }
532 /* one null byte and one newline */
523 /* one null byte and one newline */
533 dlen = plen + 41 + flen + 1;
524 dlen = plen + 41 + flen + 1;
534 dest = malloc(dlen);
525 dest = malloc(dlen);
535 if (!dest) {
526 if (!dest) {
536 PyErr_NoMemory();
527 PyErr_NoMemory();
537 return -1;
528 return -1;
538 }
529 }
539 memcpy(dest, path, plen + 1);
530 memcpy(dest, path, plen + 1);
540 for (i = 0; i < 20; i++) {
531 for (i = 0; i < 20; i++) {
541 /* Cast to unsigned, so it will not get sign-extended when promoted
532 /* Cast to unsigned, so it will not get sign-extended when promoted
542 * to int (as is done when passing to a variadic function)
533 * to int (as is done when passing to a variadic function)
543 */
534 */
544 sprintf(dest + plen + 1 + (i * 2), "%02x", (unsigned char)hash[i]);
535 sprintf(dest + plen + 1 + (i * 2), "%02x", (unsigned char)hash[i]);
545 }
536 }
546 memcpy(dest + plen + 41, flags, flen);
537 memcpy(dest + plen + 41, flags, flen);
547 dest[plen + 41 + flen] = '\n';
538 dest[plen + 41 + flen] = '\n';
548 new.start = dest;
539 new.start = dest;
549 new.len = dlen;
540 new.len = dlen;
550 new.hash_suffix = '\0';
541 new.hash_suffix = '\0';
551 if (hlen > 20) {
542 if (hlen > 20) {
552 new.hash_suffix = hash[20];
543 new.hash_suffix = hash[20];
553 }
544 }
554 new.from_malloc = true; /* is `start` a pointer we allocated? */
545 new.from_malloc = true; /* is `start` a pointer we allocated? */
555 new.deleted = false; /* is this entry deleted? */
546 new.deleted = false; /* is this entry deleted? */
556 if (internalsetitem(self, &new)) {
547 if (internalsetitem(self, &new)) {
557 return -1;
548 return -1;
558 }
549 }
559 return 0;
550 return 0;
560 }
551 }
561
552
562 static PyMappingMethods lazymanifest_mapping_methods = {
553 static PyMappingMethods lazymanifest_mapping_methods = {
563 (lenfunc)lazymanifest_size, /* mp_length */
554 (lenfunc)lazymanifest_size, /* mp_length */
564 (binaryfunc)lazymanifest_getitem, /* mp_subscript */
555 (binaryfunc)lazymanifest_getitem, /* mp_subscript */
565 (objobjargproc)lazymanifest_setitem, /* mp_ass_subscript */
556 (objobjargproc)lazymanifest_setitem, /* mp_ass_subscript */
566 };
557 };
567
558
568 /* sequence methods (important or __contains__ builds an iterator */
559 /* sequence methods (important or __contains__ builds an iterator */
569
560
570 static int lazymanifest_contains(lazymanifest *self, PyObject *key)
561 static int lazymanifest_contains(lazymanifest *self, PyObject *key)
571 {
562 {
572 line needle;
563 line needle;
573 line *hit;
564 line *hit;
574 if (!PyString_Check(key)) {
565 if (!PyString_Check(key)) {
575 /* Our keys are always strings, so if the contains
566 /* Our keys are always strings, so if the contains
576 * check is for a non-string, just return false. */
567 * check is for a non-string, just return false. */
577 return 0;
568 return 0;
578 }
569 }
579 needle.start = PyString_AsString(key);
570 needle.start = PyString_AsString(key);
580 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
571 hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
581 &linecmp);
572 &linecmp);
582 if (!hit || hit->deleted) {
573 if (!hit || hit->deleted) {
583 return 0;
574 return 0;
584 }
575 }
585 return 1;
576 return 1;
586 }
577 }
587
578
588 static PySequenceMethods lazymanifest_seq_meths = {
579 static PySequenceMethods lazymanifest_seq_meths = {
589 (lenfunc)lazymanifest_size, /* sq_length */
580 (lenfunc)lazymanifest_size, /* sq_length */
590 0, /* sq_concat */
581 0, /* sq_concat */
591 0, /* sq_repeat */
582 0, /* sq_repeat */
592 0, /* sq_item */
583 0, /* sq_item */
593 0, /* sq_slice */
584 0, /* sq_slice */
594 0, /* sq_ass_item */
585 0, /* sq_ass_item */
595 0, /* sq_ass_slice */
586 0, /* sq_ass_slice */
596 (objobjproc)lazymanifest_contains, /* sq_contains */
587 (objobjproc)lazymanifest_contains, /* sq_contains */
597 0, /* sq_inplace_concat */
588 0, /* sq_inplace_concat */
598 0, /* sq_inplace_repeat */
589 0, /* sq_inplace_repeat */
599 };
590 };
600
591
601
592
602 /* Other methods (copy, diff, etc) */
593 /* Other methods (copy, diff, etc) */
603 static PyTypeObject lazymanifestType;
594 static PyTypeObject lazymanifestType;
604
595
605 /* If the manifest has changes, build the new manifest text and reindex it. */
596 /* If the manifest has changes, build the new manifest text and reindex it. */
606 static int compact(lazymanifest *self) {
597 static int compact(lazymanifest *self) {
607 int i;
598 int i;
608 ssize_t need = 0;
599 ssize_t need = 0;
609 char *data;
600 char *data;
610 line *src, *dst;
601 line *src, *dst;
611 PyObject *pydata;
602 PyObject *pydata;
612 if (!self->dirty)
603 if (!self->dirty)
613 return 0;
604 return 0;
614 for (i = 0; i < self->numlines; i++) {
605 for (i = 0; i < self->numlines; i++) {
615 if (!self->lines[i].deleted) {
606 if (!self->lines[i].deleted) {
616 need += self->lines[i].len;
607 need += self->lines[i].len;
617 }
608 }
618 }
609 }
619 pydata = PyString_FromStringAndSize(NULL, need);
610 pydata = PyString_FromStringAndSize(NULL, need);
620 if (!pydata)
611 if (!pydata)
621 return -1;
612 return -1;
622 data = PyString_AsString(pydata);
613 data = PyString_AsString(pydata);
623 if (!data) {
614 if (!data) {
624 return -1;
615 return -1;
625 }
616 }
626 src = self->lines;
617 src = self->lines;
627 dst = self->lines;
618 dst = self->lines;
628 for (i = 0; i < self->numlines; i++, src++) {
619 for (i = 0; i < self->numlines; i++, src++) {
629 char *tofree = NULL;
620 char *tofree = NULL;
630 if (src->from_malloc) {
621 if (src->from_malloc) {
631 tofree = src->start;
622 tofree = src->start;
632 }
623 }
633 if (!src->deleted) {
624 if (!src->deleted) {
634 memcpy(data, src->start, src->len);
625 memcpy(data, src->start, src->len);
635 *dst = *src;
626 *dst = *src;
636 dst->start = data;
627 dst->start = data;
637 dst->from_malloc = false;
628 dst->from_malloc = false;
638 data += dst->len;
629 data += dst->len;
639 dst++;
630 dst++;
640 }
631 }
641 free(tofree);
632 free(tofree);
642 }
633 }
643 Py_DECREF(self->pydata);
634 Py_DECREF(self->pydata);
644 self->pydata = pydata;
635 self->pydata = pydata;
645 self->numlines = self->livelines;
636 self->numlines = self->livelines;
646 self->dirty = false;
637 self->dirty = false;
647 return 0;
638 return 0;
648 }
639 }
649
640
650 static PyObject *lazymanifest_text(lazymanifest *self)
641 static PyObject *lazymanifest_text(lazymanifest *self)
651 {
642 {
652 if (compact(self) != 0) {
643 if (compact(self) != 0) {
653 PyErr_NoMemory();
644 PyErr_NoMemory();
654 return NULL;
645 return NULL;
655 }
646 }
656 Py_INCREF(self->pydata);
647 Py_INCREF(self->pydata);
657 return self->pydata;
648 return self->pydata;
658 }
649 }
659
650
660 static lazymanifest *lazymanifest_copy(lazymanifest *self)
651 static lazymanifest *lazymanifest_copy(lazymanifest *self)
661 {
652 {
662 lazymanifest *copy = NULL;
653 lazymanifest *copy = NULL;
663 if (compact(self) != 0) {
654 if (compact(self) != 0) {
664 goto nomem;
655 goto nomem;
665 }
656 }
666 copy = PyObject_New(lazymanifest, &lazymanifestType);
657 copy = PyObject_New(lazymanifest, &lazymanifestType);
667 if (!copy) {
658 if (!copy) {
668 goto nomem;
659 goto nomem;
669 }
660 }
670 copy->numlines = self->numlines;
661 copy->numlines = self->numlines;
671 copy->livelines = self->livelines;
662 copy->livelines = self->livelines;
672 copy->dirty = false;
663 copy->dirty = false;
673 copy->lines = malloc(self->maxlines *sizeof(line));
664 copy->lines = malloc(self->maxlines *sizeof(line));
674 if (!copy->lines) {
665 if (!copy->lines) {
675 goto nomem;
666 goto nomem;
676 }
667 }
677 memcpy(copy->lines, self->lines, self->numlines * sizeof(line));
668 memcpy(copy->lines, self->lines, self->numlines * sizeof(line));
678 copy->maxlines = self->maxlines;
669 copy->maxlines = self->maxlines;
679 copy->pydata = self->pydata;
670 copy->pydata = self->pydata;
680 Py_INCREF(copy->pydata);
671 Py_INCREF(copy->pydata);
681 return copy;
672 return copy;
682 nomem:
673 nomem:
683 PyErr_NoMemory();
674 PyErr_NoMemory();
684 Py_XDECREF(copy);
675 Py_XDECREF(copy);
685 return NULL;
676 return NULL;
686 }
677 }
687
678
688 static lazymanifest *lazymanifest_filtercopy(
679 static lazymanifest *lazymanifest_filtercopy(
689 lazymanifest *self, PyObject *matchfn)
680 lazymanifest *self, PyObject *matchfn)
690 {
681 {
691 lazymanifest *copy = NULL;
682 lazymanifest *copy = NULL;
692 int i;
683 int i;
693 if (!PyCallable_Check(matchfn)) {
684 if (!PyCallable_Check(matchfn)) {
694 PyErr_SetString(PyExc_TypeError, "matchfn must be callable");
685 PyErr_SetString(PyExc_TypeError, "matchfn must be callable");
695 return NULL;
686 return NULL;
696 }
687 }
697 /* compact ourselves first to avoid double-frees later when we
688 /* compact ourselves first to avoid double-frees later when we
698 * compact tmp so that it doesn't have random pointers to our
689 * compact tmp so that it doesn't have random pointers to our
699 * underlying from_malloc-data (self->pydata is safe) */
690 * underlying from_malloc-data (self->pydata is safe) */
700 if (compact(self) != 0) {
691 if (compact(self) != 0) {
701 goto nomem;
692 goto nomem;
702 }
693 }
703 copy = PyObject_New(lazymanifest, &lazymanifestType);
694 copy = PyObject_New(lazymanifest, &lazymanifestType);
704 copy->dirty = true;
695 copy->dirty = true;
705 copy->lines = malloc(self->maxlines * sizeof(line));
696 copy->lines = malloc(self->maxlines * sizeof(line));
706 if (!copy->lines) {
697 if (!copy->lines) {
707 goto nomem;
698 goto nomem;
708 }
699 }
709 copy->maxlines = self->maxlines;
700 copy->maxlines = self->maxlines;
710 copy->numlines = 0;
701 copy->numlines = 0;
711 copy->pydata = self->pydata;
702 copy->pydata = self->pydata;
712 Py_INCREF(self->pydata);
703 Py_INCREF(self->pydata);
713 for (i = 0; i < self->numlines; i++) {
704 for (i = 0; i < self->numlines; i++) {
714 PyObject *arg = PyString_FromString(self->lines[i].start);
705 PyObject *arg = PyString_FromString(self->lines[i].start);
715 PyObject *arglist = PyTuple_Pack(1, arg);
706 PyObject *arglist = PyTuple_Pack(1, arg);
716 PyObject *result = PyObject_CallObject(matchfn, arglist);
707 PyObject *result = PyObject_CallObject(matchfn, arglist);
717 Py_DECREF(arglist);
708 Py_DECREF(arglist);
718 Py_DECREF(arg);
709 Py_DECREF(arg);
719 /* if the callback raised an exception, just let it
710 /* if the callback raised an exception, just let it
720 * through and give up */
711 * through and give up */
721 if (!result) {
712 if (!result) {
722 free(copy->lines);
713 free(copy->lines);
723 Py_DECREF(self->pydata);
714 Py_DECREF(self->pydata);
724 return NULL;
715 return NULL;
725 }
716 }
726 if (PyObject_IsTrue(result)) {
717 if (PyObject_IsTrue(result)) {
727 assert(!(self->lines[i].from_malloc));
718 assert(!(self->lines[i].from_malloc));
728 copy->lines[copy->numlines++] = self->lines[i];
719 copy->lines[copy->numlines++] = self->lines[i];
729 }
720 }
730 Py_DECREF(result);
721 Py_DECREF(result);
731 }
722 }
732 copy->livelines = copy->numlines;
723 copy->livelines = copy->numlines;
733 return copy;
724 return copy;
734 nomem:
725 nomem:
735 PyErr_NoMemory();
726 PyErr_NoMemory();
736 Py_XDECREF(copy);
727 Py_XDECREF(copy);
737 return NULL;
728 return NULL;
738 }
729 }
739
730
740 static PyObject *lazymanifest_diff(lazymanifest *self, PyObject *args)
731 static PyObject *lazymanifest_diff(lazymanifest *self, PyObject *args)
741 {
732 {
742 lazymanifest *other;
733 lazymanifest *other;
743 PyObject *pyclean = NULL;
734 PyObject *pyclean = NULL;
744 bool listclean;
735 bool listclean;
745 PyObject *emptyTup = NULL, *ret = NULL;
736 PyObject *emptyTup = NULL, *ret = NULL;
746 PyObject *es;
737 PyObject *es;
747 int sneedle = 0, oneedle = 0;
738 int sneedle = 0, oneedle = 0;
748 if (!PyArg_ParseTuple(args, "O!|O", &lazymanifestType, &other, &pyclean)) {
739 if (!PyArg_ParseTuple(args, "O!|O", &lazymanifestType, &other, &pyclean)) {
749 return NULL;
740 return NULL;
750 }
741 }
751 listclean = (!pyclean) ? false : PyObject_IsTrue(pyclean);
742 listclean = (!pyclean) ? false : PyObject_IsTrue(pyclean);
752 es = PyString_FromString("");
743 es = PyString_FromString("");
753 if (!es) {
744 if (!es) {
754 goto nomem;
745 goto nomem;
755 }
746 }
756 emptyTup = PyTuple_Pack(2, Py_None, es);
747 emptyTup = PyTuple_Pack(2, Py_None, es);
757 Py_DECREF(es);
748 Py_DECREF(es);
758 if (!emptyTup) {
749 if (!emptyTup) {
759 goto nomem;
750 goto nomem;
760 }
751 }
761 ret = PyDict_New();
752 ret = PyDict_New();
762 if (!ret) {
753 if (!ret) {
763 goto nomem;
754 goto nomem;
764 }
755 }
765 while (sneedle != self->numlines || oneedle != other->numlines) {
756 while (sneedle != self->numlines || oneedle != other->numlines) {
766 line *left = self->lines + sneedle;
757 line *left = self->lines + sneedle;
767 line *right = other->lines + oneedle;
758 line *right = other->lines + oneedle;
768 int result;
759 int result;
769 PyObject *key;
760 PyObject *key;
770 PyObject *outer;
761 PyObject *outer;
771 /* If we're looking at a deleted entry and it's not
762 /* If we're looking at a deleted entry and it's not
772 * the end of the manifest, just skip it. */
763 * the end of the manifest, just skip it. */
773 if (left->deleted && sneedle < self->numlines) {
764 if (left->deleted && sneedle < self->numlines) {
774 sneedle++;
765 sneedle++;
775 continue;
766 continue;
776 }
767 }
777 if (right->deleted && oneedle < other->numlines) {
768 if (right->deleted && oneedle < other->numlines) {
778 oneedle++;
769 oneedle++;
779 continue;
770 continue;
780 }
771 }
781 /* if we're at the end of either manifest, then we
772 /* if we're at the end of either manifest, then we
782 * know the remaining items are adds so we can skip
773 * know the remaining items are adds so we can skip
783 * the strcmp. */
774 * the strcmp. */
784 if (sneedle == self->numlines) {
775 if (sneedle == self->numlines) {
785 result = 1;
776 result = 1;
786 } else if (oneedle == other->numlines) {
777 } else if (oneedle == other->numlines) {
787 result = -1;
778 result = -1;
788 } else {
779 } else {
789 result = linecmp(left, right);
780 result = linecmp(left, right);
790 }
781 }
791 key = result <= 0 ?
782 key = result <= 0 ?
792 PyString_FromString(left->start) :
783 PyString_FromString(left->start) :
793 PyString_FromString(right->start);
784 PyString_FromString(right->start);
794 if (!key)
785 if (!key)
795 goto nomem;
786 goto nomem;
796 if (result < 0) {
787 if (result < 0) {
797 PyObject *l = hashflags(left);
788 PyObject *l = hashflags(left);
798 if (!l) {
789 if (!l) {
799 goto nomem;
790 goto nomem;
800 }
791 }
801 outer = PyTuple_Pack(2, l, emptyTup);
792 outer = PyTuple_Pack(2, l, emptyTup);
802 Py_DECREF(l);
793 Py_DECREF(l);
803 if (!outer) {
794 if (!outer) {
804 goto nomem;
795 goto nomem;
805 }
796 }
806 PyDict_SetItem(ret, key, outer);
797 PyDict_SetItem(ret, key, outer);
807 Py_DECREF(outer);
798 Py_DECREF(outer);
808 sneedle++;
799 sneedle++;
809 } else if (result > 0) {
800 } else if (result > 0) {
810 PyObject *r = hashflags(right);
801 PyObject *r = hashflags(right);
811 if (!r) {
802 if (!r) {
812 goto nomem;
803 goto nomem;
813 }
804 }
814 outer = PyTuple_Pack(2, emptyTup, r);
805 outer = PyTuple_Pack(2, emptyTup, r);
815 Py_DECREF(r);
806 Py_DECREF(r);
816 if (!outer) {
807 if (!outer) {
817 goto nomem;
808 goto nomem;
818 }
809 }
819 PyDict_SetItem(ret, key, outer);
810 PyDict_SetItem(ret, key, outer);
820 Py_DECREF(outer);
811 Py_DECREF(outer);
821 oneedle++;
812 oneedle++;
822 } else {
813 } else {
823 /* file exists in both manifests */
814 /* file exists in both manifests */
824 if (left->len != right->len
815 if (left->len != right->len
825 || memcmp(left->start, right->start, left->len)
816 || memcmp(left->start, right->start, left->len)
826 || left->hash_suffix != right->hash_suffix) {
817 || left->hash_suffix != right->hash_suffix) {
827 PyObject *l = hashflags(left);
818 PyObject *l = hashflags(left);
828 PyObject *r;
819 PyObject *r;
829 if (!l) {
820 if (!l) {
830 goto nomem;
821 goto nomem;
831 }
822 }
832 r = hashflags(right);
823 r = hashflags(right);
833 if (!r) {
824 if (!r) {
834 Py_DECREF(l);
825 Py_DECREF(l);
835 goto nomem;
826 goto nomem;
836 }
827 }
837 outer = PyTuple_Pack(2, l, r);
828 outer = PyTuple_Pack(2, l, r);
838 Py_DECREF(l);
829 Py_DECREF(l);
839 Py_DECREF(r);
830 Py_DECREF(r);
840 if (!outer) {
831 if (!outer) {
841 goto nomem;
832 goto nomem;
842 }
833 }
843 PyDict_SetItem(ret, key, outer);
834 PyDict_SetItem(ret, key, outer);
844 Py_DECREF(outer);
835 Py_DECREF(outer);
845 } else if (listclean) {
836 } else if (listclean) {
846 PyDict_SetItem(ret, key, Py_None);
837 PyDict_SetItem(ret, key, Py_None);
847 }
838 }
848 sneedle++;
839 sneedle++;
849 oneedle++;
840 oneedle++;
850 }
841 }
851 Py_DECREF(key);
842 Py_DECREF(key);
852 }
843 }
853 Py_DECREF(emptyTup);
844 Py_DECREF(emptyTup);
854 return ret;
845 return ret;
855 nomem:
846 nomem:
856 PyErr_NoMemory();
847 PyErr_NoMemory();
857 Py_XDECREF(ret);
848 Py_XDECREF(ret);
858 Py_XDECREF(emptyTup);
849 Py_XDECREF(emptyTup);
859 return NULL;
850 return NULL;
860 }
851 }
861
852
862 static PyMethodDef lazymanifest_methods[] = {
853 static PyMethodDef lazymanifest_methods[] = {
863 {"iterkeys", (PyCFunction)lazymanifest_getkeysiter, METH_NOARGS,
854 {"iterkeys", (PyCFunction)lazymanifest_getkeysiter, METH_NOARGS,
864 "Iterate over file names in this lazymanifest."},
855 "Iterate over file names in this lazymanifest."},
865 {"iterentries", (PyCFunction)lazymanifest_getentriesiter, METH_NOARGS,
856 {"iterentries", (PyCFunction)lazymanifest_getentriesiter, METH_NOARGS,
866 "Iterate over (path, nodeid, flags) typles in this lazymanifest."},
857 "Iterate over (path, nodeid, flags) typles in this lazymanifest."},
867 {"copy", (PyCFunction)lazymanifest_copy, METH_NOARGS,
858 {"copy", (PyCFunction)lazymanifest_copy, METH_NOARGS,
868 "Make a copy of this lazymanifest."},
859 "Make a copy of this lazymanifest."},
869 {"filtercopy", (PyCFunction)lazymanifest_filtercopy, METH_O,
860 {"filtercopy", (PyCFunction)lazymanifest_filtercopy, METH_O,
870 "Make a copy of this manifest filtered by matchfn."},
861 "Make a copy of this manifest filtered by matchfn."},
871 {"diff", (PyCFunction)lazymanifest_diff, METH_VARARGS,
862 {"diff", (PyCFunction)lazymanifest_diff, METH_VARARGS,
872 "Compare this lazymanifest to another one."},
863 "Compare this lazymanifest to another one."},
873 {"text", (PyCFunction)lazymanifest_text, METH_NOARGS,
864 {"text", (PyCFunction)lazymanifest_text, METH_NOARGS,
874 "Encode this manifest to text."},
865 "Encode this manifest to text."},
875 {NULL},
866 {NULL},
876 };
867 };
877
868
878 static PyTypeObject lazymanifestType = {
869 static PyTypeObject lazymanifestType = {
879 PyObject_HEAD_INIT(NULL)
870 PyObject_HEAD_INIT(NULL)
880 0, /* ob_size */
871 0, /* ob_size */
881 "parsers.lazymanifest", /* tp_name */
872 "parsers.lazymanifest", /* tp_name */
882 sizeof(lazymanifest), /* tp_basicsize */
873 sizeof(lazymanifest), /* tp_basicsize */
883 0, /* tp_itemsize */
874 0, /* tp_itemsize */
884 (destructor)lazymanifest_dealloc, /* tp_dealloc */
875 (destructor)lazymanifest_dealloc, /* tp_dealloc */
885 0, /* tp_print */
876 0, /* tp_print */
886 0, /* tp_getattr */
877 0, /* tp_getattr */
887 0, /* tp_setattr */
878 0, /* tp_setattr */
888 0, /* tp_compare */
879 0, /* tp_compare */
889 0, /* tp_repr */
880 0, /* tp_repr */
890 0, /* tp_as_number */
881 0, /* tp_as_number */
891 &lazymanifest_seq_meths, /* tp_as_sequence */
882 &lazymanifest_seq_meths, /* tp_as_sequence */
892 &lazymanifest_mapping_methods, /* tp_as_mapping */
883 &lazymanifest_mapping_methods, /* tp_as_mapping */
893 0, /* tp_hash */
884 0, /* tp_hash */
894 0, /* tp_call */
885 0, /* tp_call */
895 0, /* tp_str */
886 0, /* tp_str */
896 0, /* tp_getattro */
887 0, /* tp_getattro */
897 0, /* tp_setattro */
888 0, /* tp_setattro */
898 0, /* tp_as_buffer */
889 0, /* tp_as_buffer */
899 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_SEQUENCE_IN, /* tp_flags */
890 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_SEQUENCE_IN, /* tp_flags */
900 "TODO(augie)", /* tp_doc */
891 "TODO(augie)", /* tp_doc */
901 0, /* tp_traverse */
892 0, /* tp_traverse */
902 0, /* tp_clear */
893 0, /* tp_clear */
903 0, /* tp_richcompare */
894 0, /* tp_richcompare */
904 0, /* tp_weaklistoffset */
895 0, /* tp_weaklistoffset */
905 (getiterfunc)lazymanifest_getkeysiter, /* tp_iter */
896 (getiterfunc)lazymanifest_getkeysiter, /* tp_iter */
906 0, /* tp_iternext */
897 0, /* tp_iternext */
907 lazymanifest_methods, /* tp_methods */
898 lazymanifest_methods, /* tp_methods */
908 0, /* tp_members */
899 0, /* tp_members */
909 0, /* tp_getset */
900 0, /* tp_getset */
910 0, /* tp_base */
901 0, /* tp_base */
911 0, /* tp_dict */
902 0, /* tp_dict */
912 0, /* tp_descr_get */
903 0, /* tp_descr_get */
913 0, /* tp_descr_set */
904 0, /* tp_descr_set */
914 0, /* tp_dictoffset */
905 0, /* tp_dictoffset */
915 (initproc)lazymanifest_init, /* tp_init */
906 (initproc)lazymanifest_init, /* tp_init */
916 0, /* tp_alloc */
907 0, /* tp_alloc */
917 };
908 };
918
909
919 void manifest_module_init(PyObject * mod)
910 void manifest_module_init(PyObject * mod)
920 {
911 {
921 lazymanifestType.tp_new = PyType_GenericNew;
912 lazymanifestType.tp_new = PyType_GenericNew;
922 if (PyType_Ready(&lazymanifestType) < 0)
913 if (PyType_Ready(&lazymanifestType) < 0)
923 return;
914 return;
924 Py_INCREF(&lazymanifestType);
915 Py_INCREF(&lazymanifestType);
925
916
926 PyModule_AddObject(mod, "lazymanifest",
917 PyModule_AddObject(mod, "lazymanifest",
927 (PyObject *)&lazymanifestType);
918 (PyObject *)&lazymanifestType);
928 }
919 }
@@ -1,212 +1,221
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 #define PyInt_FromSsize_t PyInt_FromLong
113
113
114 #if !defined(PY_SSIZE_T_MIN)
114 #if !defined(PY_SSIZE_T_MIN)
115 #define PY_SSIZE_T_MAX INT_MAX
115 #define PY_SSIZE_T_MAX INT_MAX
116 #define PY_SSIZE_T_MIN INT_MIN
116 #define PY_SSIZE_T_MIN INT_MIN
117 #endif
117 #endif
118 #endif
118 #endif
119
119
120 #ifdef _WIN32
120 #ifdef _WIN32
121 #ifdef _MSC_VER
121 #ifdef _MSC_VER
122 /* msvc 6.0 has problems */
122 /* msvc 6.0 has problems */
123 #define inline __inline
123 #define inline __inline
124 typedef signed char int8_t;
124 typedef signed char int8_t;
125 typedef short int16_t;
125 typedef short int16_t;
126 typedef long int32_t;
126 typedef long int32_t;
127 typedef __int64 int64_t;
127 typedef __int64 int64_t;
128 typedef unsigned char uint8_t;
128 typedef unsigned char uint8_t;
129 typedef unsigned short uint16_t;
129 typedef unsigned short uint16_t;
130 typedef unsigned long uint32_t;
130 typedef unsigned long uint32_t;
131 typedef unsigned __int64 uint64_t;
131 typedef unsigned __int64 uint64_t;
132 #else
132 #else
133 #include <stdint.h>
133 #include <stdint.h>
134 #endif
134 #endif
135 #else
135 #else
136 /* not windows */
136 /* not windows */
137 #include <sys/types.h>
137 #include <sys/types.h>
138 #if defined __BEOS__ && !defined __HAIKU__
138 #if defined __BEOS__ && !defined __HAIKU__
139 #include <ByteOrder.h>
139 #include <ByteOrder.h>
140 #else
140 #else
141 #include <arpa/inet.h>
141 #include <arpa/inet.h>
142 #endif
142 #endif
143 #include <inttypes.h>
143 #include <inttypes.h>
144 #endif
144 #endif
145
145
146 #if defined __hpux || defined __SUNPRO_C || defined _AIX
146 #if defined __hpux || defined __SUNPRO_C || defined _AIX
147 #define inline
147 #define inline
148 #endif
148 #endif
149
149
150 #ifdef __linux
150 #ifdef __linux
151 #define inline __inline
151 #define inline __inline
152 #endif
152 #endif
153
153
154 typedef struct {
154 typedef struct {
155 PyObject_HEAD
155 PyObject_HEAD
156 char state;
156 char state;
157 int mode;
157 int mode;
158 int size;
158 int size;
159 int mtime;
159 int mtime;
160 } dirstateTupleObject;
160 } dirstateTupleObject;
161
161
162 extern PyTypeObject dirstateTupleType;
162 extern PyTypeObject dirstateTupleType;
163 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateTupleType)
163 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateTupleType)
164
164
165 static inline uint32_t getbe32(const char *c)
165 static inline uint32_t getbe32(const char *c)
166 {
166 {
167 const unsigned char *d = (const unsigned char *)c;
167 const unsigned char *d = (const unsigned char *)c;
168
168
169 return ((d[0] << 24) |
169 return ((d[0] << 24) |
170 (d[1] << 16) |
170 (d[1] << 16) |
171 (d[2] << 8) |
171 (d[2] << 8) |
172 (d[3]));
172 (d[3]));
173 }
173 }
174
174
175 static inline int16_t getbeint16(const char *c)
175 static inline int16_t getbeint16(const char *c)
176 {
176 {
177 const unsigned char *d = (const unsigned char *)c;
177 const unsigned char *d = (const unsigned char *)c;
178
178
179 return ((d[0] << 8) |
179 return ((d[0] << 8) |
180 (d[1]));
180 (d[1]));
181 }
181 }
182
182
183 static inline uint16_t getbeuint16(const char *c)
183 static inline uint16_t getbeuint16(const char *c)
184 {
184 {
185 const unsigned char *d = (const unsigned char *)c;
185 const unsigned char *d = (const unsigned char *)c;
186
186
187 return ((d[0] << 8) |
187 return ((d[0] << 8) |
188 (d[1]));
188 (d[1]));
189 }
189 }
190
190
191 static inline void putbe32(uint32_t x, char *c)
191 static inline void putbe32(uint32_t x, char *c)
192 {
192 {
193 c[0] = (x >> 24) & 0xff;
193 c[0] = (x >> 24) & 0xff;
194 c[1] = (x >> 16) & 0xff;
194 c[1] = (x >> 16) & 0xff;
195 c[2] = (x >> 8) & 0xff;
195 c[2] = (x >> 8) & 0xff;
196 c[3] = (x) & 0xff;
196 c[3] = (x) & 0xff;
197 }
197 }
198
198
199 static inline double getbefloat64(const char *c)
199 static inline double getbefloat64(const char *c)
200 {
200 {
201 const unsigned char *d = (const unsigned char *)c;
201 const unsigned char *d = (const unsigned char *)c;
202 double ret;
202 double ret;
203 int i;
203 int i;
204 uint64_t t = 0;
204 uint64_t t = 0;
205 for (i = 0; i < 8; i++) {
205 for (i = 0; i < 8; i++) {
206 t = (t<<8) + d[i];
206 t = (t<<8) + d[i];
207 }
207 }
208 memcpy(&ret, &t, sizeof(t));
208 memcpy(&ret, &t, sizeof(t));
209 return ret;
209 return ret;
210 }
210 }
211
211
212 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */
213 #ifdef _MSC_VER
214 #define true 1
215 #define false 0
216 typedef unsigned char bool;
217 #else
218 #include <stdbool.h>
219 #endif
220
212 #endif /* _HG_UTIL_H_ */
221 #endif /* _HG_UTIL_H_ */
General Comments 0
You need to be logged in to leave comments. Login now