##// END OF EJS Templates
util.h: unify some common platform tweaks
Matt Mackall -
r16385:e501f45b default
parent child Browse files
Show More
@@ -1,499 +1,467 b''
1 /*
1 /*
2 bdiff.c - efficient binary diff extension for Mercurial
2 bdiff.c - efficient binary diff extension for Mercurial
3
3
4 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
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 Based roughly on Python difflib
9 Based roughly on Python difflib
10 */
10 */
11
11
12 #include <Python.h>
12 #include <Python.h>
13 #include <stdlib.h>
13 #include <stdlib.h>
14 #include <string.h>
14 #include <string.h>
15 #include <limits.h>
15 #include <limits.h>
16
16
17 #if defined __hpux || defined __SUNPRO_C || defined _AIX
18 #define inline
19 #endif
20
21 #ifdef __linux
22 #define inline __inline
23 #endif
24
25 #ifdef _WIN32
26 #ifdef _MSC_VER
27 #define inline __inline
28 typedef unsigned long uint32_t;
29 #else
30 #include <stdint.h>
31 #endif
32 static uint32_t htonl(uint32_t x)
33 {
34 return ((x & 0x000000ffUL) << 24) |
35 ((x & 0x0000ff00UL) << 8) |
36 ((x & 0x00ff0000UL) >> 8) |
37 ((x & 0xff000000UL) >> 24);
38 }
39 #else
40 #include <sys/types.h>
41 #if defined __BEOS__ && !defined __HAIKU__
42 #include <ByteOrder.h>
43 #else
44 #include <arpa/inet.h>
45 #endif
46 #include <inttypes.h>
47 #endif
48
49 #include "util.h"
17 #include "util.h"
50
18
51 struct line {
19 struct line {
52 int hash, len, n, e;
20 int hash, len, n, e;
53 const char *l;
21 const char *l;
54 };
22 };
55
23
56 struct pos {
24 struct pos {
57 int pos, len;
25 int pos, len;
58 };
26 };
59
27
60 struct hunk;
28 struct hunk;
61 struct hunk {
29 struct hunk {
62 int a1, a2, b1, b2;
30 int a1, a2, b1, b2;
63 struct hunk *next;
31 struct hunk *next;
64 };
32 };
65
33
66 static int splitlines(const char *a, int len, struct line **lr)
34 static int splitlines(const char *a, int len, struct line **lr)
67 {
35 {
68 unsigned hash;
36 unsigned hash;
69 int i;
37 int i;
70 const char *p, *b = a;
38 const char *p, *b = a;
71 const char * const plast = a + len - 1;
39 const char * const plast = a + len - 1;
72 struct line *l;
40 struct line *l;
73
41
74 /* count the lines */
42 /* count the lines */
75 i = 1; /* extra line for sentinel */
43 i = 1; /* extra line for sentinel */
76 for (p = a; p < a + len; p++)
44 for (p = a; p < a + len; p++)
77 if (*p == '\n' || p == plast)
45 if (*p == '\n' || p == plast)
78 i++;
46 i++;
79
47
80 *lr = l = (struct line *)malloc(sizeof(struct line) * i);
48 *lr = l = (struct line *)malloc(sizeof(struct line) * i);
81 if (!l)
49 if (!l)
82 return -1;
50 return -1;
83
51
84 /* build the line array and calculate hashes */
52 /* build the line array and calculate hashes */
85 hash = 0;
53 hash = 0;
86 for (p = a; p < a + len; p++) {
54 for (p = a; p < a + len; p++) {
87 /* Leonid Yuriev's hash */
55 /* Leonid Yuriev's hash */
88 hash = (hash * 1664525) + (unsigned char)*p + 1013904223;
56 hash = (hash * 1664525) + (unsigned char)*p + 1013904223;
89
57
90 if (*p == '\n' || p == plast) {
58 if (*p == '\n' || p == plast) {
91 l->hash = hash;
59 l->hash = hash;
92 hash = 0;
60 hash = 0;
93 l->len = p - b + 1;
61 l->len = p - b + 1;
94 l->l = b;
62 l->l = b;
95 l->n = INT_MAX;
63 l->n = INT_MAX;
96 l++;
64 l++;
97 b = p + 1;
65 b = p + 1;
98 }
66 }
99 }
67 }
100
68
101 /* set up a sentinel */
69 /* set up a sentinel */
102 l->hash = 0;
70 l->hash = 0;
103 l->len = 0;
71 l->len = 0;
104 l->l = a + len;
72 l->l = a + len;
105 return i - 1;
73 return i - 1;
106 }
74 }
107
75
108 static inline int cmp(struct line *a, struct line *b)
76 static inline int cmp(struct line *a, struct line *b)
109 {
77 {
110 return a->hash != b->hash || a->len != b->len || memcmp(a->l, b->l, a->len);
78 return a->hash != b->hash || a->len != b->len || memcmp(a->l, b->l, a->len);
111 }
79 }
112
80
113 static int equatelines(struct line *a, int an, struct line *b, int bn)
81 static int equatelines(struct line *a, int an, struct line *b, int bn)
114 {
82 {
115 int i, j, buckets = 1, t, scale;
83 int i, j, buckets = 1, t, scale;
116 struct pos *h = NULL;
84 struct pos *h = NULL;
117
85
118 /* build a hash table of the next highest power of 2 */
86 /* build a hash table of the next highest power of 2 */
119 while (buckets < bn + 1)
87 while (buckets < bn + 1)
120 buckets *= 2;
88 buckets *= 2;
121
89
122 /* try to allocate a large hash table to avoid collisions */
90 /* try to allocate a large hash table to avoid collisions */
123 for (scale = 4; scale; scale /= 2) {
91 for (scale = 4; scale; scale /= 2) {
124 h = (struct pos *)malloc(scale * buckets * sizeof(struct pos));
92 h = (struct pos *)malloc(scale * buckets * sizeof(struct pos));
125 if (h)
93 if (h)
126 break;
94 break;
127 }
95 }
128
96
129 if (!h)
97 if (!h)
130 return 0;
98 return 0;
131
99
132 buckets = buckets * scale - 1;
100 buckets = buckets * scale - 1;
133
101
134 /* clear the hash table */
102 /* clear the hash table */
135 for (i = 0; i <= buckets; i++) {
103 for (i = 0; i <= buckets; i++) {
136 h[i].pos = INT_MAX;
104 h[i].pos = INT_MAX;
137 h[i].len = 0;
105 h[i].len = 0;
138 }
106 }
139
107
140 /* add lines to the hash table chains */
108 /* add lines to the hash table chains */
141 for (i = bn - 1; i >= 0; i--) {
109 for (i = bn - 1; i >= 0; i--) {
142 /* find the equivalence class */
110 /* find the equivalence class */
143 for (j = b[i].hash & buckets; h[j].pos != INT_MAX;
111 for (j = b[i].hash & buckets; h[j].pos != INT_MAX;
144 j = (j + 1) & buckets)
112 j = (j + 1) & buckets)
145 if (!cmp(b + i, b + h[j].pos))
113 if (!cmp(b + i, b + h[j].pos))
146 break;
114 break;
147
115
148 /* add to the head of the equivalence class */
116 /* add to the head of the equivalence class */
149 b[i].n = h[j].pos;
117 b[i].n = h[j].pos;
150 b[i].e = j;
118 b[i].e = j;
151 h[j].pos = i;
119 h[j].pos = i;
152 h[j].len++; /* keep track of popularity */
120 h[j].len++; /* keep track of popularity */
153 }
121 }
154
122
155 /* compute popularity threshold */
123 /* compute popularity threshold */
156 t = (bn >= 31000) ? bn / 1000 : 1000000 / (bn + 1);
124 t = (bn >= 31000) ? bn / 1000 : 1000000 / (bn + 1);
157
125
158 /* match items in a to their equivalence class in b */
126 /* match items in a to their equivalence class in b */
159 for (i = 0; i < an; i++) {
127 for (i = 0; i < an; i++) {
160 /* find the equivalence class */
128 /* find the equivalence class */
161 for (j = a[i].hash & buckets; h[j].pos != INT_MAX;
129 for (j = a[i].hash & buckets; h[j].pos != INT_MAX;
162 j = (j + 1) & buckets)
130 j = (j + 1) & buckets)
163 if (!cmp(a + i, b + h[j].pos))
131 if (!cmp(a + i, b + h[j].pos))
164 break;
132 break;
165
133
166 a[i].e = j; /* use equivalence class for quick compare */
134 a[i].e = j; /* use equivalence class for quick compare */
167 if (h[j].len <= t)
135 if (h[j].len <= t)
168 a[i].n = h[j].pos; /* point to head of match list */
136 a[i].n = h[j].pos; /* point to head of match list */
169 else
137 else
170 a[i].n = INT_MAX; /* too popular */
138 a[i].n = INT_MAX; /* too popular */
171 }
139 }
172
140
173 /* discard hash tables */
141 /* discard hash tables */
174 free(h);
142 free(h);
175 return 1;
143 return 1;
176 }
144 }
177
145
178 static int longest_match(struct line *a, struct line *b, struct pos *pos,
146 static int longest_match(struct line *a, struct line *b, struct pos *pos,
179 int a1, int a2, int b1, int b2, int *omi, int *omj)
147 int a1, int a2, int b1, int b2, int *omi, int *omj)
180 {
148 {
181 int mi = a1, mj = b1, mk = 0, mb = 0, i, j, k;
149 int mi = a1, mj = b1, mk = 0, mb = 0, i, j, k;
182
150
183 for (i = a1; i < a2; i++) {
151 for (i = a1; i < a2; i++) {
184 /* skip things before the current block */
152 /* skip things before the current block */
185 for (j = a[i].n; j < b1; j = b[j].n)
153 for (j = a[i].n; j < b1; j = b[j].n)
186 ;
154 ;
187
155
188 /* loop through all lines match a[i] in b */
156 /* loop through all lines match a[i] in b */
189 for (; j < b2; j = b[j].n) {
157 for (; j < b2; j = b[j].n) {
190 /* does this extend an earlier match? */
158 /* does this extend an earlier match? */
191 if (i > a1 && j > b1 && pos[j - 1].pos == i - 1)
159 if (i > a1 && j > b1 && pos[j - 1].pos == i - 1)
192 k = pos[j - 1].len + 1;
160 k = pos[j - 1].len + 1;
193 else
161 else
194 k = 1;
162 k = 1;
195 pos[j].pos = i;
163 pos[j].pos = i;
196 pos[j].len = k;
164 pos[j].len = k;
197
165
198 /* best match so far? */
166 /* best match so far? */
199 if (k > mk) {
167 if (k > mk) {
200 mi = i;
168 mi = i;
201 mj = j;
169 mj = j;
202 mk = k;
170 mk = k;
203 }
171 }
204 }
172 }
205 }
173 }
206
174
207 if (mk) {
175 if (mk) {
208 mi = mi - mk + 1;
176 mi = mi - mk + 1;
209 mj = mj - mk + 1;
177 mj = mj - mk + 1;
210 }
178 }
211
179
212 /* expand match to include neighboring popular lines */
180 /* expand match to include neighboring popular lines */
213 while (mi - mb > a1 && mj - mb > b1 &&
181 while (mi - mb > a1 && mj - mb > b1 &&
214 a[mi - mb - 1].e == b[mj - mb - 1].e)
182 a[mi - mb - 1].e == b[mj - mb - 1].e)
215 mb++;
183 mb++;
216 while (mi + mk < a2 && mj + mk < b2 &&
184 while (mi + mk < a2 && mj + mk < b2 &&
217 a[mi + mk].e == b[mj + mk].e)
185 a[mi + mk].e == b[mj + mk].e)
218 mk++;
186 mk++;
219
187
220 *omi = mi - mb;
188 *omi = mi - mb;
221 *omj = mj - mb;
189 *omj = mj - mb;
222
190
223 return mk + mb;
191 return mk + mb;
224 }
192 }
225
193
226 static struct hunk *recurse(struct line *a, struct line *b, struct pos *pos,
194 static struct hunk *recurse(struct line *a, struct line *b, struct pos *pos,
227 int a1, int a2, int b1, int b2, struct hunk *l)
195 int a1, int a2, int b1, int b2, struct hunk *l)
228 {
196 {
229 int i, j, k;
197 int i, j, k;
230
198
231 while (1) {
199 while (1) {
232 /* find the longest match in this chunk */
200 /* find the longest match in this chunk */
233 k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j);
201 k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j);
234 if (!k)
202 if (!k)
235 return l;
203 return l;
236
204
237 /* and recurse on the remaining chunks on either side */
205 /* and recurse on the remaining chunks on either side */
238 l = recurse(a, b, pos, a1, i, b1, j, l);
206 l = recurse(a, b, pos, a1, i, b1, j, l);
239 if (!l)
207 if (!l)
240 return NULL;
208 return NULL;
241
209
242 l->next = (struct hunk *)malloc(sizeof(struct hunk));
210 l->next = (struct hunk *)malloc(sizeof(struct hunk));
243 if (!l->next)
211 if (!l->next)
244 return NULL;
212 return NULL;
245
213
246 l = l->next;
214 l = l->next;
247 l->a1 = i;
215 l->a1 = i;
248 l->a2 = i + k;
216 l->a2 = i + k;
249 l->b1 = j;
217 l->b1 = j;
250 l->b2 = j + k;
218 l->b2 = j + k;
251 l->next = NULL;
219 l->next = NULL;
252
220
253 /* tail-recursion didn't happen, so do equivalent iteration */
221 /* tail-recursion didn't happen, so do equivalent iteration */
254 a1 = i + k;
222 a1 = i + k;
255 b1 = j + k;
223 b1 = j + k;
256 }
224 }
257 }
225 }
258
226
259 static int diff(struct line *a, int an, struct line *b, int bn,
227 static int diff(struct line *a, int an, struct line *b, int bn,
260 struct hunk *base)
228 struct hunk *base)
261 {
229 {
262 struct hunk *curr;
230 struct hunk *curr;
263 struct pos *pos;
231 struct pos *pos;
264 int t, count = 0;
232 int t, count = 0;
265
233
266 /* allocate and fill arrays */
234 /* allocate and fill arrays */
267 t = equatelines(a, an, b, bn);
235 t = equatelines(a, an, b, bn);
268 pos = (struct pos *)calloc(bn ? bn : 1, sizeof(struct pos));
236 pos = (struct pos *)calloc(bn ? bn : 1, sizeof(struct pos));
269
237
270 if (pos && t) {
238 if (pos && t) {
271 /* generate the matching block list */
239 /* generate the matching block list */
272
240
273 curr = recurse(a, b, pos, 0, an, 0, bn, base);
241 curr = recurse(a, b, pos, 0, an, 0, bn, base);
274 if (!curr)
242 if (!curr)
275 return -1;
243 return -1;
276
244
277 /* sentinel end hunk */
245 /* sentinel end hunk */
278 curr->next = (struct hunk *)malloc(sizeof(struct hunk));
246 curr->next = (struct hunk *)malloc(sizeof(struct hunk));
279 if (!curr->next)
247 if (!curr->next)
280 return -1;
248 return -1;
281 curr = curr->next;
249 curr = curr->next;
282 curr->a1 = curr->a2 = an;
250 curr->a1 = curr->a2 = an;
283 curr->b1 = curr->b2 = bn;
251 curr->b1 = curr->b2 = bn;
284 curr->next = NULL;
252 curr->next = NULL;
285 }
253 }
286
254
287 free(pos);
255 free(pos);
288
256
289 /* normalize the hunk list, try to push each hunk towards the end */
257 /* normalize the hunk list, try to push each hunk towards the end */
290 for (curr = base->next; curr; curr = curr->next) {
258 for (curr = base->next; curr; curr = curr->next) {
291 struct hunk *next = curr->next;
259 struct hunk *next = curr->next;
292 int shift = 0;
260 int shift = 0;
293
261
294 if (!next)
262 if (!next)
295 break;
263 break;
296
264
297 if (curr->a2 == next->a1)
265 if (curr->a2 == next->a1)
298 while (curr->a2 + shift < an && curr->b2 + shift < bn
266 while (curr->a2 + shift < an && curr->b2 + shift < bn
299 && !cmp(a + curr->a2 + shift,
267 && !cmp(a + curr->a2 + shift,
300 b + curr->b2 + shift))
268 b + curr->b2 + shift))
301 shift++;
269 shift++;
302 else if (curr->b2 == next->b1)
270 else if (curr->b2 == next->b1)
303 while (curr->b2 + shift < bn && curr->a2 + shift < an
271 while (curr->b2 + shift < bn && curr->a2 + shift < an
304 && !cmp(b + curr->b2 + shift,
272 && !cmp(b + curr->b2 + shift,
305 a + curr->a2 + shift))
273 a + curr->a2 + shift))
306 shift++;
274 shift++;
307 if (!shift)
275 if (!shift)
308 continue;
276 continue;
309 curr->b2 += shift;
277 curr->b2 += shift;
310 next->b1 += shift;
278 next->b1 += shift;
311 curr->a2 += shift;
279 curr->a2 += shift;
312 next->a1 += shift;
280 next->a1 += shift;
313 }
281 }
314
282
315 for (curr = base->next; curr; curr = curr->next)
283 for (curr = base->next; curr; curr = curr->next)
316 count++;
284 count++;
317 return count;
285 return count;
318 }
286 }
319
287
320 static void freehunks(struct hunk *l)
288 static void freehunks(struct hunk *l)
321 {
289 {
322 struct hunk *n;
290 struct hunk *n;
323 for (; l; l = n) {
291 for (; l; l = n) {
324 n = l->next;
292 n = l->next;
325 free(l);
293 free(l);
326 }
294 }
327 }
295 }
328
296
329 static PyObject *blocks(PyObject *self, PyObject *args)
297 static PyObject *blocks(PyObject *self, PyObject *args)
330 {
298 {
331 PyObject *sa, *sb, *rl = NULL, *m;
299 PyObject *sa, *sb, *rl = NULL, *m;
332 struct line *a, *b;
300 struct line *a, *b;
333 struct hunk l, *h;
301 struct hunk l, *h;
334 int an, bn, count, pos = 0;
302 int an, bn, count, pos = 0;
335
303
336 if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb))
304 if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb))
337 return NULL;
305 return NULL;
338
306
339 an = splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a);
307 an = splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a);
340 bn = splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b);
308 bn = splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b);
341
309
342 if (!a || !b)
310 if (!a || !b)
343 goto nomem;
311 goto nomem;
344
312
345 l.next = NULL;
313 l.next = NULL;
346 count = diff(a, an, b, bn, &l);
314 count = diff(a, an, b, bn, &l);
347 if (count < 0)
315 if (count < 0)
348 goto nomem;
316 goto nomem;
349
317
350 rl = PyList_New(count);
318 rl = PyList_New(count);
351 if (!rl)
319 if (!rl)
352 goto nomem;
320 goto nomem;
353
321
354 for (h = l.next; h; h = h->next) {
322 for (h = l.next; h; h = h->next) {
355 m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2);
323 m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2);
356 PyList_SetItem(rl, pos, m);
324 PyList_SetItem(rl, pos, m);
357 pos++;
325 pos++;
358 }
326 }
359
327
360 nomem:
328 nomem:
361 free(a);
329 free(a);
362 free(b);
330 free(b);
363 freehunks(l.next);
331 freehunks(l.next);
364 return rl ? rl : PyErr_NoMemory();
332 return rl ? rl : PyErr_NoMemory();
365 }
333 }
366
334
367 static PyObject *bdiff(PyObject *self, PyObject *args)
335 static PyObject *bdiff(PyObject *self, PyObject *args)
368 {
336 {
369 char *sa, *sb, *rb;
337 char *sa, *sb, *rb;
370 PyObject *result = NULL;
338 PyObject *result = NULL;
371 struct line *al, *bl;
339 struct line *al, *bl;
372 struct hunk l, *h;
340 struct hunk l, *h;
373 uint32_t encode[3];
341 uint32_t encode[3];
374 int an, bn, len = 0, la, lb, count;
342 int an, bn, len = 0, la, lb, count;
375
343
376 if (!PyArg_ParseTuple(args, "s#s#:bdiff", &sa, &la, &sb, &lb))
344 if (!PyArg_ParseTuple(args, "s#s#:bdiff", &sa, &la, &sb, &lb))
377 return NULL;
345 return NULL;
378
346
379 an = splitlines(sa, la, &al);
347 an = splitlines(sa, la, &al);
380 bn = splitlines(sb, lb, &bl);
348 bn = splitlines(sb, lb, &bl);
381 if (!al || !bl)
349 if (!al || !bl)
382 goto nomem;
350 goto nomem;
383
351
384 l.next = NULL;
352 l.next = NULL;
385 count = diff(al, an, bl, bn, &l);
353 count = diff(al, an, bl, bn, &l);
386 if (count < 0)
354 if (count < 0)
387 goto nomem;
355 goto nomem;
388
356
389 /* calculate length of output */
357 /* calculate length of output */
390 la = lb = 0;
358 la = lb = 0;
391 for (h = l.next; h; h = h->next) {
359 for (h = l.next; h; h = h->next) {
392 if (h->a1 != la || h->b1 != lb)
360 if (h->a1 != la || h->b1 != lb)
393 len += 12 + bl[h->b1].l - bl[lb].l;
361 len += 12 + bl[h->b1].l - bl[lb].l;
394 la = h->a2;
362 la = h->a2;
395 lb = h->b2;
363 lb = h->b2;
396 }
364 }
397
365
398 result = PyBytes_FromStringAndSize(NULL, len);
366 result = PyBytes_FromStringAndSize(NULL, len);
399
367
400 if (!result)
368 if (!result)
401 goto nomem;
369 goto nomem;
402
370
403 /* build binary patch */
371 /* build binary patch */
404 rb = PyBytes_AsString(result);
372 rb = PyBytes_AsString(result);
405 la = lb = 0;
373 la = lb = 0;
406
374
407 for (h = l.next; h; h = h->next) {
375 for (h = l.next; h; h = h->next) {
408 if (h->a1 != la || h->b1 != lb) {
376 if (h->a1 != la || h->b1 != lb) {
409 len = bl[h->b1].l - bl[lb].l;
377 len = bl[h->b1].l - bl[lb].l;
410 encode[0] = htonl(al[la].l - al->l);
378 encode[0] = htonl(al[la].l - al->l);
411 encode[1] = htonl(al[h->a1].l - al->l);
379 encode[1] = htonl(al[h->a1].l - al->l);
412 encode[2] = htonl(len);
380 encode[2] = htonl(len);
413 memcpy(rb, encode, 12);
381 memcpy(rb, encode, 12);
414 memcpy(rb + 12, bl[lb].l, len);
382 memcpy(rb + 12, bl[lb].l, len);
415 rb += 12 + len;
383 rb += 12 + len;
416 }
384 }
417 la = h->a2;
385 la = h->a2;
418 lb = h->b2;
386 lb = h->b2;
419 }
387 }
420
388
421 nomem:
389 nomem:
422 free(al);
390 free(al);
423 free(bl);
391 free(bl);
424 freehunks(l.next);
392 freehunks(l.next);
425 return result ? result : PyErr_NoMemory();
393 return result ? result : PyErr_NoMemory();
426 }
394 }
427
395
428 /*
396 /*
429 * If allws != 0, remove all whitespace (' ', \t and \r). Otherwise,
397 * If allws != 0, remove all whitespace (' ', \t and \r). Otherwise,
430 * reduce whitespace sequences to a single space and trim remaining whitespace
398 * reduce whitespace sequences to a single space and trim remaining whitespace
431 * from end of lines.
399 * from end of lines.
432 */
400 */
433 static PyObject *fixws(PyObject *self, PyObject *args)
401 static PyObject *fixws(PyObject *self, PyObject *args)
434 {
402 {
435 PyObject *s, *result = NULL;
403 PyObject *s, *result = NULL;
436 char allws, c;
404 char allws, c;
437 const char *r;
405 const char *r;
438 int i, rlen, wlen = 0;
406 int i, rlen, wlen = 0;
439 char *w;
407 char *w;
440
408
441 if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws))
409 if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws))
442 return NULL;
410 return NULL;
443 r = PyBytes_AsString(s);
411 r = PyBytes_AsString(s);
444 rlen = PyBytes_Size(s);
412 rlen = PyBytes_Size(s);
445
413
446 w = (char *)malloc(rlen ? rlen : 1);
414 w = (char *)malloc(rlen ? rlen : 1);
447 if (!w)
415 if (!w)
448 goto nomem;
416 goto nomem;
449
417
450 for (i = 0; i != rlen; i++) {
418 for (i = 0; i != rlen; i++) {
451 c = r[i];
419 c = r[i];
452 if (c == ' ' || c == '\t' || c == '\r') {
420 if (c == ' ' || c == '\t' || c == '\r') {
453 if (!allws && (wlen == 0 || w[wlen - 1] != ' '))
421 if (!allws && (wlen == 0 || w[wlen - 1] != ' '))
454 w[wlen++] = ' ';
422 w[wlen++] = ' ';
455 } else if (c == '\n' && !allws
423 } else if (c == '\n' && !allws
456 && wlen > 0 && w[wlen - 1] == ' ') {
424 && wlen > 0 && w[wlen - 1] == ' ') {
457 w[wlen - 1] = '\n';
425 w[wlen - 1] = '\n';
458 } else {
426 } else {
459 w[wlen++] = c;
427 w[wlen++] = c;
460 }
428 }
461 }
429 }
462
430
463 result = PyBytes_FromStringAndSize(w, wlen);
431 result = PyBytes_FromStringAndSize(w, wlen);
464
432
465 nomem:
433 nomem:
466 free(w);
434 free(w);
467 return result ? result : PyErr_NoMemory();
435 return result ? result : PyErr_NoMemory();
468 }
436 }
469
437
470
438
471 static char mdiff_doc[] = "Efficient binary diff.";
439 static char mdiff_doc[] = "Efficient binary diff.";
472
440
473 static PyMethodDef methods[] = {
441 static PyMethodDef methods[] = {
474 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"},
442 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"},
475 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"},
443 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"},
476 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"},
444 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"},
477 {NULL, NULL}
445 {NULL, NULL}
478 };
446 };
479
447
480 #ifdef IS_PY3K
448 #ifdef IS_PY3K
481 static struct PyModuleDef bdiff_module = {
449 static struct PyModuleDef bdiff_module = {
482 PyModuleDef_HEAD_INIT,
450 PyModuleDef_HEAD_INIT,
483 "bdiff",
451 "bdiff",
484 mdiff_doc,
452 mdiff_doc,
485 -1,
453 -1,
486 methods
454 methods
487 };
455 };
488
456
489 PyMODINIT_FUNC PyInit_bdiff(void)
457 PyMODINIT_FUNC PyInit_bdiff(void)
490 {
458 {
491 return PyModule_Create(&bdiff_module);
459 return PyModule_Create(&bdiff_module);
492 }
460 }
493 #else
461 #else
494 PyMODINIT_FUNC initbdiff(void)
462 PyMODINIT_FUNC initbdiff(void)
495 {
463 {
496 Py_InitModule3("bdiff", methods, mdiff_doc);
464 Py_InitModule3("bdiff", methods, mdiff_doc);
497 }
465 }
498 #endif
466 #endif
499
467
@@ -1,460 +1,434 b''
1 /*
1 /*
2 mpatch.c - efficient binary patching for Mercurial
2 mpatch.c - efficient binary patching for Mercurial
3
3
4 This implements a patch algorithm that's O(m + nlog n) where m is the
4 This implements a patch algorithm that's O(m + nlog n) where m is the
5 size of the output and n is the number of patches.
5 size of the output and n is the number of patches.
6
6
7 Given a list of binary patches, it unpacks each into a hunk list,
7 Given a list of binary patches, it unpacks each into a hunk list,
8 then combines the hunk lists with a treewise recursion to form a
8 then combines the hunk lists with a treewise recursion to form a
9 single hunk list. This hunk list is then applied to the original
9 single hunk list. This hunk list is then applied to the original
10 text.
10 text.
11
11
12 The text (or binary) fragments are copied directly from their source
12 The text (or binary) fragments are copied directly from their source
13 Python objects into a preallocated output string to avoid the
13 Python objects into a preallocated output string to avoid the
14 allocation of intermediate Python objects. Working memory is about 2x
14 allocation of intermediate Python objects. Working memory is about 2x
15 the total number of hunks.
15 the total number of hunks.
16
16
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
18
18
19 This software may be used and distributed according to the terms
19 This software may be used and distributed according to the terms
20 of the GNU General Public License, incorporated herein by reference.
20 of the GNU General Public License, incorporated herein by reference.
21 */
21 */
22
22
23 #include <Python.h>
23 #include <Python.h>
24 #include <stdlib.h>
24 #include <stdlib.h>
25 #include <string.h>
25 #include <string.h>
26
26
27 #include "util.h"
27 #include "util.h"
28
28
29 #ifdef _WIN32
30 #ifdef _MSC_VER
31 /* msvc 6.0 has problems */
32 #define inline __inline
33 typedef unsigned long uint32_t;
34 #else
35 #include <stdint.h>
36 #endif
37 static uint32_t ntohl(uint32_t x)
38 {
39 return ((x & 0x000000ffUL) << 24) |
40 ((x & 0x0000ff00UL) << 8) |
41 ((x & 0x00ff0000UL) >> 8) |
42 ((x & 0xff000000UL) >> 24);
43 }
44 #else
45 /* not windows */
46 #include <sys/types.h>
47 #if defined __BEOS__ && !defined __HAIKU__
48 #include <ByteOrder.h>
49 #else
50 #include <arpa/inet.h>
51 #endif
52 #include <inttypes.h>
53 #endif
54
55 static char mpatch_doc[] = "Efficient binary patching.";
29 static char mpatch_doc[] = "Efficient binary patching.";
56 static PyObject *mpatch_Error;
30 static PyObject *mpatch_Error;
57
31
58 struct frag {
32 struct frag {
59 int start, end, len;
33 int start, end, len;
60 const char *data;
34 const char *data;
61 };
35 };
62
36
63 struct flist {
37 struct flist {
64 struct frag *base, *head, *tail;
38 struct frag *base, *head, *tail;
65 };
39 };
66
40
67 static struct flist *lalloc(int size)
41 static struct flist *lalloc(int size)
68 {
42 {
69 struct flist *a = NULL;
43 struct flist *a = NULL;
70
44
71 if (size < 1)
45 if (size < 1)
72 size = 1;
46 size = 1;
73
47
74 a = (struct flist *)malloc(sizeof(struct flist));
48 a = (struct flist *)malloc(sizeof(struct flist));
75 if (a) {
49 if (a) {
76 a->base = (struct frag *)malloc(sizeof(struct frag) * size);
50 a->base = (struct frag *)malloc(sizeof(struct frag) * size);
77 if (a->base) {
51 if (a->base) {
78 a->head = a->tail = a->base;
52 a->head = a->tail = a->base;
79 return a;
53 return a;
80 }
54 }
81 free(a);
55 free(a);
82 a = NULL;
56 a = NULL;
83 }
57 }
84 if (!PyErr_Occurred())
58 if (!PyErr_Occurred())
85 PyErr_NoMemory();
59 PyErr_NoMemory();
86 return NULL;
60 return NULL;
87 }
61 }
88
62
89 static void lfree(struct flist *a)
63 static void lfree(struct flist *a)
90 {
64 {
91 if (a) {
65 if (a) {
92 free(a->base);
66 free(a->base);
93 free(a);
67 free(a);
94 }
68 }
95 }
69 }
96
70
97 static int lsize(struct flist *a)
71 static int lsize(struct flist *a)
98 {
72 {
99 return a->tail - a->head;
73 return a->tail - a->head;
100 }
74 }
101
75
102 /* move hunks in source that are less cut to dest, compensating
76 /* move hunks in source that are less cut to dest, compensating
103 for changes in offset. the last hunk may be split if necessary.
77 for changes in offset. the last hunk may be split if necessary.
104 */
78 */
105 static int gather(struct flist *dest, struct flist *src, int cut, int offset)
79 static int gather(struct flist *dest, struct flist *src, int cut, int offset)
106 {
80 {
107 struct frag *d = dest->tail, *s = src->head;
81 struct frag *d = dest->tail, *s = src->head;
108 int postend, c, l;
82 int postend, c, l;
109
83
110 while (s != src->tail) {
84 while (s != src->tail) {
111 if (s->start + offset >= cut)
85 if (s->start + offset >= cut)
112 break; /* we've gone far enough */
86 break; /* we've gone far enough */
113
87
114 postend = offset + s->start + s->len;
88 postend = offset + s->start + s->len;
115 if (postend <= cut) {
89 if (postend <= cut) {
116 /* save this hunk */
90 /* save this hunk */
117 offset += s->start + s->len - s->end;
91 offset += s->start + s->len - s->end;
118 *d++ = *s++;
92 *d++ = *s++;
119 }
93 }
120 else {
94 else {
121 /* break up this hunk */
95 /* break up this hunk */
122 c = cut - offset;
96 c = cut - offset;
123 if (s->end < c)
97 if (s->end < c)
124 c = s->end;
98 c = s->end;
125 l = cut - offset - s->start;
99 l = cut - offset - s->start;
126 if (s->len < l)
100 if (s->len < l)
127 l = s->len;
101 l = s->len;
128
102
129 offset += s->start + l - c;
103 offset += s->start + l - c;
130
104
131 d->start = s->start;
105 d->start = s->start;
132 d->end = c;
106 d->end = c;
133 d->len = l;
107 d->len = l;
134 d->data = s->data;
108 d->data = s->data;
135 d++;
109 d++;
136 s->start = c;
110 s->start = c;
137 s->len = s->len - l;
111 s->len = s->len - l;
138 s->data = s->data + l;
112 s->data = s->data + l;
139
113
140 break;
114 break;
141 }
115 }
142 }
116 }
143
117
144 dest->tail = d;
118 dest->tail = d;
145 src->head = s;
119 src->head = s;
146 return offset;
120 return offset;
147 }
121 }
148
122
149 /* like gather, but with no output list */
123 /* like gather, but with no output list */
150 static int discard(struct flist *src, int cut, int offset)
124 static int discard(struct flist *src, int cut, int offset)
151 {
125 {
152 struct frag *s = src->head;
126 struct frag *s = src->head;
153 int postend, c, l;
127 int postend, c, l;
154
128
155 while (s != src->tail) {
129 while (s != src->tail) {
156 if (s->start + offset >= cut)
130 if (s->start + offset >= cut)
157 break;
131 break;
158
132
159 postend = offset + s->start + s->len;
133 postend = offset + s->start + s->len;
160 if (postend <= cut) {
134 if (postend <= cut) {
161 offset += s->start + s->len - s->end;
135 offset += s->start + s->len - s->end;
162 s++;
136 s++;
163 }
137 }
164 else {
138 else {
165 c = cut - offset;
139 c = cut - offset;
166 if (s->end < c)
140 if (s->end < c)
167 c = s->end;
141 c = s->end;
168 l = cut - offset - s->start;
142 l = cut - offset - s->start;
169 if (s->len < l)
143 if (s->len < l)
170 l = s->len;
144 l = s->len;
171
145
172 offset += s->start + l - c;
146 offset += s->start + l - c;
173 s->start = c;
147 s->start = c;
174 s->len = s->len - l;
148 s->len = s->len - l;
175 s->data = s->data + l;
149 s->data = s->data + l;
176
150
177 break;
151 break;
178 }
152 }
179 }
153 }
180
154
181 src->head = s;
155 src->head = s;
182 return offset;
156 return offset;
183 }
157 }
184
158
185 /* combine hunk lists a and b, while adjusting b for offset changes in a/
159 /* combine hunk lists a and b, while adjusting b for offset changes in a/
186 this deletes a and b and returns the resultant list. */
160 this deletes a and b and returns the resultant list. */
187 static struct flist *combine(struct flist *a, struct flist *b)
161 static struct flist *combine(struct flist *a, struct flist *b)
188 {
162 {
189 struct flist *c = NULL;
163 struct flist *c = NULL;
190 struct frag *bh, *ct;
164 struct frag *bh, *ct;
191 int offset = 0, post;
165 int offset = 0, post;
192
166
193 if (a && b)
167 if (a && b)
194 c = lalloc((lsize(a) + lsize(b)) * 2);
168 c = lalloc((lsize(a) + lsize(b)) * 2);
195
169
196 if (c) {
170 if (c) {
197
171
198 for (bh = b->head; bh != b->tail; bh++) {
172 for (bh = b->head; bh != b->tail; bh++) {
199 /* save old hunks */
173 /* save old hunks */
200 offset = gather(c, a, bh->start, offset);
174 offset = gather(c, a, bh->start, offset);
201
175
202 /* discard replaced hunks */
176 /* discard replaced hunks */
203 post = discard(a, bh->end, offset);
177 post = discard(a, bh->end, offset);
204
178
205 /* insert new hunk */
179 /* insert new hunk */
206 ct = c->tail;
180 ct = c->tail;
207 ct->start = bh->start - offset;
181 ct->start = bh->start - offset;
208 ct->end = bh->end - post;
182 ct->end = bh->end - post;
209 ct->len = bh->len;
183 ct->len = bh->len;
210 ct->data = bh->data;
184 ct->data = bh->data;
211 c->tail++;
185 c->tail++;
212 offset = post;
186 offset = post;
213 }
187 }
214
188
215 /* hold on to tail from a */
189 /* hold on to tail from a */
216 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
190 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
217 c->tail += lsize(a);
191 c->tail += lsize(a);
218 }
192 }
219
193
220 lfree(a);
194 lfree(a);
221 lfree(b);
195 lfree(b);
222 return c;
196 return c;
223 }
197 }
224
198
225 /* decode a binary patch into a hunk list */
199 /* decode a binary patch into a hunk list */
226 static struct flist *decode(const char *bin, int len)
200 static struct flist *decode(const char *bin, int len)
227 {
201 {
228 struct flist *l;
202 struct flist *l;
229 struct frag *lt;
203 struct frag *lt;
230 const char *data = bin + 12, *end = bin + len;
204 const char *data = bin + 12, *end = bin + len;
231 uint32_t decode[3]; /* for dealing with alignment issues */
205 uint32_t decode[3]; /* for dealing with alignment issues */
232
206
233 /* assume worst case size, we won't have many of these lists */
207 /* assume worst case size, we won't have many of these lists */
234 l = lalloc(len / 12);
208 l = lalloc(len / 12);
235 if (!l)
209 if (!l)
236 return NULL;
210 return NULL;
237
211
238 lt = l->tail;
212 lt = l->tail;
239
213
240 while (data <= end) {
214 while (data <= end) {
241 memcpy(decode, bin, 12);
215 memcpy(decode, bin, 12);
242 lt->start = ntohl(decode[0]);
216 lt->start = ntohl(decode[0]);
243 lt->end = ntohl(decode[1]);
217 lt->end = ntohl(decode[1]);
244 lt->len = ntohl(decode[2]);
218 lt->len = ntohl(decode[2]);
245 if (lt->start > lt->end)
219 if (lt->start > lt->end)
246 break; /* sanity check */
220 break; /* sanity check */
247 bin = data + lt->len;
221 bin = data + lt->len;
248 if (bin < data)
222 if (bin < data)
249 break; /* big data + big (bogus) len can wrap around */
223 break; /* big data + big (bogus) len can wrap around */
250 lt->data = data;
224 lt->data = data;
251 data = bin + 12;
225 data = bin + 12;
252 lt++;
226 lt++;
253 }
227 }
254
228
255 if (bin != end) {
229 if (bin != end) {
256 if (!PyErr_Occurred())
230 if (!PyErr_Occurred())
257 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
231 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
258 lfree(l);
232 lfree(l);
259 return NULL;
233 return NULL;
260 }
234 }
261
235
262 l->tail = lt;
236 l->tail = lt;
263 return l;
237 return l;
264 }
238 }
265
239
266 /* calculate the size of resultant text */
240 /* calculate the size of resultant text */
267 static int calcsize(int len, struct flist *l)
241 static int calcsize(int len, struct flist *l)
268 {
242 {
269 int outlen = 0, last = 0;
243 int outlen = 0, last = 0;
270 struct frag *f = l->head;
244 struct frag *f = l->head;
271
245
272 while (f != l->tail) {
246 while (f != l->tail) {
273 if (f->start < last || f->end > len) {
247 if (f->start < last || f->end > len) {
274 if (!PyErr_Occurred())
248 if (!PyErr_Occurred())
275 PyErr_SetString(mpatch_Error,
249 PyErr_SetString(mpatch_Error,
276 "invalid patch");
250 "invalid patch");
277 return -1;
251 return -1;
278 }
252 }
279 outlen += f->start - last;
253 outlen += f->start - last;
280 last = f->end;
254 last = f->end;
281 outlen += f->len;
255 outlen += f->len;
282 f++;
256 f++;
283 }
257 }
284
258
285 outlen += len - last;
259 outlen += len - last;
286 return outlen;
260 return outlen;
287 }
261 }
288
262
289 static int apply(char *buf, const char *orig, int len, struct flist *l)
263 static int apply(char *buf, const char *orig, int len, struct flist *l)
290 {
264 {
291 struct frag *f = l->head;
265 struct frag *f = l->head;
292 int last = 0;
266 int last = 0;
293 char *p = buf;
267 char *p = buf;
294
268
295 while (f != l->tail) {
269 while (f != l->tail) {
296 if (f->start < last || f->end > len) {
270 if (f->start < last || f->end > len) {
297 if (!PyErr_Occurred())
271 if (!PyErr_Occurred())
298 PyErr_SetString(mpatch_Error,
272 PyErr_SetString(mpatch_Error,
299 "invalid patch");
273 "invalid patch");
300 return 0;
274 return 0;
301 }
275 }
302 memcpy(p, orig + last, f->start - last);
276 memcpy(p, orig + last, f->start - last);
303 p += f->start - last;
277 p += f->start - last;
304 memcpy(p, f->data, f->len);
278 memcpy(p, f->data, f->len);
305 last = f->end;
279 last = f->end;
306 p += f->len;
280 p += f->len;
307 f++;
281 f++;
308 }
282 }
309 memcpy(p, orig + last, len - last);
283 memcpy(p, orig + last, len - last);
310 return 1;
284 return 1;
311 }
285 }
312
286
313 /* recursively generate a patch of all bins between start and end */
287 /* recursively generate a patch of all bins between start and end */
314 static struct flist *fold(PyObject *bins, int start, int end)
288 static struct flist *fold(PyObject *bins, int start, int end)
315 {
289 {
316 int len;
290 int len;
317 Py_ssize_t blen;
291 Py_ssize_t blen;
318 const char *buffer;
292 const char *buffer;
319
293
320 if (start + 1 == end) {
294 if (start + 1 == end) {
321 /* trivial case, output a decoded list */
295 /* trivial case, output a decoded list */
322 PyObject *tmp = PyList_GetItem(bins, start);
296 PyObject *tmp = PyList_GetItem(bins, start);
323 if (!tmp)
297 if (!tmp)
324 return NULL;
298 return NULL;
325 if (PyObject_AsCharBuffer(tmp, &buffer, &blen))
299 if (PyObject_AsCharBuffer(tmp, &buffer, &blen))
326 return NULL;
300 return NULL;
327 return decode(buffer, blen);
301 return decode(buffer, blen);
328 }
302 }
329
303
330 /* divide and conquer, memory management is elsewhere */
304 /* divide and conquer, memory management is elsewhere */
331 len = (end - start) / 2;
305 len = (end - start) / 2;
332 return combine(fold(bins, start, start + len),
306 return combine(fold(bins, start, start + len),
333 fold(bins, start + len, end));
307 fold(bins, start + len, end));
334 }
308 }
335
309
336 static PyObject *
310 static PyObject *
337 patches(PyObject *self, PyObject *args)
311 patches(PyObject *self, PyObject *args)
338 {
312 {
339 PyObject *text, *bins, *result;
313 PyObject *text, *bins, *result;
340 struct flist *patch;
314 struct flist *patch;
341 const char *in;
315 const char *in;
342 char *out;
316 char *out;
343 int len, outlen;
317 int len, outlen;
344 Py_ssize_t inlen;
318 Py_ssize_t inlen;
345
319
346 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
320 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
347 return NULL;
321 return NULL;
348
322
349 len = PyList_Size(bins);
323 len = PyList_Size(bins);
350 if (!len) {
324 if (!len) {
351 /* nothing to do */
325 /* nothing to do */
352 Py_INCREF(text);
326 Py_INCREF(text);
353 return text;
327 return text;
354 }
328 }
355
329
356 if (PyObject_AsCharBuffer(text, &in, &inlen))
330 if (PyObject_AsCharBuffer(text, &in, &inlen))
357 return NULL;
331 return NULL;
358
332
359 patch = fold(bins, 0, len);
333 patch = fold(bins, 0, len);
360 if (!patch)
334 if (!patch)
361 return NULL;
335 return NULL;
362
336
363 outlen = calcsize(inlen, patch);
337 outlen = calcsize(inlen, patch);
364 if (outlen < 0) {
338 if (outlen < 0) {
365 result = NULL;
339 result = NULL;
366 goto cleanup;
340 goto cleanup;
367 }
341 }
368 result = PyBytes_FromStringAndSize(NULL, outlen);
342 result = PyBytes_FromStringAndSize(NULL, outlen);
369 if (!result) {
343 if (!result) {
370 result = NULL;
344 result = NULL;
371 goto cleanup;
345 goto cleanup;
372 }
346 }
373 out = PyBytes_AsString(result);
347 out = PyBytes_AsString(result);
374 if (!apply(out, in, inlen, patch)) {
348 if (!apply(out, in, inlen, patch)) {
375 Py_DECREF(result);
349 Py_DECREF(result);
376 result = NULL;
350 result = NULL;
377 }
351 }
378 cleanup:
352 cleanup:
379 lfree(patch);
353 lfree(patch);
380 return result;
354 return result;
381 }
355 }
382
356
383 /* calculate size of a patched file directly */
357 /* calculate size of a patched file directly */
384 static PyObject *
358 static PyObject *
385 patchedsize(PyObject *self, PyObject *args)
359 patchedsize(PyObject *self, PyObject *args)
386 {
360 {
387 long orig, start, end, len, outlen = 0, last = 0;
361 long orig, start, end, len, outlen = 0, last = 0;
388 int patchlen;
362 int patchlen;
389 char *bin, *binend, *data;
363 char *bin, *binend, *data;
390 uint32_t decode[3]; /* for dealing with alignment issues */
364 uint32_t decode[3]; /* for dealing with alignment issues */
391
365
392 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
366 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
393 return NULL;
367 return NULL;
394
368
395 binend = bin + patchlen;
369 binend = bin + patchlen;
396 data = bin + 12;
370 data = bin + 12;
397
371
398 while (data <= binend) {
372 while (data <= binend) {
399 memcpy(decode, bin, 12);
373 memcpy(decode, bin, 12);
400 start = ntohl(decode[0]);
374 start = ntohl(decode[0]);
401 end = ntohl(decode[1]);
375 end = ntohl(decode[1]);
402 len = ntohl(decode[2]);
376 len = ntohl(decode[2]);
403 if (start > end)
377 if (start > end)
404 break; /* sanity check */
378 break; /* sanity check */
405 bin = data + len;
379 bin = data + len;
406 if (bin < data)
380 if (bin < data)
407 break; /* big data + big (bogus) len can wrap around */
381 break; /* big data + big (bogus) len can wrap around */
408 data = bin + 12;
382 data = bin + 12;
409 outlen += start - last;
383 outlen += start - last;
410 last = end;
384 last = end;
411 outlen += len;
385 outlen += len;
412 }
386 }
413
387
414 if (bin != binend) {
388 if (bin != binend) {
415 if (!PyErr_Occurred())
389 if (!PyErr_Occurred())
416 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
390 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
417 return NULL;
391 return NULL;
418 }
392 }
419
393
420 outlen += orig - last;
394 outlen += orig - last;
421 return Py_BuildValue("l", outlen);
395 return Py_BuildValue("l", outlen);
422 }
396 }
423
397
424 static PyMethodDef methods[] = {
398 static PyMethodDef methods[] = {
425 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},
399 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},
426 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"},
400 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"},
427 {NULL, NULL}
401 {NULL, NULL}
428 };
402 };
429
403
430 #ifdef IS_PY3K
404 #ifdef IS_PY3K
431 static struct PyModuleDef mpatch_module = {
405 static struct PyModuleDef mpatch_module = {
432 PyModuleDef_HEAD_INIT,
406 PyModuleDef_HEAD_INIT,
433 "mpatch",
407 "mpatch",
434 mpatch_doc,
408 mpatch_doc,
435 -1,
409 -1,
436 methods
410 methods
437 };
411 };
438
412
439 PyMODINIT_FUNC PyInit_mpatch(void)
413 PyMODINIT_FUNC PyInit_mpatch(void)
440 {
414 {
441 PyObject *m;
415 PyObject *m;
442
416
443 m = PyModule_Create(&mpatch_module);
417 m = PyModule_Create(&mpatch_module);
444 if (m == NULL)
418 if (m == NULL)
445 return NULL;
419 return NULL;
446
420
447 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
421 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
448 Py_INCREF(mpatch_Error);
422 Py_INCREF(mpatch_Error);
449 PyModule_AddObject(m, "mpatchError", mpatch_Error);
423 PyModule_AddObject(m, "mpatchError", mpatch_Error);
450
424
451 return m;
425 return m;
452 }
426 }
453 #else
427 #else
454 PyMODINIT_FUNC
428 PyMODINIT_FUNC
455 initmpatch(void)
429 initmpatch(void)
456 {
430 {
457 Py_InitModule3("mpatch", methods, mpatch_doc);
431 Py_InitModule3("mpatch", methods, mpatch_doc);
458 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
432 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
459 }
433 }
460 #endif
434 #endif
@@ -1,740 +1,713 b''
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <ctype.h>
11 #include <ctype.h>
12 #include <string.h>
12 #include <string.h>
13
13
14 #include "util.h"
14 #include "util.h"
15
15
16 static int hexdigit(char c)
16 static int hexdigit(char c)
17 {
17 {
18 if (c >= '0' && c <= '9')
18 if (c >= '0' && c <= '9')
19 return c - '0';
19 return c - '0';
20 if (c >= 'a' && c <= 'f')
20 if (c >= 'a' && c <= 'f')
21 return c - 'a' + 10;
21 return c - 'a' + 10;
22 if (c >= 'A' && c <= 'F')
22 if (c >= 'A' && c <= 'F')
23 return c - 'A' + 10;
23 return c - 'A' + 10;
24
24
25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
26 return 0;
26 return 0;
27 }
27 }
28
28
29 /*
29 /*
30 * Turn a hex-encoded string into binary.
30 * Turn a hex-encoded string into binary.
31 */
31 */
32 static PyObject *unhexlify(const char *str, int len)
32 static PyObject *unhexlify(const char *str, int len)
33 {
33 {
34 PyObject *ret;
34 PyObject *ret;
35 const char *c;
35 const char *c;
36 char *d;
36 char *d;
37
37
38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
39
39
40 if (!ret)
40 if (!ret)
41 return NULL;
41 return NULL;
42
42
43 d = PyBytes_AsString(ret);
43 d = PyBytes_AsString(ret);
44
44
45 for (c = str; c < str + len;) {
45 for (c = str; c < str + len;) {
46 int hi = hexdigit(*c++);
46 int hi = hexdigit(*c++);
47 int lo = hexdigit(*c++);
47 int lo = hexdigit(*c++);
48 *d++ = (hi << 4) | lo;
48 *d++ = (hi << 4) | lo;
49 }
49 }
50
50
51 return ret;
51 return ret;
52 }
52 }
53
53
54 /*
54 /*
55 * This code assumes that a manifest is stitched together with newline
55 * This code assumes that a manifest is stitched together with newline
56 * ('\n') characters.
56 * ('\n') characters.
57 */
57 */
58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
59 {
59 {
60 PyObject *mfdict, *fdict;
60 PyObject *mfdict, *fdict;
61 char *str, *cur, *start, *zero;
61 char *str, *cur, *start, *zero;
62 int len;
62 int len;
63
63
64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
65 &PyDict_Type, &mfdict,
65 &PyDict_Type, &mfdict,
66 &PyDict_Type, &fdict,
66 &PyDict_Type, &fdict,
67 &str, &len))
67 &str, &len))
68 goto quit;
68 goto quit;
69
69
70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
71 PyObject *file = NULL, *node = NULL;
71 PyObject *file = NULL, *node = NULL;
72 PyObject *flags = NULL;
72 PyObject *flags = NULL;
73 int nlen;
73 int nlen;
74
74
75 if (!*cur) {
75 if (!*cur) {
76 zero = cur;
76 zero = cur;
77 continue;
77 continue;
78 }
78 }
79 else if (*cur != '\n')
79 else if (*cur != '\n')
80 continue;
80 continue;
81
81
82 if (!zero) {
82 if (!zero) {
83 PyErr_SetString(PyExc_ValueError,
83 PyErr_SetString(PyExc_ValueError,
84 "manifest entry has no separator");
84 "manifest entry has no separator");
85 goto quit;
85 goto quit;
86 }
86 }
87
87
88 file = PyBytes_FromStringAndSize(start, zero - start);
88 file = PyBytes_FromStringAndSize(start, zero - start);
89
89
90 if (!file)
90 if (!file)
91 goto bail;
91 goto bail;
92
92
93 nlen = cur - zero - 1;
93 nlen = cur - zero - 1;
94
94
95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
96 if (!node)
96 if (!node)
97 goto bail;
97 goto bail;
98
98
99 if (nlen > 40) {
99 if (nlen > 40) {
100 flags = PyBytes_FromStringAndSize(zero + 41,
100 flags = PyBytes_FromStringAndSize(zero + 41,
101 nlen - 40);
101 nlen - 40);
102 if (!flags)
102 if (!flags)
103 goto bail;
103 goto bail;
104
104
105 if (PyDict_SetItem(fdict, file, flags) == -1)
105 if (PyDict_SetItem(fdict, file, flags) == -1)
106 goto bail;
106 goto bail;
107 }
107 }
108
108
109 if (PyDict_SetItem(mfdict, file, node) == -1)
109 if (PyDict_SetItem(mfdict, file, node) == -1)
110 goto bail;
110 goto bail;
111
111
112 start = cur + 1;
112 start = cur + 1;
113 zero = NULL;
113 zero = NULL;
114
114
115 Py_XDECREF(flags);
115 Py_XDECREF(flags);
116 Py_XDECREF(node);
116 Py_XDECREF(node);
117 Py_XDECREF(file);
117 Py_XDECREF(file);
118 continue;
118 continue;
119 bail:
119 bail:
120 Py_XDECREF(flags);
120 Py_XDECREF(flags);
121 Py_XDECREF(node);
121 Py_XDECREF(node);
122 Py_XDECREF(file);
122 Py_XDECREF(file);
123 goto quit;
123 goto quit;
124 }
124 }
125
125
126 if (len > 0 && *(cur - 1) != '\n') {
126 if (len > 0 && *(cur - 1) != '\n') {
127 PyErr_SetString(PyExc_ValueError,
127 PyErr_SetString(PyExc_ValueError,
128 "manifest contains trailing garbage");
128 "manifest contains trailing garbage");
129 goto quit;
129 goto quit;
130 }
130 }
131
131
132 Py_INCREF(Py_None);
132 Py_INCREF(Py_None);
133 return Py_None;
133 return Py_None;
134 quit:
134 quit:
135 return NULL;
135 return NULL;
136 }
136 }
137
137
138 #ifdef _WIN32
139 #ifdef _MSC_VER
140 /* msvc 6.0 has problems */
141 #define inline __inline
142 typedef unsigned long uint32_t;
143 typedef unsigned __int64 uint64_t;
144 #else
145 #include <stdint.h>
146 #endif
147 static uint32_t ntohl(uint32_t x)
148 {
149 return ((x & 0x000000ffUL) << 24) |
150 ((x & 0x0000ff00UL) << 8) |
151 ((x & 0x00ff0000UL) >> 8) |
152 ((x & 0xff000000UL) >> 24);
153 }
154 #else
155 /* not windows */
156 #include <sys/types.h>
157 #if defined __BEOS__ && !defined __HAIKU__
158 #include <ByteOrder.h>
159 #else
160 #include <arpa/inet.h>
161 #endif
162 #include <inttypes.h>
163 #endif
164
165 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
138 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
166 {
139 {
167 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
140 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
168 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
141 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
169 char *str, *cur, *end, *cpos;
142 char *str, *cur, *end, *cpos;
170 int state, mode, size, mtime;
143 int state, mode, size, mtime;
171 unsigned int flen;
144 unsigned int flen;
172 int len;
145 int len;
173 uint32_t decode[4]; /* for alignment */
146 uint32_t decode[4]; /* for alignment */
174
147
175 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
148 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
176 &PyDict_Type, &dmap,
149 &PyDict_Type, &dmap,
177 &PyDict_Type, &cmap,
150 &PyDict_Type, &cmap,
178 &str, &len))
151 &str, &len))
179 goto quit;
152 goto quit;
180
153
181 /* read parents */
154 /* read parents */
182 if (len < 40)
155 if (len < 40)
183 goto quit;
156 goto quit;
184
157
185 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
158 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
186 if (!parents)
159 if (!parents)
187 goto quit;
160 goto quit;
188
161
189 /* read filenames */
162 /* read filenames */
190 cur = str + 40;
163 cur = str + 40;
191 end = str + len;
164 end = str + len;
192
165
193 while (cur < end - 17) {
166 while (cur < end - 17) {
194 /* unpack header */
167 /* unpack header */
195 state = *cur;
168 state = *cur;
196 memcpy(decode, cur + 1, 16);
169 memcpy(decode, cur + 1, 16);
197 mode = ntohl(decode[0]);
170 mode = ntohl(decode[0]);
198 size = ntohl(decode[1]);
171 size = ntohl(decode[1]);
199 mtime = ntohl(decode[2]);
172 mtime = ntohl(decode[2]);
200 flen = ntohl(decode[3]);
173 flen = ntohl(decode[3]);
201 cur += 17;
174 cur += 17;
202 if (cur + flen > end || cur + flen < cur) {
175 if (cur + flen > end || cur + flen < cur) {
203 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
176 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
204 goto quit;
177 goto quit;
205 }
178 }
206
179
207 entry = Py_BuildValue("ciii", state, mode, size, mtime);
180 entry = Py_BuildValue("ciii", state, mode, size, mtime);
208 if (!entry)
181 if (!entry)
209 goto quit;
182 goto quit;
210 PyObject_GC_UnTrack(entry); /* don't waste time with this */
183 PyObject_GC_UnTrack(entry); /* don't waste time with this */
211
184
212 cpos = memchr(cur, 0, flen);
185 cpos = memchr(cur, 0, flen);
213 if (cpos) {
186 if (cpos) {
214 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
187 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
215 cname = PyBytes_FromStringAndSize(cpos + 1,
188 cname = PyBytes_FromStringAndSize(cpos + 1,
216 flen - (cpos - cur) - 1);
189 flen - (cpos - cur) - 1);
217 if (!fname || !cname ||
190 if (!fname || !cname ||
218 PyDict_SetItem(cmap, fname, cname) == -1 ||
191 PyDict_SetItem(cmap, fname, cname) == -1 ||
219 PyDict_SetItem(dmap, fname, entry) == -1)
192 PyDict_SetItem(dmap, fname, entry) == -1)
220 goto quit;
193 goto quit;
221 Py_DECREF(cname);
194 Py_DECREF(cname);
222 } else {
195 } else {
223 fname = PyBytes_FromStringAndSize(cur, flen);
196 fname = PyBytes_FromStringAndSize(cur, flen);
224 if (!fname ||
197 if (!fname ||
225 PyDict_SetItem(dmap, fname, entry) == -1)
198 PyDict_SetItem(dmap, fname, entry) == -1)
226 goto quit;
199 goto quit;
227 }
200 }
228 cur += flen;
201 cur += flen;
229 Py_DECREF(fname);
202 Py_DECREF(fname);
230 Py_DECREF(entry);
203 Py_DECREF(entry);
231 fname = cname = entry = NULL;
204 fname = cname = entry = NULL;
232 }
205 }
233
206
234 ret = parents;
207 ret = parents;
235 Py_INCREF(ret);
208 Py_INCREF(ret);
236 quit:
209 quit:
237 Py_XDECREF(fname);
210 Py_XDECREF(fname);
238 Py_XDECREF(cname);
211 Py_XDECREF(cname);
239 Py_XDECREF(entry);
212 Py_XDECREF(entry);
240 Py_XDECREF(parents);
213 Py_XDECREF(parents);
241 return ret;
214 return ret;
242 }
215 }
243
216
244 /*
217 /*
245 * A list-like object that decodes the contents of a RevlogNG index
218 * A list-like object that decodes the contents of a RevlogNG index
246 * file on demand. It has limited support for insert and delete at the
219 * file on demand. It has limited support for insert and delete at the
247 * last element before the end. The last entry is always a sentinel
220 * last element before the end. The last entry is always a sentinel
248 * nullid.
221 * nullid.
249 */
222 */
250 typedef struct {
223 typedef struct {
251 PyObject_HEAD
224 PyObject_HEAD
252 /* Type-specific fields go here. */
225 /* Type-specific fields go here. */
253 PyObject *data; /* raw bytes of index */
226 PyObject *data; /* raw bytes of index */
254 PyObject **cache; /* cached tuples */
227 PyObject **cache; /* cached tuples */
255 const char **offsets; /* populated on demand */
228 const char **offsets; /* populated on demand */
256 Py_ssize_t raw_length; /* original number of elements */
229 Py_ssize_t raw_length; /* original number of elements */
257 Py_ssize_t length; /* current number of elements */
230 Py_ssize_t length; /* current number of elements */
258 PyObject *added; /* populated on demand */
231 PyObject *added; /* populated on demand */
259 int inlined;
232 int inlined;
260 } indexObject;
233 } indexObject;
261
234
262 static Py_ssize_t index_length(indexObject *self)
235 static Py_ssize_t index_length(indexObject *self)
263 {
236 {
264 if (self->added == NULL)
237 if (self->added == NULL)
265 return self->length;
238 return self->length;
266 return self->length + PyList_GET_SIZE(self->added);
239 return self->length + PyList_GET_SIZE(self->added);
267 }
240 }
268
241
269 static PyObject *nullentry;
242 static PyObject *nullentry;
270
243
271 static long inline_scan(indexObject *self, const char **offsets);
244 static long inline_scan(indexObject *self, const char **offsets);
272
245
273 #if LONG_MAX == 0x7fffffffL
246 #if LONG_MAX == 0x7fffffffL
274 static const char *tuple_format = "Kiiiiiis#";
247 static const char *tuple_format = "Kiiiiiis#";
275 #else
248 #else
276 static const char *tuple_format = "kiiiiiis#";
249 static const char *tuple_format = "kiiiiiis#";
277 #endif
250 #endif
278
251
279 /* RevlogNG format (all in big endian, data may be inlined):
252 /* RevlogNG format (all in big endian, data may be inlined):
280 * 6 bytes: offset
253 * 6 bytes: offset
281 * 2 bytes: flags
254 * 2 bytes: flags
282 * 4 bytes: compressed length
255 * 4 bytes: compressed length
283 * 4 bytes: uncompressed length
256 * 4 bytes: uncompressed length
284 * 4 bytes: base revision
257 * 4 bytes: base revision
285 * 4 bytes: link revision
258 * 4 bytes: link revision
286 * 4 bytes: parent 1 revision
259 * 4 bytes: parent 1 revision
287 * 4 bytes: parent 2 revision
260 * 4 bytes: parent 2 revision
288 * 32 bytes: nodeid (only 20 bytes used)
261 * 32 bytes: nodeid (only 20 bytes used)
289 */
262 */
290 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
263 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
291 {
264 {
292 uint32_t decode[8]; /* to enforce alignment with inline data */
265 uint32_t decode[8]; /* to enforce alignment with inline data */
293 uint64_t offset_flags;
266 uint64_t offset_flags;
294 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
267 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
295 const char *c_node_id;
268 const char *c_node_id;
296 const char *data;
269 const char *data;
297 Py_ssize_t length = index_length(self);
270 Py_ssize_t length = index_length(self);
298 PyObject *entry;
271 PyObject *entry;
299
272
300 if (pos >= length) {
273 if (pos >= length) {
301 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
274 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
302 return NULL;
275 return NULL;
303 }
276 }
304
277
305 if (pos == length - 1) {
278 if (pos == length - 1) {
306 Py_INCREF(nullentry);
279 Py_INCREF(nullentry);
307 return nullentry;
280 return nullentry;
308 }
281 }
309
282
310 if (pos >= self->length - 1) {
283 if (pos >= self->length - 1) {
311 PyObject *obj;
284 PyObject *obj;
312 obj = PyList_GET_ITEM(self->added, pos - self->length + 1);
285 obj = PyList_GET_ITEM(self->added, pos - self->length + 1);
313 Py_INCREF(obj);
286 Py_INCREF(obj);
314 return obj;
287 return obj;
315 }
288 }
316
289
317 if (self->cache) {
290 if (self->cache) {
318 if (self->cache[pos]) {
291 if (self->cache[pos]) {
319 Py_INCREF(self->cache[pos]);
292 Py_INCREF(self->cache[pos]);
320 return self->cache[pos];
293 return self->cache[pos];
321 }
294 }
322 } else {
295 } else {
323 self->cache = calloc(self->raw_length, sizeof(PyObject *));
296 self->cache = calloc(self->raw_length, sizeof(PyObject *));
324 if (self->cache == NULL)
297 if (self->cache == NULL)
325 return PyErr_NoMemory();
298 return PyErr_NoMemory();
326 }
299 }
327
300
328 if (self->inlined && pos > 0) {
301 if (self->inlined && pos > 0) {
329 if (self->offsets == NULL) {
302 if (self->offsets == NULL) {
330 self->offsets = malloc(self->raw_length *
303 self->offsets = malloc(self->raw_length *
331 sizeof(*self->offsets));
304 sizeof(*self->offsets));
332 if (self->offsets == NULL)
305 if (self->offsets == NULL)
333 return PyErr_NoMemory();
306 return PyErr_NoMemory();
334 inline_scan(self, self->offsets);
307 inline_scan(self, self->offsets);
335 }
308 }
336 data = self->offsets[pos];
309 data = self->offsets[pos];
337 } else
310 } else
338 data = PyString_AS_STRING(self->data) + pos * 64;
311 data = PyString_AS_STRING(self->data) + pos * 64;
339
312
340 memcpy(decode, data, 8 * sizeof(uint32_t));
313 memcpy(decode, data, 8 * sizeof(uint32_t));
341
314
342 offset_flags = ntohl(decode[1]);
315 offset_flags = ntohl(decode[1]);
343 if (pos == 0) /* mask out version number for the first entry */
316 if (pos == 0) /* mask out version number for the first entry */
344 offset_flags &= 0xFFFF;
317 offset_flags &= 0xFFFF;
345 else {
318 else {
346 uint32_t offset_high = ntohl(decode[0]);
319 uint32_t offset_high = ntohl(decode[0]);
347 offset_flags |= ((uint64_t)offset_high) << 32;
320 offset_flags |= ((uint64_t)offset_high) << 32;
348 }
321 }
349
322
350 comp_len = ntohl(decode[2]);
323 comp_len = ntohl(decode[2]);
351 uncomp_len = ntohl(decode[3]);
324 uncomp_len = ntohl(decode[3]);
352 base_rev = ntohl(decode[4]);
325 base_rev = ntohl(decode[4]);
353 link_rev = ntohl(decode[5]);
326 link_rev = ntohl(decode[5]);
354 parent_1 = ntohl(decode[6]);
327 parent_1 = ntohl(decode[6]);
355 parent_2 = ntohl(decode[7]);
328 parent_2 = ntohl(decode[7]);
356 c_node_id = data + 32;
329 c_node_id = data + 32;
357
330
358 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
331 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
359 uncomp_len, base_rev, link_rev,
332 uncomp_len, base_rev, link_rev,
360 parent_1, parent_2, c_node_id, 20);
333 parent_1, parent_2, c_node_id, 20);
361
334
362 if (entry)
335 if (entry)
363 PyObject_GC_UnTrack(entry);
336 PyObject_GC_UnTrack(entry);
364
337
365 self->cache[pos] = entry;
338 self->cache[pos] = entry;
366 Py_INCREF(entry);
339 Py_INCREF(entry);
367
340
368 return entry;
341 return entry;
369 }
342 }
370
343
371 static PyObject *index_insert(indexObject *self, PyObject *args)
344 static PyObject *index_insert(indexObject *self, PyObject *args)
372 {
345 {
373 PyObject *obj, *node;
346 PyObject *obj, *node;
374 long offset;
347 long offset;
375 Py_ssize_t len;
348 Py_ssize_t len;
376
349
377 if (!PyArg_ParseTuple(args, "lO", &offset, &obj))
350 if (!PyArg_ParseTuple(args, "lO", &offset, &obj))
378 return NULL;
351 return NULL;
379
352
380 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
353 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
381 PyErr_SetString(PyExc_ValueError, "8-tuple required");
354 PyErr_SetString(PyExc_ValueError, "8-tuple required");
382 return NULL;
355 return NULL;
383 }
356 }
384
357
385 node = PyTuple_GET_ITEM(obj, 7);
358 node = PyTuple_GET_ITEM(obj, 7);
386 if (!PyString_Check(node) || PyString_GET_SIZE(node) != 20) {
359 if (!PyString_Check(node) || PyString_GET_SIZE(node) != 20) {
387 PyErr_SetString(PyExc_ValueError,
360 PyErr_SetString(PyExc_ValueError,
388 "20-byte hash required as last element");
361 "20-byte hash required as last element");
389 return NULL;
362 return NULL;
390 }
363 }
391
364
392 len = index_length(self);
365 len = index_length(self);
393
366
394 if (offset < 0)
367 if (offset < 0)
395 offset += len;
368 offset += len;
396
369
397 if (offset != len - 1) {
370 if (offset != len - 1) {
398 PyErr_SetString(PyExc_IndexError,
371 PyErr_SetString(PyExc_IndexError,
399 "insert only supported at index -1");
372 "insert only supported at index -1");
400 return NULL;
373 return NULL;
401 }
374 }
402
375
403 if (self->added == NULL) {
376 if (self->added == NULL) {
404 self->added = PyList_New(0);
377 self->added = PyList_New(0);
405 if (self->added == NULL)
378 if (self->added == NULL)
406 return NULL;
379 return NULL;
407 }
380 }
408
381
409 if (PyList_Append(self->added, obj) == -1)
382 if (PyList_Append(self->added, obj) == -1)
410 return NULL;
383 return NULL;
411
384
412 Py_RETURN_NONE;
385 Py_RETURN_NONE;
413 }
386 }
414
387
415 static void _index_clearcaches(indexObject *self)
388 static void _index_clearcaches(indexObject *self)
416 {
389 {
417 if (self->cache) {
390 if (self->cache) {
418 Py_ssize_t i;
391 Py_ssize_t i;
419
392
420 for (i = 0; i < self->raw_length; i++) {
393 for (i = 0; i < self->raw_length; i++) {
421 Py_XDECREF(self->cache[i]);
394 Py_XDECREF(self->cache[i]);
422 self->cache[i] = NULL;
395 self->cache[i] = NULL;
423 }
396 }
424 free(self->cache);
397 free(self->cache);
425 self->cache = NULL;
398 self->cache = NULL;
426 }
399 }
427 if (self->offsets) {
400 if (self->offsets) {
428 free(self->offsets);
401 free(self->offsets);
429 self->offsets = NULL;
402 self->offsets = NULL;
430 }
403 }
431 }
404 }
432
405
433 static PyObject *index_clearcaches(indexObject *self)
406 static PyObject *index_clearcaches(indexObject *self)
434 {
407 {
435 _index_clearcaches(self);
408 _index_clearcaches(self);
436 Py_RETURN_NONE;
409 Py_RETURN_NONE;
437 }
410 }
438
411
439 static int index_assign_subscript(indexObject *self, PyObject *item,
412 static int index_assign_subscript(indexObject *self, PyObject *item,
440 PyObject *value)
413 PyObject *value)
441 {
414 {
442 Py_ssize_t start, stop, step, slicelength;
415 Py_ssize_t start, stop, step, slicelength;
443 Py_ssize_t length = index_length(self);
416 Py_ssize_t length = index_length(self);
444
417
445 if (!PySlice_Check(item) || value != NULL) {
418 if (!PySlice_Check(item) || value != NULL) {
446 PyErr_SetString(PyExc_TypeError,
419 PyErr_SetString(PyExc_TypeError,
447 "revlog index only supports slice deletion");
420 "revlog index only supports slice deletion");
448 return -1;
421 return -1;
449 }
422 }
450
423
451 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
424 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
452 &start, &stop, &step, &slicelength) < 0)
425 &start, &stop, &step, &slicelength) < 0)
453 return -1;
426 return -1;
454
427
455 if (slicelength <= 0)
428 if (slicelength <= 0)
456 return 0;
429 return 0;
457
430
458 if ((step < 0 && start < stop) || (step > 0 && start > stop))
431 if ((step < 0 && start < stop) || (step > 0 && start > stop))
459 stop = start;
432 stop = start;
460
433
461 if (step < 0) {
434 if (step < 0) {
462 stop = start + 1;
435 stop = start + 1;
463 start = stop + step*(slicelength - 1) - 1;
436 start = stop + step*(slicelength - 1) - 1;
464 step = -step;
437 step = -step;
465 }
438 }
466
439
467 if (step != 1) {
440 if (step != 1) {
468 PyErr_SetString(PyExc_ValueError,
441 PyErr_SetString(PyExc_ValueError,
469 "revlog index delete requires step size of 1");
442 "revlog index delete requires step size of 1");
470 return -1;
443 return -1;
471 }
444 }
472
445
473 if (stop != length - 1) {
446 if (stop != length - 1) {
474 PyErr_SetString(PyExc_IndexError,
447 PyErr_SetString(PyExc_IndexError,
475 "revlog index deletion indices are invalid");
448 "revlog index deletion indices are invalid");
476 return -1;
449 return -1;
477 }
450 }
478
451
479 if (start < self->length) {
452 if (start < self->length) {
480 self->length = start + 1;
453 self->length = start + 1;
481 if (self->added) {
454 if (self->added) {
482 Py_DECREF(self->added);
455 Py_DECREF(self->added);
483 self->added = NULL;
456 self->added = NULL;
484 }
457 }
485 return 0;
458 return 0;
486 }
459 }
487
460
488 return PyList_SetSlice(self->added, start - self->length + 1,
461 return PyList_SetSlice(self->added, start - self->length + 1,
489 PyList_GET_SIZE(self->added),
462 PyList_GET_SIZE(self->added),
490 NULL);
463 NULL);
491 }
464 }
492
465
493 static long inline_scan(indexObject *self, const char **offsets)
466 static long inline_scan(indexObject *self, const char **offsets)
494 {
467 {
495 const char *data = PyString_AS_STRING(self->data);
468 const char *data = PyString_AS_STRING(self->data);
496 const char *end = data + PyString_GET_SIZE(self->data);
469 const char *end = data + PyString_GET_SIZE(self->data);
497 const long hdrsize = 64;
470 const long hdrsize = 64;
498 long incr = hdrsize;
471 long incr = hdrsize;
499 Py_ssize_t len = 0;
472 Py_ssize_t len = 0;
500
473
501 while (data + hdrsize <= end) {
474 while (data + hdrsize <= end) {
502 uint32_t comp_len;
475 uint32_t comp_len;
503 const char *old_data;
476 const char *old_data;
504 /* 3rd element of header is length of compressed inline data */
477 /* 3rd element of header is length of compressed inline data */
505 memcpy(&comp_len, data + 8, sizeof(uint32_t));
478 memcpy(&comp_len, data + 8, sizeof(uint32_t));
506 incr = hdrsize + ntohl(comp_len);
479 incr = hdrsize + ntohl(comp_len);
507 if (incr < hdrsize)
480 if (incr < hdrsize)
508 break;
481 break;
509 if (offsets)
482 if (offsets)
510 offsets[len] = data;
483 offsets[len] = data;
511 len++;
484 len++;
512 old_data = data;
485 old_data = data;
513 data += incr;
486 data += incr;
514 if (data <= old_data)
487 if (data <= old_data)
515 break;
488 break;
516 }
489 }
517
490
518 if (data != end && data + hdrsize != end) {
491 if (data != end && data + hdrsize != end) {
519 if (!PyErr_Occurred())
492 if (!PyErr_Occurred())
520 PyErr_SetString(PyExc_ValueError, "corrupt index file");
493 PyErr_SetString(PyExc_ValueError, "corrupt index file");
521 return -1;
494 return -1;
522 }
495 }
523
496
524 return len;
497 return len;
525 }
498 }
526
499
527 static int index_real_init(indexObject *self, const char *data, int size,
500 static int index_real_init(indexObject *self, const char *data, int size,
528 PyObject *inlined_obj, PyObject *data_obj)
501 PyObject *inlined_obj, PyObject *data_obj)
529 {
502 {
530 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
503 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
531 self->data = data_obj;
504 self->data = data_obj;
532 self->cache = NULL;
505 self->cache = NULL;
533
506
534 self->added = NULL;
507 self->added = NULL;
535 self->offsets = NULL;
508 self->offsets = NULL;
536 Py_INCREF(self->data);
509 Py_INCREF(self->data);
537
510
538 if (self->inlined) {
511 if (self->inlined) {
539 long len = inline_scan(self, NULL);
512 long len = inline_scan(self, NULL);
540 if (len == -1)
513 if (len == -1)
541 goto bail;
514 goto bail;
542 self->raw_length = len;
515 self->raw_length = len;
543 self->length = len + 1;
516 self->length = len + 1;
544 } else {
517 } else {
545 if (size % 64) {
518 if (size % 64) {
546 PyErr_SetString(PyExc_ValueError, "corrupt index file");
519 PyErr_SetString(PyExc_ValueError, "corrupt index file");
547 goto bail;
520 goto bail;
548 }
521 }
549 self->raw_length = size / 64;
522 self->raw_length = size / 64;
550 self->length = self->raw_length + 1;
523 self->length = self->raw_length + 1;
551 }
524 }
552
525
553 return 0;
526 return 0;
554 bail:
527 bail:
555 return -1;
528 return -1;
556 }
529 }
557
530
558 static int index_init(indexObject *self, PyObject *args, PyObject *kwds)
531 static int index_init(indexObject *self, PyObject *args, PyObject *kwds)
559 {
532 {
560 const char *data;
533 const char *data;
561 int size;
534 int size;
562 PyObject *inlined_obj;
535 PyObject *inlined_obj;
563
536
564 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
537 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
565 return -1;
538 return -1;
566
539
567 return index_real_init(self, data, size, inlined_obj,
540 return index_real_init(self, data, size, inlined_obj,
568 PyTuple_GET_ITEM(args, 0));
541 PyTuple_GET_ITEM(args, 0));
569 }
542 }
570
543
571 static void index_dealloc(indexObject *self)
544 static void index_dealloc(indexObject *self)
572 {
545 {
573 _index_clearcaches(self);
546 _index_clearcaches(self);
574 Py_DECREF(self->data);
547 Py_DECREF(self->data);
575 Py_XDECREF(self->added);
548 Py_XDECREF(self->added);
576 PyObject_Del(self);
549 PyObject_Del(self);
577 }
550 }
578
551
579 static PySequenceMethods index_sequence_methods = {
552 static PySequenceMethods index_sequence_methods = {
580 (lenfunc)index_length, /* sq_length */
553 (lenfunc)index_length, /* sq_length */
581 0, /* sq_concat */
554 0, /* sq_concat */
582 0, /* sq_repeat */
555 0, /* sq_repeat */
583 (ssizeargfunc)index_get, /* sq_item */
556 (ssizeargfunc)index_get, /* sq_item */
584 };
557 };
585
558
586 static PyMappingMethods index_mapping_methods = {
559 static PyMappingMethods index_mapping_methods = {
587 (lenfunc)index_length, /* mp_length */
560 (lenfunc)index_length, /* mp_length */
588 NULL, /* mp_subscript */
561 NULL, /* mp_subscript */
589 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
562 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
590 };
563 };
591
564
592 static PyMethodDef index_methods[] = {
565 static PyMethodDef index_methods[] = {
593 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
566 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
594 "clear the index caches"},
567 "clear the index caches"},
595 {"insert", (PyCFunction)index_insert, METH_VARARGS,
568 {"insert", (PyCFunction)index_insert, METH_VARARGS,
596 "insert an index entry"},
569 "insert an index entry"},
597 {NULL} /* Sentinel */
570 {NULL} /* Sentinel */
598 };
571 };
599
572
600 static PyTypeObject indexType = {
573 static PyTypeObject indexType = {
601 PyObject_HEAD_INIT(NULL)
574 PyObject_HEAD_INIT(NULL)
602 0, /* ob_size */
575 0, /* ob_size */
603 "parsers.index", /* tp_name */
576 "parsers.index", /* tp_name */
604 sizeof(indexObject), /* tp_basicsize */
577 sizeof(indexObject), /* tp_basicsize */
605 0, /* tp_itemsize */
578 0, /* tp_itemsize */
606 (destructor)index_dealloc, /* tp_dealloc */
579 (destructor)index_dealloc, /* tp_dealloc */
607 0, /* tp_print */
580 0, /* tp_print */
608 0, /* tp_getattr */
581 0, /* tp_getattr */
609 0, /* tp_setattr */
582 0, /* tp_setattr */
610 0, /* tp_compare */
583 0, /* tp_compare */
611 0, /* tp_repr */
584 0, /* tp_repr */
612 0, /* tp_as_number */
585 0, /* tp_as_number */
613 &index_sequence_methods, /* tp_as_sequence */
586 &index_sequence_methods, /* tp_as_sequence */
614 &index_mapping_methods, /* tp_as_mapping */
587 &index_mapping_methods, /* tp_as_mapping */
615 0, /* tp_hash */
588 0, /* tp_hash */
616 0, /* tp_call */
589 0, /* tp_call */
617 0, /* tp_str */
590 0, /* tp_str */
618 0, /* tp_getattro */
591 0, /* tp_getattro */
619 0, /* tp_setattro */
592 0, /* tp_setattro */
620 0, /* tp_as_buffer */
593 0, /* tp_as_buffer */
621 Py_TPFLAGS_DEFAULT, /* tp_flags */
594 Py_TPFLAGS_DEFAULT, /* tp_flags */
622 "revlog index", /* tp_doc */
595 "revlog index", /* tp_doc */
623 0, /* tp_traverse */
596 0, /* tp_traverse */
624 0, /* tp_clear */
597 0, /* tp_clear */
625 0, /* tp_richcompare */
598 0, /* tp_richcompare */
626 0, /* tp_weaklistoffset */
599 0, /* tp_weaklistoffset */
627 0, /* tp_iter */
600 0, /* tp_iter */
628 0, /* tp_iternext */
601 0, /* tp_iternext */
629 index_methods, /* tp_methods */
602 index_methods, /* tp_methods */
630 0, /* tp_members */
603 0, /* tp_members */
631 0, /* tp_getset */
604 0, /* tp_getset */
632 0, /* tp_base */
605 0, /* tp_base */
633 0, /* tp_dict */
606 0, /* tp_dict */
634 0, /* tp_descr_get */
607 0, /* tp_descr_get */
635 0, /* tp_descr_set */
608 0, /* tp_descr_set */
636 0, /* tp_dictoffset */
609 0, /* tp_dictoffset */
637 (initproc)index_init, /* tp_init */
610 (initproc)index_init, /* tp_init */
638 0, /* tp_alloc */
611 0, /* tp_alloc */
639 PyType_GenericNew, /* tp_new */
612 PyType_GenericNew, /* tp_new */
640 };
613 };
641
614
642 /*
615 /*
643 * returns a tuple of the form (index, None, cache) with elements as
616 * returns a tuple of the form (index, None, cache) with elements as
644 * follows:
617 * follows:
645 *
618 *
646 * index: an index object that lazily parses the RevlogNG records
619 * index: an index object that lazily parses the RevlogNG records
647 * cache: if data is inlined, a tuple (index_file_content, 0), else None
620 * cache: if data is inlined, a tuple (index_file_content, 0), else None
648 *
621 *
649 * added complications are for backwards compatibility
622 * added complications are for backwards compatibility
650 */
623 */
651 static PyObject *parse_index2(PyObject *self, PyObject *args)
624 static PyObject *parse_index2(PyObject *self, PyObject *args)
652 {
625 {
653 const char *data;
626 const char *data;
654 int size, ret;
627 int size, ret;
655 PyObject *inlined_obj, *tuple = NULL, *cache = NULL;
628 PyObject *inlined_obj, *tuple = NULL, *cache = NULL;
656 indexObject *idx;
629 indexObject *idx;
657
630
658 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
631 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
659 return NULL;
632 return NULL;
660
633
661 idx = PyObject_New(indexObject, &indexType);
634 idx = PyObject_New(indexObject, &indexType);
662
635
663 if (idx == NULL)
636 if (idx == NULL)
664 goto bail;
637 goto bail;
665
638
666 ret = index_real_init(idx, data, size, inlined_obj,
639 ret = index_real_init(idx, data, size, inlined_obj,
667 PyTuple_GET_ITEM(args, 0));
640 PyTuple_GET_ITEM(args, 0));
668 if (ret)
641 if (ret)
669 goto bail;
642 goto bail;
670
643
671 if (idx->inlined) {
644 if (idx->inlined) {
672 Py_INCREF(idx->data);
645 Py_INCREF(idx->data);
673 cache = Py_BuildValue("iO", 0, idx->data);
646 cache = Py_BuildValue("iO", 0, idx->data);
674 if (cache == NULL)
647 if (cache == NULL)
675 goto bail;
648 goto bail;
676 } else {
649 } else {
677 cache = Py_None;
650 cache = Py_None;
678 Py_INCREF(cache);
651 Py_INCREF(cache);
679 }
652 }
680
653
681 tuple = Py_BuildValue("NN", idx, cache);
654 tuple = Py_BuildValue("NN", idx, cache);
682 if (!tuple)
655 if (!tuple)
683 goto bail;
656 goto bail;
684 return tuple;
657 return tuple;
685
658
686 bail:
659 bail:
687 Py_XDECREF(idx);
660 Py_XDECREF(idx);
688 Py_XDECREF(cache);
661 Py_XDECREF(cache);
689 Py_XDECREF(tuple);
662 Py_XDECREF(tuple);
690 return NULL;
663 return NULL;
691 }
664 }
692
665
693 static char parsers_doc[] = "Efficient content parsing.";
666 static char parsers_doc[] = "Efficient content parsing.";
694
667
695 static PyMethodDef methods[] = {
668 static PyMethodDef methods[] = {
696 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
669 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
697 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
670 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
698 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
671 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
699 {NULL, NULL}
672 {NULL, NULL}
700 };
673 };
701
674
702 static void module_init(PyObject *mod)
675 static void module_init(PyObject *mod)
703 {
676 {
704 static const char nullid[20];
677 static const char nullid[20];
705
678
706 if (PyType_Ready(&indexType) < 0)
679 if (PyType_Ready(&indexType) < 0)
707 return;
680 return;
708 Py_INCREF(&indexType);
681 Py_INCREF(&indexType);
709
682
710 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
683 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
711
684
712 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
685 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
713 -1, -1, -1, -1, nullid, 20);
686 -1, -1, -1, -1, nullid, 20);
714 if (nullentry)
687 if (nullentry)
715 PyObject_GC_UnTrack(nullentry);
688 PyObject_GC_UnTrack(nullentry);
716 }
689 }
717
690
718 #ifdef IS_PY3K
691 #ifdef IS_PY3K
719 static struct PyModuleDef parsers_module = {
692 static struct PyModuleDef parsers_module = {
720 PyModuleDef_HEAD_INIT,
693 PyModuleDef_HEAD_INIT,
721 "parsers",
694 "parsers",
722 parsers_doc,
695 parsers_doc,
723 -1,
696 -1,
724 methods
697 methods
725 };
698 };
726
699
727 PyMODINIT_FUNC PyInit_parsers(void)
700 PyMODINIT_FUNC PyInit_parsers(void)
728 {
701 {
729 PyObject *mod = PyModule_Create(&parsers_module);
702 PyObject *mod = PyModule_Create(&parsers_module);
730 module_init(mod);
703 module_init(mod);
731 return mod;
704 return mod;
732 }
705 }
733 #else
706 #else
734 PyMODINIT_FUNC initparsers(void)
707 PyMODINIT_FUNC initparsers(void)
735 {
708 {
736 PyObject *mod = Py_InitModule3("parsers", methods, parsers_doc);
709 PyObject *mod = Py_InitModule3("parsers", methods, parsers_doc);
737 module_init(mod);
710 module_init(mod);
738 }
711 }
739 #endif
712 #endif
740
713
@@ -1,116 +1,151 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 #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 #if !defined(PY_SSIZE_T_MIN)
110 #if !defined(PY_SSIZE_T_MIN)
111 #define PY_SSIZE_T_MAX INT_MAX
111 #define PY_SSIZE_T_MAX INT_MAX
112 #define PY_SSIZE_T_MIN INT_MIN
112 #define PY_SSIZE_T_MIN INT_MIN
113 #endif
113 #endif
114 #endif
114 #endif
115
115
116 #ifdef _WIN32
117 #ifdef _MSC_VER
118 /* msvc 6.0 has problems */
119 #define inline __inline
120 typedef unsigned long uint32_t;
121 typedef unsigned __int64 uint64_t;
122 #else
123 #include <stdint.h>
124 #endif
125 static uint32_t ntohl(uint32_t x)
126 {
127 return ((x & 0x000000ffUL) << 24) |
128 ((x & 0x0000ff00UL) << 8) |
129 ((x & 0x00ff0000UL) >> 8) |
130 ((x & 0xff000000UL) >> 24);
131 }
132 #else
133 /* not windows */
134 #include <sys/types.h>
135 #if defined __BEOS__ && !defined __HAIKU__
136 #include <ByteOrder.h>
137 #else
138 #include <arpa/inet.h>
139 #endif
140 #include <inttypes.h>
141 #endif
142
143 #if defined __hpux || defined __SUNPRO_C || defined _AIX
144 #define inline
145 #endif
146
147 #ifdef __linux
148 #define inline __inline
149 #endif
150
116 #endif /* _HG_UTIL_H_ */
151 #endif /* _HG_UTIL_H_ */
General Comments 0
You need to be logged in to leave comments. Login now