mercurial/parsers.c
changeset 16955 92e1c64ba0d4
parent 16863 bbedef66c6f3
child 17165 249cc4ec4327
equal deleted inserted replaced
16954:8f36806b8f6a 16955:92e1c64ba0d4
   210 	Py_XDECREF(fname);
   210 	Py_XDECREF(fname);
   211 	Py_XDECREF(cname);
   211 	Py_XDECREF(cname);
   212 	Py_XDECREF(entry);
   212 	Py_XDECREF(entry);
   213 	Py_XDECREF(parents);
   213 	Py_XDECREF(parents);
   214 	return ret;
   214 	return ret;
       
   215 }
       
   216 
       
   217 static inline int getintat(PyObject *tuple, int off, uint32_t *v)
       
   218 {
       
   219 	PyObject *o = PyTuple_GET_ITEM(tuple, off);
       
   220 	long val;
       
   221 
       
   222 	if (PyInt_Check(o))
       
   223 		val = PyInt_AS_LONG(o);
       
   224 	else if (PyLong_Check(o)) {
       
   225 		val = PyLong_AsLong(o);
       
   226 		if (val == -1 && PyErr_Occurred())
       
   227 			return -1;
       
   228 	} else {
       
   229 		PyErr_SetString(PyExc_TypeError, "expected an int or long");
       
   230 		return -1;
       
   231 	}
       
   232 	if (LONG_MAX > INT_MAX && (val > INT_MAX || val < INT_MIN)) {
       
   233 		PyErr_SetString(PyExc_OverflowError,
       
   234 				"Python value to large to convert to uint32_t");
       
   235 		return -1;
       
   236 	}
       
   237 	*v = (uint32_t)val;
       
   238 	return 0;
       
   239 }
       
   240 
       
   241 static PyObject *dirstate_unset;
       
   242 
       
   243 /*
       
   244  * Efficiently pack a dirstate object into its on-disk format.
       
   245  */
       
   246 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
       
   247 {
       
   248 	PyObject *packobj = NULL;
       
   249 	PyObject *map, *copymap, *pl;
       
   250 	Py_ssize_t nbytes, pos, l;
       
   251 	PyObject *k, *v, *pn;
       
   252 	char *p, *s;
       
   253 	double now;
       
   254 
       
   255 	if (!PyArg_ParseTuple(args, "O!O!Od:pack_dirstate",
       
   256 			      &PyDict_Type, &map, &PyDict_Type, &copymap,
       
   257 			      &pl, &now))
       
   258 		return NULL;
       
   259 
       
   260 	if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
       
   261 		PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
       
   262 		return NULL;
       
   263 	}
       
   264 
       
   265 	/* Figure out how much we need to allocate. */
       
   266 	for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
       
   267 		PyObject *c;
       
   268 		if (!PyString_Check(k)) {
       
   269 			PyErr_SetString(PyExc_TypeError, "expected string key");
       
   270 			goto bail;
       
   271 		}
       
   272 		nbytes += PyString_GET_SIZE(k) + 17;
       
   273 		c = PyDict_GetItem(copymap, k);
       
   274 		if (c) {
       
   275 			if (!PyString_Check(c)) {
       
   276 				PyErr_SetString(PyExc_TypeError,
       
   277 						"expected string key");
       
   278 				goto bail;
       
   279 			}
       
   280 			nbytes += PyString_GET_SIZE(c) + 1;
       
   281 		}
       
   282 	}
       
   283 
       
   284 	packobj = PyString_FromStringAndSize(NULL, nbytes);
       
   285 	if (packobj == NULL)
       
   286 		goto bail;
       
   287 
       
   288 	p = PyString_AS_STRING(packobj);
       
   289 
       
   290 	pn = PySequence_ITEM(pl, 0);
       
   291 	if (PyString_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
       
   292 		PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
       
   293 		goto bail;
       
   294 	}
       
   295 	memcpy(p, s, l);
       
   296 	p += 20;
       
   297 	pn = PySequence_ITEM(pl, 1);
       
   298 	if (PyString_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
       
   299 		PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
       
   300 		goto bail;
       
   301 	}
       
   302 	memcpy(p, s, l);
       
   303 	p += 20;
       
   304 
       
   305 	for (pos = 0; PyDict_Next(map, &pos, &k, &v); ) {
       
   306 		uint32_t mode, size, mtime;
       
   307 		Py_ssize_t len, l;
       
   308 		PyObject *o;
       
   309 		char *s, *t;
       
   310 		int err;
       
   311 
       
   312 		if (!PyTuple_Check(v) || PyTuple_GET_SIZE(v) != 4) {
       
   313 			PyErr_SetString(PyExc_TypeError, "expected a 4-tuple");
       
   314 			goto bail;
       
   315 		}
       
   316 		o = PyTuple_GET_ITEM(v, 0);
       
   317 		if (PyString_AsStringAndSize(o, &s, &l) == -1 || l != 1) {
       
   318 			PyErr_SetString(PyExc_TypeError, "expected one byte");
       
   319 			goto bail;
       
   320 		}
       
   321 		*p++ = *s;
       
   322 		err = getintat(v, 1, &mode);
       
   323 		err |= getintat(v, 2, &size);
       
   324 		err |= getintat(v, 3, &mtime);
       
   325 		if (err)
       
   326 			goto bail;
       
   327 		if (*s == 'n' && mtime == (uint32_t)now) {
       
   328 			/* See dirstate.py:write for why we do this. */
       
   329 			if (PyDict_SetItem(map, k, dirstate_unset) == -1)
       
   330 				goto bail;
       
   331 			mode = 0, size = -1, mtime = -1;
       
   332 		}
       
   333 		putbe32(mode, p);
       
   334 		putbe32(size, p + 4);
       
   335 		putbe32(mtime, p + 8);
       
   336 		t = p + 12;
       
   337 		p += 16;
       
   338 		len = PyString_GET_SIZE(k);
       
   339 		memcpy(p, PyString_AS_STRING(k), len);
       
   340 		p += len;
       
   341 		o = PyDict_GetItem(copymap, k);
       
   342 		if (o) {
       
   343 			*p++ = '\0';
       
   344 			l = PyString_GET_SIZE(o);
       
   345 			memcpy(p, PyString_AS_STRING(o), l);
       
   346 			p += l;
       
   347 			len += l + 1;
       
   348 		}
       
   349 		putbe32((uint32_t)len, t);
       
   350 	}
       
   351 
       
   352 	pos = p - PyString_AS_STRING(packobj);
       
   353 	if (pos != nbytes) {
       
   354 		PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
       
   355                              (long)pos, (long)nbytes);
       
   356 		goto bail;
       
   357 	}
       
   358 
       
   359 	return packobj;
       
   360 bail:
       
   361 	Py_XDECREF(packobj);
       
   362 	return NULL;
   215 }
   363 }
   216 
   364 
   217 /*
   365 /*
   218  * A base-16 trie for fast node->rev mapping.
   366  * A base-16 trie for fast node->rev mapping.
   219  *
   367  *
  1354 }
  1502 }
  1355 
  1503 
  1356 static char parsers_doc[] = "Efficient content parsing.";
  1504 static char parsers_doc[] = "Efficient content parsing.";
  1357 
  1505 
  1358 static PyMethodDef methods[] = {
  1506 static PyMethodDef methods[] = {
       
  1507 	{"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
  1359 	{"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
  1508 	{"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
  1360 	{"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
  1509 	{"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
  1361 	{"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
  1510 	{"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
  1362 	{NULL, NULL}
  1511 	{NULL, NULL}
  1363 };
  1512 };
  1373 
  1522 
  1374 	nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
  1523 	nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
  1375 				  -1, -1, -1, -1, nullid, 20);
  1524 				  -1, -1, -1, -1, nullid, 20);
  1376 	if (nullentry)
  1525 	if (nullentry)
  1377 		PyObject_GC_UnTrack(nullentry);
  1526 		PyObject_GC_UnTrack(nullentry);
       
  1527 
       
  1528 	dirstate_unset = Py_BuildValue("ciii", 'n', 0, -1, -1);
  1378 }
  1529 }
  1379 
  1530 
  1380 #ifdef IS_PY3K
  1531 #ifdef IS_PY3K
  1381 static struct PyModuleDef parsers_module = {
  1532 static struct PyModuleDef parsers_module = {
  1382 	PyModuleDef_HEAD_INIT,
  1533 	PyModuleDef_HEAD_INIT,