mercurial/mpatch_module.c
changeset 29694 55dd12204b8e
parent 29693 b9b9f9a92481
child 29740 21ac534d7d30
equal deleted inserted replaced
29693:b9b9f9a92481 29694:55dd12204b8e
    31 #include "mpatch.h"
    31 #include "mpatch.h"
    32 
    32 
    33 static char mpatch_doc[] = "Efficient binary patching.";
    33 static char mpatch_doc[] = "Efficient binary patching.";
    34 static PyObject *mpatch_Error;
    34 static PyObject *mpatch_Error;
    35 
    35 
       
    36 struct mpatch_flist *cpygetitem(void *bins, ssize_t pos)
       
    37 {
       
    38 	const char *buffer;
       
    39 	struct mpatch_flist *res;
       
    40 	ssize_t blen;
       
    41 	int r;
       
    42 
       
    43 	PyObject *tmp = PyList_GetItem((PyObject*)bins, pos);
       
    44 	if (!tmp)
       
    45 		return NULL;
       
    46 	if (PyObject_AsCharBuffer(tmp, &buffer, (Py_ssize_t*)&blen))
       
    47 		return NULL;
       
    48 	if ((r = mpatch_decode(buffer, blen, &res)) < 0) {
       
    49 		if (!PyErr_Occurred())
       
    50 			PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
       
    51  		return NULL;
       
    52 	}
       
    53 	return res;
       
    54 }
       
    55 
    36 static PyObject *
    56 static PyObject *
    37 patches(PyObject *self, PyObject *args)
    57 patches(PyObject *self, PyObject *args)
    38 {
    58 {
    39 	PyObject *text, *bins, *result;
    59 	PyObject *text, *bins, *result;
    40 	struct mpatch_flist *patch;
    60 	struct mpatch_flist *patch;
    41 	const char *in;
    61 	const char *in;
       
    62 	int r;
    42 	char *out;
    63 	char *out;
    43 	Py_ssize_t len, outlen, inlen;
    64 	Py_ssize_t len, outlen, inlen;
    44 
    65 
    45 	if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
    66 	if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
    46 		return NULL;
    67 		return NULL;
    53 	}
    74 	}
    54 
    75 
    55 	if (PyObject_AsCharBuffer(text, &in, &inlen))
    76 	if (PyObject_AsCharBuffer(text, &in, &inlen))
    56 		return NULL;
    77 		return NULL;
    57 
    78 
    58 	patch = mpatch_fold(bins, 0, len);
    79 	patch = mpatch_fold(bins, cpygetitem, 0, len);
    59 	if (!patch)
    80 	if (!patch) { /* error already set or memory error */
       
    81 		if (!PyErr_Occurred())
       
    82 			PyErr_NoMemory();
    60 		return NULL;
    83 		return NULL;
       
    84 	}
    61 
    85 
    62 	outlen = mpatch_calcsize(inlen, patch);
    86 	outlen = mpatch_calcsize(inlen, patch);
    63 	if (outlen < 0) {
    87 	if (outlen < 0) {
       
    88 		r = (int)outlen;
    64 		result = NULL;
    89 		result = NULL;
    65 		goto cleanup;
    90 		goto cleanup;
    66 	}
    91 	}
    67 	result = PyBytes_FromStringAndSize(NULL, outlen);
    92 	result = PyBytes_FromStringAndSize(NULL, outlen);
    68 	if (!result) {
    93 	if (!result) {
    69 		result = NULL;
    94 		result = NULL;
    70 		goto cleanup;
    95 		goto cleanup;
    71 	}
    96 	}
    72 	out = PyBytes_AsString(result);
    97 	out = PyBytes_AsString(result);
    73 	if (!mpatch_apply(out, in, inlen, patch)) {
    98 	if ((r = mpatch_apply(out, in, inlen, patch)) < 0) {
    74 		Py_DECREF(result);
    99 		Py_DECREF(result);
    75 		result = NULL;
   100 		result = NULL;
    76 	}
   101 	}
    77 cleanup:
   102 cleanup:
    78 	mpatch_lfree(patch);
   103 	mpatch_lfree(patch);
       
   104 	if (!result && !PyErr_Occurred())
       
   105 		PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
    79 	return result;
   106 	return result;
    80 }
   107 }
    81 
   108 
    82 /* calculate size of a patched file directly */
   109 /* calculate size of a patched file directly */
    83 static PyObject *
   110 static PyObject *