comparison mercurial/parsers.c @ 24017:72c9b5ae7278

parsers: add fm1readmarker This lets us do most of the interesting work of parsing obsolete markers in C, which should provide significant time savings. Thanks to Martin von Zweigbergk for some cleanups on this code.
author Augie Fackler <augie@google.com>
date Fri, 23 Jan 2015 15:11:25 -0500
parents 8a5267cd5286
children 26fbf07482b2
comparison
equal deleted inserted replaced
24016:fb93721cc229 24017:72c9b5ae7278
2144 Py_XDECREF(cache); 2144 Py_XDECREF(cache);
2145 Py_XDECREF(tuple); 2145 Py_XDECREF(tuple);
2146 return NULL; 2146 return NULL;
2147 } 2147 }
2148 2148
2149 #define BUMPED_FIX 1
2150 #define USING_SHA_256 2
2151
2152 static PyObject *readshas(
2153 const char *source, unsigned char num, Py_ssize_t hashwidth)
2154 {
2155 int i;
2156 PyObject *list = PyTuple_New(num);
2157 if (list == NULL) {
2158 return NULL;
2159 }
2160 for (i = 0; i < num; i++) {
2161 PyObject *hash = PyString_FromStringAndSize(source, hashwidth);
2162 if (hash == NULL) {
2163 Py_DECREF(list);
2164 return NULL;
2165 }
2166 PyTuple_SetItem(list, i, hash);
2167 source += hashwidth;
2168 }
2169 return list;
2170 }
2171
2172 static PyObject *fm1readmarker(PyObject *self, PyObject *args)
2173 {
2174 const char *data;
2175 const char *meta;
2176 Py_ssize_t datalen, offset;
2177
2178 uint32_t msize;
2179 double mtime;
2180 int16_t tz;
2181 uint16_t flags;
2182 unsigned char nsuccs, nparents, nmetadata;
2183 Py_ssize_t hashwidth = 20;
2184
2185 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
2186 PyObject *metadata = NULL, *ret = NULL;
2187 int i;
2188
2189 if (!PyArg_ParseTuple(args, "s#n", &data, &datalen, &offset)) {
2190 return NULL;
2191 }
2192 data += offset;
2193
2194 msize = getbe32(data);
2195 data += 4;
2196 mtime = getbefloat64(data);
2197 data += 8;
2198 tz = getbeint16(data);
2199 data += 2;
2200 flags = getbeuint16(data);
2201 data += 2;
2202
2203 if (flags & USING_SHA_256) {
2204 hashwidth = 32;
2205 }
2206
2207 nsuccs = (unsigned char)(*data++);
2208 nparents = (unsigned char)(*data++);
2209 nmetadata = (unsigned char)(*data++);
2210
2211 prec = PyString_FromStringAndSize(data, hashwidth);
2212 data += hashwidth;
2213 if (prec == NULL) {
2214 goto bail;
2215 }
2216
2217 succs = readshas(data, nsuccs, hashwidth);
2218 if (succs == NULL) {
2219 goto bail;
2220 }
2221 data += nsuccs * hashwidth;
2222
2223 if (nparents == 1 || nparents == 2) {
2224 parents = readshas(data, nparents, hashwidth);
2225 if (parents == NULL) {
2226 goto bail;
2227 }
2228 data += nparents * hashwidth;
2229 } else {
2230 parents = Py_None;
2231 }
2232
2233 meta = data + (2 * nmetadata);
2234 metadata = PyTuple_New(nmetadata);
2235 if (metadata == NULL) {
2236 goto bail;
2237 }
2238 for (i = 0; i < nmetadata; i++) {
2239 PyObject *tmp, *left = NULL, *right = NULL;
2240 Py_ssize_t metasize = (unsigned char)(*data++);
2241 left = PyString_FromStringAndSize(meta, metasize);
2242 meta += metasize;
2243 metasize = (unsigned char)(*data++);
2244 right = PyString_FromStringAndSize(meta, metasize);
2245 meta += metasize;
2246 if (!left || !right) {
2247 Py_XDECREF(left);
2248 Py_XDECREF(right);
2249 goto bail;
2250 }
2251 tmp = PyTuple_Pack(2, left, right);
2252 Py_DECREF(left);
2253 Py_DECREF(right);
2254 if (!tmp) {
2255 goto bail;
2256 }
2257 PyTuple_SetItem(metadata, i, tmp);
2258 }
2259 ret = Py_BuildValue("(nOOHO(di)O)", msize, prec, succs, flags,
2260 metadata, mtime, (int)tz * 60, parents);
2261 bail:
2262 Py_XDECREF(prec);
2263 Py_XDECREF(succs);
2264 Py_XDECREF(metadata);
2265 if (parents != Py_None)
2266 Py_XDECREF(parents);
2267 return ret;
2268 }
2269
2149 static char parsers_doc[] = "Efficient content parsing."; 2270 static char parsers_doc[] = "Efficient content parsing.";
2150 2271
2151 PyObject *encodedir(PyObject *self, PyObject *args); 2272 PyObject *encodedir(PyObject *self, PyObject *args);
2152 PyObject *pathencode(PyObject *self, PyObject *args); 2273 PyObject *pathencode(PyObject *self, PyObject *args);
2153 PyObject *lowerencode(PyObject *self, PyObject *args); 2274 PyObject *lowerencode(PyObject *self, PyObject *args);
2159 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, 2280 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
2160 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, 2281 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
2161 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"}, 2282 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
2162 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"}, 2283 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
2163 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"}, 2284 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
2285 {"fm1readmarker", fm1readmarker, METH_VARARGS, "parse v1 obsolete marker\n"},
2164 {NULL, NULL} 2286 {NULL, NULL}
2165 }; 2287 };
2166 2288
2167 void dirs_module_init(PyObject *mod); 2289 void dirs_module_init(PyObject *mod);
2168 2290