mercurial/cext/bdiff.c
changeset 41361 763b45bc4483
parent 38784 ad76032d27da
child 46819 d4ba4d51f85f
equal deleted inserted replaced
41360:b81ca9a3f4e4 41361:763b45bc4483
    27 	struct bdiff_hunk l, *h;
    27 	struct bdiff_hunk l, *h;
    28 	int an, bn, count, pos = 0;
    28 	int an, bn, count, pos = 0;
    29 
    29 
    30 	l.next = NULL;
    30 	l.next = NULL;
    31 
    31 
    32 	if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb))
    32 	if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb)) {
    33 		return NULL;
    33 		return NULL;
       
    34 	}
    34 
    35 
    35 	an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a);
    36 	an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a);
    36 	bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b);
    37 	bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b);
    37 
    38 
    38 	if (!a || !b)
    39 	if (!a || !b) {
    39 		goto nomem;
    40 		goto nomem;
       
    41 	}
    40 
    42 
    41 	count = bdiff_diff(a, an, b, bn, &l);
    43 	count = bdiff_diff(a, an, b, bn, &l);
    42 	if (count < 0)
    44 	if (count < 0) {
    43 		goto nomem;
    45 		goto nomem;
       
    46 	}
    44 
    47 
    45 	rl = PyList_New(count);
    48 	rl = PyList_New(count);
    46 	if (!rl)
    49 	if (!rl) {
    47 		goto nomem;
    50 		goto nomem;
       
    51 	}
    48 
    52 
    49 	for (h = l.next; h; h = h->next) {
    53 	for (h = l.next; h; h = h->next) {
    50 		m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2);
    54 		m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2);
    51 		PyList_SetItem(rl, pos, m);
    55 		PyList_SetItem(rl, pos, m);
    52 		pos++;
    56 		pos++;
    70 	Py_ssize_t len = 0, la, lb, li = 0, lcommon = 0, lmax;
    74 	Py_ssize_t len = 0, la, lb, li = 0, lcommon = 0, lmax;
    71 	PyThreadState *_save = NULL;
    75 	PyThreadState *_save = NULL;
    72 
    76 
    73 	l.next = NULL;
    77 	l.next = NULL;
    74 
    78 
    75 	if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, &bb))
    79 	if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba,
       
    80 	                      &bb)) {
    76 		return NULL;
    81 		return NULL;
       
    82 	}
    77 
    83 
    78 	if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) {
    84 	if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) {
    79 		PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
    85 		PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
    80 		goto cleanup;
    86 		goto cleanup;
    81 	}
    87 	}
    96 	_save = PyEval_SaveThread();
   102 	_save = PyEval_SaveThread();
    97 
   103 
    98 	lmax = la > lb ? lb : la;
   104 	lmax = la > lb ? lb : la;
    99 	for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib;
   105 	for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib;
   100 	     ++li, ++ia, ++ib) {
   106 	     ++li, ++ia, ++ib) {
   101 		if (*ia == '\n')
   107 		if (*ia == '\n') {
   102 			lcommon = li + 1;
   108 			lcommon = li + 1;
       
   109 		}
   103 	}
   110 	}
   104 	/* we can almost add: if (li == lmax) lcommon = li; */
   111 	/* we can almost add: if (li == lmax) lcommon = li; */
   105 
   112 
   106 	an = bdiff_splitlines((char *)ba.buf + lcommon, la - lcommon, &al);
   113 	an = bdiff_splitlines((char *)ba.buf + lcommon, la - lcommon, &al);
   107 	bn = bdiff_splitlines((char *)bb.buf + lcommon, lb - lcommon, &bl);
   114 	bn = bdiff_splitlines((char *)bb.buf + lcommon, lb - lcommon, &bl);
   117 	}
   124 	}
   118 
   125 
   119 	/* calculate length of output */
   126 	/* calculate length of output */
   120 	la = lb = 0;
   127 	la = lb = 0;
   121 	for (h = l.next; h; h = h->next) {
   128 	for (h = l.next; h; h = h->next) {
   122 		if (h->a1 != la || h->b1 != lb)
   129 		if (h->a1 != la || h->b1 != lb) {
   123 			len += 12 + bl[h->b1].l - bl[lb].l;
   130 			len += 12 + bl[h->b1].l - bl[lb].l;
       
   131 		}
   124 		la = h->a2;
   132 		la = h->a2;
   125 		lb = h->b2;
   133 		lb = h->b2;
   126 	}
   134 	}
   127 	PyEval_RestoreThread(_save);
   135 	PyEval_RestoreThread(_save);
   128 	_save = NULL;
   136 	_save = NULL;
   129 
   137 
   130 	result = PyBytes_FromStringAndSize(NULL, len);
   138 	result = PyBytes_FromStringAndSize(NULL, len);
   131 
   139 
   132 	if (!result)
   140 	if (!result) {
   133 		goto cleanup;
   141 		goto cleanup;
       
   142 	}
   134 
   143 
   135 	/* build binary patch */
   144 	/* build binary patch */
   136 	rb = PyBytes_AsString(result);
   145 	rb = PyBytes_AsString(result);
   137 	la = lb = 0;
   146 	la = lb = 0;
   138 
   147 
   149 		la = h->a2;
   158 		la = h->a2;
   150 		lb = h->b2;
   159 		lb = h->b2;
   151 	}
   160 	}
   152 
   161 
   153 cleanup:
   162 cleanup:
   154 	if (_save)
   163 	if (_save) {
   155 		PyEval_RestoreThread(_save);
   164 		PyEval_RestoreThread(_save);
       
   165 	}
   156 	PyBuffer_Release(&ba);
   166 	PyBuffer_Release(&ba);
   157 	PyBuffer_Release(&bb);
   167 	PyBuffer_Release(&bb);
   158 	free(al);
   168 	free(al);
   159 	free(bl);
   169 	free(bl);
   160 	bdiff_freehunks(l.next);
   170 	bdiff_freehunks(l.next);
   172 	char allws, c;
   182 	char allws, c;
   173 	const char *r;
   183 	const char *r;
   174 	Py_ssize_t i, rlen, wlen = 0;
   184 	Py_ssize_t i, rlen, wlen = 0;
   175 	char *w;
   185 	char *w;
   176 
   186 
   177 	if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws))
   187 	if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws)) {
   178 		return NULL;
   188 		return NULL;
       
   189 	}
   179 	r = PyBytes_AsString(s);
   190 	r = PyBytes_AsString(s);
   180 	rlen = PyBytes_Size(s);
   191 	rlen = PyBytes_Size(s);
   181 
   192 
   182 	w = (char *)PyMem_Malloc(rlen ? rlen : 1);
   193 	w = (char *)PyMem_Malloc(rlen ? rlen : 1);
   183 	if (!w)
   194 	if (!w) {
   184 		goto nomem;
   195 		goto nomem;
       
   196 	}
   185 
   197 
   186 	for (i = 0; i != rlen; i++) {
   198 	for (i = 0; i != rlen; i++) {
   187 		c = r[i];
   199 		c = r[i];
   188 		if (c == ' ' || c == '\t' || c == '\r') {
   200 		if (c == ' ' || c == '\t' || c == '\r') {
   189 			if (!allws && (wlen == 0 || w[wlen - 1] != ' '))
   201 			if (!allws && (wlen == 0 || w[wlen - 1] != ' ')) {
   190 				w[wlen++] = ' ';
   202 				w[wlen++] = ' ';
       
   203 			}
   191 		} else if (c == '\n' && !allws && wlen > 0 &&
   204 		} else if (c == '\n' && !allws && wlen > 0 &&
   192 		           w[wlen - 1] == ' ') {
   205 		           w[wlen - 1] == ' ') {
   193 			w[wlen - 1] = '\n';
   206 			w[wlen - 1] = '\n';
   194 		} else {
   207 		} else {
   195 			w[wlen++] = c;
   208 			w[wlen++] = c;
   205 
   218 
   206 static bool sliceintolist(PyObject *list, Py_ssize_t destidx,
   219 static bool sliceintolist(PyObject *list, Py_ssize_t destidx,
   207                           const char *source, Py_ssize_t len)
   220                           const char *source, Py_ssize_t len)
   208 {
   221 {
   209 	PyObject *sliced = PyBytes_FromStringAndSize(source, len);
   222 	PyObject *sliced = PyBytes_FromStringAndSize(source, len);
   210 	if (sliced == NULL)
   223 	if (sliced == NULL) {
   211 		return false;
   224 		return false;
       
   225 	}
   212 	PyList_SET_ITEM(list, destidx, sliced);
   226 	PyList_SET_ITEM(list, destidx, sliced);
   213 	return true;
   227 	return true;
   214 }
   228 }
   215 
   229 
   216 static PyObject *splitnewlines(PyObject *self, PyObject *args)
   230 static PyObject *splitnewlines(PyObject *self, PyObject *args)
   230 	for (i = 0; i < size - 1; ++i) {
   244 	for (i = 0; i < size - 1; ++i) {
   231 		if (text[i] == '\n') {
   245 		if (text[i] == '\n') {
   232 			++nelts;
   246 			++nelts;
   233 		}
   247 		}
   234 	}
   248 	}
   235 	if ((result = PyList_New(nelts + 1)) == NULL)
   249 	if ((result = PyList_New(nelts + 1)) == NULL) {
   236 		goto abort;
   250 		goto abort;
       
   251 	}
   237 	nelts = 0;
   252 	nelts = 0;
   238 	for (i = 0; i < size - 1; ++i) {
   253 	for (i = 0; i < size - 1; ++i) {
   239 		if (text[i] == '\n') {
   254 		if (text[i] == '\n') {
   240 			if (!sliceintolist(result, nelts++, text + start,
   255 			if (!sliceintolist(result, nelts++, text + start,
   241 			                   i - start + 1))
   256 			                   i - start + 1)) {
   242 				goto abort;
   257 				goto abort;
       
   258 			}
   243 			start = i + 1;
   259 			start = i + 1;
   244 		}
   260 		}
   245 	}
   261 	}
   246 	if (!sliceintolist(result, nelts++, text + start, size - start))
   262 	if (!sliceintolist(result, nelts++, text + start, size - start)) {
   247 		goto abort;
   263 		goto abort;
       
   264 	}
   248 	return result;
   265 	return result;
   249 abort:
   266 abort:
   250 	Py_XDECREF(result);
   267 	Py_XDECREF(result);
   251 	return NULL;
   268 	return NULL;
   252 }
   269 }
   255                          void *priv)
   272                          void *priv)
   256 {
   273 {
   257 	PyObject *rl = (PyObject *)priv;
   274 	PyObject *rl = (PyObject *)priv;
   258 	PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2);
   275 	PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2);
   259 	int r;
   276 	int r;
   260 	if (!m)
   277 	if (!m) {
   261 		return -1;
   278 		return -1;
       
   279 	}
   262 	r = PyList_Append(rl, m);
   280 	r = PyList_Append(rl, m);
   263 	Py_DECREF(m);
   281 	Py_DECREF(m);
   264 	return r;
   282 	return r;
   265 }
   283 }
   266 
   284 
   280 	xdemitcb_t ecb = {
   298 	xdemitcb_t ecb = {
   281 	    NULL, /* priv */
   299 	    NULL, /* priv */
   282 	};
   300 	};
   283 
   301 
   284 	if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr,
   302 	if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr,
   285 	                      &lb))
   303 	                      &lb)) {
   286 		return NULL;
   304 		return NULL;
       
   305 	}
   287 
   306 
   288 	a.size = la;
   307 	a.size = la;
   289 	b.size = lb;
   308 	b.size = lb;
   290 
   309 
   291 	rl = PyList_New(0);
   310 	rl = PyList_New(0);
   292 	if (!rl)
   311 	if (!rl) {
   293 		return PyErr_NoMemory();
   312 		return PyErr_NoMemory();
       
   313 	}
   294 
   314 
   295 	ecb.priv = rl;
   315 	ecb.priv = rl;
   296 
   316 
   297 	if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) {
   317 	if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) {
   298 		Py_DECREF(rl);
   318 		Py_DECREF(rl);