mercurial/cext/revlog.c
changeset 40273 3b275f549777
parent 40099 994010b87534
child 40300 72b94f946e90
equal deleted inserted replaced
40272:a36c5e23c055 40273:3b275f549777
  2288 	Py_XDECREF(cache);
  2288 	Py_XDECREF(cache);
  2289 	Py_XDECREF(tuple);
  2289 	Py_XDECREF(tuple);
  2290 	return NULL;
  2290 	return NULL;
  2291 }
  2291 }
  2292 
  2292 
       
  2293 #ifdef WITH_RUST
       
  2294 
       
  2295 /* rustlazyancestors: iteration over ancestors implemented in Rust
       
  2296  *
       
  2297  * This class holds a reference to an index and to the Rust iterator.
       
  2298  */
       
  2299 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject;
       
  2300 
       
  2301 struct rustlazyancestorsObjectStruct {
       
  2302 	PyObject_HEAD
       
  2303 	/* Type-specific fields go here. */
       
  2304 	indexObject *index;    /* Ref kept to avoid GC'ing the index */
       
  2305 	void *iter;        /* Rust iterator */
       
  2306 };
       
  2307 
       
  2308 /* FFI exposed from Rust code */
       
  2309 rustlazyancestorsObject *rustlazyancestors_init(
       
  2310 	indexObject *index,
       
  2311 	/* to pass index_get_parents() */
       
  2312 	int (*)(indexObject *, Py_ssize_t, int*, int),
       
  2313 	/* intrevs vector */
       
  2314 	int initrevslen, long *initrevs,
       
  2315 	long stoprev,
       
  2316 	int inclusive);
       
  2317 void rustlazyancestors_drop(rustlazyancestorsObject *self);
       
  2318 int rustlazyancestors_next(rustlazyancestorsObject *self);
       
  2319 
       
  2320 /* CPython instance methods */
       
  2321 static int rustla_init(rustlazyancestorsObject *self,
       
  2322                        PyObject *args) {
       
  2323 	PyObject *initrevsarg = NULL;
       
  2324 	PyObject *inclusivearg = NULL;
       
  2325 	long stoprev = 0;
       
  2326 	long *initrevs = NULL;
       
  2327 	int inclusive = 0;
       
  2328 	Py_ssize_t i;
       
  2329 
       
  2330 	indexObject *index;
       
  2331 	if (!PyArg_ParseTuple(args, "O!O!lO!",
       
  2332 			      &indexType, &index,
       
  2333                               &PyList_Type, &initrevsarg,
       
  2334                               &stoprev,
       
  2335                               &PyBool_Type, &inclusivearg))
       
  2336 	return -1;
       
  2337 
       
  2338 	Py_INCREF(index);
       
  2339 	self->index = index;
       
  2340 
       
  2341 	if (inclusivearg == Py_True)
       
  2342 		inclusive = 1;
       
  2343 
       
  2344 	Py_ssize_t linit = PyList_GET_SIZE(initrevsarg);
       
  2345 
       
  2346 	initrevs = (long*)calloc(linit, sizeof(long));
       
  2347 
       
  2348 	if (initrevs == NULL) {
       
  2349 		PyErr_NoMemory();
       
  2350 		goto bail;
       
  2351 	}
       
  2352 
       
  2353 	for (i=0; i<linit; i++) {
       
  2354 		initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i));
       
  2355 	}
       
  2356 	if (PyErr_Occurred())
       
  2357 		goto bail;
       
  2358 
       
  2359 	self->iter = rustlazyancestors_init(index,
       
  2360 		                            index_get_parents,
       
  2361 		                            linit, initrevs,
       
  2362 		                            stoprev, inclusive);
       
  2363 	if (self->iter == NULL) {
       
  2364 		/* if this is because of GraphError::ParentOutOfRange
       
  2365 		 * index_get_parents() has already set the proper ValueError */
       
  2366 		goto bail;
       
  2367 	}
       
  2368 
       
  2369 	free(initrevs);
       
  2370 	return 0;
       
  2371 
       
  2372 bail:
       
  2373 	free(initrevs);
       
  2374 	return -1;
       
  2375 };
       
  2376 
       
  2377 static void rustla_dealloc(rustlazyancestorsObject *self)
       
  2378 {
       
  2379 	Py_XDECREF(self->index);
       
  2380 	if (self->iter != NULL) { /* can happen if rustla_init failed */
       
  2381 		rustlazyancestors_drop(self->iter);
       
  2382 	}
       
  2383 	PyObject_Del(self);
       
  2384 }
       
  2385 
       
  2386 static PyObject *rustla_next(rustlazyancestorsObject *self) {
       
  2387 	int res = rustlazyancestors_next(self->iter);
       
  2388 	if (res == -1) {
       
  2389 		/* Setting an explicit exception seems unnecessary
       
  2390 		 * as examples from Python source code (Objects/rangeobjets.c and
       
  2391 		 * Modules/_io/stringio.c) seem to demonstrate.
       
  2392 		 */
       
  2393 		return NULL;
       
  2394 	}
       
  2395 	return PyInt_FromLong(res);
       
  2396 }
       
  2397 
       
  2398 static PyTypeObject rustlazyancestorsType = {
       
  2399 	PyVarObject_HEAD_INIT(NULL, 0) /* header */
       
  2400 	"parsers.rustlazyancestors",           /* tp_name */
       
  2401 	sizeof(rustlazyancestorsObject),       /* tp_basicsize */
       
  2402 	0,                         /* tp_itemsize */
       
  2403 	(destructor)rustla_dealloc, /* tp_dealloc */
       
  2404 	0,                         /* tp_print */
       
  2405 	0,                         /* tp_getattr */
       
  2406 	0,                         /* tp_setattr */
       
  2407 	0,                         /* tp_compare */
       
  2408 	0,                         /* tp_repr */
       
  2409 	0,                         /* tp_as_number */
       
  2410 	0,                         /* tp_as_sequence */
       
  2411 	0,                         /* tp_as_mapping */
       
  2412 	0,                         /* tp_hash */
       
  2413 	0,                         /* tp_call */
       
  2414 	0,                         /* tp_str */
       
  2415 	0,                         /* tp_getattro */
       
  2416 	0,                         /* tp_setattro */
       
  2417 	0,                         /* tp_as_buffer */
       
  2418 	Py_TPFLAGS_DEFAULT,        /* tp_flags */
       
  2419 	"Iterator over ancestors, implemented in Rust", /* tp_doc */
       
  2420 	0,                         /* tp_traverse */
       
  2421 	0,                         /* tp_clear */
       
  2422 	0,                         /* tp_richcompare */
       
  2423 	0,                         /* tp_weaklistoffset */
       
  2424 	0,                         /* tp_iter */
       
  2425 	(iternextfunc)rustla_next, /* tp_iternext */
       
  2426 	0,                         /* tp_methods */
       
  2427 	0,                         /* tp_members */
       
  2428 	0,                         /* tp_getset */
       
  2429 	0,                         /* tp_base */
       
  2430 	0,                         /* tp_dict */
       
  2431 	0,                         /* tp_descr_get */
       
  2432 	0,                         /* tp_descr_set */
       
  2433 	0,                         /* tp_dictoffset */
       
  2434 	(initproc)rustla_init,     /* tp_init */
       
  2435 	0,                         /* tp_alloc */
       
  2436 };
       
  2437 #endif /* WITH_RUST */
       
  2438 
  2293 void revlog_module_init(PyObject *mod)
  2439 void revlog_module_init(PyObject *mod)
  2294 {
  2440 {
  2295 	indexType.tp_new = PyType_GenericNew;
  2441 	indexType.tp_new = PyType_GenericNew;
  2296 	if (PyType_Ready(&indexType) < 0)
  2442 	if (PyType_Ready(&indexType) < 0)
  2297 		return;
  2443 		return;
  2308 		nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
  2454 		nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0,
  2309 					  -1, -1, -1, -1, nullid, 20);
  2455 					  -1, -1, -1, -1, nullid, 20);
  2310 	}
  2456 	}
  2311 	if (nullentry)
  2457 	if (nullentry)
  2312 		PyObject_GC_UnTrack(nullentry);
  2458 		PyObject_GC_UnTrack(nullentry);
  2313 }
  2459 
       
  2460 #ifdef WITH_RUST
       
  2461 	rustlazyancestorsType.tp_new = PyType_GenericNew;
       
  2462 	if (PyType_Ready(&rustlazyancestorsType) < 0)
       
  2463 		return;
       
  2464 	Py_INCREF(&rustlazyancestorsType);
       
  2465 	PyModule_AddObject(mod, "rustlazyancestors",
       
  2466 		(PyObject *)&rustlazyancestorsType);
       
  2467 #endif
       
  2468 
       
  2469 }