diff -r fb3fc27617a2 -r 16bafcebd3d1 mercurial/parsers.c --- a/mercurial/parsers.c Sun Oct 12 15:21:08 2008 -0500 +++ b/mercurial/parsers.c Sun Oct 12 15:21:08 2008 -0500 @@ -128,15 +128,117 @@ Py_INCREF(Py_None); return Py_None; - quit: return NULL; } +#ifdef _WIN32 +# ifdef _MSC_VER +/* msvc 6.0 has problems */ +# define inline __inline +typedef unsigned long uint32_t; +# else +# include +# endif +static uint32_t ntohl(uint32_t x) +{ + return ((x & 0x000000ffUL) << 24) | + ((x & 0x0000ff00UL) << 8) | + ((x & 0x00ff0000UL) >> 8) | + ((x & 0xff000000UL) >> 24); +} +#else +/* not windows */ +# include +# if defined __BEOS__ && !defined __HAIKU__ +# include +# else +# include +# endif +# include +#endif + +static PyObject *parse_dirstate(PyObject *self, PyObject *args) +{ + PyObject *dmap, *cmap, *parents = NULL, *ret = NULL; + PyObject *fname = NULL, *cname = NULL, *entry = NULL; + char *str, *cur, *end, *cpos; + int state, mode, size, mtime, flen; + int len; + char decode[16]; /* for alignment */ + + if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate", + &PyDict_Type, &dmap, + &PyDict_Type, &cmap, + &str, &len)) + goto quit; + + /* read parents */ + if (len < 40) + goto quit; + + parents = Py_BuildValue("s#s#", str, 20, str + 20, 20); + if (!parents) + goto quit; + + /* read filenames */ + cur = str + 40; + end = str + len; + + while (cur < end - 17) { + /* unpack header */ + state = *cur; + memcpy(decode, cur + 1, 16); + mode = ntohl(*(uint32_t *)(decode)); + size = ntohl(*(uint32_t *)(decode + 4)); + mtime = ntohl(*(uint32_t *)(decode + 8)); + flen = ntohl(*(uint32_t *)(decode + 12)); + cur += 17; + if (cur + flen > end) + goto quit; + + entry = Py_BuildValue("ciii", state, mode, size, mtime); + PyObject_GC_UnTrack(entry); /* don't waste time with this */ + if (!entry) + goto quit; + + cpos = memchr(cur, 0, flen); + if (cpos) { + fname = PyString_FromStringAndSize(cur, cpos - cur); + cname = PyString_FromStringAndSize(cpos + 1, + flen - (cpos - cur) - 1); + if (!fname || !cname || + PyDict_SetItem(cmap, fname, cname) == -1 || + PyDict_SetItem(dmap, fname, entry) == -1) + goto quit; + Py_DECREF(cname); + } else { + fname = PyString_FromStringAndSize(cur, flen); + if (!fname || + PyDict_SetItem(dmap, fname, entry) == -1) + goto quit; + } + cur += flen; + Py_DECREF(fname); + Py_DECREF(entry); + fname = cname = entry = NULL; + } + + ret = parents; + Py_INCREF(ret); +quit: + Py_XDECREF(fname); + Py_XDECREF(cname); + Py_XDECREF(entry); + Py_XDECREF(parents); + return ret; +} + static char parsers_doc[] = "Efficient content parsing."; static PyMethodDef methods[] = { {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, + {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, {NULL, NULL} };