mercurial/mpatch.c
changeset 128 d6afb6dbf9f2
parent 82 7ed96baa7caa
child 282 97d83e7fbf2f
equal deleted inserted replaced
127:44538462d3c8 128:d6afb6dbf9f2
    37 	struct frag *base, *head, *tail;
    37 	struct frag *base, *head, *tail;
    38 };
    38 };
    39 
    39 
    40 static struct flist *lalloc(int size)
    40 static struct flist *lalloc(int size)
    41 {
    41 {
    42 	struct flist *a;
    42 	struct flist *a = NULL;
    43 
    43 
    44 	a = malloc(sizeof(struct flist));
    44 	a = malloc(sizeof(struct flist));
    45 	a->head = a->tail = a->base = malloc(sizeof(struct frag) * size);
    45 	if (a) {
       
    46 		a->base = malloc(sizeof(struct frag) * size);
       
    47 		if (!a->base)
       
    48 			free(a);
       
    49 		else
       
    50 			a->head = a->tail = a->base;
       
    51 	}
    46 	return a;
    52 	return a;
    47 }
    53 }
    48 
    54 
    49 static void lfree(struct flist *a)
    55 static void lfree(struct flist *a)
    50 {
    56 {
    51 	free(a->base);
    57 	if (a) {
    52 	free(a);
    58 		free(a->base);
       
    59 		free(a);
       
    60 	}
    53 }
    61 }
    54 
    62 
    55 static int lsize(struct flist *a)
    63 static int lsize(struct flist *a)
    56 {
    64 {
    57 	return a->tail - a->head;
    65 	return a->tail - a->head;
   142 
   150 
   143 /* combine hunk lists a and b, while adjusting b for offset changes in a/
   151 /* combine hunk lists a and b, while adjusting b for offset changes in a/
   144    this deletes a and b and returns the resultant list. */
   152    this deletes a and b and returns the resultant list. */
   145 static struct flist *combine(struct flist *a, struct flist *b)
   153 static struct flist *combine(struct flist *a, struct flist *b)
   146 {
   154 {
   147 	struct flist *c;
   155 	struct flist *c = NULL;
   148 	struct frag *bh = b->head, *ct;
   156 	struct frag *bh, *ct;
   149 	int offset = 0, post;
   157 	int offset = 0, post;
   150 
   158 
   151 	c = lalloc((lsize(a) + lsize(b)) * 2);
   159 	if (a && b)
   152 
   160 		c = lalloc((lsize(a) + lsize(b)) * 2);
   153 	while (bh != b->tail) {
   161 
   154 		/* save old hunks */
   162 	if (c) {
   155 		offset = gather(c, a, bh->start, offset);
   163 
   156 
   164 		for (bh = b->head; bh != b->tail; bh++) {
   157 		/* discard replaced hunks */
   165 			/* save old hunks */
   158 		post = discard(a, bh->end, offset);
   166 			offset = gather(c, a, bh->start, offset);
   159 
   167 
   160 		/* insert new hunk */
   168 			/* discard replaced hunks */
   161 		ct = c->tail;
   169 			post = discard(a, bh->end, offset);
   162 		ct->start = bh->start - offset;
   170 
   163 		ct->end = bh->end - post;
   171 			/* insert new hunk */
   164 		ct->len = bh->len;
   172 			ct = c->tail;
   165 		ct->data = bh->data;
   173 			ct->start = bh->start - offset;
   166 		c->tail++;
   174 			ct->end = bh->end - post;
   167 		bh++;
   175 			ct->len = bh->len;
   168 		offset = post;
   176 			ct->data = bh->data;
   169 	}
   177 			c->tail++;
   170 
   178 			offset = post;
   171 	/* hold on to tail from a */
   179 		}
   172 	memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
   180 
   173 	c->tail += lsize(a);
   181 		/* hold on to tail from a */
       
   182 		memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
       
   183 		c->tail += lsize(a);
       
   184 	}
       
   185 
   174 	lfree(a);
   186 	lfree(a);
   175 	lfree(b);
   187 	lfree(b);
   176 	return c;
   188 	return c;
   177 }
   189 }
   178 
   190 
   240 	int len;
   252 	int len;
   241 
   253 
   242 	if (start + 1 == end) {
   254 	if (start + 1 == end) {
   243 		/* trivial case, output a decoded list */
   255 		/* trivial case, output a decoded list */
   244 		PyObject *tmp = PyList_GetItem(bins, start);
   256 		PyObject *tmp = PyList_GetItem(bins, start);
       
   257 		if (!tmp)
       
   258 			return NULL;
   245 		return decode(PyString_AsString(tmp), PyString_Size(tmp));
   259 		return decode(PyString_AsString(tmp), PyString_Size(tmp));
   246 	}
   260 	}
   247 
   261 
   248 	/* divide and conquer, memory management is elsewhere */
   262 	/* divide and conquer, memory management is elsewhere */
   249 	len = (end - start) / 2;
   263 	len = (end - start) / 2;
   257 	PyObject *text, *bins, *result;
   271 	PyObject *text, *bins, *result;
   258 	struct flist *patch;
   272 	struct flist *patch;
   259 	char *in, *out;
   273 	char *in, *out;
   260 	int len, outlen;
   274 	int len, outlen;
   261 
   275 
   262 	if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
   276 	if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins))
   263 		return NULL;
   277 		return NULL;
   264 
   278 
   265 	len = PyList_Size(bins);
   279 	len = PyList_Size(bins);
   266 	if (!len) {
   280 	if (!len) {
   267 		/* nothing to do */
   281 		/* nothing to do */
   268 		Py_INCREF(text);
   282 		Py_INCREF(text);
   269 		return text;
   283 		return text;
   270 	}
   284 	}
   271 
   285 
   272 	patch = fold(bins, 0, len);
   286 	patch = fold(bins, 0, len);
       
   287 	if (!patch)
       
   288 		return PyErr_NoMemory();
       
   289 
   273 	outlen = calcsize(PyString_Size(text), patch);
   290 	outlen = calcsize(PyString_Size(text), patch);
   274 	result = PyString_FromStringAndSize(NULL, outlen);
   291 	result = PyString_FromStringAndSize(NULL, outlen);
   275 	in = PyString_AsString(text);
   292 	if (result) {
   276 	out = PyString_AsString(result);
   293 		in = PyString_AsString(text);
   277 	apply(out, in, PyString_Size(text), patch);
   294 		out = PyString_AsString(result);
       
   295 		apply(out, in, PyString_Size(text), patch);
       
   296 	}
       
   297 
   278 	lfree(patch);
   298 	lfree(patch);
   279 
       
   280 	return result;
   299 	return result;
   281 }
   300 }
   282 
   301 
   283 static PyMethodDef methods[] = {
   302 static PyMethodDef methods[] = {
   284 	{"patches", patches, METH_VARARGS, "apply a series of patches\n"},
   303 	{"patches", patches, METH_VARARGS, "apply a series of patches\n"},