[PATCH 1 of 7 V2 of F2 series] pathencode: add new cutdirs function
Adrian Buehlmann
adrian at cadifra.com
Sun Oct 7 05:54:53 CDT 2012
# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1349606346 -7200
# Node ID 2f8dcee6ee70474d18488183a6e93bbf99c5d27e
# Parent 4f2f0f367ef64a979c68002e8689e28f579c7d07
pathencode: add new cutdirs function
diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -1508,6 +1508,7 @@
PyObject *encodedir(PyObject *self, PyObject *args);
PyObject *pathencode(PyObject *self, PyObject *args);
+PyObject *cutdirs(PyObject *self, PyObject *args);
static PyMethodDef methods[] = {
{"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
@@ -1516,6 +1517,7 @@
{"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
{"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
{"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
+ {"cutdirs", cutdirs, METH_VARARGS, "cutdirs-encode a path\n"},
{NULL, NULL}
};
diff --git a/mercurial/pathencode.c b/mercurial/pathencode.c
--- a/mercurial/pathencode.c
+++ b/mercurial/pathencode.c
@@ -481,6 +481,92 @@
static const Py_ssize_t maxstorepathlen = 120;
+static const char encchar[256] =
+ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ "~!~#$%&'()~+,-~~0123456789~;~=~~"
+ "@abcdefghijklmnopqrstuvwxyz[~]^_"
+ "`abcdefghijklmnopqrstuvwxyz{~}~~"
+ "~abcdefghijklmnopqrstuvwxyz{~}~~"
+ "~!~#$%&'()~+,-~~0123456789~;~=~~"
+ "@abcdefghijklmnopqrstuvwxyz[~]^_"
+ "`abcdefghijklmnopqrstuvwxyz{~}~~";
+
+/* this encoding folds */
+static inline char encodechar(char c)
+{
+ return encchar[0xff & c];
+}
+
+static Py_ssize_t _cutdirs(char *dest, Py_ssize_t destlen, size_t destsize,
+ const char *src, Py_ssize_t len)
+{
+ Py_ssize_t i = 0, spaceleft = maxstorepathlen - 45 + 1;
+ char seg[8];
+ int seglen = 0;
+ uint32_t cmp;
+
+ while (i < len && spaceleft > 0) {
+ if (src[i] == '/' || src[i] == '\0') {
+ if (seglen != 0) {
+ if (seglen == 3) {
+ cmp = seg[0] << 16 | seg[1] << 8 | seg[2];
+ if ( cmp == 0x617578 /* aux */
+ || cmp == 0x636f6e /* con */
+ || cmp == 0x70726e /* prn */
+ || cmp == 0x6e756c /* nul */)
+ seg[2] = '~';
+ }
+ else if (seglen == 4 && seg[3] <= '9'
+ && seg[3] >= '0') {
+ cmp = seg[0] << 16 | seg[1] << 8 | seg[2];
+ if ( cmp == 0x636f6d /* com0..9 */
+ || cmp == 0x6c7074 /* lpt0..9 */)
+ seg[3] = '~';
+ }
+ memcopy(dest, &destlen, destsize, &seg, seglen);
+ seglen = 0;
+ }
+ charcopy(dest, &destlen, destsize, src[i++]);
+ spaceleft--;
+ }
+ else if (seglen == sizeof(seg)) {
+ i++;
+ }
+ else {
+ seg[seglen++] = encodechar(src[i++]);
+ spaceleft--;
+ }
+ }
+
+ return destlen;
+}
+
+PyObject *cutdirs(PyObject *self, PyObject *args)
+{
+ Py_ssize_t len, newlen;
+ PyObject *pathobj, *newobj;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "O:cutdirs", &pathobj))
+ return NULL;
+
+ if (PyString_AsStringAndSize(pathobj, &path, &len) == -1) {
+ PyErr_SetString(PyExc_TypeError, "expected a string");
+ return NULL;
+ }
+
+ newlen = len ? _cutdirs(NULL, 0, 0, path, len + 1) : 1;
+
+ newobj = PyString_FromStringAndSize(NULL, newlen);
+
+ if (newobj) {
+ PyString_GET_SIZE(newobj)--;
+ _cutdirs(PyString_AS_STRING(newobj), 0, newlen, path, len + 1);
+ }
+
+ return newobj;
+}
+
/*
* We currently implement only basic encoding.
*
More information about the Mercurial-devel
mailing list