Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BTreeModuleTemplate.c 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*****************************************************************************
  2. Copyright (c) 2001, 2002 Zope Foundation and Contributors.
  3. All Rights Reserved.
  4. This software is subject to the provisions of the Zope Public License,
  5. Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  6. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  7. WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  8. WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  9. FOR A PARTICULAR PURPOSE
  10. ****************************************************************************/
  11. #include "Python.h"
  12. /* include structmember.h for offsetof */
  13. #include "structmember.h"
  14. #include "bytesobject.h"
  15. #ifdef PERSISTENT
  16. #include "persistent/cPersistence.h"
  17. #else
  18. #define PER_USE_OR_RETURN(self, NULL)
  19. #define PER_ALLOW_DEACTIVATION(self)
  20. #define PER_PREVENT_DEACTIVATION(self)
  21. #define PER_DEL(self)
  22. #define PER_USE(O) 1
  23. #define PER_ACCESSED(O) 1
  24. #endif
  25. #include "_compat.h"
  26. /* So sue me. This pair gets used all over the place, so much so that it
  27. * interferes with understanding non-persistence parts of algorithms.
  28. * PER_UNUSE can be used after a successul PER_USE or PER_USE_OR_RETURN.
  29. * It allows the object to become ghostified, and tells the persistence
  30. * machinery that the object's fields were used recently.
  31. */
  32. #define PER_UNUSE(OBJ) do { \
  33. PER_ALLOW_DEACTIVATION(OBJ); \
  34. PER_ACCESSED(OBJ); \
  35. } while (0)
  36. /* The tp_name slots of the various BTree types contain the fully
  37. * qualified names of the types, e.g. zodb.btrees.OOBTree.OOBTree.
  38. * The full name is usd to support pickling and because it is not
  39. * possible to modify the __module__ slot of a type dynamically. (This
  40. * may be a bug in Python 2.2).
  41. *
  42. * The MODULE_NAME here used to be "BTrees._". We actually want the module
  43. * name to point to the Python module rather than the C, so the underline
  44. * is now removed.
  45. */
  46. #define MODULE_NAME "BTrees." MOD_NAME_PREFIX "BTree."
  47. static PyObject *sort_str, *reverse_str, *__setstate___str;
  48. static PyObject *_bucket_type_str, *max_internal_size_str, *max_leaf_size_str;
  49. static PyObject *ConflictError = NULL;
  50. static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
  51. #define ASSIGN(V,E) PyVar_Assign(&(V),(E))
  52. #define UNLESS(E) if (!(E))
  53. #define OBJECT(O) ((PyObject*)(O))
  54. #define MIN_BUCKET_ALLOC 16
  55. #define SameType_Check(O1, O2) (Py_TYPE((O1))==Py_TYPE((O2)))
  56. #define ASSERT(C, S, R) if (! (C)) { \
  57. PyErr_SetString(PyExc_AssertionError, (S)); return (R); }
  58. #ifdef NEED_LONG_LONG_SUPPORT
  59. /* Helper code used to support long long instead of int. */
  60. #ifndef PY_LONG_LONG
  61. #error "PY_LONG_LONG required but not defined"
  62. #endif
  63. #ifdef NEED_LONG_LONG_KEYS
  64. static int
  65. longlong_check(PyObject *ob)
  66. {
  67. if (INT_CHECK(ob))
  68. return 1;
  69. if (PyLong_Check(ob)) {
  70. int overflow;
  71. (void)PyLong_AsLongLongAndOverflow(ob, &overflow);
  72. if (overflow)
  73. goto overflow;
  74. return 1;
  75. }
  76. return 0;
  77. overflow:
  78. PyErr_SetString(PyExc_ValueError,
  79. "longlong_check: long integer out of range");
  80. return 0;
  81. }
  82. #endif
  83. static PyObject *
  84. longlong_as_object(PY_LONG_LONG val)
  85. {
  86. if ((val > LONG_MAX) || (val < LONG_MIN))
  87. return PyLong_FromLongLong(val);
  88. return INT_FROM_LONG((long)val);
  89. }
  90. static int
  91. longlong_convert(PyObject *ob, PY_LONG_LONG *value)
  92. {
  93. #ifndef PY3K
  94. if (PyInt_Check(ob))
  95. {
  96. (*value) = (PY_LONG_LONG)PyInt_AS_LONG(ob);
  97. return 1;
  98. }
  99. #endif
  100. if (!PyLong_Check(ob))
  101. {
  102. PyErr_SetString(PyExc_TypeError, "expected integer key");
  103. return 0;
  104. }
  105. else
  106. {
  107. PY_LONG_LONG val;
  108. int overflow;
  109. val = PyLong_AsLongLongAndOverflow(ob, &overflow);
  110. if (overflow)
  111. goto overflow;
  112. (*value) = val;
  113. return 1;
  114. }
  115. overflow:
  116. PyErr_SetString(PyExc_ValueError, "long integer out of range");
  117. return 0;
  118. }
  119. #endif /* NEED_LONG_LONG_SUPPORT */
  120. /* Various kinds of BTree and Bucket structs are instances of
  121. * "sized containers", and have a common initial layout:
  122. * The stuff needed for all Python objects, or all Persistent objects.
  123. * int size: The maximum number of things that could be contained
  124. * without growing the container.
  125. * int len: The number of things currently contained.
  126. *
  127. * Invariant: 0 <= len <= size.
  128. *
  129. * A sized container typically goes on to declare one or more pointers
  130. * to contiguous arrays with 'size' elements each, the initial 'len' of
  131. * which are currently in use.
  132. */
  133. #ifdef PERSISTENT
  134. #define sizedcontainer_HEAD \
  135. cPersistent_HEAD \
  136. int size; \
  137. int len;
  138. #else
  139. #define sizedcontainer_HEAD \
  140. PyObject_HEAD \
  141. int size; \
  142. int len;
  143. #endif
  144. /* Nothing is actually of type Sized, but (pointers to) BTree nodes and
  145. * Buckets can be cast to Sized* in contexts that only need to examine
  146. * the members common to all sized containers.
  147. */
  148. typedef struct Sized_s {
  149. sizedcontainer_HEAD
  150. } Sized;
  151. #define SIZED(O) ((Sized*)(O))
  152. /* A Bucket wraps contiguous vectors of keys and values. Keys are unique,
  153. * and stored in sorted order. The 'values' pointer may be NULL if the
  154. * Bucket is used to implement a set. Buckets serving as leafs of BTrees
  155. * are chained together via 'next', so that the entire BTree contents
  156. * can be traversed in sorted order quickly and easily.
  157. */
  158. typedef struct Bucket_s {
  159. sizedcontainer_HEAD
  160. struct Bucket_s *next; /* the bucket with the next-larger keys */
  161. KEY_TYPE *keys; /* 'len' keys, in increasing order */
  162. VALUE_TYPE *values; /* 'len' corresponding values; NULL if a set */
  163. } Bucket;
  164. #define BUCKET(O) ((Bucket*)(O))
  165. /* A BTree is complicated. See Maintainer.txt.
  166. */
  167. typedef struct BTreeItem_s {
  168. KEY_TYPE key;
  169. Sized *child; /* points to another BTree, or to a Bucket of some sort */
  170. } BTreeItem;
  171. typedef struct BTree_s {
  172. sizedcontainer_HEAD
  173. /* firstbucket points to the bucket containing the smallest key in
  174. * the BTree. This is found by traversing leftmost child pointers
  175. * (data[0].child) until reaching a Bucket.
  176. */
  177. Bucket *firstbucket;
  178. /* The BTree points to 'len' children, via the "child" fields of the data
  179. * array. There are len-1 keys in the 'key' fields, stored in increasing
  180. * order. data[0].key is unused. For i in 0 .. len-1, all keys reachable
  181. * from data[i].child are >= data[i].key and < data[i+1].key, at the
  182. * endpoints pretending that data[0].key is minus infinity and
  183. * data[len].key is positive infinity.
  184. */
  185. BTreeItem *data;
  186. long max_internal_size;
  187. long max_leaf_size;
  188. } BTree;
  189. static PyTypeObject BTreeType;
  190. static PyTypeObject BucketType;
  191. #define BTREE(O) ((BTree*)(O))
  192. /* Use BTREE_SEARCH to find which child pointer to follow.
  193. * RESULT An int lvalue to hold the index i such that SELF->data[i].child
  194. * is the correct node to search next.
  195. * SELF A pointer to a BTree node.
  196. * KEY The key you're looking for, of type KEY_TYPE.
  197. * ONERROR What to do if key comparison raises an exception; for example,
  198. * perhaps 'return NULL'.
  199. *
  200. * See Maintainer.txt for discussion: this is optimized in subtle ways.
  201. * It's recommended that you call this at the start of a routine, waiting
  202. * to check for self->len == 0 after.
  203. */
  204. #define BTREE_SEARCH(RESULT, SELF, KEY, ONERROR) { \
  205. int _lo = 0; \
  206. int _hi = (SELF)->len; \
  207. int _i, _cmp; \
  208. for (_i = _hi >> 1; _i > _lo; _i = (_lo + _hi) >> 1) { \
  209. TEST_KEY_SET_OR(_cmp, (SELF)->data[_i].key, (KEY)) \
  210. ONERROR; \
  211. if (_cmp < 0) _lo = _i; \
  212. else if (_cmp > 0) _hi = _i; \
  213. else /* equal */ break; \
  214. } \
  215. (RESULT) = _i; \
  216. }
  217. /* SetIteration structs are used in the internal set iteration protocol.
  218. * When you want to iterate over a set or bucket or BTree (even an
  219. * individual key!),
  220. * 1. Declare a new iterator:
  221. * SetIteration si = {0,0,0};
  222. * Using "{0,0,0}" or "{0,0}" appear most common. Only one {0} is
  223. * necssary. At least one must be given so that finiSetIteration() works
  224. * correctly even if you don't get around to calling initSetIteration().
  225. * 2. Initialize it via
  226. * initSetIteration(&si, PyObject *s, useValues)
  227. * It's an error if that returns an int < 0. In case of error on the
  228. * init call, calling finiSetIteration(&si) is optional. But if the
  229. * init call succeeds, you must eventually call finiSetIteration(),
  230. * and whether or not subsequent calls to si.next() fail.
  231. * 3. Get the first element:
  232. * if (si.next(&si) < 0) { there was an error }
  233. * If the set isn't empty, this sets si.position to an int >= 0,
  234. * si.key to the element's key (of type KEY_TYPE), and maybe si.value to
  235. * the element's value (of type VALUE_TYPE). si.value is defined
  236. * iff si.usesValue is true.
  237. * 4. Process all the elements:
  238. * while (si.position >= 0) {
  239. * do something with si.key and/or si.value;
  240. * if (si.next(&si) < 0) { there was an error; }
  241. * }
  242. * 5. Finalize the SetIterator:
  243. * finiSetIteration(&si);
  244. * This is mandatory! si may contain references to iterator objects,
  245. * keys and values, and they must be cleaned up else they'll leak. If
  246. * this were C++ we'd hide that in the destructor, but in C you have to
  247. * do it by hand.
  248. */
  249. typedef struct SetIteration_s
  250. {
  251. PyObject *set; /* the set, bucket, BTree, ..., being iterated */
  252. int position; /* initialized to 0; set to -1 by next() when done */
  253. int usesValue; /* true iff 'set' has values & we iterate them */
  254. KEY_TYPE key; /* next() sets to next key */
  255. VALUE_TYPE value; /* next() may set to next value */
  256. int (*next)(struct SetIteration_s*); /* function to get next key+value */
  257. } SetIteration;
  258. /* Finish the set iteration protocol. This MUST be called by everyone
  259. * who starts a set iteration, unless the initial call to initSetIteration
  260. * failed; in that case, and only that case, calling finiSetIteration is
  261. * optional.
  262. */
  263. static void
  264. finiSetIteration(SetIteration *i)
  265. {
  266. assert(i != NULL);
  267. if (i->set == NULL)
  268. return;
  269. Py_DECREF(i->set);
  270. i->set = NULL; /* so it doesn't hurt to call this again */
  271. if (i->position > 0) {
  272. /* next() was called at least once, but didn't finish iterating
  273. * (else position would be negative). So the cached key and
  274. * value need to be cleaned up.
  275. */
  276. DECREF_KEY(i->key);
  277. if (i->usesValue) {
  278. DECREF_VALUE(i->value);
  279. }
  280. }
  281. i->position = -1; /* stop any stray next calls from doing harm */
  282. }
  283. static PyObject *
  284. IndexError(int i)
  285. {
  286. PyObject *v;
  287. v = INT_FROM_LONG(i);
  288. if (!v) {
  289. v = Py_None;
  290. Py_INCREF(v);
  291. }
  292. PyErr_SetObject(PyExc_IndexError, v);
  293. Py_DECREF(v);
  294. return NULL;
  295. }
  296. /* Search for the bucket immediately preceding *current, in the bucket chain
  297. * starting at first. current, *current and first must not be NULL.
  298. *
  299. * Return:
  300. * 1 *current holds the correct bucket; this is a borrowed reference
  301. * 0 no such bucket exists; *current unaltered
  302. * -1 error; *current unaltered
  303. */
  304. static int
  305. PreviousBucket(Bucket **current, Bucket *first)
  306. {
  307. Bucket *trailing = NULL; /* first travels; trailing follows it */
  308. int result = 0;
  309. assert(current && *current && first);
  310. if (first == *current)
  311. return 0;
  312. do {
  313. trailing = first;
  314. PER_USE_OR_RETURN(first, -1);
  315. first = first->next;
  316. ((trailing)->state==cPersistent_STICKY_STATE
  317. &&
  318. ((trailing)->state=cPersistent_UPTODATE_STATE));
  319. PER_ACCESSED(trailing);
  320. if (first == *current) {
  321. *current = trailing;
  322. result = 1;
  323. break;
  324. }
  325. } while (first);
  326. return result;
  327. }
  328. static void *
  329. BTree_Malloc(size_t sz)
  330. {
  331. void *r;
  332. ASSERT(sz > 0, "non-positive size malloc", NULL);
  333. r = malloc(sz);
  334. if (r)
  335. return r;
  336. PyErr_NoMemory();
  337. return NULL;
  338. }
  339. static void *
  340. BTree_Realloc(void *p, size_t sz)
  341. {
  342. void *r;
  343. ASSERT(sz > 0, "non-positive size realloc", NULL);
  344. if (p)
  345. r = realloc(p, sz);
  346. else
  347. r = malloc(sz);
  348. UNLESS (r)
  349. PyErr_NoMemory();
  350. return r;
  351. }
  352. /* Shared keyword-argument list for BTree/Bucket
  353. * (iter)?(keys|values|items)
  354. */
  355. static char *search_keywords[] = {"min", "max",
  356. "excludemin", "excludemax",
  357. 0};
  358. #include "BTreeItemsTemplate.c"
  359. #include "BucketTemplate.c"
  360. #include "SetTemplate.c"
  361. #include "BTreeTemplate.c"
  362. #include "TreeSetTemplate.c"
  363. #include "SetOpTemplate.c"
  364. #include "MergeTemplate.c"
  365. static struct PyMethodDef module_methods[] = {
  366. {"difference", (PyCFunction) difference_m, METH_VARARGS,
  367. "difference(o1, o2) -- "
  368. "compute the difference between o1 and o2"
  369. },
  370. {"union", (PyCFunction) union_m, METH_VARARGS,
  371. "union(o1, o2) -- compute the union of o1 and o2\n"
  372. },
  373. {"intersection", (PyCFunction) intersection_m, METH_VARARGS,
  374. "intersection(o1, o2) -- "
  375. "compute the intersection of o1 and o2"
  376. },
  377. #ifdef MERGE
  378. {"weightedUnion", (PyCFunction) wunion_m, METH_VARARGS,
  379. "weightedUnion(o1, o2 [, w1, w2]) -- compute the union of o1 and o2\n"
  380. "\nw1 and w2 are weights."
  381. },
  382. {"weightedIntersection", (PyCFunction) wintersection_m, METH_VARARGS,
  383. "weightedIntersection(o1, o2 [, w1, w2]) -- "
  384. "compute the intersection of o1 and o2\n"
  385. "\nw1 and w2 are weights."
  386. },
  387. #endif
  388. #ifdef MULTI_INT_UNION
  389. {"multiunion", (PyCFunction) multiunion_m, METH_VARARGS,
  390. "multiunion(seq) -- compute union of a sequence of integer sets.\n"
  391. "\n"
  392. "Each element of seq must be an integer set, or convertible to one\n"
  393. "via the set iteration protocol. The union returned is an IISet."
  394. },
  395. #endif
  396. {NULL, NULL} /* sentinel */
  397. };
  398. static char BTree_module_documentation[] =
  399. "\n"
  400. MASTER_ID
  401. BTREEITEMSTEMPLATE_C
  402. "$Id$\n"
  403. BTREETEMPLATE_C
  404. BUCKETTEMPLATE_C
  405. KEYMACROS_H
  406. MERGETEMPLATE_C
  407. SETOPTEMPLATE_C
  408. SETTEMPLATE_C
  409. TREESETTEMPLATE_C
  410. VALUEMACROS_H
  411. BTREEITEMSTEMPLATE_C
  412. ;
  413. int
  414. init_persist_type(PyTypeObject *type)
  415. {
  416. #ifdef PY3K
  417. ((PyObject*)type)->ob_type = &PyType_Type;
  418. #else
  419. type->ob_type = &PyType_Type;
  420. #endif
  421. type->tp_base = cPersistenceCAPI->pertype;
  422. if (PyType_Ready(type) < 0)
  423. return 0;
  424. return 1;
  425. }
  426. #ifdef PY3K
  427. static struct PyModuleDef moduledef = {
  428. PyModuleDef_HEAD_INIT,
  429. "_" MOD_NAME_PREFIX "BTree", /* m_name */
  430. BTree_module_documentation, /* m_doc */
  431. -1, /* m_size */
  432. module_methods, /* m_methods */
  433. NULL, /* m_reload */
  434. NULL, /* m_traverse */
  435. NULL, /* m_clear */
  436. NULL, /* m_free */
  437. };
  438. #endif
  439. static PyObject*
  440. module_init(void)
  441. {
  442. PyObject *module, *mod_dict, *interfaces, *conflicterr;
  443. #ifdef KEY_TYPE_IS_PYOBJECT
  444. object_ = PyTuple_GetItem(Py_TYPE(Py_None)->tp_bases, 0);
  445. if (object_ == NULL)
  446. return NULL;
  447. #endif
  448. sort_str = INTERN("sort");
  449. if (!sort_str)
  450. return NULL;
  451. reverse_str = INTERN("reverse");
  452. if (!reverse_str)
  453. return NULL;
  454. __setstate___str = INTERN("__setstate__");
  455. if (!__setstate___str)
  456. return NULL;
  457. _bucket_type_str = INTERN("_bucket_type");
  458. if (!_bucket_type_str)
  459. return NULL;
  460. max_internal_size_str = INTERN("max_internal_size");
  461. if (! max_internal_size_str)
  462. return NULL;
  463. max_leaf_size_str = INTERN("max_leaf_size");
  464. if (! max_leaf_size_str)
  465. return NULL;
  466. /* Grab the ConflictError class */
  467. interfaces = PyImport_ImportModule("BTrees.Interfaces");
  468. if (interfaces != NULL)
  469. {
  470. conflicterr = PyObject_GetAttrString(interfaces, "BTreesConflictError");
  471. if (conflicterr != NULL)
  472. ConflictError = conflicterr;
  473. Py_DECREF(interfaces);
  474. }
  475. if (ConflictError == NULL)
  476. {
  477. Py_INCREF(PyExc_ValueError);
  478. ConflictError=PyExc_ValueError;
  479. }
  480. /* Initialize the PyPersist_C_API and the type objects. */
  481. #ifdef PY3K
  482. cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCapsule_Import(
  483. "persistent.cPersistence.CAPI", 0);
  484. #else
  485. cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCObject_Import(
  486. "persistent.cPersistence", "CAPI");
  487. #endif
  488. if (cPersistenceCAPI == NULL) {
  489. /* The Capsule API attempts to import 'persistent' and then
  490. * walk down to the specified attribute using getattr. If the C
  491. * extensions aren't available, this can result in an
  492. * AttributeError being raised. Let that percolate up as an
  493. * ImportError so it can be caught in the expected way.
  494. */
  495. if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_ImportError)) {
  496. PyErr_SetString(PyExc_ImportError, "persistent C extension unavailable");
  497. }
  498. return NULL;
  499. }
  500. #ifdef PY3K
  501. #define _SET_TYPE(typ) ((PyObject*)(&typ))->ob_type = &PyType_Type
  502. #else
  503. #define _SET_TYPE(typ) (typ).ob_type = &PyType_Type
  504. #endif
  505. _SET_TYPE(BTreeItemsType);
  506. _SET_TYPE(BTreeIter_Type);
  507. BTreeIter_Type.tp_getattro = PyObject_GenericGetAttr;
  508. BucketType.tp_new = PyType_GenericNew;
  509. SetType.tp_new = PyType_GenericNew;
  510. BTreeType.tp_new = PyType_GenericNew;
  511. TreeSetType.tp_new = PyType_GenericNew;
  512. if (!init_persist_type(&BucketType))
  513. return NULL;
  514. if (!init_persist_type(&BTreeType))
  515. return NULL;
  516. if (!init_persist_type(&SetType))
  517. return NULL;
  518. if (!init_persist_type(&TreeSetType))
  519. return NULL;
  520. if (PyDict_SetItem(BTreeType.tp_dict, _bucket_type_str,
  521. (PyObject *)&BucketType) < 0)
  522. {
  523. fprintf(stderr, "btree failed\n");
  524. return NULL;
  525. }
  526. if (PyDict_SetItem(TreeSetType.tp_dict, _bucket_type_str,
  527. (PyObject *)&SetType) < 0)
  528. {
  529. fprintf(stderr, "bucket failed\n");
  530. return NULL;
  531. }
  532. /* Create the module and add the functions */
  533. #ifdef PY3K
  534. module = PyModule_Create(&moduledef);
  535. #else
  536. module = Py_InitModule4("_" MOD_NAME_PREFIX "BTree",
  537. module_methods, BTree_module_documentation,
  538. (PyObject *)NULL, PYTHON_API_VERSION);
  539. #endif
  540. /* Add some symbolic constants to the module */
  541. mod_dict = PyModule_GetDict(module);
  542. if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "Bucket",
  543. (PyObject *)&BucketType) < 0)
  544. return NULL;
  545. if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "BTree",
  546. (PyObject *)&BTreeType) < 0)
  547. return NULL;
  548. if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "Set",
  549. (PyObject *)&SetType) < 0)
  550. return NULL;
  551. if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "TreeSet",
  552. (PyObject *)&TreeSetType) < 0)
  553. return NULL;
  554. if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "TreeIterator",
  555. (PyObject *)&BTreeIter_Type) < 0)
  556. return NULL;
  557. /* We also want to be able to access these constants without the prefix
  558. * so that code can more easily exchange modules (particularly the integer
  559. * and long modules, but also others). The TreeIterator is only internal,
  560. * so we don't bother to expose that.
  561. */
  562. if (PyDict_SetItemString(mod_dict, "Bucket",
  563. (PyObject *)&BucketType) < 0)
  564. return NULL;
  565. if (PyDict_SetItemString(mod_dict, "BTree",
  566. (PyObject *)&BTreeType) < 0)
  567. return NULL;
  568. if (PyDict_SetItemString(mod_dict, "Set",
  569. (PyObject *)&SetType) < 0)
  570. return NULL;
  571. if (PyDict_SetItemString(mod_dict, "TreeSet",
  572. (PyObject *)&TreeSetType) < 0)
  573. return NULL;
  574. #if defined(ZODB_64BIT_INTS) && defined(NEED_LONG_LONG_SUPPORT)
  575. if (PyDict_SetItemString(mod_dict, "using64bits", Py_True) < 0)
  576. return NULL;
  577. #else
  578. if (PyDict_SetItemString(mod_dict, "using64bits", Py_False) < 0)
  579. return NULL;
  580. #endif
  581. return module;
  582. }
  583. #ifdef PY3K
  584. PyMODINIT_FUNC INITMODULE(void)
  585. {
  586. return module_init();
  587. }
  588. #else
  589. PyMODINIT_FUNC INITMODULE(void)
  590. {
  591. module_init();
  592. }
  593. #endif