17db96d56Sopenharmony_ci 27db96d56Sopenharmony_ci/* GDBM module using dictionary interface */ 37db96d56Sopenharmony_ci/* Author: Anthony Baxter, after dbmmodule.c */ 47db96d56Sopenharmony_ci/* Doc strings: Mitch Chapman */ 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN 77db96d56Sopenharmony_ci#include "Python.h" 87db96d56Sopenharmony_ci#include "gdbm.h" 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci#include <fcntl.h> 117db96d56Sopenharmony_ci#include <stdlib.h> // free() 127db96d56Sopenharmony_ci#include <sys/stat.h> 137db96d56Sopenharmony_ci#include <sys/types.h> 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci#if defined(WIN32) && !defined(__CYGWIN__) 167db96d56Sopenharmony_ci#include "gdbmerrno.h" 177db96d56Sopenharmony_ciextern const char * gdbm_strerror(gdbm_error); 187db96d56Sopenharmony_ci#endif 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_citypedef struct { 217db96d56Sopenharmony_ci PyTypeObject *gdbm_type; 227db96d56Sopenharmony_ci PyObject *gdbm_error; 237db96d56Sopenharmony_ci} _gdbm_state; 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_cistatic inline _gdbm_state* 267db96d56Sopenharmony_ciget_gdbm_state(PyObject *module) 277db96d56Sopenharmony_ci{ 287db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 297db96d56Sopenharmony_ci assert(state != NULL); 307db96d56Sopenharmony_ci return (_gdbm_state *)state; 317db96d56Sopenharmony_ci} 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci/*[clinic input] 347db96d56Sopenharmony_cimodule _gdbm 357db96d56Sopenharmony_ciclass _gdbm.gdbm "gdbmobject *" "&Gdbmtype" 367db96d56Sopenharmony_ci[clinic start generated code]*/ 377db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/ 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ciPyDoc_STRVAR(gdbmmodule__doc__, 407db96d56Sopenharmony_ci"This module provides an interface to the GNU DBM (GDBM) library.\n\ 417db96d56Sopenharmony_ci\n\ 427db96d56Sopenharmony_ciThis module is quite similar to the dbm module, but uses GDBM instead to\n\ 437db96d56Sopenharmony_ciprovide some additional functionality. Please note that the file formats\n\ 447db96d56Sopenharmony_cicreated by GDBM and dbm are incompatible.\n\ 457db96d56Sopenharmony_ci\n\ 467db96d56Sopenharmony_ciGDBM objects behave like mappings (dictionaries), except that keys and\n\ 477db96d56Sopenharmony_civalues are always immutable bytes-like objects or strings. Printing\n\ 487db96d56Sopenharmony_cia GDBM object doesn't print the keys and values, and the items() and\n\ 497db96d56Sopenharmony_civalues() methods are not supported."); 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_citypedef struct { 527db96d56Sopenharmony_ci PyObject_HEAD 537db96d56Sopenharmony_ci Py_ssize_t di_size; /* -1 means recompute */ 547db96d56Sopenharmony_ci GDBM_FILE di_dbm; 557db96d56Sopenharmony_ci} gdbmobject; 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ci#include "clinic/_gdbmmodule.c.h" 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci#define check_gdbmobject_open(v, err) \ 607db96d56Sopenharmony_ci if ((v)->di_dbm == NULL) { \ 617db96d56Sopenharmony_ci PyErr_SetString(err, "GDBM object has already been closed"); \ 627db96d56Sopenharmony_ci return NULL; \ 637db96d56Sopenharmony_ci } 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ciPyDoc_STRVAR(gdbm_object__doc__, 667db96d56Sopenharmony_ci"This object represents a GDBM database.\n\ 677db96d56Sopenharmony_ciGDBM objects behave like mappings (dictionaries), except that keys and\n\ 687db96d56Sopenharmony_civalues are always immutable bytes-like objects or strings. Printing\n\ 697db96d56Sopenharmony_cia GDBM object doesn't print the keys and values, and the items() and\n\ 707db96d56Sopenharmony_civalues() methods are not supported.\n\ 717db96d56Sopenharmony_ci\n\ 727db96d56Sopenharmony_ciGDBM objects also support additional operations such as firstkey,\n\ 737db96d56Sopenharmony_cinextkey, reorganize, and sync."); 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_cistatic PyObject * 767db96d56Sopenharmony_cinewgdbmobject(_gdbm_state *state, const char *file, int flags, int mode) 777db96d56Sopenharmony_ci{ 787db96d56Sopenharmony_ci gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type); 797db96d56Sopenharmony_ci if (dp == NULL) { 807db96d56Sopenharmony_ci return NULL; 817db96d56Sopenharmony_ci } 827db96d56Sopenharmony_ci dp->di_size = -1; 837db96d56Sopenharmony_ci errno = 0; 847db96d56Sopenharmony_ci PyObject_GC_Track(dp); 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) { 877db96d56Sopenharmony_ci if (errno != 0) { 887db96d56Sopenharmony_ci PyErr_SetFromErrnoWithFilename(state->gdbm_error, file); 897db96d56Sopenharmony_ci } 907db96d56Sopenharmony_ci else { 917db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno)); 927db96d56Sopenharmony_ci } 937db96d56Sopenharmony_ci Py_DECREF(dp); 947db96d56Sopenharmony_ci return NULL; 957db96d56Sopenharmony_ci } 967db96d56Sopenharmony_ci return (PyObject *)dp; 977db96d56Sopenharmony_ci} 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci/* Methods */ 1007db96d56Sopenharmony_cistatic int 1017db96d56Sopenharmony_cigdbm_traverse(gdbmobject *dp, visitproc visit, void *arg) 1027db96d56Sopenharmony_ci{ 1037db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(dp)); 1047db96d56Sopenharmony_ci return 0; 1057db96d56Sopenharmony_ci} 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_cistatic void 1087db96d56Sopenharmony_cigdbm_dealloc(gdbmobject *dp) 1097db96d56Sopenharmony_ci{ 1107db96d56Sopenharmony_ci PyObject_GC_UnTrack(dp); 1117db96d56Sopenharmony_ci if (dp->di_dbm) { 1127db96d56Sopenharmony_ci gdbm_close(dp->di_dbm); 1137db96d56Sopenharmony_ci } 1147db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(dp); 1157db96d56Sopenharmony_ci tp->tp_free(dp); 1167db96d56Sopenharmony_ci Py_DECREF(tp); 1177db96d56Sopenharmony_ci} 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_cistatic Py_ssize_t 1207db96d56Sopenharmony_cigdbm_length(gdbmobject *dp) 1217db96d56Sopenharmony_ci{ 1227db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp)); 1237db96d56Sopenharmony_ci if (dp->di_dbm == NULL) { 1247db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, "GDBM object has already been closed"); 1257db96d56Sopenharmony_ci return -1; 1267db96d56Sopenharmony_ci } 1277db96d56Sopenharmony_ci if (dp->di_size < 0) { 1287db96d56Sopenharmony_ci#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11 1297db96d56Sopenharmony_ci errno = 0; 1307db96d56Sopenharmony_ci gdbm_count_t count; 1317db96d56Sopenharmony_ci if (gdbm_count(dp->di_dbm, &count) == -1) { 1327db96d56Sopenharmony_ci if (errno != 0) { 1337db96d56Sopenharmony_ci PyErr_SetFromErrno(state->gdbm_error); 1347db96d56Sopenharmony_ci } 1357db96d56Sopenharmony_ci else { 1367db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno)); 1377db96d56Sopenharmony_ci } 1387db96d56Sopenharmony_ci return -1; 1397db96d56Sopenharmony_ci } 1407db96d56Sopenharmony_ci if (count > PY_SSIZE_T_MAX) { 1417db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX"); 1427db96d56Sopenharmony_ci return -1; 1437db96d56Sopenharmony_ci } 1447db96d56Sopenharmony_ci dp->di_size = count; 1457db96d56Sopenharmony_ci#else 1467db96d56Sopenharmony_ci datum key,okey; 1477db96d56Sopenharmony_ci okey.dsize=0; 1487db96d56Sopenharmony_ci okey.dptr=NULL; 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci Py_ssize_t size = 0; 1517db96d56Sopenharmony_ci for (key = gdbm_firstkey(dp->di_dbm); key.dptr; 1527db96d56Sopenharmony_ci key = gdbm_nextkey(dp->di_dbm,okey)) { 1537db96d56Sopenharmony_ci size++; 1547db96d56Sopenharmony_ci if (okey.dsize) { 1557db96d56Sopenharmony_ci free(okey.dptr); 1567db96d56Sopenharmony_ci } 1577db96d56Sopenharmony_ci okey=key; 1587db96d56Sopenharmony_ci } 1597db96d56Sopenharmony_ci dp->di_size = size; 1607db96d56Sopenharmony_ci#endif 1617db96d56Sopenharmony_ci } 1627db96d56Sopenharmony_ci return dp->di_size; 1637db96d56Sopenharmony_ci} 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci// Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size). 1667db96d56Sopenharmony_ci// This function is needed to support PY_SSIZE_T_CLEAN. 1677db96d56Sopenharmony_ci// Return 1 on success, same to PyArg_Parse(). 1687db96d56Sopenharmony_cistatic int 1697db96d56Sopenharmony_ciparse_datum(PyObject *o, datum *d, const char *failmsg) 1707db96d56Sopenharmony_ci{ 1717db96d56Sopenharmony_ci Py_ssize_t size; 1727db96d56Sopenharmony_ci if (!PyArg_Parse(o, "s#", &d->dptr, &size)) { 1737db96d56Sopenharmony_ci if (failmsg != NULL) { 1747db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, failmsg); 1757db96d56Sopenharmony_ci } 1767db96d56Sopenharmony_ci return 0; 1777db96d56Sopenharmony_ci } 1787db96d56Sopenharmony_ci if (INT_MAX < size) { 1797db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); 1807db96d56Sopenharmony_ci return 0; 1817db96d56Sopenharmony_ci } 1827db96d56Sopenharmony_ci d->dsize = size; 1837db96d56Sopenharmony_ci return 1; 1847db96d56Sopenharmony_ci} 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_cistatic PyObject * 1877db96d56Sopenharmony_cigdbm_subscript(gdbmobject *dp, PyObject *key) 1887db96d56Sopenharmony_ci{ 1897db96d56Sopenharmony_ci PyObject *v; 1907db96d56Sopenharmony_ci datum drec, krec; 1917db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp)); 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci if (!parse_datum(key, &krec, NULL)) { 1947db96d56Sopenharmony_ci return NULL; 1957db96d56Sopenharmony_ci } 1967db96d56Sopenharmony_ci if (dp->di_dbm == NULL) { 1977db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, 1987db96d56Sopenharmony_ci "GDBM object has already been closed"); 1997db96d56Sopenharmony_ci return NULL; 2007db96d56Sopenharmony_ci } 2017db96d56Sopenharmony_ci drec = gdbm_fetch(dp->di_dbm, krec); 2027db96d56Sopenharmony_ci if (drec.dptr == 0) { 2037db96d56Sopenharmony_ci PyErr_SetObject(PyExc_KeyError, key); 2047db96d56Sopenharmony_ci return NULL; 2057db96d56Sopenharmony_ci } 2067db96d56Sopenharmony_ci v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize); 2077db96d56Sopenharmony_ci free(drec.dptr); 2087db96d56Sopenharmony_ci return v; 2097db96d56Sopenharmony_ci} 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci/*[clinic input] 2127db96d56Sopenharmony_ci_gdbm.gdbm.get 2137db96d56Sopenharmony_ci 2147db96d56Sopenharmony_ci key: object 2157db96d56Sopenharmony_ci default: object = None 2167db96d56Sopenharmony_ci / 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ciGet the value for key, or default if not present. 2197db96d56Sopenharmony_ci[clinic start generated code]*/ 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_cistatic PyObject * 2227db96d56Sopenharmony_ci_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value) 2237db96d56Sopenharmony_ci/*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/ 2247db96d56Sopenharmony_ci{ 2257db96d56Sopenharmony_ci PyObject *res; 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci res = gdbm_subscript(self, key); 2287db96d56Sopenharmony_ci if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { 2297db96d56Sopenharmony_ci PyErr_Clear(); 2307db96d56Sopenharmony_ci Py_INCREF(default_value); 2317db96d56Sopenharmony_ci return default_value; 2327db96d56Sopenharmony_ci } 2337db96d56Sopenharmony_ci return res; 2347db96d56Sopenharmony_ci} 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_cistatic int 2377db96d56Sopenharmony_cigdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w) 2387db96d56Sopenharmony_ci{ 2397db96d56Sopenharmony_ci datum krec, drec; 2407db96d56Sopenharmony_ci const char *failmsg = "gdbm mappings have bytes or string indices only"; 2417db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp)); 2427db96d56Sopenharmony_ci 2437db96d56Sopenharmony_ci if (!parse_datum(v, &krec, failmsg)) { 2447db96d56Sopenharmony_ci return -1; 2457db96d56Sopenharmony_ci } 2467db96d56Sopenharmony_ci if (dp->di_dbm == NULL) { 2477db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, 2487db96d56Sopenharmony_ci "GDBM object has already been closed"); 2497db96d56Sopenharmony_ci return -1; 2507db96d56Sopenharmony_ci } 2517db96d56Sopenharmony_ci dp->di_size = -1; 2527db96d56Sopenharmony_ci if (w == NULL) { 2537db96d56Sopenharmony_ci if (gdbm_delete(dp->di_dbm, krec) < 0) { 2547db96d56Sopenharmony_ci if (gdbm_errno == GDBM_ITEM_NOT_FOUND) { 2557db96d56Sopenharmony_ci PyErr_SetObject(PyExc_KeyError, v); 2567db96d56Sopenharmony_ci } 2577db96d56Sopenharmony_ci else { 2587db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno)); 2597db96d56Sopenharmony_ci } 2607db96d56Sopenharmony_ci return -1; 2617db96d56Sopenharmony_ci } 2627db96d56Sopenharmony_ci } 2637db96d56Sopenharmony_ci else { 2647db96d56Sopenharmony_ci if (!parse_datum(w, &drec, failmsg)) { 2657db96d56Sopenharmony_ci return -1; 2667db96d56Sopenharmony_ci } 2677db96d56Sopenharmony_ci errno = 0; 2687db96d56Sopenharmony_ci if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) { 2697db96d56Sopenharmony_ci if (errno != 0) 2707db96d56Sopenharmony_ci PyErr_SetFromErrno(state->gdbm_error); 2717db96d56Sopenharmony_ci else 2727db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, 2737db96d56Sopenharmony_ci gdbm_strerror(gdbm_errno)); 2747db96d56Sopenharmony_ci return -1; 2757db96d56Sopenharmony_ci } 2767db96d56Sopenharmony_ci } 2777db96d56Sopenharmony_ci return 0; 2787db96d56Sopenharmony_ci} 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci/*[clinic input] 2817db96d56Sopenharmony_ci_gdbm.gdbm.setdefault 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci key: object 2847db96d56Sopenharmony_ci default: object = None 2857db96d56Sopenharmony_ci / 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ciGet value for key, or set it to default and return default if not present. 2887db96d56Sopenharmony_ci[clinic start generated code]*/ 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_cistatic PyObject * 2917db96d56Sopenharmony_ci_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key, 2927db96d56Sopenharmony_ci PyObject *default_value) 2937db96d56Sopenharmony_ci/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/ 2947db96d56Sopenharmony_ci{ 2957db96d56Sopenharmony_ci PyObject *res; 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ci res = gdbm_subscript(self, key); 2987db96d56Sopenharmony_ci if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { 2997db96d56Sopenharmony_ci PyErr_Clear(); 3007db96d56Sopenharmony_ci if (gdbm_ass_sub(self, key, default_value) < 0) 3017db96d56Sopenharmony_ci return NULL; 3027db96d56Sopenharmony_ci return gdbm_subscript(self, key); 3037db96d56Sopenharmony_ci } 3047db96d56Sopenharmony_ci return res; 3057db96d56Sopenharmony_ci} 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci/*[clinic input] 3087db96d56Sopenharmony_ci_gdbm.gdbm.close 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_ciClose the database. 3117db96d56Sopenharmony_ci[clinic start generated code]*/ 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_cistatic PyObject * 3147db96d56Sopenharmony_ci_gdbm_gdbm_close_impl(gdbmobject *self) 3157db96d56Sopenharmony_ci/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/ 3167db96d56Sopenharmony_ci{ 3177db96d56Sopenharmony_ci if (self->di_dbm) { 3187db96d56Sopenharmony_ci gdbm_close(self->di_dbm); 3197db96d56Sopenharmony_ci } 3207db96d56Sopenharmony_ci self->di_dbm = NULL; 3217db96d56Sopenharmony_ci Py_RETURN_NONE; 3227db96d56Sopenharmony_ci} 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ci/* XXX Should return a set or a set view */ 3257db96d56Sopenharmony_ci/*[clinic input] 3267db96d56Sopenharmony_ci_gdbm.gdbm.keys 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci cls: defining_class 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ciGet a list of all keys in the database. 3317db96d56Sopenharmony_ci[clinic start generated code]*/ 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_cistatic PyObject * 3347db96d56Sopenharmony_ci_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls) 3357db96d56Sopenharmony_ci/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/ 3367db96d56Sopenharmony_ci{ 3377db96d56Sopenharmony_ci PyObject *v, *item; 3387db96d56Sopenharmony_ci datum key, nextkey; 3397db96d56Sopenharmony_ci int err; 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(cls); 3427db96d56Sopenharmony_ci assert(state != NULL); 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) { 3457db96d56Sopenharmony_ci PyErr_BadInternalCall(); 3467db96d56Sopenharmony_ci return NULL; 3477db96d56Sopenharmony_ci } 3487db96d56Sopenharmony_ci check_gdbmobject_open(self, state->gdbm_error); 3497db96d56Sopenharmony_ci 3507db96d56Sopenharmony_ci v = PyList_New(0); 3517db96d56Sopenharmony_ci if (v == NULL) 3527db96d56Sopenharmony_ci return NULL; 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci key = gdbm_firstkey(self->di_dbm); 3557db96d56Sopenharmony_ci while (key.dptr) { 3567db96d56Sopenharmony_ci item = PyBytes_FromStringAndSize(key.dptr, key.dsize); 3577db96d56Sopenharmony_ci if (item == NULL) { 3587db96d56Sopenharmony_ci free(key.dptr); 3597db96d56Sopenharmony_ci Py_DECREF(v); 3607db96d56Sopenharmony_ci return NULL; 3617db96d56Sopenharmony_ci } 3627db96d56Sopenharmony_ci err = PyList_Append(v, item); 3637db96d56Sopenharmony_ci Py_DECREF(item); 3647db96d56Sopenharmony_ci if (err != 0) { 3657db96d56Sopenharmony_ci free(key.dptr); 3667db96d56Sopenharmony_ci Py_DECREF(v); 3677db96d56Sopenharmony_ci return NULL; 3687db96d56Sopenharmony_ci } 3697db96d56Sopenharmony_ci nextkey = gdbm_nextkey(self->di_dbm, key); 3707db96d56Sopenharmony_ci free(key.dptr); 3717db96d56Sopenharmony_ci key = nextkey; 3727db96d56Sopenharmony_ci } 3737db96d56Sopenharmony_ci return v; 3747db96d56Sopenharmony_ci} 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_cistatic int 3777db96d56Sopenharmony_cigdbm_contains(PyObject *self, PyObject *arg) 3787db96d56Sopenharmony_ci{ 3797db96d56Sopenharmony_ci gdbmobject *dp = (gdbmobject *)self; 3807db96d56Sopenharmony_ci datum key; 3817db96d56Sopenharmony_ci Py_ssize_t size; 3827db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp)); 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci if ((dp)->di_dbm == NULL) { 3857db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, 3867db96d56Sopenharmony_ci "GDBM object has already been closed"); 3877db96d56Sopenharmony_ci return -1; 3887db96d56Sopenharmony_ci } 3897db96d56Sopenharmony_ci if (PyUnicode_Check(arg)) { 3907db96d56Sopenharmony_ci key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size); 3917db96d56Sopenharmony_ci key.dsize = size; 3927db96d56Sopenharmony_ci if (key.dptr == NULL) 3937db96d56Sopenharmony_ci return -1; 3947db96d56Sopenharmony_ci } 3957db96d56Sopenharmony_ci else if (!PyBytes_Check(arg)) { 3967db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 3977db96d56Sopenharmony_ci "gdbm key must be bytes or string, not %.100s", 3987db96d56Sopenharmony_ci Py_TYPE(arg)->tp_name); 3997db96d56Sopenharmony_ci return -1; 4007db96d56Sopenharmony_ci } 4017db96d56Sopenharmony_ci else { 4027db96d56Sopenharmony_ci key.dptr = PyBytes_AS_STRING(arg); 4037db96d56Sopenharmony_ci key.dsize = PyBytes_GET_SIZE(arg); 4047db96d56Sopenharmony_ci } 4057db96d56Sopenharmony_ci return gdbm_exists(dp->di_dbm, key); 4067db96d56Sopenharmony_ci} 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci/*[clinic input] 4097db96d56Sopenharmony_ci_gdbm.gdbm.firstkey 4107db96d56Sopenharmony_ci 4117db96d56Sopenharmony_ci cls: defining_class 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ciReturn the starting key for the traversal. 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ciIt's possible to loop over every key in the database using this method 4167db96d56Sopenharmony_ciand the nextkey() method. The traversal is ordered by GDBM's internal 4177db96d56Sopenharmony_cihash values, and won't be sorted by the key values. 4187db96d56Sopenharmony_ci[clinic start generated code]*/ 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_cistatic PyObject * 4217db96d56Sopenharmony_ci_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls) 4227db96d56Sopenharmony_ci/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/ 4237db96d56Sopenharmony_ci{ 4247db96d56Sopenharmony_ci PyObject *v; 4257db96d56Sopenharmony_ci datum key; 4267db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(cls); 4277db96d56Sopenharmony_ci assert(state != NULL); 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci check_gdbmobject_open(self, state->gdbm_error); 4307db96d56Sopenharmony_ci key = gdbm_firstkey(self->di_dbm); 4317db96d56Sopenharmony_ci if (key.dptr) { 4327db96d56Sopenharmony_ci v = PyBytes_FromStringAndSize(key.dptr, key.dsize); 4337db96d56Sopenharmony_ci free(key.dptr); 4347db96d56Sopenharmony_ci return v; 4357db96d56Sopenharmony_ci } 4367db96d56Sopenharmony_ci else { 4377db96d56Sopenharmony_ci Py_RETURN_NONE; 4387db96d56Sopenharmony_ci } 4397db96d56Sopenharmony_ci} 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci/*[clinic input] 4427db96d56Sopenharmony_ci_gdbm.gdbm.nextkey 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci cls: defining_class 4457db96d56Sopenharmony_ci key: str(accept={str, robuffer}, zeroes=True) 4467db96d56Sopenharmony_ci / 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ciReturns the key that follows key in the traversal. 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ciThe following code prints every key in the database db, without having 4517db96d56Sopenharmony_cito create a list in memory that contains them all: 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci k = db.firstkey() 4547db96d56Sopenharmony_ci while k is not None: 4557db96d56Sopenharmony_ci print(k) 4567db96d56Sopenharmony_ci k = db.nextkey(k) 4577db96d56Sopenharmony_ci[clinic start generated code]*/ 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_cistatic PyObject * 4607db96d56Sopenharmony_ci_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key, 4617db96d56Sopenharmony_ci Py_ssize_t key_length) 4627db96d56Sopenharmony_ci/*[clinic end generated code: output=c81a69300ef41766 input=365e297bc0b3db48]*/ 4637db96d56Sopenharmony_ci{ 4647db96d56Sopenharmony_ci PyObject *v; 4657db96d56Sopenharmony_ci datum dbm_key, nextkey; 4667db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(cls); 4677db96d56Sopenharmony_ci assert(state != NULL); 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci dbm_key.dptr = (char *)key; 4707db96d56Sopenharmony_ci dbm_key.dsize = key_length; 4717db96d56Sopenharmony_ci check_gdbmobject_open(self, state->gdbm_error); 4727db96d56Sopenharmony_ci nextkey = gdbm_nextkey(self->di_dbm, dbm_key); 4737db96d56Sopenharmony_ci if (nextkey.dptr) { 4747db96d56Sopenharmony_ci v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize); 4757db96d56Sopenharmony_ci free(nextkey.dptr); 4767db96d56Sopenharmony_ci return v; 4777db96d56Sopenharmony_ci } 4787db96d56Sopenharmony_ci else { 4797db96d56Sopenharmony_ci Py_RETURN_NONE; 4807db96d56Sopenharmony_ci } 4817db96d56Sopenharmony_ci} 4827db96d56Sopenharmony_ci 4837db96d56Sopenharmony_ci/*[clinic input] 4847db96d56Sopenharmony_ci_gdbm.gdbm.reorganize 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci cls: defining_class 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ciReorganize the database. 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ciIf you have carried out a lot of deletions and would like to shrink 4917db96d56Sopenharmony_cithe space used by the GDBM file, this routine will reorganize the 4927db96d56Sopenharmony_cidatabase. GDBM will not shorten the length of a database file except 4937db96d56Sopenharmony_ciby using this reorganization; otherwise, deleted file space will be 4947db96d56Sopenharmony_cikept and reused as new (key,value) pairs are added. 4957db96d56Sopenharmony_ci[clinic start generated code]*/ 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_cistatic PyObject * 4987db96d56Sopenharmony_ci_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls) 4997db96d56Sopenharmony_ci/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/ 5007db96d56Sopenharmony_ci{ 5017db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(cls); 5027db96d56Sopenharmony_ci assert(state != NULL); 5037db96d56Sopenharmony_ci check_gdbmobject_open(self, state->gdbm_error); 5047db96d56Sopenharmony_ci errno = 0; 5057db96d56Sopenharmony_ci if (gdbm_reorganize(self->di_dbm) < 0) { 5067db96d56Sopenharmony_ci if (errno != 0) 5077db96d56Sopenharmony_ci PyErr_SetFromErrno(state->gdbm_error); 5087db96d56Sopenharmony_ci else 5097db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno)); 5107db96d56Sopenharmony_ci return NULL; 5117db96d56Sopenharmony_ci } 5127db96d56Sopenharmony_ci Py_RETURN_NONE; 5137db96d56Sopenharmony_ci} 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci/*[clinic input] 5167db96d56Sopenharmony_ci_gdbm.gdbm.sync 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci cls: defining_class 5197db96d56Sopenharmony_ci 5207db96d56Sopenharmony_ciFlush the database to the disk file. 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ciWhen the database has been opened in fast mode, this method forces 5237db96d56Sopenharmony_ciany unwritten data to be written to the disk. 5247db96d56Sopenharmony_ci[clinic start generated code]*/ 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_cistatic PyObject * 5277db96d56Sopenharmony_ci_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls) 5287db96d56Sopenharmony_ci/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/ 5297db96d56Sopenharmony_ci{ 5307db96d56Sopenharmony_ci _gdbm_state *state = PyType_GetModuleState(cls); 5317db96d56Sopenharmony_ci assert(state != NULL); 5327db96d56Sopenharmony_ci check_gdbmobject_open(self, state->gdbm_error); 5337db96d56Sopenharmony_ci gdbm_sync(self->di_dbm); 5347db96d56Sopenharmony_ci Py_RETURN_NONE; 5357db96d56Sopenharmony_ci} 5367db96d56Sopenharmony_ci 5377db96d56Sopenharmony_cistatic PyObject * 5387db96d56Sopenharmony_cigdbm__enter__(PyObject *self, PyObject *args) 5397db96d56Sopenharmony_ci{ 5407db96d56Sopenharmony_ci Py_INCREF(self); 5417db96d56Sopenharmony_ci return self; 5427db96d56Sopenharmony_ci} 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_cistatic PyObject * 5457db96d56Sopenharmony_cigdbm__exit__(PyObject *self, PyObject *args) 5467db96d56Sopenharmony_ci{ 5477db96d56Sopenharmony_ci return _gdbm_gdbm_close_impl((gdbmobject *)self); 5487db96d56Sopenharmony_ci} 5497db96d56Sopenharmony_ci 5507db96d56Sopenharmony_cistatic PyMethodDef gdbm_methods[] = { 5517db96d56Sopenharmony_ci _GDBM_GDBM_CLOSE_METHODDEF 5527db96d56Sopenharmony_ci _GDBM_GDBM_KEYS_METHODDEF 5537db96d56Sopenharmony_ci _GDBM_GDBM_FIRSTKEY_METHODDEF 5547db96d56Sopenharmony_ci _GDBM_GDBM_NEXTKEY_METHODDEF 5557db96d56Sopenharmony_ci _GDBM_GDBM_REORGANIZE_METHODDEF 5567db96d56Sopenharmony_ci _GDBM_GDBM_SYNC_METHODDEF 5577db96d56Sopenharmony_ci _GDBM_GDBM_GET_METHODDEF 5587db96d56Sopenharmony_ci _GDBM_GDBM_SETDEFAULT_METHODDEF 5597db96d56Sopenharmony_ci {"__enter__", gdbm__enter__, METH_NOARGS, NULL}, 5607db96d56Sopenharmony_ci {"__exit__", gdbm__exit__, METH_VARARGS, NULL}, 5617db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 5627db96d56Sopenharmony_ci}; 5637db96d56Sopenharmony_ci 5647db96d56Sopenharmony_cistatic PyType_Slot gdbmtype_spec_slots[] = { 5657db96d56Sopenharmony_ci {Py_tp_dealloc, gdbm_dealloc}, 5667db96d56Sopenharmony_ci {Py_tp_traverse, gdbm_traverse}, 5677db96d56Sopenharmony_ci {Py_tp_methods, gdbm_methods}, 5687db96d56Sopenharmony_ci {Py_sq_contains, gdbm_contains}, 5697db96d56Sopenharmony_ci {Py_mp_length, gdbm_length}, 5707db96d56Sopenharmony_ci {Py_mp_subscript, gdbm_subscript}, 5717db96d56Sopenharmony_ci {Py_mp_ass_subscript, gdbm_ass_sub}, 5727db96d56Sopenharmony_ci {Py_tp_doc, (char*)gdbm_object__doc__}, 5737db96d56Sopenharmony_ci {0, 0} 5747db96d56Sopenharmony_ci}; 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_cistatic PyType_Spec gdbmtype_spec = { 5777db96d56Sopenharmony_ci .name = "_gdbm.gdbm", 5787db96d56Sopenharmony_ci .basicsize = sizeof(gdbmobject), 5797db96d56Sopenharmony_ci // Calling PyType_GetModuleState() on a subclass is not safe. 5807db96d56Sopenharmony_ci // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag 5817db96d56Sopenharmony_ci // which prevents to create a subclass. 5827db96d56Sopenharmony_ci // So calling PyType_GetModuleState() in this file is always safe. 5837db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | 5847db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), 5857db96d56Sopenharmony_ci .slots = gdbmtype_spec_slots, 5867db96d56Sopenharmony_ci}; 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_ci/* ----------------------------------------------------------------- */ 5897db96d56Sopenharmony_ci 5907db96d56Sopenharmony_ci/*[clinic input] 5917db96d56Sopenharmony_ci_gdbm.open as dbmopen 5927db96d56Sopenharmony_ci 5937db96d56Sopenharmony_ci filename: object 5947db96d56Sopenharmony_ci flags: str="r" 5957db96d56Sopenharmony_ci mode: int(py_default="0o666") = 0o666 5967db96d56Sopenharmony_ci / 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ciOpen a dbm database and return a dbm object. 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ciThe filename argument is the name of the database file. 6017db96d56Sopenharmony_ci 6027db96d56Sopenharmony_ciThe optional flags argument can be 'r' (to open an existing database 6037db96d56Sopenharmony_cifor reading only -- default), 'w' (to open an existing database for 6047db96d56Sopenharmony_cireading and writing), 'c' (which creates the database if it doesn't 6057db96d56Sopenharmony_ciexist), or 'n' (which always creates a new empty database). 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_ciSome versions of gdbm support additional flags which must be 6087db96d56Sopenharmony_ciappended to one of the flags described above. The module constant 6097db96d56Sopenharmony_ci'open_flags' is a string of valid additional flags. The 'f' flag 6107db96d56Sopenharmony_ciopens the database in fast mode; altered data will not automatically 6117db96d56Sopenharmony_cibe written to the disk after every change. This results in faster 6127db96d56Sopenharmony_ciwrites to the database, but may result in an inconsistent database 6137db96d56Sopenharmony_ciif the program crashes while the database is still open. Use the 6147db96d56Sopenharmony_cisync() method to force any unwritten data to be written to the disk. 6157db96d56Sopenharmony_ciThe 's' flag causes all database operations to be synchronized to 6167db96d56Sopenharmony_cidisk. The 'u' flag disables locking of the database file. 6177db96d56Sopenharmony_ci 6187db96d56Sopenharmony_ciThe optional mode argument is the Unix mode of the file, used only 6197db96d56Sopenharmony_ciwhen the database has to be created. It defaults to octal 0o666. 6207db96d56Sopenharmony_ci[clinic start generated code]*/ 6217db96d56Sopenharmony_ci 6227db96d56Sopenharmony_cistatic PyObject * 6237db96d56Sopenharmony_cidbmopen_impl(PyObject *module, PyObject *filename, const char *flags, 6247db96d56Sopenharmony_ci int mode) 6257db96d56Sopenharmony_ci/*[clinic end generated code: output=9527750f5df90764 input=bca6ec81dc49292c]*/ 6267db96d56Sopenharmony_ci{ 6277db96d56Sopenharmony_ci int iflags; 6287db96d56Sopenharmony_ci _gdbm_state *state = get_gdbm_state(module); 6297db96d56Sopenharmony_ci assert(state != NULL); 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci switch (flags[0]) { 6327db96d56Sopenharmony_ci case 'r': 6337db96d56Sopenharmony_ci iflags = GDBM_READER; 6347db96d56Sopenharmony_ci break; 6357db96d56Sopenharmony_ci case 'w': 6367db96d56Sopenharmony_ci iflags = GDBM_WRITER; 6377db96d56Sopenharmony_ci break; 6387db96d56Sopenharmony_ci case 'c': 6397db96d56Sopenharmony_ci iflags = GDBM_WRCREAT; 6407db96d56Sopenharmony_ci break; 6417db96d56Sopenharmony_ci case 'n': 6427db96d56Sopenharmony_ci iflags = GDBM_NEWDB; 6437db96d56Sopenharmony_ci break; 6447db96d56Sopenharmony_ci default: 6457db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, 6467db96d56Sopenharmony_ci "First flag must be one of 'r', 'w', 'c' or 'n'"); 6477db96d56Sopenharmony_ci return NULL; 6487db96d56Sopenharmony_ci } 6497db96d56Sopenharmony_ci for (flags++; *flags != '\0'; flags++) { 6507db96d56Sopenharmony_ci char buf[40]; 6517db96d56Sopenharmony_ci switch (*flags) { 6527db96d56Sopenharmony_ci#ifdef GDBM_FAST 6537db96d56Sopenharmony_ci case 'f': 6547db96d56Sopenharmony_ci iflags |= GDBM_FAST; 6557db96d56Sopenharmony_ci break; 6567db96d56Sopenharmony_ci#endif 6577db96d56Sopenharmony_ci#ifdef GDBM_SYNC 6587db96d56Sopenharmony_ci case 's': 6597db96d56Sopenharmony_ci iflags |= GDBM_SYNC; 6607db96d56Sopenharmony_ci break; 6617db96d56Sopenharmony_ci#endif 6627db96d56Sopenharmony_ci#ifdef GDBM_NOLOCK 6637db96d56Sopenharmony_ci case 'u': 6647db96d56Sopenharmony_ci iflags |= GDBM_NOLOCK; 6657db96d56Sopenharmony_ci break; 6667db96d56Sopenharmony_ci#endif 6677db96d56Sopenharmony_ci default: 6687db96d56Sopenharmony_ci PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.", 6697db96d56Sopenharmony_ci *flags); 6707db96d56Sopenharmony_ci PyErr_SetString(state->gdbm_error, buf); 6717db96d56Sopenharmony_ci return NULL; 6727db96d56Sopenharmony_ci } 6737db96d56Sopenharmony_ci } 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci PyObject *filenamebytes; 6767db96d56Sopenharmony_ci if (!PyUnicode_FSConverter(filename, &filenamebytes)) { 6777db96d56Sopenharmony_ci return NULL; 6787db96d56Sopenharmony_ci } 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci const char *name = PyBytes_AS_STRING(filenamebytes); 6817db96d56Sopenharmony_ci if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { 6827db96d56Sopenharmony_ci Py_DECREF(filenamebytes); 6837db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "embedded null character"); 6847db96d56Sopenharmony_ci return NULL; 6857db96d56Sopenharmony_ci } 6867db96d56Sopenharmony_ci PyObject *self = newgdbmobject(state, name, iflags, mode); 6877db96d56Sopenharmony_ci Py_DECREF(filenamebytes); 6887db96d56Sopenharmony_ci return self; 6897db96d56Sopenharmony_ci} 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_cistatic const char gdbmmodule_open_flags[] = "rwcn" 6927db96d56Sopenharmony_ci#ifdef GDBM_FAST 6937db96d56Sopenharmony_ci "f" 6947db96d56Sopenharmony_ci#endif 6957db96d56Sopenharmony_ci#ifdef GDBM_SYNC 6967db96d56Sopenharmony_ci "s" 6977db96d56Sopenharmony_ci#endif 6987db96d56Sopenharmony_ci#ifdef GDBM_NOLOCK 6997db96d56Sopenharmony_ci "u" 7007db96d56Sopenharmony_ci#endif 7017db96d56Sopenharmony_ci ; 7027db96d56Sopenharmony_ci 7037db96d56Sopenharmony_cistatic PyMethodDef _gdbm_module_methods[] = { 7047db96d56Sopenharmony_ci DBMOPEN_METHODDEF 7057db96d56Sopenharmony_ci { 0, 0 }, 7067db96d56Sopenharmony_ci}; 7077db96d56Sopenharmony_ci 7087db96d56Sopenharmony_cistatic int 7097db96d56Sopenharmony_ci_gdbm_exec(PyObject *module) 7107db96d56Sopenharmony_ci{ 7117db96d56Sopenharmony_ci _gdbm_state *state = get_gdbm_state(module); 7127db96d56Sopenharmony_ci state->gdbm_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 7137db96d56Sopenharmony_ci &gdbmtype_spec, NULL); 7147db96d56Sopenharmony_ci if (state->gdbm_type == NULL) { 7157db96d56Sopenharmony_ci return -1; 7167db96d56Sopenharmony_ci } 7177db96d56Sopenharmony_ci state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL); 7187db96d56Sopenharmony_ci if (state->gdbm_error == NULL) { 7197db96d56Sopenharmony_ci return -1; 7207db96d56Sopenharmony_ci } 7217db96d56Sopenharmony_ci if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) { 7227db96d56Sopenharmony_ci return -1; 7237db96d56Sopenharmony_ci } 7247db96d56Sopenharmony_ci if (PyModule_AddStringConstant(module, "open_flags", 7257db96d56Sopenharmony_ci gdbmmodule_open_flags) < 0) { 7267db96d56Sopenharmony_ci return -1; 7277db96d56Sopenharmony_ci } 7287db96d56Sopenharmony_ci 7297db96d56Sopenharmony_ci#if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \ 7307db96d56Sopenharmony_ci defined(GDBM_VERSION_PATCH) 7317db96d56Sopenharmony_ci PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR, 7327db96d56Sopenharmony_ci GDBM_VERSION_MINOR, GDBM_VERSION_PATCH); 7337db96d56Sopenharmony_ci if (obj == NULL) { 7347db96d56Sopenharmony_ci return -1; 7357db96d56Sopenharmony_ci } 7367db96d56Sopenharmony_ci if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) { 7377db96d56Sopenharmony_ci Py_DECREF(obj); 7387db96d56Sopenharmony_ci return -1; 7397db96d56Sopenharmony_ci } 7407db96d56Sopenharmony_ci#endif 7417db96d56Sopenharmony_ci return 0; 7427db96d56Sopenharmony_ci} 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_cistatic int 7457db96d56Sopenharmony_ci_gdbm_module_traverse(PyObject *module, visitproc visit, void *arg) 7467db96d56Sopenharmony_ci{ 7477db96d56Sopenharmony_ci _gdbm_state *state = get_gdbm_state(module); 7487db96d56Sopenharmony_ci Py_VISIT(state->gdbm_error); 7497db96d56Sopenharmony_ci Py_VISIT(state->gdbm_type); 7507db96d56Sopenharmony_ci return 0; 7517db96d56Sopenharmony_ci} 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_cistatic int 7547db96d56Sopenharmony_ci_gdbm_module_clear(PyObject *module) 7557db96d56Sopenharmony_ci{ 7567db96d56Sopenharmony_ci _gdbm_state *state = get_gdbm_state(module); 7577db96d56Sopenharmony_ci Py_CLEAR(state->gdbm_error); 7587db96d56Sopenharmony_ci Py_CLEAR(state->gdbm_type); 7597db96d56Sopenharmony_ci return 0; 7607db96d56Sopenharmony_ci} 7617db96d56Sopenharmony_ci 7627db96d56Sopenharmony_cistatic void 7637db96d56Sopenharmony_ci_gdbm_module_free(void *module) 7647db96d56Sopenharmony_ci{ 7657db96d56Sopenharmony_ci _gdbm_module_clear((PyObject *)module); 7667db96d56Sopenharmony_ci} 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_cistatic PyModuleDef_Slot _gdbm_module_slots[] = { 7697db96d56Sopenharmony_ci {Py_mod_exec, _gdbm_exec}, 7707db96d56Sopenharmony_ci {0, NULL} 7717db96d56Sopenharmony_ci}; 7727db96d56Sopenharmony_ci 7737db96d56Sopenharmony_cistatic struct PyModuleDef _gdbmmodule = { 7747db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 7757db96d56Sopenharmony_ci .m_name = "_gdbm", 7767db96d56Sopenharmony_ci .m_doc = gdbmmodule__doc__, 7777db96d56Sopenharmony_ci .m_size = sizeof(_gdbm_state), 7787db96d56Sopenharmony_ci .m_methods = _gdbm_module_methods, 7797db96d56Sopenharmony_ci .m_slots = _gdbm_module_slots, 7807db96d56Sopenharmony_ci .m_traverse = _gdbm_module_traverse, 7817db96d56Sopenharmony_ci .m_clear = _gdbm_module_clear, 7827db96d56Sopenharmony_ci .m_free = _gdbm_module_free, 7837db96d56Sopenharmony_ci}; 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ciPyMODINIT_FUNC 7867db96d56Sopenharmony_ciPyInit__gdbm(void) 7877db96d56Sopenharmony_ci{ 7887db96d56Sopenharmony_ci return PyModuleDef_Init(&_gdbmmodule); 7897db96d56Sopenharmony_ci} 790