/*----- Data structures ---------------------------------------------------*/
typedef struct keydata_pyobj {
- PyObject_HEAD
+ GMAP_PYOBJ_HEAD
key_data *kd;
} keydata_pyobj;
#define KEYDATA_PYCHECK(o) PyObject_TypeCheck(o, keydata_pytype)
#define KEYDATA_KD(o) (((keydata_pyobj *)(o))->kd)
-typedef struct subkeyiter_pyobj {
- PyObject_HEAD
- key_subkeyiter i;
- PyObject *kdobj;
-} subkeyiter_pyobj;
-
-static PyTypeObject *subkeyiter_pytype;
-#define SUBKEYITER_PYCHECK(o) PyObject_TypeCheck(o, subkeyiter_pytype);
-#define SUBKEYITER_I(o) (&((subkeyiter_pyobj *)(o))->i)
-#define SUBKEYITER_KDOBJ(o) (((subkeyiter_pyobj *)(o))->kdobj)
-
typedef struct keyfile_pyobj {
- PyObject_HEAD
+ GMAP_PYOBJ_HEAD
key_file kf;
} keyfile_pyobj;
#define KEY_KFOBJ(o) (((key_pyobj *)(o))->kfobj)
#define KEY_KF(o) KEYFILE_KF(KEY_KFOBJ(o))
-typedef struct keyiter_pyobj {
- PyObject_HEAD
- key_iter i;
- PyObject *kfobj;
-} keyiter_pyobj;
-
-static PyTypeObject *keyiter_pytype;
-#define KEYITER_PYCHECK(o) PyObject_TypeCheck(o, keyiter_pytype)
-#define KEYITER_I(o) (&((keyiter_pyobj *)(o))->i)
-#define KEYITER_KFOBJ(o) (((keyiter_pyobj *)(o))->kfobj)
-#define KEYITER_KF(o) KEYFILE_KF(KEYITER_KFOBJ(o))
-
typedef struct keyattrs_pyobj {
- PyObject_HEAD
+ GMAP_PYOBJ_HEAD
PyObject *kobj;
} keyattrs_pyobj;
#define KEYATTRS_KF(o) KEY_KF(KEYATTRS_KOBJ(o))
#define KEYATTRS_K(o) KEY_K(KEYATTRS_KOBJ(o))
-typedef struct keyattriter_pyobj {
- PyObject_HEAD
- key_attriter i;
- PyObject *kobj;
-} keyattriter_pyobj;
-
-static PyTypeObject *keyattriter_pytype;
-#define KEYATTRITER_PYCHECK(o) PyObject_TypeCheck(o, keyattriter_pytype)
-#define KEYATTRITER_I(o) (&((keyattriter_pyobj *)(o))->i)
-#define KEYATTRITER_KOBJ(o) (((keyattriter_pyobj *)(o))->kobj)
-#define KEYATTRITER_K(o) KEY_K(KEYATTRITER_KOBJ(o))
-#define KEYATTRITER_KFOBJ(o) KEY_KFOBJ(KEYATTRITER_KOBJ(o))
-#define KEYATTRITER_KF(o) KEY_KF(KEYATTRITER_KOBJ(o))
-
/*----- Filters -----------------------------------------------------------*/
static int convfilter(PyObject *x, void *p)
/*----- Key data ----------------------------------------------------------*/
+static const gmap_ops keydatastruct_gmops;
+
static PyObject *keydata_pywrap(key_data *kd)
{
PyTypeObject *ty;
keydata_pyobj *kdobj;
+ const gmap_ops *gmops = 0;
switch (kd->e & KF_ENCMASK) {
case KENC_BINARY: ty = keydatabin_pytype; break;
case KENC_ENCRYPT: ty = keydataenc_pytype; break;
case KENC_MP: ty = keydatamp_pytype; break;
- case KENC_STRUCT: ty = keydatastruct_pytype; break;
+ case KENC_STRUCT:
+ ty = keydatastruct_pytype;
+ gmops = &keydatastruct_gmops;
+ break;
case KENC_STRING: ty = keydatastr_pytype; break;
case KENC_EC: ty = keydataec_pytype; break;
default: abort();
}
kdobj = PyObject_NEW(keydata_pyobj, ty);
+ kdobj->gmops = gmops;
kdobj->kd = kd;
return ((PyObject *)kdobj);
}
0 /* @tp_is_gc@ */
};
-static PyObject *subkeyiter_make(PyObject *kdobj)
+static void *keydatastruct_gmlookup(PyObject *me, PyObject *k, unsigned *f)
{
- subkeyiter_pyobj *me = PyObject_NEW(subkeyiter_pyobj, subkeyiter_pytype);
- me->kdobj = kdobj;
- Py_INCREF(kdobj);
- key_mksubkeyiter(&me->i, KEYDATA_KD(kdobj));
- return ((PyObject *)me);
+ key_data *kd = KEYDATA_KD(me);
+ const char *tag;
+ key_struct *ks;
+
+ assert((kd->e&KF_ENCMASK) == KENC_STRUCT);
+ if ((tag = PyString_AsString(k)) == 0) return (0);
+ if (f) { key_split(&kd); KEYDATA_KD(me) = kd; }
+ ks = sym_find(&kd->u.s, tag, -1, f ? sizeof(key_struct) : 0, f);
+ if (ks && f && !*f) ks->k = 0;
+ return (ks);
}
-static PyObject *subkeyiter_pynext(PyObject *me)
+static void keydatastruct_gmiterinit(PyObject *me, void *i)
{
- const char *tag;
- if (!key_nextsubkey(SUBKEYITER_I(me), &tag, 0))
- return (0);
- return (PyString_FromString(tag));
+ key_data *kd = KEYDATA_KD(me);
+
+ assert((kd->e&KF_ENCMASK) == KENC_STRUCT);
+ sym_mkiter(i, &kd->u.s);
}
-static void subkeyiter_pydealloc(PyObject *me)
+static void *keydatastruct_gmiternext(PyObject *me, void *i)
+ { return (sym_next(i)); }
+
+static PyObject *keydatastruct_gmentrykey(PyObject *me, void *e)
+ { key_struct *ks = e; return (PyString_FromString(SYM_NAME(ks))); }
+
+static PyObject *keydatastruct_gmentryvalue(PyObject *me, void *e)
{
- Py_DECREF(SUBKEYITER_KDOBJ(me));
- FREEOBJ(me);
+ key_struct *ks = e;
+ key_data *kd = ks->k;
+
+ key_incref(kd);
+ return (keydata_pywrap(kd));
}
-static const PyTypeObject subkeyiter_pytype_skel = {
- PyObject_HEAD_INIT(0) 0, /* Header */
- "SubKeyIter", /* @tp_name@ */
- sizeof(subkeyiter_pyobj), /* @tp_basicsize@ */
- 0, /* @tp_itemsize@ */
+static key_struct *maybe_split_and_reprobe(PyObject *me, key_struct *ks)
+{
+ key_data *kd = KEYDATA_KD(me);
- subkeyiter_pydealloc, /* @tp_dealloc@ */
- 0, /* @tp_print@ */
- 0, /* @tp_getattr@ */
- 0, /* @tp_setattr@ */
- 0, /* @tp_compare@ */
- 0, /* @tp_repr@ */
- 0, /* @tp_as_number@ */
- 0, /* @tp_as_sequence@ */
- 0, /* @tp_as_mapping@ */
- 0, /* @tp_hash@ */
- 0, /* @tp_call@ */
- 0, /* @tp_str@ */
- 0, /* @tp_getattro@ */
- 0, /* @tp_setattro@ */
- 0, /* @tp_as_buffer@ */
- Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
- Py_TPFLAGS_BASETYPE,
+ if (kd->ref == 1) return (ks);
+ key_split(&kd); KEYDATA_KD(me) = kd;
+ ks = sym_find(&kd->u.s, SYM_NAME(ks), SYM_LEN(ks), 0, 0); assert(ks);
+ return (ks);
+}
- /* @tp_doc@ */
- "Iterator for structured keys.",
+static int keydatastruct_gmsetentry(PyObject *me, void *e, PyObject *val)
+{
+ key_struct *ks;
+ key_data *kd;
+ int rc = -1;
- 0, /* @tp_traverse@ */
- 0, /* @tp_clear@ */
- 0, /* @tp_richcompare@ */
- 0, /* @tp_weaklistoffset@ */
- PyObject_SelfIter, /* @tp_iter@ */
- subkeyiter_pynext, /* @tp_iternext@ */
- 0, /* @tp_methods@ */
- 0, /* @tp_members@ */
- 0, /* @tp_getset@ */
- 0, /* @tp_base@ */
- 0, /* @tp_dict@ */
- 0, /* @tp_descr_get@ */
- 0, /* @tp_descr_set@ */
- 0, /* @tp_dictoffset@ */
- 0, /* @tp_init@ */
- PyType_GenericAlloc, /* @tp_alloc@ */
- abstract_pynew, /* @tp_new@ */
- 0, /* @tp_free@ */
- 0 /* @tp_is_gc@ */
+ if (!KEYDATA_PYCHECK(val)) TYERR("expected KeyData value");
+ ks = maybe_split_and_reprobe(me, e);
+ if (ks->k) key_drop(ks->k);
+ ks->k = kd = KEYDATA_KD(val); key_incref(kd);
+ rc = 0;
+end:
+ return (rc);
+}
+
+static int keydatastruct_gmdelentry(PyObject *me, void *e)
+{
+ key_struct *ks;
+
+ ks = maybe_split_and_reprobe(me, e);
+ if (ks->k) key_drop(ks->k);
+ sym_remove(&KEYDATA_KD(me)->u.s, ks);
+ return (0);
+}
+
+static const gmap_ops keydatastruct_gmops = {
+ sizeof(sym_iter),
+ keydatastruct_gmlookup,
+ keydatastruct_gmiterinit,
+ keydatastruct_gmiternext,
+ keydatastruct_gmentrykey,
+ keydatastruct_gmentryvalue,
+ keydatastruct_gmsetentry,
+ keydatastruct_gmdelentry
};
static PyObject *keydatastruct_pynew(PyTypeObject *ty,
Py_DECREF(it); it = 0;
}
me = (keydata_pyobj *)ty->tp_alloc(ty, 0);
+ me->gmops = &keydatastruct_gmops;
me->kd = kd;
end:
if (kd && !me) key_drop(kd);
return ((PyObject *)me);
}
-static PyObject *keydatastruct_pylookup(PyObject *me, PyObject *key)
-{
- const char *tag;
- key_data *kd;
- PyObject *rc = 0;
-
- if ((tag = PyString_AsString(key)) == 0)
- goto end;
- if ((kd = key_structfind(KEYDATA_KD(me), tag)) == 0)
- MAPERR(key);
- key_incref(kd);
- rc = keydata_pywrap(kd);
-end:
- return (rc);
-}
-
-static int keydatastruct_pystore(PyObject *me,
- PyObject *key, PyObject *value)
-{
- const char *tag;
- int rc = -1;
-
- if ((tag = PyString_AsString(key)) == 0)
- goto end;
- key_split(&KEYDATA_KD(me));
- if (value) {
- if (!KEYDATA_PYCHECK(value))
- TYERR("expected KeyData value");
- key_structset(KEYDATA_KD(me), tag, KEYDATA_KD(value));
- } else {
- if (!key_structfind(KEYDATA_KD(me), tag))
- MAPERR(key);
- key_structset(KEYDATA_KD(me), tag, 0);
- }
- rc = 0;
-end:
- return (rc);
-}
+static Py_ssize_t keydatastruct_pysize(PyObject *me)
+ { return gmap_pysize_from_sym(&KEYDATA_KD(me)->u.s); }
static const PyMappingMethods keydatastruct_pymapping = {
- gmap_pysize, /* @mp_length@ */
- keydatastruct_pylookup, /* @mp_subscript@ */
- keydatastruct_pystore /* @mp_ass_subscript@ */
+ keydatastruct_pysize,
+ gmap_pylookup,
+ gmap_pystore
};
static const PyTypeObject keydatastruct_pytype_skel = {
0, /* @tp_compare@ */
0, /* @tp_repr@ */
0, /* @tp_as_number@ */
- 0, /* @tp_as_sequence@ */
+ PYSEQUENCE(gmap), /* @tp_as_sequence@ */
PYMAPPING(keydatastruct), /* @tp_as_mapping@ */
0, /* @tp_hash@ */
0, /* @tp_call@ */
0, /* @tp_clear@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
- subkeyiter_make, /* @tp_iter@ */
+ gmap_pyiter, /* @tp_iter@ */
0, /* @tp_iternext@ */
PYMETHODS(gmap), /* @tp_methods@ */
0, /* @tp_members@ */
/*----- Key attributes ----------------------------------------------------*/
-static PyObject *keyattriter_make(PyObject *kaobj)
-{
- PyObject *kobj = KEYATTRS_KOBJ(kaobj);
- keyattriter_pyobj *me = PyObject_NEW(keyattriter_pyobj,
- keyattriter_pytype);
- me->kobj = kobj;
- Py_INCREF(kobj);
- key_mkattriter(&me->i, KEY_K(kobj));
- return ((PyObject *)me);
-}
-
-static PyObject *keyattriter_pynext(PyObject *me)
+static void *keyattrs_gmlookup(PyObject *me, PyObject *k, unsigned *f)
{
- const char *name;
+ char *name = PyString_AsString(k);
+ key_attr *a = 0;
- if (!key_nextattr(KEYATTRITER_I(me), &name, 0))
- return (0);
- return (PyString_FromString(name));
+ if (!name) goto end;
+ if (f && !(KEYATTRS_KF(me)->f&KF_WRITE)) KEYERR(KERR_READONLY);
+ a = sym_find(&KEYATTRS_K(me)->a, name, -1, f ? sizeof(key_attr) : 0, f);
+ if (f && !*f) a->p = 0;
+end:
+ return (a);
}
-static void keyattriter_pydealloc(PyObject *me)
-{
- Py_DECREF(KEYATTRITER_KOBJ(me));
- FREEOBJ(me);
-}
+static void keyattrs_gmiterinit(PyObject *me, void *i)
+ { sym_mkiter(i, &KEYATTRS_K(me)->a); }
-static const PyTypeObject keyattriter_pytype_skel = {
- PyObject_HEAD_INIT(0) 0, /* Header */
- "KeyAttributeIter", /* @tp_name@ */
- sizeof(keyattriter_pyobj), /* @tp_basicsize@ */
- 0, /* @tp_itemsize@ */
+static void *keyattrs_gmiternext(PyObject *me, void *i)
+ { return (sym_next(i)); }
- keyattriter_pydealloc, /* @tp_dealloc@ */
- 0, /* @tp_print@ */
- 0, /* @tp_getattr@ */
- 0, /* @tp_setattr@ */
- 0, /* @tp_compare@ */
- 0, /* @tp_repr@ */
- 0, /* @tp_as_number@ */
- 0, /* @tp_as_sequence@ */
- 0, /* @tp_as_mapping@ */
- 0, /* @tp_hash@ */
- 0, /* @tp_call@ */
- 0, /* @tp_str@ */
- 0, /* @tp_getattro@ */
- 0, /* @tp_setattro@ */
- 0, /* @tp_as_buffer@ */
- Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
- Py_TPFLAGS_BASETYPE,
-
- /* @tp_doc@ */
- "Iterator for key attributes.",
+static PyObject *keyattrs_gmentrykey(PyObject *me, void *e)
+ { return (PyString_FromString(SYM_NAME(e))); }
- 0, /* @tp_traverse@ */
- 0, /* @tp_clear@ */
- 0, /* @tp_richcompare@ */
- 0, /* @tp_weaklistoffset@ */
- PyObject_SelfIter, /* @tp_iter@ */
- keyattriter_pynext, /* @tp_iternext@ */
- 0, /* @tp_methods@ */
- 0, /* @tp_members@ */
- 0, /* @tp_getset@ */
- 0, /* @tp_base@ */
- 0, /* @tp_dict@ */
- 0, /* @tp_descr_get@ */
- 0, /* @tp_descr_set@ */
- 0, /* @tp_dictoffset@ */
- 0, /* @tp_init@ */
- PyType_GenericAlloc, /* @tp_alloc@ */
- abstract_pynew, /* @tp_new@ */
- 0, /* @tp_free@ */
- 0 /* @tp_is_gc@ */
-};
+static PyObject *keyattrs_gmentryvalue(PyObject *me, void *e)
+ { return (PyString_FromString(((key_attr *)e)->p)); }
-static PyObject *keyattrs_pylookup(PyObject *me, PyObject *key)
+static int keyattrs_gmsetentry(PyObject *me, void *e, PyObject *val)
{
- const char *attr;
- const char *value;
- PyObject *rc = 0;
+ key_attr *a = e;
+ const char *p;
+ Py_ssize_t n;
+ int rc = -1;
- if ((attr = PyString_AsString(key)) == 0)
- goto end;
- if ((value = key_getattr(KEYATTRS_KF(me), KEYATTRS_K(me), attr)) == 0)
- MAPERR(key);
- rc = PyString_FromString(value);
+ if (!PyString_Check(val)) TYERR("expected string");
+ p = PyString_AS_STRING(val); n = PyString_GET_SIZE(val);
+ if (n > 255) VALERR("attribute too long");
+ if (memchr(p, 0, n)) VALERR("attribute must not contain nul");
+ if (a->p) xfree(a->p);
+ a->p = xmalloc(n + 1); memcpy(a->p, p, n + 1);
+ KEYATTRS_KF(me)->f |= KF_MODIFIED;
+ rc = 0;
end:
return (rc);
}
-static int keyattrs_pystore(PyObject *me,
- PyObject *key, PyObject *value)
+static int keyattrs_gmdelentry(PyObject *me, void *e)
{
- const char *attr;
- const char *val;
- int err;
+ key_attr *a = e;
int rc = -1;
- if ((attr = PyString_AsString(key)) == 0)
- goto end;
- if (value) {
- if ((val = PyString_AsString(value)) == 0)
- goto end;
- if ((err = key_putattr(KEYATTRS_KF(me), KEYATTRS_K(me),
- attr, val)) != 0)
- KEYERR(err);
- } else {
- if (!key_getattr(KEYATTRS_KF(me), KEYATTRS_K(me), attr))
- MAPERR(key);
- if ((err = key_putattr(KEYATTRS_KF(me), KEYATTRS_K(me), attr, 0)) != 0)
- KEYERR(err);
- }
+ if (!(KEYATTRS_KF(me)->f&KF_WRITE)) KEYERR(KERR_READONLY);
+ if (a->p) { KEYATTRS_KF(me)->f |= KF_MODIFIED; xfree(a->p); }
+ sym_remove(&KEYATTRS_K(me)->a, a);
rc = 0;
end:
return (rc);
}
+static const gmap_ops keyattrs_gmops = {
+ sizeof(sym_iter),
+ keyattrs_gmlookup,
+ keyattrs_gmiterinit,
+ keyattrs_gmiternext,
+ keyattrs_gmentrykey,
+ keyattrs_gmentryvalue,
+ keyattrs_gmsetentry,
+ keyattrs_gmdelentry
+};
+
static PyObject *keyattrs_make(PyObject *kobj)
{
keyattrs_pyobj *me = PyObject_NEW(keyattrs_pyobj, keyattrs_pytype);
+ me->gmops = &keyattrs_gmops;
me->kobj = kobj;
Py_INCREF(kobj);
return ((PyObject *)me);
FREEOBJ(me);
}
+static Py_ssize_t keyattrs_pysize(PyObject *me)
+ { return gmap_pysize_from_sym(&KEYATTRS_K(me)->a); }
+
static const PyMappingMethods keyattrs_pymapping = {
- gmap_pysize, /* @mp_length@ */
- keyattrs_pylookup, /* @mp_subscript@ */
- keyattrs_pystore /* @mp_ass_subscript@ */
+ keyattrs_pysize,
+ gmap_pylookup,
+ gmap_pystore
};
static const PyTypeObject keyattrs_pytype_skel = {
0, /* @tp_clear@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
- keyattriter_make, /* @tp_iter@ */
+ gmap_pyiter, /* @tp_iter@ */
0, /* @tp_iternext@ */
PYMETHODS(gmap), /* @tp_methods@ */
0, /* @tp_members@ */
0 /* @tp_is_gc@ */
};
-/*----- Key iteration -----------------------------------------------------*/
-
-static PyObject *keyiter_new(PyObject *kfobj)
-{
- keyiter_pyobj *me = PyObject_NEW(keyiter_pyobj, keyiter_pytype);
- key_mkiter(&me->i, KEYFILE_KF(kfobj));
- me->kfobj = kfobj;
- Py_INCREF(kfobj);
- return ((PyObject *)me);
-}
+/*----- Key files ---------------------------------------------------------*/
-static PyObject *keyiter_pynext(PyObject *me)
+static key *bytag(PyObject *me, PyObject *tagobj)
{
- key *k;
+ uint32 id;
+ char *tag;
+ key *k = 0;
- if ((k = key_next(KEYITER_I(me))) == 0)
- return (0);
- return (getulong(k->id));
+ if (convu32(tagobj, &id))
+ k = key_byid(KEYFILE_KF(me), id);
+ else {
+ PyErr_Clear();
+ if ((tag = PyString_AsString(tagobj)) == 0)
+ goto end;
+ k = key_bytag(KEYFILE_KF(me), tag);
+ }
+end:
+ return (k);
}
-static void keyiter_pydealloc(PyObject *me)
-{
- Py_DECREF(KEYITER_KFOBJ(me));
- FREEOBJ(me);
-}
+static void *keyfile_gmlookup(PyObject *me, PyObject *k, unsigned *f)
+ { key *kk = bytag(me, k); if (f) *f = !!kk; return (kk); }
-static const PyTypeObject keyiter_pytype_skel = {
- PyObject_HEAD_INIT(0) 0, /* Header */
- "KeyFileIter", /* @tp_name@ */
- sizeof(keyiter_pyobj), /* @tp_basicsize@ */
- 0, /* @tp_itemsize@ */
+static void keyfile_gmiterinit(PyObject *me, void *i)
+ { key_mkiter(i, KEYFILE_KF(me)); }
- keyiter_pydealloc, /* @tp_dealloc@ */
- 0, /* @tp_print@ */
- 0, /* @tp_getattr@ */
- 0, /* @tp_setattr@ */
- 0, /* @tp_compare@ */
- 0, /* @tp_repr@ */
- 0, /* @tp_as_number@ */
- 0, /* @tp_as_sequence@ */
- 0, /* @tp_as_mapping@ */
- 0, /* @tp_hash@ */
- 0, /* @tp_call@ */
- 0, /* @tp_str@ */
- 0, /* @tp_getattro@ */
- 0, /* @tp_setattro@ */
- 0, /* @tp_as_buffer@ */
- Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
- Py_TPFLAGS_BASETYPE,
+static void *keyfile_gmiternext(PyObject *me, void *i)
+ { return (key_next(i)); }
- /* @tp_doc@ */
- "Keyring iterator.",
+static PyObject *keyfile_gmentrykey(PyObject *me, void *e)
+ { key *k = e; return (getulong(k->id)); }
- 0, /* @tp_traverse@ */
- 0, /* @tp_clear@ */
- 0, /* @tp_richcompare@ */
- 0, /* @tp_weaklistoffset@ */
- PyObject_SelfIter, /* @tp_iter@ */
- keyiter_pynext, /* @tp_iternext@ */
- 0, /* @tp_methods@ */
- 0, /* @tp_members@ */
- 0, /* @tp_getset@ */
- 0, /* @tp_base@ */
- 0, /* @tp_dict@ */
- 0, /* @tp_descr_get@ */
- 0, /* @tp_descr_set@ */
- 0, /* @tp_dictoffset@ */
- 0, /* @tp_init@ */
- PyType_GenericAlloc, /* @tp_alloc@ */
- abstract_pynew, /* @tp_new@ */
- 0, /* @tp_free@ */
- 0 /* @tp_is_gc@ */
-};
+static PyObject *keyfile_gmentryvalue(PyObject *me, void *e)
+ { return (key_pywrap(me, e)); }
-/*----- Key files ---------------------------------------------------------*/
+static const gmap_ops keyfile_gmops = {
+ sizeof(key_iter),
+ keyfile_gmlookup,
+ keyfile_gmiterinit,
+ keyfile_gmiternext,
+ keyfile_gmentrykey,
+ keyfile_gmentryvalue,
+ 0,
+ 0
+};
struct reportinfo {
PyObject *func;
TYERR("reporter function not callable");
if ((rc = (keyfile_pyobj *)ty->tp_alloc(ty, 0)) == 0)
goto end;
+ rc->gmops = &keyfile_gmops;
if (key_open(&rc->kf, file, how, pythonreporter, &ri))
OSERR(file);
if (ri.stop) {
return (rc);
}
-static PyObject *bytag(PyObject *me, PyObject *tagobj)
-{
- uint32 id;
- char *tag;
- key *k;
- PyObject *rc = 0;
-
- if (convu32(tagobj, &id))
- k = key_byid(KEYFILE_KF(me), id);
- else {
- PyErr_Clear();
- if ((tag = PyString_AsString(tagobj)) == 0)
- goto end;
- k = key_bytag(KEYFILE_KF(me), tag);
- }
- if (!k) RETURN_NONE;
- rc = key_pywrap(me, k);
-end:
- return (rc);
-}
-
static PyObject *kfmeth_bytag(PyObject *me, PyObject *arg)
{
PyObject *tagobj;
+ key *k;
if (!PyArg_ParseTuple(arg, "O:bytag", &tagobj)) return (0);
- return (bytag(me, tagobj));
-}
-
-static PyObject *keyfile_pylookup(PyObject *me, PyObject *key)
-{
- PyObject *rc = bytag(me, key);
- if (!rc) goto end;
- if (rc == Py_None) {
- Py_DECREF(rc);
- rc = 0;
- MAPERR(key);
- }
-end:
- return (rc);
+ if ((k = bytag(me, tagobj)) == 0) RETURN_NONE;
+ else return (key_pywrap(me, k));
}
static PyObject *kfmeth_newkey(PyObject *me, PyObject *arg, PyObject *kw)
static const PyMappingMethods keyfile_pymapping = {
gmap_pysize,
- keyfile_pylookup,
+ gmap_pylookup,
0
};
0, /* @tp_clear@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
- keyiter_new, /* @tp_iter@ */
+ gmap_pyiter, /* @tp_iter@ */
0, /* @tp_iternext@ */
PYMETHODS(keyfile), /* @tp_methods@ */
0, /* @tp_members@ */
{
INITTYPE(keyfile, root);
INITTYPE(key, root);
- INITTYPE(keyiter, root);
INITTYPE(keydata, root);
INITTYPE(keydatabin, keydata);
INITTYPE(keydataenc, keydata);
INITTYPE(keydatamp, keydata);
INITTYPE(keydataec, keydata);
INITTYPE(keydatastruct, keydata);
- INITTYPE(subkeyiter, root);
INITTYPE(keyattrs, root);
- INITTYPE(keyattriter, root);
}
void key_pyinsert(PyObject *mod)
INSEXC("KeyFileIOError", keyioexc, PyExc_OSError, 0);
INSEXC("KeyFileBroken", keyfilebrokenexc, keyioexc, 0);
INSERT("KeyFile", keyfile_pytype);
- INSERT("KeyFileIter", keyiter_pytype);
INSERT("Key", key_pytype);
INSERT("KeyAttributes", keyattrs_pytype);
- INSERT("KeyAttributeIter", keyattriter_pytype);
INSERT("KeyData", keydata_pytype);
INSERT("KeyDataBinary", keydatabin_pytype);
INSERT("KeyDataEncrypted", keydataenc_pytype);
INSERT("KeyDataECPt", keydataec_pytype);
INSERT("KeyDataString", keydatastr_pytype);
INSERT("KeyDataStructured", keydatastruct_pytype);
- INSERT("SubKeyIter", subkeyiter_pytype);
setconstants(mod, consts);
}
--- /dev/null
+/* -*-c-*-
+ *
+ * Generic mapping support, with mLib integration
+ *
+ * (c) 2019 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Pyke: the Python Kit for Extensions.
+ *
+ * Pyke is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Pyke is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pyke. If not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "pyke-mLib.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+Py_ssize_t gmap_pysize_from_sym(sym_table *tab)
+ { return (SYM_LIMIT(tab->t.mask + 1) - tab->load); }
+
+/*----- That's all, folks -------------------------------------------------*/
/*----- Iteration ---------------------------------------------------------*/
-static PyTypeObject *itemiter_pytype, *valiter_pytype;
+static PyTypeObject *keyiter_pytype, *itemiter_pytype, *valiter_pytype;
+
+union iterstate {
+ void *external;
+ void *internal[4];
+};
typedef struct iter_pyobj {
PyObject_HEAD
PyObject *map;
- PyObject *i;
+ union iterstate iter;
} iter_pyobj;
#define ITER_MAP(o) (((iter_pyobj *)(o))->map)
-#define ITER_I(o) (((iter_pyobj *)(o))->i)
+#define ITER_ITER(o) (&((iter_pyobj *)(o))->iter)
+#define ITER_EXTERNALP(o) \
+ (GMAP_OPS(ITER_MAP(o))->isz > sizeof(union iterstate))
+#define ITER_I(o) (ITER_EXTERNALP(o) ? ITER_ITER(o)->external \
+ : &ITER_ITER(o)->internal)
+
+static void *iter_init(PyObject *me, union iterstate *iter)
+{
+ const gmap_ops *gmops = GMAP_OPS(me);
+ void *i;
+
+ if (gmops->isz <= sizeof(*iter)) i = &iter->internal;
+ else { i = iter->external = PyObject_Malloc(gmops->isz); assert(i); }
+ gmops->iter_init(me, i);
+ return (i);
+}
+
+static void iter_free(PyObject *me, union iterstate *iter)
+ { if (GMAP_OPS(me)->isz > sizeof(*iter)) PyObject_Free(iter->external); }
static void iter_pydealloc(PyObject *me)
- { Py_DECREF(ITER_MAP(me)); Py_DECREF(ITER_I(me)); FREEOBJ(me); }
+{
+ PyObject *map = ITER_MAP(me);
+ iter_free(map, ITER_ITER(me));
+ Py_DECREF(map); FREEOBJ(me);
+}
-static PyObject *itemiter_pynext(PyObject *me)
+static PyObject *gmap_mkiter(PyObject *me, PyTypeObject *ty)
{
- PyObject *k = 0, *v = 0, *rc = 0;
+ iter_pyobj *iter = PyObject_NEW(iter_pyobj, ty);
- if ((k = PyIter_Next(ITER_I(me))) != 0 &&
- (v = PyObject_GetItem(ITER_MAP(me), k)) != 0)
- rc = Py_BuildValue("(OO)", k, v);
- Py_XDECREF(k); Py_XDECREF(v);
- return (rc);
+ iter->map = me; Py_INCREF(me);
+ iter_init(me, &iter->iter);
+ return ((PyObject *)iter);
}
-static const PyTypeObject itemiter_pytype_skel = {
+static PyObject *keyiter_pynext(PyObject *me)
+{
+ PyObject *map = ITER_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ void *e = gmops->iter_next(map, ITER_I(me));
+
+ if (!e) return (0);
+ else return (gmops->entry_key(map, e));
+}
+
+static const PyTypeObject keyiter_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "ItemIter", /* @tp_name@ */
+ "_KeyIter", /* @tp_name@ */
sizeof(iter_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
- "Iterates over the items of a mapping.",
+ "Iterates over the keys of a mapping.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
PyObject_SelfIter, /* @tp_iter@ */
- itemiter_pynext, /* @tp_iternext@ */
+ keyiter_pynext, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
static PyObject *valiter_pynext(PyObject *me)
{
- PyObject *k = 0, *rc = 0;
+ PyObject *map = ITER_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ void *e = gmops->iter_next(map, ITER_I(me));
- if ((k = PyIter_Next(ITER_I(me))) != 0)
- rc = PyObject_GetItem(ITER_MAP(me), k);
- Py_XDECREF(k);
- return (rc);
+ if (!e) return (0);
+ else return (gmops->entry_value(map, e));
}
static const PyTypeObject valiter_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "ValueIter", /* @tp_name@ */
+ "_ValueIter", /* @tp_name@ */
sizeof(iter_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0 /* @tp_is_gc@ */
};
+static PyObject *itemiter_pynext(PyObject *me)
+{
+ PyObject *map = ITER_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ void *e = gmops->iter_next(map, ITER_I(me));
+ PyObject *rc = 0;
+
+ if (e)
+ rc = Py_BuildValue("(NN)",
+ gmops->entry_key(map, e),
+ gmops->entry_value(map, e));
+ return (rc);
+}
+
+static const PyTypeObject itemiter_pytype_skel = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "_ItemIter", /* @tp_name@ */
+ sizeof(iter_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ iter_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ 0, /* @tp_as_number@ */
+ 0, /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "Iterates over the items of a mapping.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ PyObject_SelfIter, /* @tp_iter@ */
+ itemiter_pynext, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+/*----- Other mapping protocol support ------------------------------------*/
+
+Py_ssize_t gmap_pysize(PyObject *me)
+{
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter;
+ void *i;
+ Py_ssize_t n = 0;
+
+ i = iter_init(me, &iter);
+ while (gmops->iter_next(me, i)) n++;
+ iter_free(me, &iter);
+ return (n);
+}
+
+PyObject *gmap_pylookup(PyObject *me, PyObject *key)
+{
+ const gmap_ops *gmops = GMAP_OPS(me);
+ void *e = gmops->lookup(me, key, 0);
+ PyObject *rc = 0;
+
+ if (!e) { if (!PyErr_Occurred()) MAPERR(key); else goto end; }
+ rc = gmops->entry_value(me, e);
+end:
+ return (rc);
+}
+
+int gmap_pystore(PyObject *me, PyObject *key, PyObject *value)
+{
+ const gmap_ops *gmops = GMAP_OPS(me);
+ unsigned f;
+ void *e = gmops->lookup(me, key, &f);
+ int rc = -1;
+
+ if (!e) goto end;
+ if (!value)
+ rc = gmops->del_entry(me, e);
+ else {
+ rc = gmops->set_entry(me, e, value);
+ if (rc && !f) gmops->del_entry(me, e);
+ }
+ rc = 0;
+end:
+ return (rc);
+}
+
+int gmap_pyhaskey(PyObject *me, PyObject *key)
+ { return (GMAP_OPS(me)->lookup(me, key, 0) ? 1 : PyErr_Occurred() ? -1 : 0); }
+
const PySequenceMethods gmap_pysequence = {
0, /* @sq_length@ */
0, /* @sq_concat@ */
0, /* @sq_slice@ */
0, /* @sq_ass_item@ */
0, /* @sq_ass_slice@ */
- PyMapping_HasKey, /* @sq_contains@ */
+ gmap_pyhaskey, /* @sq_contains@ */
0, /* @sq_inplace_concat@ */
0 /* @sq_inplace_repeat@ */
};
-/*----- Other mapping protocol support ------------------------------------*/
-
-Py_ssize_t gmap_pysize(PyObject *me)
-{
- PyObject *i = 0, *x = 0;
- Py_ssize_t rc = -1, n = 0;
-
- if ((i = PyObject_GetIter(me)) == 0) goto done;
- while ((x = PyIter_Next(i)) != 0) { n++; Py_DECREF(x); x = 0; }
- if (PyErr_Occurred()) goto done;
- rc = n;
-done:
- Py_XDECREF(i); Py_XDECREF(x);
- return (rc);
-}
-
PyObject *gmapmeth_has_key(PyObject *me, PyObject *arg)
{
PyObject *k;
+ void *e;
if (!PyArg_ParseTuple(arg, "O:has_key", &k)) return (0);
- return (getbool(PyMapping_HasKey(me, k)));
+ e = GMAP_OPS(me)->lookup(me, k, 0);
+ if (e) RETURN_TRUE;
+ else if (!PyErr_Occurred()) RETURN_FALSE;
+ else return (0);
}
PyObject *gmapmeth_keys(PyObject *me)
{
- PyObject *l = 0, *i = 0, *k, *rc = 0;
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter; void *i = 0, *e;
+ PyObject *l = 0, *k, *rc = 0;
int err;
- if ((l = PyList_New(0)) == 0 ||
- (i = PyObject_GetIter(me)) == 0)
- goto done;
- while ((k = PyIter_Next(i)) != 0)
- { err = PyList_Append(l, k); Py_DECREF(k); if (err) goto done; }
- if (PyErr_Occurred()) goto done;
+ if ((l = PyList_New(0)) == 0) goto done;
+ i = iter_init(me, &iter);
+ while ((e = gmops->iter_next(me, i)) != 0) {
+ k = gmops->entry_key(me, e);
+ err = PyList_Append(l, k);
+ Py_DECREF(k);
+ if (err) goto done;
+ }
rc = l; l = 0;
done:
- Py_XDECREF(l); Py_XDECREF(i);
+ Py_XDECREF(l);
+ if (i) iter_free(me, &iter);
return (rc);
}
PyObject *gmapmeth_values(PyObject *me)
{
- PyObject *l = 0, *i = 0, *k, *v, *rc = 0;
- int err = 0;
-
- if ((l = PyList_New(0)) == 0 ||
- (i = PyObject_GetIter(me)) == 0)
- goto done;
- while ((k = PyIter_Next(i)) != 0) {
- if ((v = PyObject_GetItem(me, k)) == 0 ||
- PyList_Append(l, v))
- err = -1;
- Py_DECREF(k); Py_XDECREF(v);
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter; void *i = 0, *e;
+ PyObject *l = 0, *v, *rc = 0;
+ int err;
+
+ if ((l = PyList_New(0)) == 0) goto done;
+ i = iter_init(me, &iter);
+ while ((e = gmops->iter_next(me, i)) != 0) {
+ v = gmops->entry_value(me, e);
+ err = PyList_Append(l, v);
+ Py_DECREF(v);
if (err) goto done;
}
- if (PyErr_Occurred()) goto done;
rc = l; l = 0;
done:
- Py_XDECREF(l); Py_XDECREF(i);
+ Py_XDECREF(l);
+ if (i) iter_free(me, &iter);
return (rc);
}
PyObject *gmapmeth_items(PyObject *me)
{
- PyObject *l = 0, *i = 0, *k, *v, *z, *rc = 0;
- int err = 0;
-
- if ((l = PyList_New(0)) == 0 ||
- (i = PyObject_GetIter(me)) == 0)
- goto done;
- while ((k = PyIter_Next(i)) != 0) {
- z = 0;
- if ((v = PyObject_GetItem(me, k)) == 0 ||
- (z = Py_BuildValue("(OO)", k, v)) == 0 ||
- PyList_Append(l, z))
- err = -1;
- Py_DECREF(k); Py_XDECREF(v); Py_XDECREF(z);
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter; void *i = 0, *e;
+ PyObject *l = 0, *z, *rc = 0;
+ int err;
+
+ if ((l = PyList_New(0)) == 0) goto done;
+ i = iter_init(me, &iter);
+ while ((e = gmops->iter_next(me, i)) != 0) {
+ if ((z = Py_BuildValue("(NN)",
+ gmops->entry_key(me, e),
+ gmops->entry_value(me, e))) == 0)
+ goto done;
+ err = PyList_Append(l, z);
+ Py_XDECREF(z);
if (err) goto done;
}
- if (PyErr_Occurred()) goto done;
rc = l; l = 0;
done:
- Py_XDECREF(l); Py_XDECREF(i);
+ Py_XDECREF(l);
+ if (i) iter_free(me, &iter);
return (rc);
}
PyObject *gmapmeth_iterkeys(PyObject *me)
- { return (PyObject_GetIter(me)); }
+ { return (gmap_mkiter(me, keyiter_pytype)); }
PyObject *gmapmeth_itervalues(PyObject *me)
-{
- PyObject *i;
- iter_pyobj *ii;
-
- if ((i = PyObject_GetIter(me)) == 0)
- return (0);
- ii = PyObject_NEW(iter_pyobj, valiter_pytype);
- ii->map = me; Py_INCREF(me);
- ii->i = i;
- return ((PyObject *)ii);
-}
+ { return (gmap_mkiter(me, valiter_pytype)); }
PyObject *gmapmeth_iteritems(PyObject *me)
-{
- PyObject *i;
- iter_pyobj *ii;
+ { return (gmap_mkiter(me, itemiter_pytype)); }
- if ((i = PyObject_GetIter(me)) == 0)
- return (0);
- ii = PyObject_NEW(iter_pyobj, itemiter_pytype);
- ii->map = me; Py_INCREF(me);
- ii->i = i;
- return ((PyObject *)ii);
-}
+PyObject *gmap_pyiter(PyObject *me)
+ { return gmap_mkiter(me, keyiter_pytype); }
PyObject *gmapmeth_clear(PyObject *me)
{
- PyObject *i = 0, *k = 0, *rc = 0;
-
- if ((i = PyObject_GetIter(me)) == 0)
- goto end;
- while ((k = PyIter_Next(i)) != 0) {
- PyObject_DelItem(me, k);
- Py_DECREF(k);
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter;
+ void *i, *e;
+ PyObject *rc = 0;
+
+ i = iter_init(me, &iter);
+ for (;;) {
+ e = gmops->iter_next(me, i); if (!e) break;
+ if (gmops->del_entry(me, e)) goto end;
}
- if (PyErr_Occurred()) goto end;
+ iter_free(me, &iter);
rc = me; Py_INCREF(me);
end:
- Py_XDECREF(i);
return (rc);
}
PyObject *gmapmeth_get(PyObject *me, PyObject *arg, PyObject *kw)
{
- PyObject *k, *def = Py_None, *v;
+ const gmap_ops *gmops = GMAP_OPS(me);
+ PyObject *k, *def = Py_None;
+ void *e;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:get", DEF_KWLIST, &k, &def))
return (0);
- if ((v = PyObject_GetItem(me, k)) != 0) return (v);
- PyErr_Clear();
- RETURN_OBJ(def);
+ e = gmops->lookup(me, k, 0);
+ if (e) return (gmops->entry_value(me, e));
+ else if (!PyErr_Occurred()) RETURN_OBJ(def);
+ else return (0);
}
PyObject *gmapmeth_setdefault(PyObject *me, PyObject *arg, PyObject *kw)
{
- PyObject *k, *def = Py_None, *v;
+ const gmap_ops *gmops = GMAP_OPS(me);
+ PyObject *k, *def = Py_None;
+ void *e;
+ unsigned f;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:setdefault", DEF_KWLIST,
&k, &def))
return (0);
- if ((v = PyObject_GetItem(me, k)) != 0) return (v);
- PyErr_Clear();
- if (PyObject_SetItem(me, k, def)) return (0);
- RETURN_OBJ(def);
+ e = gmops->lookup(me, k, &f);
+ if (!e) return (0);
+ else if (f) return (gmops->entry_value(me, e));
+ else if (gmops->set_entry(me, e, def)) return (0);
+ else RETURN_OBJ(def);
}
PyObject *gmapmeth_pop(PyObject *me, PyObject *arg, PyObject *kw)
{
- PyObject *k, *def = 0, *v;
+ const gmap_ops *gmops = GMAP_OPS(me);
+ PyObject *k, *def = 0;
+ PyObject *rc = 0;
+ void *e;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:pop", DEF_KWLIST, &k, &def))
- return (0);
- if ((v = PyObject_GetItem(me, k)) != 0) {
- PyObject_DelItem(me, k);
- return (v);
- } else if (def) {
- PyErr_Clear();
- RETURN_OBJ(def);
- } else
- return (0);
+ goto end;
+ e = gmops->lookup(me, k, 0);
+ if (!e) {
+ if (PyErr_Occurred()) goto end;
+ else if (def) { rc = def; Py_INCREF(rc); }
+ else MAPERR(k);
+ } else {
+ rc = gmops->entry_value(me, e);
+ if (gmops->del_entry(me, e)) { Py_DECREF(rc); rc = 0; }
+ }
+end:
+ return (rc);
}
-PyObject *gmapmeth_update(PyObject *me, PyObject *arg)
+static int update_core(PyObject *me, PyObject *map)
{
- PyObject *map, *i = 0, *k, *v, *rc = 0;
- int err = 0;
-
- if (!PyArg_ParseTuple(arg, "O:update", &map) ||
- (i = PyObject_GetIter(map)) == 0)
- goto end;
- while ((k = PyIter_Next(i)) != 0) {
- if ((v = PyObject_GetItem(map, k)) == 0 ||
- PyObject_SetItem(me, k, v))
- err = -1;
- Py_DECREF(k); Py_XDECREF(v);
- if (err) goto end;
+ const gmap_ops *gmops = GMAP_OPS(me);
+ PyObject *i = 0, *item = 0, *k = 0, *v = 0;
+ void *e;
+ unsigned foundp;
+ int rc = -1;
+
+ i = PyObject_CallMethod(map, "iteritems", 0);
+
+ if (i) {
+ for (;;) {
+ item = PyIter_Next(i); if (!item) break;
+ if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2)
+ TYERR("wanted a pair");
+ k = PyTuple_GET_ITEM(item, 0); Py_INCREF(k);
+ v = PyTuple_GET_ITEM(item, 1); Py_INCREF(v);
+ e = gmops->lookup(me, k, &foundp); if (!e) goto end;
+ if (gmops->set_entry(me, e, v)) goto end;
+ Py_DECREF(item); Py_DECREF(k); Py_DECREF(v); item = k = v = 0;
+ }
+ if (PyErr_Occurred()) goto end;
+ } else {
+ PyErr_Clear();
+ i = PyObject_GetIter(map); if (!i) goto end;
+ for (;;) {
+ k = PyIter_Next(i); if (!k) goto end;
+ v = PyObject_GetItem(map, k); if (!v) goto end;
+ e = gmops->lookup(me, k, &foundp); if (!e) goto end;
+ if (gmops->set_entry(me, e, v)) goto end;
+ Py_DECREF(k); Py_DECREF(v); k = v = 0;
+ }
+ if (PyErr_Occurred()) goto end;
}
- if (PyErr_Occurred()) goto end;
- rc = me; Py_INCREF(me);
+ rc = 0;
end:
- Py_XDECREF(i);
+ Py_XDECREF(i); Py_XDECREF(item);
+ Py_XDECREF(k); Py_XDECREF(v);
return (rc);
}
-PyObject *gmapmeth_popitem(PyObject *me)
+PyObject *gmapmeth_update(PyObject *me, PyObject *arg, PyObject *kw)
{
- PyObject *i = 0, *k = 0, *v = 0, *rc = 0;
+ PyObject *map = 0;
- if ((i = PyObject_GetIter(me)) == 0)
- goto end;
- if ((k = PyIter_Next(i)) == 0) {
- if (!PyErr_Occurred()) VALERR("popitem(): mapping is empty");
- goto end;
+ if (!PyArg_ParseTuple(arg, "|O:update", &map)) return (0);
+ if (map && update_core(me, map)) return (0);
+ if (kw && update_core(me, kw)) return (0);
+ RETURN_ME;
+}
+
+PyObject *gmapmeth_popitem(PyObject *me)
+{
+ const gmap_ops *gmops = GMAP_OPS(me);
+ union iterstate iter;
+ void *i;
+ PyObject *rc = 0;
+ void *e;
+
+ i = iter_init(me, &iter);
+ e = gmops->iter_next(me, i);
+ iter_free(me, &iter);
+ if (!e)
+ MAPERR(Py_None);
+ else {
+ rc = Py_BuildValue("(NN)",
+ gmops->entry_key(me, e), gmops->entry_value(me, e));
+ if (gmops->del_entry(me, e)) { Py_DECREF(rc); rc = 0; }
}
- if ((v = PyObject_GetItem(me, k)) == 0 ||
- PyObject_DelItem(me, k))
- goto end;
- rc = Py_BuildValue("(OO)", k, v);
end:
- Py_XDECREF(i); Py_XDECREF(k); Py_XDECREF(v);
return (rc);
}
+const PyMethodDef gmapro_pymethods[] = {
+ GMAP_ROMETHODS
+ { 0 }
+};
+
const PyMethodDef gmap_pymethods[] = {
GMAP_METHODS
{ 0 }
void pyke_gmap_pyinit(void)
{
+ INITTYPE(keyiter, root);
INITTYPE(itemiter, root);
INITTYPE(valiter, root);
}
void pyke_gmap_pyinsert(PyObject *mod)
{
- INSERT("ItemIter", itemiter_pytype);
- INSERT("ValueIter", valiter_pytype);
+ INSERT("_KeyIter", keyiter_pytype);
+ INSERT("_ValueIter", valiter_pytype);
+ INSERT("_ItemIter", itemiter_pytype);
}
/*----- That's all, folks -------------------------------------------------*/
PUBLIC_SYMBOLS;
#include <mLib/bits.h>
+#include <mLib/sym.h>
PRIVATE_SYMBOLS;
/*----- Conversions -------------------------------------------------------*/
extern PyObject *getk64(kludge64);
/* Output conversion for `kludge64'. */
+/*----- Mapping support ---------------------------------------------------*/
+
+extern Py_ssize_t gmap_pysize_from_sym(sym_table *);
+ /* Determine the size of a mapping based on a `sym_table'. */
+
/*----- That's all, folks -------------------------------------------------*/
#ifdef __cplusplus
/*----- Generic mapping support -------------------------------------------*/
+/* Operations table. ME is the mapping object throughout. */
+typedef struct gmap_ops {
+ size_t isz; /* iterator size */
+
+ void *(*lookup)(PyObject *me, PyObject *key, unsigned *f);
+ /* Lookup the KEY. If it is found, return an entry pointer for it; if F
+ * is not null, set *F nonzero. Otherwise, if F is null, return a null
+ * pointer (without setting a pending exception); if F is not null, then
+ * set *F zero and return a fresh entry pointer. Return null on a Python
+ * exception (the caller will notice the difference.)
+ */
+
+ void (*iter_init)(PyObject *me, void *i);
+ /* Initialize an iterator at I. */
+
+ void *(*iter_next)(PyObject *me, void *i);
+ /* Return an entry pointer for a different item, or null if all have been
+ * visited.
+ */
+
+ PyObject *(*entry_key)(PyObject *me, void *e);
+ /* Return the key object for a mapping entry. */
+
+ PyObject *(*entry_value)(PyObject *me, void *e);
+ /* Return the value object for a mapping entry. */
+
+ int (*set_entry)(PyObject *me, void *e, PyObject *val);
+ /* Modify the entry by storing VAL in its place. Return 0 on success,
+ * or -1 on a Python error.
+ */
+
+ int (*del_entry)(PyObject *me, void *e);
+ /* Delete the entry. (It may be necessary to delete a freshly allocated
+ * entry, e.g., if `set_entry' failed.) Return 0 on success, or -1 on a
+ * Python error.
+ */
+} gmap_ops;
+
+/* The intrusion at the head of a mapping object. */
+#define GMAP_PYOBJ_HEAD \
+ PyObject_HEAD \
+ const gmap_ops *gmops;
+
+typedef struct gmap_pyobj {
+ GMAP_PYOBJ_HEAD
+} gmap_pyobj;
+#define GMAP_OPS(obj) (((gmap_pyobj *)(obj))->gmops)
+ /* Discover the operations from a mapping object. */
+
/* Mapping methods. */
#define GMAP_METMNAME(func) gmapmeth_##func
#define GMAP_METH(func, doc) STD_METHOD(GMAP_METMNAME, func, 0, doc)
KWMETH(setdefault, "D.setdefault(K, [default = None]) -> VALUE") \
KWMETH(pop, "D.pop(KEY, [default = <error>]) -> VALUE") \
NAMETH(popitem, "D.popitem() -> (KEY, VALUE)") \
- METH (update, "D.update(MAP)")
+ KWMETH(update, "D.update(MAP)")
GMAP_DOMETHODS(GMAP_METHDECL, GMAP_KWMETHDECL, GMAP_NAMETHDECL)
#define GMAP_ROMETHODS GMAP_DOROMETHODS(GMAP_METH, GMAP_KWMETH, GMAP_NAMETH)
/* Mapping protocol implementation. */
extern Py_ssize_t gmap_pysize(PyObject *); /* for `mp_length' */
+extern PyObject *gmap_pyiter(PyObject *); /* for `tp_iter' */
+extern PyObject *gmap_pylookup(PyObject *, PyObject *); /* for `mp_subscript' */
+extern int gmap_pystore(PyObject *, PyObject *, PyObject *); /* for `mp_ass_subscript' */
+extern int gmap_pyhaskey(PyObject *, PyObject *); /* for `sq_contains' */
extern const PySequenceMethods gmap_pysequence; /* for `tp_as_sequence' */
+extern const PyMethodDef gmapro_pymethods[]; /* read-only methods */
extern const PyMethodDef gmap_pymethods[]; /* all the standard methods */
/*----- That's all, folks -------------------------------------------------*/
'mp.c', 'field.c', 'ec.c', 'group.c', 'passphrase.c',
'share.c', 'key.c',
'pyke/pyke.c', 'pyke/pyke-mLib.c',
- 'pyke/mapping.c'],
+ 'pyke/mapping.c', 'pyke/mapping-mLib.c'],
##extra_compile_args = ['-O0'],
include_dirs = MS.uniquify(MS.INCLUDEDIRS),
library_dirs = MS.uniquify(MS.LIBDIRS),
model.update({ 2: 212, 6: 606, 7: 707 })
map.update({ me._mkkey(2): me._mkvalue(212),
- me._mkkey(6): me._mkvalue(606),
- me._mkkey(7): me._mkvalue(707) })
+ me._mkkey(6): me._mkvalue(606) },
+ **{ me._mkkey(7): me._mkvalue(707) })
check_views()
model[9] = 909