##// END OF EJS Templates
xdiff: remove unused structure, functions, and constants...
Jun Wu -
r36780:b5bb0f99 default
parent child Browse files
Show More
@@ -1,352 +1,350 b''
1 1 /*
2 2 bdiff.c - efficient binary diff extension for Mercurial
3 3
4 4 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8
9 9 Based roughly on Python difflib
10 10 */
11 11
12 12 #define PY_SSIZE_T_CLEAN
13 13 #include <Python.h>
14 14 #include <limits.h>
15 15 #include <stdlib.h>
16 16 #include <string.h>
17 17
18 18 #include "bdiff.h"
19 19 #include "bitmanipulation.h"
20 20 #include "thirdparty/xdiff/xdiff.h"
21 21 #include "util.h"
22 22
23 23 static PyObject *blocks(PyObject *self, PyObject *args)
24 24 {
25 25 PyObject *sa, *sb, *rl = NULL, *m;
26 26 struct bdiff_line *a, *b;
27 27 struct bdiff_hunk l, *h;
28 28 int an, bn, count, pos = 0;
29 29
30 30 l.next = NULL;
31 31
32 32 if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb))
33 33 return NULL;
34 34
35 35 an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a);
36 36 bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b);
37 37
38 38 if (!a || !b)
39 39 goto nomem;
40 40
41 41 count = bdiff_diff(a, an, b, bn, &l);
42 42 if (count < 0)
43 43 goto nomem;
44 44
45 45 rl = PyList_New(count);
46 46 if (!rl)
47 47 goto nomem;
48 48
49 49 for (h = l.next; h; h = h->next) {
50 50 m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2);
51 51 PyList_SetItem(rl, pos, m);
52 52 pos++;
53 53 }
54 54
55 55 nomem:
56 56 free(a);
57 57 free(b);
58 58 bdiff_freehunks(l.next);
59 59 return rl ? rl : PyErr_NoMemory();
60 60 }
61 61
62 62 static PyObject *bdiff(PyObject *self, PyObject *args)
63 63 {
64 64 Py_buffer ba, bb;
65 65 char *rb, *ia, *ib;
66 66 PyObject *result = NULL;
67 67 struct bdiff_line *al = NULL, *bl = NULL;
68 68 struct bdiff_hunk l, *h;
69 69 int an, bn, count;
70 70 Py_ssize_t len = 0, la, lb, li = 0, lcommon = 0, lmax;
71 71 PyThreadState *_save = NULL;
72 72
73 73 l.next = NULL;
74 74
75 75 if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, &bb))
76 76 return NULL;
77 77
78 78 if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) {
79 79 PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
80 80 goto cleanup;
81 81 }
82 82
83 83 if (!PyBuffer_IsContiguous(&bb, 'C') || bb.ndim > 1) {
84 84 PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
85 85 goto cleanup;
86 86 }
87 87
88 88 la = ba.len;
89 89 lb = bb.len;
90 90
91 91 if (la > UINT_MAX || lb > UINT_MAX) {
92 92 PyErr_SetString(PyExc_ValueError, "bdiff inputs too large");
93 93 goto cleanup;
94 94 }
95 95
96 96 _save = PyEval_SaveThread();
97 97
98 98 lmax = la > lb ? lb : la;
99 99 for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib;
100 100 ++li, ++ia, ++ib) {
101 101 if (*ia == '\n')
102 102 lcommon = li + 1;
103 103 }
104 104 /* we can almost add: if (li == lmax) lcommon = li; */
105 105
106 106 an = bdiff_splitlines((char *)ba.buf + lcommon, la - lcommon, &al);
107 107 bn = bdiff_splitlines((char *)bb.buf + lcommon, lb - lcommon, &bl);
108 108 if (!al || !bl) {
109 109 PyErr_NoMemory();
110 110 goto cleanup;
111 111 }
112 112
113 113 count = bdiff_diff(al, an, bl, bn, &l);
114 114 if (count < 0) {
115 115 PyErr_NoMemory();
116 116 goto cleanup;
117 117 }
118 118
119 119 /* calculate length of output */
120 120 la = lb = 0;
121 121 for (h = l.next; h; h = h->next) {
122 122 if (h->a1 != la || h->b1 != lb)
123 123 len += 12 + bl[h->b1].l - bl[lb].l;
124 124 la = h->a2;
125 125 lb = h->b2;
126 126 }
127 127 PyEval_RestoreThread(_save);
128 128 _save = NULL;
129 129
130 130 result = PyBytes_FromStringAndSize(NULL, len);
131 131
132 132 if (!result)
133 133 goto cleanup;
134 134
135 135 /* build binary patch */
136 136 rb = PyBytes_AsString(result);
137 137 la = lb = 0;
138 138
139 139 for (h = l.next; h; h = h->next) {
140 140 if (h->a1 != la || h->b1 != lb) {
141 141 len = bl[h->b1].l - bl[lb].l;
142 142 putbe32((uint32_t)(al[la].l + lcommon - al->l), rb);
143 143 putbe32((uint32_t)(al[h->a1].l + lcommon - al->l),
144 144 rb + 4);
145 145 putbe32((uint32_t)len, rb + 8);
146 146 memcpy(rb + 12, bl[lb].l, len);
147 147 rb += 12 + len;
148 148 }
149 149 la = h->a2;
150 150 lb = h->b2;
151 151 }
152 152
153 153 cleanup:
154 154 if (_save)
155 155 PyEval_RestoreThread(_save);
156 156 PyBuffer_Release(&ba);
157 157 PyBuffer_Release(&bb);
158 158 if (al) {
159 159 free(al);
160 160 }
161 161 if (bl) {
162 162 free(bl);
163 163 }
164 164 if (l.next) {
165 165 bdiff_freehunks(l.next);
166 166 }
167 167 return result;
168 168 }
169 169
170 170 /*
171 171 * If allws != 0, remove all whitespace (' ', \t and \r). Otherwise,
172 172 * reduce whitespace sequences to a single space and trim remaining whitespace
173 173 * from end of lines.
174 174 */
175 175 static PyObject *fixws(PyObject *self, PyObject *args)
176 176 {
177 177 PyObject *s, *result = NULL;
178 178 char allws, c;
179 179 const char *r;
180 180 Py_ssize_t i, rlen, wlen = 0;
181 181 char *w;
182 182
183 183 if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws))
184 184 return NULL;
185 185 r = PyBytes_AsString(s);
186 186 rlen = PyBytes_Size(s);
187 187
188 188 w = (char *)PyMem_Malloc(rlen ? rlen : 1);
189 189 if (!w)
190 190 goto nomem;
191 191
192 192 for (i = 0; i != rlen; i++) {
193 193 c = r[i];
194 194 if (c == ' ' || c == '\t' || c == '\r') {
195 195 if (!allws && (wlen == 0 || w[wlen - 1] != ' '))
196 196 w[wlen++] = ' ';
197 197 } else if (c == '\n' && !allws && wlen > 0 &&
198 198 w[wlen - 1] == ' ') {
199 199 w[wlen - 1] = '\n';
200 200 } else {
201 201 w[wlen++] = c;
202 202 }
203 203 }
204 204
205 205 result = PyBytes_FromStringAndSize(w, wlen);
206 206
207 207 nomem:
208 208 PyMem_Free(w);
209 209 return result ? result : PyErr_NoMemory();
210 210 }
211 211
212 212 static bool sliceintolist(PyObject *list, Py_ssize_t destidx,
213 213 const char *source, Py_ssize_t len)
214 214 {
215 215 PyObject *sliced = PyBytes_FromStringAndSize(source, len);
216 216 if (sliced == NULL)
217 217 return false;
218 218 PyList_SET_ITEM(list, destidx, sliced);
219 219 return true;
220 220 }
221 221
222 222 static PyObject *splitnewlines(PyObject *self, PyObject *args)
223 223 {
224 224 const char *text;
225 225 Py_ssize_t nelts = 0, size, i, start = 0;
226 226 PyObject *result = NULL;
227 227
228 228 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &size)) {
229 229 goto abort;
230 230 }
231 231 if (!size) {
232 232 return PyList_New(0);
233 233 }
234 234 /* This loops to size-1 because if the last byte is a newline,
235 235 * we don't want to perform a split there. */
236 236 for (i = 0; i < size - 1; ++i) {
237 237 if (text[i] == '\n') {
238 238 ++nelts;
239 239 }
240 240 }
241 241 if ((result = PyList_New(nelts + 1)) == NULL)
242 242 goto abort;
243 243 nelts = 0;
244 244 for (i = 0; i < size - 1; ++i) {
245 245 if (text[i] == '\n') {
246 246 if (!sliceintolist(result, nelts++, text + start,
247 247 i - start + 1))
248 248 goto abort;
249 249 start = i + 1;
250 250 }
251 251 }
252 252 if (!sliceintolist(result, nelts++, text + start, size - start))
253 253 goto abort;
254 254 return result;
255 255 abort:
256 256 Py_XDECREF(result);
257 257 return NULL;
258 258 }
259 259
260 260 static int hunk_consumer(long a1, long a2, long b1, long b2, void *priv)
261 261 {
262 262 PyObject *rl = (PyObject *)priv;
263 263 PyObject *m = Py_BuildValue("llll", a1, a2, b1, b2);
264 264 if (!m)
265 265 return -1;
266 266 if (PyList_Append(rl, m) != 0) {
267 267 Py_DECREF(m);
268 268 return -1;
269 269 }
270 270 return 0;
271 271 }
272 272
273 273 static PyObject *xdiffblocks(PyObject *self, PyObject *args)
274 274 {
275 275 Py_ssize_t la, lb;
276 276 mmfile_t a, b;
277 277 PyObject *rl;
278 278
279 279 xpparam_t xpp = {
280 280 XDF_INDENT_HEURISTIC, /* flags */
281 NULL, /* anchors */
282 0, /* anchors_nr */
283 281 };
284 282 xdemitconf_t xecfg = {
285 283 0, /* ctxlen */
286 284 0, /* interhunkctxlen */
287 285 XDL_EMIT_BDIFFHUNK, /* flags */
288 286 NULL, /* find_func */
289 287 NULL, /* find_func_priv */
290 288 hunk_consumer, /* hunk_consume_func */
291 289 };
292 290 xdemitcb_t ecb = {
293 291 NULL, /* priv */
294 292 NULL, /* outf */
295 293 };
296 294
297 295 if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr,
298 296 &lb))
299 297 return NULL;
300 298
301 299 a.size = la;
302 300 b.size = lb;
303 301
304 302 rl = PyList_New(0);
305 303 if (!rl)
306 304 return PyErr_NoMemory();
307 305
308 306 ecb.priv = rl;
309 307
310 308 if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) {
311 309 Py_DECREF(rl);
312 310 return PyErr_NoMemory();
313 311 }
314 312
315 313 return rl;
316 314 }
317 315
318 316 static char mdiff_doc[] = "Efficient binary diff.";
319 317
320 318 static PyMethodDef methods[] = {
321 319 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"},
322 320 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"},
323 321 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"},
324 322 {"splitnewlines", splitnewlines, METH_VARARGS,
325 323 "like str.splitlines, but only split on newlines\n"},
326 324 {"xdiffblocks", xdiffblocks, METH_VARARGS,
327 325 "find a list of matching lines using xdiff algorithm\n"},
328 326 {NULL, NULL},
329 327 };
330 328
331 329 static const int version = 3;
332 330
333 331 #ifdef IS_PY3K
334 332 static struct PyModuleDef bdiff_module = {
335 333 PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods,
336 334 };
337 335
338 336 PyMODINIT_FUNC PyInit_bdiff(void)
339 337 {
340 338 PyObject *m;
341 339 m = PyModule_Create(&bdiff_module);
342 340 PyModule_AddIntConstant(m, "version", version);
343 341 return m;
344 342 }
345 343 #else
346 344 PyMODINIT_FUNC initbdiff(void)
347 345 {
348 346 PyObject *m;
349 347 m = Py_InitModule3("bdiff", methods, mdiff_doc);
350 348 PyModule_AddIntConstant(m, "version", version);
351 349 }
352 350 #endif
@@ -1,139 +1,123 b''
1 1 /*
2 2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 3 * Copyright (C) 2003 Davide Libenzi
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * You should have received a copy of the GNU Lesser General Public
16 16 * License along with this library; if not, see
17 17 * <http://www.gnu.org/licenses/>.
18 18 *
19 19 * Davide Libenzi <davidel@xmailserver.org>
20 20 *
21 21 */
22 22
23 23 #if !defined(XDIFF_H)
24 24 #define XDIFF_H
25 25
26 26 #ifdef __cplusplus
27 27 extern "C" {
28 28 #endif /* #ifdef __cplusplus */
29 29
30 30 #include <stddef.h> /* size_t */
31 31
32 32 /* xpparm_t.flags */
33 33 #define XDF_NEED_MINIMAL (1 << 0)
34 34
35 35 #define XDF_INDENT_HEURISTIC (1 << 23)
36 36
37 37 /* xdemitconf_t.flags */
38 38 #define XDL_EMIT_FUNCNAMES (1 << 0)
39 39 #define XDL_EMIT_FUNCCONTEXT (1 << 2)
40 40 /* emit bdiff-style "matched" (a1, a2, b1, b2) hunks instead of "different"
41 41 * (a1, a2 - a1, b1, b2 - b1) hunks */
42 42 #define XDL_EMIT_BDIFFHUNK (1 << 4)
43 43
44 #define XDL_MMB_READONLY (1 << 0)
45
46 #define XDL_MMF_ATOMIC (1 << 0)
47
48 #define XDL_BDOP_INS 1
49 #define XDL_BDOP_CPY 2
50 #define XDL_BDOP_INSB 3
51
52 44 /* merge simplification levels */
53 45 #define XDL_MERGE_MINIMAL 0
54 46 #define XDL_MERGE_EAGER 1
55 47 #define XDL_MERGE_ZEALOUS 2
56 48 #define XDL_MERGE_ZEALOUS_ALNUM 3
57 49
58 50 /* merge favor modes */
59 51 #define XDL_MERGE_FAVOR_OURS 1
60 52 #define XDL_MERGE_FAVOR_THEIRS 2
61 53 #define XDL_MERGE_FAVOR_UNION 3
62 54
63 55 /* merge output styles */
64 56 #define XDL_MERGE_DIFF3 1
65 57
66 58 typedef struct s_mmfile {
67 59 char *ptr;
68 60 long size;
69 61 } mmfile_t;
70 62
71 63 typedef struct s_mmbuffer {
72 64 char *ptr;
73 65 long size;
74 66 } mmbuffer_t;
75 67
76 68 typedef struct s_xpparam {
77 69 unsigned long flags;
78
79 /* See Documentation/diff-options.txt. */
80 char **anchors;
81 size_t anchors_nr;
82 70 } xpparam_t;
83 71
84 72 typedef struct s_xdemitcb {
85 73 void *priv;
86 74 int (*outf)(void *, mmbuffer_t *, int);
87 75 } xdemitcb_t;
88 76
89 77 typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
90 78
91 79 typedef int (*xdl_emit_hunk_consume_func_t)(long start_a, long count_a,
92 80 long start_b, long count_b,
93 81 void *cb_data);
94 82
95 83 typedef struct s_xdemitconf {
96 84 long ctxlen;
97 85 long interhunkctxlen;
98 86 unsigned long flags;
99 87 find_func_t find_func;
100 88 void *find_func_priv;
101 89 xdl_emit_hunk_consume_func_t hunk_func;
102 90 } xdemitconf_t;
103 91
104 typedef struct s_bdiffparam {
105 long bsize;
106 } bdiffparam_t;
107
108 92
109 93 #define xdl_malloc(x) malloc(x)
110 94 #define xdl_free(ptr) free(ptr)
111 95 #define xdl_realloc(ptr,x) realloc(ptr,x)
112 96
113 97 void *xdl_mmfile_first(mmfile_t *mmf, long *size);
114 98 long xdl_mmfile_size(mmfile_t *mmf);
115 99
116 100 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
117 101 xdemitconf_t const *xecfg, xdemitcb_t *ecb);
118 102
119 103 typedef struct s_xmparam {
120 104 xpparam_t xpp;
121 105 int marker_size;
122 106 int level;
123 107 int favor;
124 108 int style;
125 109 const char *ancestor; /* label for orig */
126 110 const char *file1; /* label for mf1 */
127 111 const char *file2; /* label for mf2 */
128 112 } xmparam_t;
129 113
130 114 #define DEFAULT_CONFLICT_MARKER_SIZE 7
131 115
132 116 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
133 117 xmparam_t const *xmp, mmbuffer_t *result);
134 118
135 119 #ifdef __cplusplus
136 120 }
137 121 #endif /* #ifdef __cplusplus */
138 122
139 123 #endif /* #if !defined(XDIFF_H) */
@@ -1,64 +1,60 b''
1 1 /*
2 2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 3 * Copyright (C) 2003 Davide Libenzi
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * You should have received a copy of the GNU Lesser General Public
16 16 * License along with this library; if not, see
17 17 * <http://www.gnu.org/licenses/>.
18 18 *
19 19 * Davide Libenzi <davidel@xmailserver.org>
20 20 *
21 21 */
22 22
23 23 #if !defined(XDIFFI_H)
24 24 #define XDIFFI_H
25 25
26 26
27 27 typedef struct s_diffdata {
28 28 long nrec;
29 29 unsigned long const *ha;
30 30 long *rindex;
31 31 char *rchg;
32 32 } diffdata_t;
33 33
34 34 typedef struct s_xdalgoenv {
35 35 long mxcost;
36 36 long snake_cnt;
37 37 long heur_min;
38 38 } xdalgoenv_t;
39 39
40 40 typedef struct s_xdchange {
41 41 struct s_xdchange *next;
42 42 long i1, i2;
43 43 long chg1, chg2;
44 44 int ignore;
45 45 } xdchange_t;
46 46
47 47
48 48
49 49 int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
50 50 diffdata_t *dd2, long off2, long lim2,
51 51 long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv);
52 52 int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
53 53 xdfenv_t *xe);
54 54 int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags);
55 55 int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr);
56 56 void xdl_free_script(xdchange_t *xscr);
57 57 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
58 58 xdemitconf_t const *xecfg);
59 int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
60 xdfenv_t *env);
61 int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
62 xdfenv_t *env);
63 59
64 60 #endif /* #if !defined(XDIFFI_H) */
@@ -1,274 +1,243 b''
1 1 /*
2 2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 3 * Copyright (C) 2003 Davide Libenzi
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * You should have received a copy of the GNU Lesser General Public
16 16 * License along with this library; if not, see
17 17 * <http://www.gnu.org/licenses/>.
18 18 *
19 19 * Davide Libenzi <davidel@xmailserver.org>
20 20 *
21 21 */
22 22
23 23 #include <limits.h>
24 24 #include <assert.h>
25 25 #include "xinclude.h"
26 26
27 27
28 28
29 29
30 30 long xdl_bogosqrt(long n) {
31 31 long i;
32 32
33 33 /*
34 34 * Classical integer square root approximation using shifts.
35 35 */
36 36 for (i = 1; n > 0; n >>= 2)
37 37 i <<= 1;
38 38
39 39 return i;
40 40 }
41 41
42 42
43 43 int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
44 44 xdemitcb_t *ecb) {
45 45 int i = 2;
46 46 mmbuffer_t mb[3];
47 47
48 48 mb[0].ptr = (char *) pre;
49 49 mb[0].size = psize;
50 50 mb[1].ptr = (char *) rec;
51 51 mb[1].size = size;
52 52 if (size > 0 && rec[size - 1] != '\n') {
53 53 mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
54 54 mb[2].size = strlen(mb[2].ptr);
55 55 i++;
56 56 }
57 57 if (ecb->outf(ecb->priv, mb, i) < 0) {
58 58
59 59 return -1;
60 60 }
61 61
62 62 return 0;
63 63 }
64 64
65 65 void *xdl_mmfile_first(mmfile_t *mmf, long *size)
66 66 {
67 67 *size = mmf->size;
68 68 return mmf->ptr;
69 69 }
70 70
71 71
72 72 long xdl_mmfile_size(mmfile_t *mmf)
73 73 {
74 74 return mmf->size;
75 75 }
76 76
77 77
78 78 int xdl_cha_init(chastore_t *cha, long isize, long icount) {
79 79
80 80 cha->head = cha->tail = NULL;
81 81 cha->isize = isize;
82 82 cha->nsize = icount * isize;
83 83 cha->ancur = cha->sncur = NULL;
84 84 cha->scurr = 0;
85 85
86 86 return 0;
87 87 }
88 88
89 89
90 90 void xdl_cha_free(chastore_t *cha) {
91 91 chanode_t *cur, *tmp;
92 92
93 93 for (cur = cha->head; (tmp = cur) != NULL;) {
94 94 cur = cur->next;
95 95 xdl_free(tmp);
96 96 }
97 97 }
98 98
99 99
100 100 void *xdl_cha_alloc(chastore_t *cha) {
101 101 chanode_t *ancur;
102 102 void *data;
103 103
104 104 if (!(ancur = cha->ancur) || ancur->icurr == cha->nsize) {
105 105 if (!(ancur = (chanode_t *) xdl_malloc(sizeof(chanode_t) + cha->nsize))) {
106 106
107 107 return NULL;
108 108 }
109 109 ancur->icurr = 0;
110 110 ancur->next = NULL;
111 111 if (cha->tail)
112 112 cha->tail->next = ancur;
113 113 if (!cha->head)
114 114 cha->head = ancur;
115 115 cha->tail = ancur;
116 116 cha->ancur = ancur;
117 117 }
118 118
119 119 data = (char *) ancur + sizeof(chanode_t) + ancur->icurr;
120 120 ancur->icurr += cha->isize;
121 121
122 122 return data;
123 123 }
124 124
125 125 long xdl_guess_lines(mmfile_t *mf, long sample) {
126 126 long nl = 0, size, tsize = 0;
127 127 char const *data, *cur, *top;
128 128
129 129 if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) {
130 130 for (top = data + size; nl < sample && cur < top; ) {
131 131 nl++;
132 132 if (!(cur = memchr(cur, '\n', top - cur)))
133 133 cur = top;
134 134 else
135 135 cur++;
136 136 }
137 137 tsize += (long) (cur - data);
138 138 }
139 139
140 140 if (nl && tsize)
141 141 nl = xdl_mmfile_size(mf) / (tsize / nl);
142 142
143 143 return nl + 1;
144 144 }
145 145
146 146 int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
147 147 {
148 148 if (s1 == s2 && !memcmp(l1, l2, s1))
149 149 return 1;
150 150 return 0;
151 151 }
152 152
153 153 unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
154 154 unsigned long ha = 5381;
155 155 char const *ptr = *data;
156 156
157 157 for (; ptr < top && *ptr != '\n'; ptr++) {
158 158 ha += (ha << 5);
159 159 ha ^= (unsigned long) *ptr;
160 160 }
161 161 *data = ptr < top ? ptr + 1: ptr;
162 162
163 163 return ha;
164 164 }
165 165
166 166 unsigned int xdl_hashbits(unsigned int size) {
167 167 unsigned int val = 1, bits = 0;
168 168
169 169 for (; val < size && bits < CHAR_BIT * sizeof(unsigned int); val <<= 1, bits++);
170 170 return bits ? bits: 1;
171 171 }
172 172
173 173
174 174 int xdl_num_out(char *out, long val) {
175 175 char *ptr, *str = out;
176 176 char buf[32];
177 177
178 178 ptr = buf + sizeof(buf) - 1;
179 179 *ptr = '\0';
180 180 if (val < 0) {
181 181 *--ptr = '-';
182 182 val = -val;
183 183 }
184 184 for (; val && ptr > buf; val /= 10)
185 185 *--ptr = "0123456789"[val % 10];
186 186 if (*ptr)
187 187 for (; *ptr; ptr++, str++)
188 188 *str = *ptr;
189 189 else
190 190 *str++ = '0';
191 191 *str = '\0';
192 192
193 193 return str - out;
194 194 }
195 195
196 196 int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
197 197 const char *func, long funclen, xdemitcb_t *ecb) {
198 198 int nb = 0;
199 199 mmbuffer_t mb;
200 200 char buf[128];
201 201
202 202 memcpy(buf, "@@ -", 4);
203 203 nb += 4;
204 204
205 205 nb += xdl_num_out(buf + nb, c1 ? s1: s1 - 1);
206 206
207 207 if (c1 != 1) {
208 208 memcpy(buf + nb, ",", 1);
209 209 nb += 1;
210 210
211 211 nb += xdl_num_out(buf + nb, c1);
212 212 }
213 213
214 214 memcpy(buf + nb, " +", 2);
215 215 nb += 2;
216 216
217 217 nb += xdl_num_out(buf + nb, c2 ? s2: s2 - 1);
218 218
219 219 if (c2 != 1) {
220 220 memcpy(buf + nb, ",", 1);
221 221 nb += 1;
222 222
223 223 nb += xdl_num_out(buf + nb, c2);
224 224 }
225 225
226 226 memcpy(buf + nb, " @@", 3);
227 227 nb += 3;
228 228 if (func && funclen) {
229 229 buf[nb++] = ' ';
230 230 if (funclen > sizeof(buf) - nb - 1)
231 231 funclen = sizeof(buf) - nb - 1;
232 232 memcpy(buf + nb, func, funclen);
233 233 nb += funclen;
234 234 }
235 235 buf[nb++] = '\n';
236 236
237 237 mb.ptr = buf;
238 238 mb.size = nb;
239 239 if (ecb->outf(ecb->priv, &mb, 1) < 0)
240 240 return -1;
241 241
242 242 return 0;
243 243 }
244
245 int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
246 int line1, int count1, int line2, int count2)
247 {
248 /*
249 * This probably does not work outside Git, since
250 * we have a very simple mmfile structure.
251 *
252 * Note: ideally, we would reuse the prepared environment, but
253 * the libxdiff interface does not (yet) allow for diffing only
254 * ranges of lines instead of the whole files.
255 */
256 mmfile_t subfile1, subfile2;
257 xdfenv_t env;
258
259 subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1]->ptr;
260 subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2]->ptr +
261 diff_env->xdf1.recs[line1 + count1 - 2]->size - subfile1.ptr;
262 subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1]->ptr;
263 subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2]->ptr +
264 diff_env->xdf2.recs[line2 + count2 - 2]->size - subfile2.ptr;
265 if (xdl_do_diff(&subfile1, &subfile2, xpp, &env) < 0)
266 return -1;
267
268 memcpy(diff_env->xdf1.rchg + line1 - 1, env.xdf1.rchg, count1);
269 memcpy(diff_env->xdf2.rchg + line2 - 1, env.xdf2.rchg, count2);
270
271 xdl_free_env(&env);
272
273 return 0;
274 }
@@ -1,46 +1,44 b''
1 1 /*
2 2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 3 * Copyright (C) 2003 Davide Libenzi
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * You should have received a copy of the GNU Lesser General Public
16 16 * License along with this library; if not, see
17 17 * <http://www.gnu.org/licenses/>.
18 18 *
19 19 * Davide Libenzi <davidel@xmailserver.org>
20 20 *
21 21 */
22 22
23 23 #if !defined(XUTILS_H)
24 24 #define XUTILS_H
25 25
26 26
27 27
28 28 long xdl_bogosqrt(long n);
29 29 int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
30 30 xdemitcb_t *ecb);
31 31 int xdl_cha_init(chastore_t *cha, long isize, long icount);
32 32 void xdl_cha_free(chastore_t *cha);
33 33 void *xdl_cha_alloc(chastore_t *cha);
34 34 long xdl_guess_lines(mmfile_t *mf, long sample);
35 35 int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags);
36 36 unsigned long xdl_hash_record(char const **data, char const *top, long flags);
37 37 unsigned int xdl_hashbits(unsigned int size);
38 38 int xdl_num_out(char *out, long val);
39 39 int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
40 40 const char *func, long funclen, xdemitcb_t *ecb);
41 int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
42 int line1, int count1, int line2, int count2);
43 41
44 42
45 43
46 44 #endif /* #if !defined(XUTILS_H) */
General Comments 0
You need to be logged in to leave comments. Login now