Mercurial > hg
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 |