--- /dev/null
+base32.pyx
+base64.pyx
+hex.pyx
+build
+MANIFEST
+dist
+mLib.c
+COPYING
+mdwsetup.py
+*.pyc
+auto-version
+pysetup.mk
--- /dev/null
+COPYING
+auto-version
+mdwsetup.py
+pysetup.mk
--- /dev/null
+Mark Wooding <mdw@distorted.org.uk> <mdw>
+Mark Wooding <mdw@distorted.org.uk> <mdw@metalzone.distorted.org.uk>
(append
'((author . "Straylight/Edgeware")
(licence-text . "[[gpl]]")
- (full-title . "Pyke: the Python Kit for Extensions")
- (program . "Pyke"))
+ (full-title . "the Python interface to mLib")
+ (program . "mLib/Python"))
skel-alist))
--- /dev/null
+### Manifest template for mLib/Python.
+
+## Generated build machinery.
+include COPYING auto-version mdwsetup.py pysetup.mk
+
+## Basic stuff.
+include MANIFEST.in setup.py Makefile mLib.pyx
+include defs.pxi grim.h utils.pyx
+
+## buf
+include lbuf.pyx pkbuf.pyx
+
+## codec
+include codec.pyx codec.pyx.in url.pyx
+
+## hash
+include crc32.pyx unihash.pyx
+
+## sel
+include bres.pyx conn.pyx ident.pyx
+include sel-base.pyx sel-file.pyx sel-timer.pyx
+include selbuf.pyx selpk.pyx sig.pyx
+
+## struct
+include mapping.pyx
+include array.h array.c assoc.pyx atom.h atom-base.c atom.pyx sym.pyx
+
+## sys
+include stuff.pyx fdutils.pyx fwatch.pyx mdup.pyx
+
+## ui
+include report.pyx
+
+## utils
+include str.pyx
+
+## Debian.
+include debian/rules debian/control debian/changelog
+include debian/copyright debian/compat debian/source/format
--- /dev/null
+### -*-makefile-*-
+include pysetup.mk
--- /dev/null
+Nothing much to say
--- /dev/null
+/* -*-c-*-
+ *
+ * Double-ended arrays
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Python interface to mLib.
+ *
+ * mLib/Python 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.
+ *
+ * mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+
+#include <string.h>
+
+#include <mLib/darray.h>
+#include <mLib/dstr.h>
+#include <mLib/exc.h>
+
+#include "array.h"
+#include "grim.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+DA_DECL(obj_v, PyObject *);
+
+typedef struct da_pyobj {
+ PyObject_HEAD
+ obj_v v;
+} da_pyobj;
+#define DA_PYCHECK(o) PyObject_TypeCheck((o), &da_pytype)
+#define DA_V(o) (&((da_pyobj *)(o))->v)
+
+typedef struct daiter_pyobj {
+ PyObject_HEAD
+ PyObject *da;
+ size_t i;
+} daiter_pyobj;
+#define DAITER_DA(obj) (((daiter_pyobj *)(obj))->da)
+#define DAITER_V(obj) DA_V(DAITER_DA(obj))
+#define DAITER_I(obj) (((daiter_pyobj *)(obj))->i)
+
+static int getseq(PyObject **pseq, PyObject ***v, size_t *n)
+{
+ PyObject *seq = *pseq;
+
+ if (!seq || seq == Py_None) {
+ *v = 0;
+ *n = 0;
+ *pseq = 0;
+ } else if (DA_PYCHECK(seq)) {
+ *v = DA(DA_V(seq));
+ *n = DA_LEN(DA_V(seq));
+ Py_INCREF(seq);
+ } else if ((seq = PySequence_Fast(seq, "expected iterable")) == 0)
+ return (-1);
+ else {
+ *pseq = seq;
+ *v = PySequence_Fast_ITEMS(seq);
+ *n = PySequence_Fast_GET_SIZE(seq);
+ }
+ return (0);
+}
+
+static void range_inc(PyObject **v, PyObject **vl)
+ { while (v < vl) { Py_INCREF(*v); v++; } }
+static void range_dec(PyObject **v, PyObject **vl)
+ { if (v) { while (v < vl) { Py_DECREF(*v); v++; } } }
+static void range_copy(PyObject ***gv, PyObject ***gvl)
+{
+ size_t n = *gvl - *gv;
+ size_t sz = sizeof(PyObject *) * n;
+ PyObject **v;
+ if (!n) { *gv = *gvl = 0; return; }
+ v = xmalloc(sz);
+ memcpy(v, *gv, sz);
+ *gv = v;
+ *gvl = v + n;
+}
+
+static PyObject *abstract_pynew(PyTypeObject *ty,
+ PyObject *hunoz, PyObject *hukairz)
+{
+ PyErr_SetString(PyExc_TypeError, "can't instantiate this type");
+ return (0);
+}
+
+/*----- Iterator ----------------------------------------------------------*/
+
+static PyObject *daiter_pynext(PyObject *me)
+{
+ PyObject *x;
+
+ if (DAITER_I(me) >= DA_LEN(DAITER_V(me))) return (0);
+ x = DA(DAITER_V(me))[DAITER_I(me)]; DAITER_I(me)++; RETURN_OBJ(x);
+}
+
+static void daiter_pydealloc(PyObject *me)
+ { Py_DECREF(DAITER_DA(me)); PyObject_DEL(me); }
+
+PyTypeObject daiter_pytype = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "mLib.ArrayIter", /* @tp_name@ */
+ sizeof(daiter_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ daiter_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@ */
+"Array iterator.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ PyObject_SelfIter, /* @tp_iter@ */
+ daiter_pynext, /* @tp_iternexr@ */
+ 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@ */
+};
+
+/*----- Main array code ---------------------------------------------------*/
+
+static void da_doinsert(PyObject *me, PyObject **items, size_t n,
+ size_t start, size_t end)
+{
+ PyObject **v, **gv, **gvl;
+ obj_v *da = DA_V(me);
+ size_t off, ne;
+
+ ne = end - start;
+ v = DA(da);
+ gv = v + start; gvl = v + end; range_copy(&gv, &gvl);
+ if (start < DA_LEN(da) - end) {
+ if (n > ne) {
+ off = n - ne;
+ DA_SHUNT(da, off);
+ DA_UNSAFE_SLIDE(da, off);
+ memmove(v, v + off, sizeof(PyObject *) * start);
+ } else {
+ off = ne - n;
+ memmove(v + off, v, sizeof(PyObject *) * start);
+ DA_UNSAFE_UNSLIDE(da, off);
+ }
+ } else {
+ if (n > ne) {
+ off = n - ne;
+ DA_ENSURE(da, off);
+ memmove(v + end + off, v + end,
+ sizeof(PyObject *) * (DA_LEN(da) - end));
+ } else {
+ off = ne - n;
+ memmove(v + end - off, v + end,
+ sizeof(PyObject *) * (DA_LEN(da) - end));
+ DA_UNSAFE_SHRINK(da, off);
+ }
+ DA_UNSAFE_EXTEND(da, off);
+ }
+
+ if (n) {
+ v = DA(da) + start;
+ memcpy(v, items, sizeof(PyObject *) * n);
+ range_inc(v, v + n);
+ }
+ if (gv) {
+ range_dec(gv, gvl);
+ xfree(gv);
+ }
+}
+
+static int da_insert(PyObject *me, PyObject *seq, int start, int end)
+{
+ PyObject **items;
+ size_t n;
+
+ if (0 > start || start > end || end > DA_LEN(DA_V(me))) {
+ PyErr_SetString(PyExc_IndexError, "bad slice");
+ return (-1);
+ }
+ if (getseq(&seq, &items, &n)) return (-1);
+ da_doinsert(me, items, n, start, end);
+ Py_XDECREF(seq);
+ return (0);
+}
+
+static PyObject *da_new(PyTypeObject *ty)
+{
+ da_pyobj *me = (da_pyobj *)ty->tp_alloc(ty, 0);
+ DA_CREATE(&me->v);
+ return ((PyObject *)me);
+}
+
+static PyObject *da_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+ { return (da_new(ty)); }
+static int da_pyinit(PyObject *me, PyObject *arg, PyObject *kw)
+{
+ PyObject *init = 0;
+ static char *kwlist[] = { "sequence", 0 };
+
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:new", kwlist, &init) ||
+ (init && da_insert((PyObject *)me, init, 0, 0)))
+ return (-1);
+ return (0);
+}
+
+static void da_pydealloc(PyObject *me)
+{
+ size_t i;
+ PyObject **v = DA(DA_V(me));
+ size_t n = DA_LEN(DA_V(me));
+
+ for (i = 0; i < n; i++) Py_DECREF(v[i]);
+ DA_DESTROY(DA_V(me));
+}
+
+static Py_ssize_t da_pylength(PyObject *me)
+ { return (DA_LEN(DA_V(me))); }
+
+static int da_pytraverse(PyObject *me, visitproc proc, void *arg)
+{
+ size_t i;
+ PyObject **v = DA(DA_V(me));
+ size_t n = DA_LEN(DA_V(me));
+ int err;
+
+ for (i = 0; i < n; i++) {
+ if ((err = proc(v[i], arg)) != 0)
+ return (err);
+ }
+ return (0);
+}
+
+static int da_pyclear(PyObject *me)
+{
+ range_dec(DA(DA_V(me)), DA(DA_V(me)) + DA_LEN(DA_V(me)));
+ DA_RESET(DA_V(me));
+ return (0);
+}
+
+static PyObject *da_pyconcat(PyObject *me, PyObject *other)
+{
+ PyObject *x = da_new(&da_pytype);
+ PyObject **items = DA(DA_V(me));
+ size_t n = DA_LEN(DA_V(me));
+
+ da_doinsert(x, items, n, 0, 0);
+ if (da_insert(x, other, n, n)) {
+ Py_DECREF(x);
+ return (0);
+ }
+ return (x);
+}
+
+static PyObject *da_pyrepeat(PyObject *me, Py_ssize_t times)
+{
+ PyObject *x = da_new(&da_pytype);
+ PyObject **items = DA(DA_V(me)), **dest;
+ size_t n = DA_LEN(DA_V(me));
+ Py_ssize_t i;
+
+ DA_ENSURE(DA_V(x), n * times);
+ DA_UNSAFE_EXTEND(DA_V(x), n * times);
+ for (i = 0, dest = DA(DA_V(x)); i < times; i++, dest += n)
+ memcpy(dest, items, n * sizeof(PyObject *));
+ range_inc(DA(DA_V(x)), DA(DA_V(x)) + n * times);
+ return (x);
+}
+
+static PyObject *da_pygetitem(PyObject *me, Py_ssize_t i)
+{
+ PyObject *o;
+
+ if (i < 0 || i >= DA_LEN(DA_V(me))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return (0);
+ }
+ o = DA(DA_V(me))[i];
+ Py_INCREF(o);
+ return (o);
+}
+
+static PyObject *da_pygetslice(PyObject *me, Py_ssize_t i, Py_ssize_t j)
+{
+ PyObject *x;
+
+ if (i < 0 || j < i || DA_LEN(DA_V(me)) < j) {
+ PyErr_SetString(PyExc_IndexError, "bad slice");
+ return (0);
+ }
+ x = da_new(&da_pytype);
+ da_doinsert(x, DA(DA_V(me)) + i, j - i, 0, 0);
+ return (x);
+}
+
+static int da_pyputitem(PyObject *me, Py_ssize_t i, PyObject *x)
+{
+ PyObject **p;
+
+ if (i < 0 || i >= DA_LEN(DA_V(me))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return (-1);
+ }
+ p = DA(DA_V(me)) + i;
+ Py_DECREF(*p);
+ *p = x;
+ Py_INCREF(*p);
+ return (0);
+}
+
+static int da_pyputslice(PyObject *me, Py_ssize_t i, Py_ssize_t j,
+ PyObject *x)
+ { return (da_insert(me, x, i, j)); }
+
+static int da_pycontainsp(PyObject *me, PyObject *x)
+{
+ PyObject **items = DA(DA_V(me));
+ size_t n = DA_LEN(DA_V(me));
+ size_t i;
+ int rc;
+
+ for (i = 0; i < n; i++) {
+ if (PyObject_Cmp(items[i], x, &rc))
+ return (-1);
+ if (rc)
+ return (1);
+ }
+ return (0);
+}
+
+static PyObject *da_pyrepr(PyObject *me)
+{
+ dstr d = DSTR_INIT;
+ PyObject *s, *rc = 0;
+ char *p;
+ Py_ssize_t n;
+ size_t i;
+
+ dstr_puts(&d, "Array([");
+ for (i = 0; i < DA_LEN(DA_V(me)); i++) {
+ if ((s = PyObject_Repr(DA(DA_V(me))[i])) == 0 ||
+ PyString_AsStringAndSize(s, &p, &n)) {
+ Py_XDECREF(s);
+ goto done;
+ }
+ if (i) dstr_puts(&d, ", ");
+ dstr_putm(&d, p, n);
+ Py_DECREF(s);
+ }
+ dstr_puts(&d, "])");
+ rc = PyString_FromStringAndSize(d.buf, d.len);
+done:
+ dstr_destroy(&d);
+ return (rc);
+}
+
+static PyObject *da_pyappend(PyObject *me, PyObject *seq)
+{
+ size_t n = DA_LEN(DA_V(me));
+ if (da_insert(me, seq, n, n)) return (0);
+ RETURN_ME;
+}
+
+static PyObject *da_pyiprepeat(PyObject *me, Py_ssize_t times)
+{
+ PyObject **items, **dest;
+ size_t n = DA_LEN(DA_V(me));
+ Py_ssize_t i;
+
+ if (times < 0) {
+ PyErr_SetString(PyExc_ValueError, "multiplier must be nonnegative");
+ return (0);
+ }
+ if (!times) {
+ items = DA(DA_V(me));
+ range_dec(items, items + n);
+ DA_RESET(DA_V(me));
+ RETURN_ME;
+ }
+ times--;
+ DA_ENSURE(DA_V(me), n * times);
+ items = DA(DA_V(me));
+ for (i = 0, dest = items + n; i < times; i++, dest += n)
+ memcpy(dest, items, n * sizeof(PyObject *));
+ range_inc(items + n, dest);
+ DA_UNSAFE_EXTEND(DA_V(me), n * times);
+ RETURN_ME;
+}
+
+static PyObject *da_pyget(PyObject *me, PyObject *index)
+{
+ if (PySlice_Check(index)) {
+ Py_ssize_t start, stop, step, len;
+ PyObject *v;
+ PyObject **ww;
+ PyObject **vv;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)index, DA_LEN(DA_V(me)),
+ &start, &stop, &step, &len))
+ return (0);
+ if (step == 1) return (da_pygetslice(me, start, stop));
+ v = da_new(&da_pytype);
+ DA_ENSURE(DA_V(v), len);
+ vv = DA(DA_V(v));
+ ww = DA(DA_V(me)) + start;
+ DA_UNSAFE_EXTEND(DA_V(v), len);
+ while (len) {
+ *vv = *ww;
+ Py_INCREF(*vv);
+ vv++; ww += step; len--;
+ }
+ return ((PyObject *)v);
+ } else {
+ int i;
+
+ if ((i = PyInt_AsLong(index)) == -1 && PyErr_Occurred()) return (0);
+ return (da_pygetitem(me, i));
+ }
+}
+
+static int da_pyput(PyObject *me, PyObject *index, PyObject *x)
+{
+ if (PySlice_Check(index)) {
+ Py_ssize_t start, stop, step, len;
+ size_t n;
+ PyObject **ww;
+ PyObject **vv;
+ PyObject **g, **gg;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)index, DA_LEN(DA_V(me)),
+ &start, &stop, &step, &len))
+ return (-1);
+ if (step == 1) return (da_insert(me, x, start, stop));
+ if (getseq(&x, &vv, &n)) return (-1);
+ if (n != len) {
+ PyErr_SetString(PyExc_ValueError, "wrong number of items");
+ Py_XDECREF(x);
+ return (-1);
+ }
+ g = gg = xmalloc(len * sizeof(PyObject *));
+ ww = DA(DA_V(me)) + start;
+ while (len) {
+ *gg++ = *ww; *ww = *vv++;
+ Py_INCREF(*ww);
+ ww += step; len--;
+ }
+ range_dec(g, gg);
+ xfree(g);
+ Py_XDECREF(x);
+ return (0);
+ } else {
+ int i;
+
+ if ((i = PyInt_AsLong(index)) == -1 && PyErr_Occurred()) return (-1);
+ return (da_pyputitem(me, i, x));
+ }
+}
+
+static PyObject *da_pyiter(PyObject *me)
+{
+ daiter_pyobj *i = PyObject_NEW(daiter_pyobj, &daiter_pytype);
+ i->da = me; Py_INCREF(me);
+ i->i = 0;
+ return ((PyObject *)i);
+}
+
+static PyObject *dameth_push(PyObject *me, PyObject *arg)
+{
+ PyObject *x;
+
+ if (!PyArg_ParseTuple(arg, "O:push", &x)) return (0);
+ Py_INCREF(x);
+ DA_PUSH(DA_V(me), x);
+ RETURN_ME;
+}
+
+static PyObject *dameth_pop(PyObject *me, PyObject *arg)
+{
+ PyObject *x = Py_None;
+
+ if (!PyArg_ParseTuple(arg, ":pop")) return (0);
+ TRY
+ x = DA_POP(DA_V(me));
+ CATCH switch (exc_type) {
+ case DAEXC_UFLOW:
+ PyErr_SetString(PyExc_ValueError, "stack underflow");
+ return (0);
+ default:
+ RETHROW;
+ } END_TRY;
+ RETURN_OBJ(x);
+}
+
+static PyObject *dameth_unshift(PyObject *me, PyObject *arg)
+{
+ PyObject *x;
+
+ if (!PyArg_ParseTuple(arg, "O:unshift", &x)) return (0);
+ Py_INCREF(x);
+ DA_UNSHIFT(DA_V(me), x);
+ RETURN_ME;
+}
+
+static PyObject *dameth_shift(PyObject *me, PyObject *arg)
+{
+ PyObject *x = Py_None;
+
+ if (!PyArg_ParseTuple(arg, ":shift")) return (0);
+ TRY
+ x = DA_SHIFT(DA_V(me));
+ CATCH switch (exc_type) {
+ case DAEXC_UFLOW:
+ PyErr_SetString(PyExc_ValueError, "stack underflow");
+ return (0);
+ default:
+ RETHROW;
+ } END_TRY;
+ RETURN_OBJ(x);
+}
+
+static PyObject *dameth_tidy(PyObject *me, PyObject *arg)
+{
+ if (!PyArg_ParseTuple(arg, ":tidy")) return (0);
+ DA_TIDY(DA_V(me));
+ RETURN_ME;
+}
+
+static PyMethodDef da_pymethods[] = {
+#define METHNAME(func) dameth_##func
+ METH (push, "A.push(X): [A, B, ..., W], X -> [A, B, ..., W, X]")
+ METH (pop, "A.pop() -> X: [A, B, ..., W, X] -> [A, B, ..., W]")
+ METH (unshift, "A.unshift(X): [A, B, ..., W], X -> [X, A, ..., W]")
+ METH (shift, "A.shift() -> X: [X, A, ..., W] -> [A, ..., W], X")
+ METH (tidy, "A.tidy()")
+#undef METHNAME
+ { 0 }
+};
+
+static PySequenceMethods da_pysequence = {
+ da_pylength, /* @sq_length@ */
+ da_pyconcat, /* @sq_concat@ */
+ da_pyrepeat, /* @sq_repeat@ */
+ da_pygetitem, /* @sq_item@ */
+ da_pygetslice, /* @sq_slice@ */
+ da_pyputitem, /* @sq_ass_item@ */
+ da_pyputslice, /* @sq_ass_slice@ */
+ da_pycontainsp, /* @sq_contains@ */
+ da_pyappend, /* @sq_inplace_concat@ */
+ da_pyiprepeat /* @sq_inplace_repeat@ */
+};
+
+static PyMappingMethods da_pymapping = {
+ da_pylength, /* @mp_length@ */
+ da_pyget, /* @mp_subscript@ */
+ da_pyput /* @mp_ass_subscript@ */
+};
+
+PyTypeObject da_pytype = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "mLib.Array", /* @tp_name@ */
+ sizeof(da_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ da_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ da_pyrepr, /* @tp_repr@ */
+ 0, /* @tp_as_number@ */
+ &da_pysequence, /* @tp_as_sequence@ */
+ &da_pymapping, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ &da_pyrepr, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_HAVE_GC,
+
+ /* @tp_doc@ */
+"Double-ended array type.",
+
+ da_pytraverse, /* @tp_traverse@ */
+ da_pyclear, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ da_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ da_pymethods, /* @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@ */
+ da_pyinit, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ da_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+/*----- Initialization ----------------------------------------------------*/
+
+void da_pysetup(void)
+ { PyType_Ready(&da_pytype); PyType_Ready(&daiter_pytype); }
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Double-ended arrays
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Python interface to mLib.
+ *
+ * mLib/Python 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.
+ *
+ * mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <Python.h>
+
+extern void da_pysetup(void);
+extern PyTypeObject da_pytype, daiter_pytype;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+### -*-pyrex-*-
+###
+### Association tables
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef struct _assoc_entry:
+ sym_base _b
+ PyObject *v
+
+cdef class AssocTable (Mapping):
+ cdef assoc_table _t
+ cdef int _init(me) except -1:
+ assoc_create(&me._t)
+ return 0
+ cdef void *_find(me, object key, unsigned *f) except NULL:
+ cdef void *p
+ cdef Py_ssize_t n
+ cdef _assoc_entry *e
+ cdef atom *a
+ a = ATOM_A(atom_pyintern(key))
+ PyObject_AsReadBuffer(key, <cvp *>&p, &n)
+ if f:
+ f[0] = 0
+ e = <_assoc_entry *>assoc_find(&me._t, a, PSIZEOF(e), f)
+ if not f[0]:
+ e.v = NULL
+ else:
+ e = <_assoc_entry *>assoc_find(&me._t, a, 0, NULL)
+ return <void *>e
+ cdef object _key(me, void *e):
+ return atom_pywrap(ASSOC_ATOM(e))
+ cdef object _value(me, void *e):
+ cdef _assoc_entry *ee
+ ee = <_assoc_entry *>e
+ Py_INCREF(ee.v)
+ return <object>ee.v
+ cdef void _setval(me, void *e, object val):
+ cdef _assoc_entry *ee
+ ee = <_assoc_entry *>e
+ if ee.v:
+ Py_DECREF(ee.v)
+ ee.v = <PyObject *>v
+ Py_INCREF(ee.v)
+ cdef void _del(me, void *e):
+ cdef _assoc_entry *ee
+ ee = <_assoc_entry *>e
+ if ee.v:
+ Py_DECREF(ee.v)
+ assoc_remove(&me._t, <void *>ee)
+ cdef _MapIterator _iter(me):
+ return _AssocIter(me)
+
+cdef class _AssocIter (_MapIterator):
+ cdef AssocTable t
+ cdef assoc_iter i
+ def __cinit__(me, AssocTable t not None):
+ me.t = t
+ assoc_mkiter(&me.i, &me.t._t)
+ cdef void *_next(me):
+ return assoc_next(&me.i)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+/* -*-c-*-
+ *
+ * Atom stuff
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Python interface to mLib.
+ *
+ * mLib/Python 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.
+ *
+ * mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <Python.h>
+
+#include <mLib/atom.h>
+#include <mLib/assoc.h>
+#include <mLib/dstr.h>
+
+#include "atom.h"
+#include "grim.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct entry {
+ assoc_base _b;
+ PyObject *a;
+} entry;
+
+/*----- Static variables --------------------------------------------------*/
+
+static assoc_table obarray;
+
+/*----- Main code ---------------------------------------------------------*/
+
+PyObject *atom_pywrap(atom *a)
+{
+ entry *e;
+ unsigned f = 0;
+
+ e = assoc_find(&obarray, a, sizeof(entry), &f);
+ if (!f) {
+ atom_pyobj *ao = PyObject_NEW(atom_pyobj, &atom_pytype);
+ ao->a = a;
+ e->a = (PyObject *)ao;
+ }
+ RETURN_OBJ(e->a);
+}
+
+PyObject *atom_pyintern(PyObject *x)
+{
+ atom *a;
+ const void *p;
+ Py_ssize_t n;
+
+ if (ATOM_PYCHECK(x))
+ RETURN_OBJ(x);
+ if (x == Py_None)
+ a = atom_gensym(ATOM_GLOBAL);
+ else {
+ if (PyObject_AsReadBuffer(x, &p, &n)) return (0);
+ a = atom_nintern(ATOM_GLOBAL, p, n);
+ }
+ return (atom_pywrap(a));
+}
+
+static void atom_pydealloc(PyObject *me)
+ { fprintf(stderr, "ouch! freeing atom\n"); abort(); }
+
+static PyObject *atom_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+ PyObject *name;
+ static char *kwlist[] = { "name", 0 };
+
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &name))
+ return (0);
+ return (atom_pyintern(name));
+}
+
+static PyObject *aget_name(PyObject *me, void *hunoz)
+{
+ return (PyString_FromStringAndSize(ATOM_NAME(ATOM_A(me)),
+ ATOM_LEN(ATOM_A(me))));
+}
+
+static PyObject *aget_internedp(PyObject *me, void *hunoz)
+{
+ PyObject *rc = (ATOM_A(me)->f & ATOMF_GENSYM) ? Py_False : Py_True;
+ RETURN_OBJ(rc);
+}
+
+static PyGetSetDef atom_pygetset[] = {
+#define GETSETNAME(op, name) a##op##_##name
+ GET (name, "A.name -> NAME")
+ GET (internedp, "A.internedp -> BOOL")
+#undef GETSETNAME
+ { 0 }
+};
+
+static PyObject *atom_pyrichcompare(PyObject *x, PyObject *y, int op)
+{
+ PyObject *rc = 0;
+
+ switch (op) {
+ case Py_EQ: rc = (x == y) ? Py_True : Py_False; break;
+ case Py_NE: rc = (x != y) ? Py_True : Py_False; break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "atoms are unordered");
+ return (0);
+ }
+ RETURN_OBJ(rc);
+}
+
+static PyObject *atom_pyrepr(PyObject *me)
+{
+ PyObject *s, *sr = 0;
+ PyObject *rc = 0;
+ char *p;
+ Py_ssize_t n;
+ dstr d = DSTR_INIT;
+
+ if ((s = aget_name(me, 0)) == 0 ||
+ (sr = PyObject_Repr(s)) == 0 ||
+ PyString_AsStringAndSize(sr, &p, &n))
+ goto done;
+ dstr_puts(&d, "Atom(");
+ dstr_putm(&d, p, n);
+ dstr_puts(&d, ")");
+ rc = PyString_FromStringAndSize(d.buf, d.len);
+done:
+ Py_XDECREF(s);
+ Py_XDECREF(sr);
+ dstr_destroy(&d);
+ return (rc);
+}
+
+static long atom_pyhash(PyObject *me)
+ { long h = ATOM_HASH(ATOM_A(me)); if (h == -1) h = -2; return (h); }
+
+PyTypeObject atom_pytype = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "mLib.Atom", /* @tp_name@ */
+ sizeof(atom_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ atom_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ atom_pyrepr, /* @tp_repr@ */
+ 0, /* @tp_as_number@ */
+ 0, /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ atom_pyhash, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ atom_pyrepr, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT, /* @tp_flags@ */
+
+ /* @tp_doc@ */
+"Atom.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ atom_pyrichcompare, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ 0, /* @tp_iter@ */
+ 0, /* @tp_iternexr@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ atom_pygetset, /* @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@ */
+ atom_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+void atom_pysetup(void)
+ { assoc_create(&obarray); PyType_Ready(&atom_pytype); }
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Atom stuff
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Python interface to mLib.
+ *
+ * mLib/Python 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.
+ *
+ * mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ATOM_H
+#define ATOM_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <Python.h>
+
+#include <mLib/atom.h>
+#include <mLib/assoc.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct atom_pyobj {
+ PyObject_HEAD
+ atom *a;
+} atom_pyobj;
+#define ATOM_PYCHECK(obj) PyObject_TypeCheck(obj, &atom_pytype)
+#define ATOM_A(obj) (((atom_pyobj *)(obj))->a)
+
+extern PyTypeObject atom_pytype;
+
+/*----- Functions provided ------------------------------------------------*/
+
+extern PyObject *atom_pywrap(atom *);
+extern PyObject *atom_pyintern(PyObject *);
+extern void atom_pysetup(void);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+### -*-pyrex-*-
+###
+### Atom tables
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class AtomIter:
+ cdef atom_iter _i
+ def __cinit__(me):
+ atom_mkiter(&me._i, ATOM_GLOBAL)
+ def __next__(me):
+ cdef atom *a
+ a = atom_next(&me._i)
+ if not a:
+ raise StopIteration
+ return atom_pywrap(a)
+ def __iter__(me):
+ return me
+
+def atoms():
+ """atoms() -> ITER: return iterator over known atoms"""
+ return AtomIter()
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Background name resolution
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class SelResolve:
+ """Abstract superclass for background name resolution."""
+ cdef bres_client r
+ cdef int _activep
+ cdef _resolved
+ cdef _failed
+ def __init__(me, *hunoz, **hukairz):
+ raise TypeError, 'abstract class'
+ def __dealloc__(me):
+ if me._activep:
+ me._dead()
+ bres_abort(&me.r)
+ property activep:
+ """BR.activep: is lookup still waiting?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ def kill(me):
+ """BR.kill(): cancel in-progress lookup"""
+ if not me._activep:
+ raise ValueError, 'already dead'
+ me._dead()
+ bres_abort(&me.r)
+ return me
+ cdef _dead(me):
+ me._activep = 0
+ me.dead()
+ def dead(me):
+ """BR.dead(): called when lookup completes or is cancelled"""
+ pass
+ property resolvedproc:
+ """BR.resolvedproc -> FUNC: call FUNC(NAME, ALIASES, ADDRS) when ok"""
+ def __get__(me):
+ return me._resolved
+ def __set__(me, proc):
+ me._resolved = _checkcallable(proc, 'resolved proc')
+ def __del__(me):
+ me._resolved = None
+ property failedproc:
+ """BR.failedproc -> FUNC: call FUNC() when lookup fails"""
+ def __get__(me):
+ return me._failed
+ def __set__(me, proc):
+ me._failed = _checkcallable(proc, 'failed proc')
+ def __del__(me):
+ me._failed = None
+ def resolved(me, name, aliases, addrs):
+ """BR.resolved(NAME, ALIASES, ADDRS): called when lookup completes"""
+ return _maybecall(me._resolved, (name, aliases, addrs))
+ def failed(me):
+ """BR.failed(): called when lookup fails"""
+ return _maybecall(me._failed, ())
+
+cdef class SelResolveByName (SelResolve):
+ """
+ Resolve a hostname to an IP address, asynchronously.
+
+ SelResolveByName(NAME, [resolvedproc = None], [failedproc = None])
+
+ Calls RESOLVEDPROC(NAME, ALIASES, ADDRS) on success, or FAILEDPROC() on
+ failure.
+ """
+ def __cinit__(me, char *name, resolvedproc = None, failedproc = None,
+ *hunoz, **hukairz):
+ me._resolved = _checkcallable(resolvedproc, 'resolved proc')
+ me._failed = _checkcallable(failedproc, 'failed proc')
+ me._activep = 1
+ bres_byname(&me.r, name, _resfunc, <void *>me)
+ def __init__(me, name, resolvedproc = None, failedproc = None):
+ pass
+
+cdef class SelResolveByAddr (SelResolve):
+ """
+ Resolve an IPv4 address to a hostname, asynchronously.
+
+ SelResolveByAddr(ADDR, [resolvedproc = None], [failedproc = None])
+
+ Calls RESOLVEDPROC(NAME, ALIASES, ADDRS) on success, or FAILEDPROC() on
+ failure.
+ """
+ def __cinit__(me, char *addr, resolvedproc = None, failedproc = None,
+ *hunoz, **hukairz):
+ cdef in_addr ia
+ if not inet_aton(addr, &ia):
+ raise TypeError, 'bad IP address'
+ me._resolved = _checkcallable(resolvedproc, 'resolved proc')
+ me._failed = _checkcallable(failedproc, 'failed proc')
+ me._activep = 1
+ bres_byaddr(&me.r, ia, _resfunc, <void *>me)
+ def __init__(me, addr, resolvedproc = None, failedproc = None):
+ pass
+
+cdef void _resfunc(hostent *h, void *arg):
+ cdef SelResolve r
+ cdef int i
+ r = <SelResolve>arg
+ r._dead()
+ if h is NULL:
+ r.failed()
+ else:
+ alias = []
+ addr = []
+ i = 0
+ while h.h_aliases[i]:
+ alias.append(h.h_aliases[i])
+ i = i + 1
+ i = 0
+ while h.h_addr_list[i]:
+ addr.append(inet_ntoa((<in_addr *>h.h_addr_list[i])[0]))
+ i = i + 1
+ r.resolved(h.h_name, alias, addr)
+
+bres_exec(NULL)
+bres_init(&_sel)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Generic encoder/decoder
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Base classes.
+
+cdef extern from 'mLib/codec.h':
+
+ ctypedef struct codec
+
+ ctypedef struct codec_class:
+ char *name
+ codec *(*encoder)(unsigned f, char *ind, unsigned max)
+ codec *(*decoder)(unsigned f)
+
+ ctypedef struct codec_ops:
+ codec_class *c
+ int (*code)(codec *c, void *p, size_t, dstr *d)
+ void (*destroy)(codec *c)
+ ctypedef struct codec:
+ codec_ops *ops
+
+ enum:
+ CDCF_LOWERC
+ CDCF_IGNCASE
+ CDCF_NOEQPAD
+ CDCF_IGNEQPAD
+ CDCF_IGNEQMID
+ CDCF_IGNZPAD
+ CDCF_IGNNEWL
+ CDCF_IGNSPC
+ CDCF_IGNINVCH
+ CDCF_IGNJUNK
+
+ enum:
+ CDCERR_OK
+ CDCERR_INVCH
+ CDCERR_INVEQPAD
+ CDCERR_INVZPAD
+
+ char *_codec_strerror "codec_strerror"(int err)
+
+class CDCF:
+ LOWERC = CDCF_LOWERC
+ IGNCASE = CDCF_IGNCASE
+ NOEQPAD = CDCF_NOEQPAD
+ IGNEQPAD = CDCF_IGNEQPAD
+ IGNEQMID = CDCF_IGNEQMID
+ IGNZPAD = CDCF_IGNZPAD
+ IGNNEWL = CDCF_IGNNEWL
+ IGNSPC = CDCF_IGNSPC
+ IGNINVCH = CDCF_IGNINVCH
+ IGNJUNK = CDCF_IGNJUNK
+
+class CDCERR:
+ OK = CDCERR_OK
+ INVCH = CDCERR_INVCH
+ INVEQPAD = CDCERR_INVEQPAD
+ INVZPAD = CDCERR_INVZPAD
+
+class CodecError (Exception):
+ """
+ Exception from decoding operation.
+
+ Attributes: err = CDCERR.* code, msg = message string
+ """
+ def __init__(me, err):
+ me.err = err
+ me.msg = _codec_strerror(err)
+ def __str__(me):
+ return me.msg
+
+def codec_strerror(err):
+ """codec_strerror(ERR) -> STR: message for CDCERR.* code"""
+ return _codec_strerror(err)
+
+cdef int code(codec *c, void *p, size_t len, dstr *d) except -1:
+ cdef int err
+ err = c.ops.code(c, p, len, d)
+ if err:
+ raise CodecError(err)
+ return 0
+
+cdef class _BaseCodec:
+ """Abstract superclass for codecs."""
+ cdef codec *c
+ def __cinit__(me, *hunoz, **hukairz):
+ me.c = NULL
+ def __init__(me, *hunoz, **hukairz):
+ raise TypeError, 'abstract class'
+ def __dealloc__(me):
+ if me.c is not NULL:
+ me.c.ops.destroy(me.c)
+ cdef code(me, text, int finishp):
+ cdef void *p
+ cdef Py_ssize_t len
+ cdef dstr d
+ cdef int err
+ if me.c is NULL:
+ raise ValueError, 'Encoding finished'
+ DCREATE(&d)
+ try:
+ PyObject_AsReadBuffer(text, <cvp *>&p, &len)
+ code(me.c, p, len, &d)
+ if finishp:
+ code(me.c, NULL, 0, &d)
+ me.c.ops.destroy(me.c)
+ me.c = NULL
+ return PyString_FromStringAndSize(d.buf, d.len)
+ finally:
+ dstr_destroy(&d)
+ def done(me):
+ """C.done() -> OUT: final output"""
+ me.code('', True)
+
+cdef class _BaseEncoder (_BaseCodec):
+ def encode(me, text, finishp = False):
+ """C.encode(IN, [finishp = False]) -> OUT: continue/finish encoding"""
+ return me.code(text, finishp)
+
+cdef class _BaseDecoder (_BaseCodec):
+ def decode(me, text, finishp = False):
+ """C.decode(IN, [finishp = False]) -> OUT: continue/finish decoding"""
+ return me.code(text, finishp)
+
+###--------------------------------------------------------------------------
+### Base64.
+
+cdef extern from 'mLib/base64.h':
+ codec_class base64_class
+ codec_class file64_class
+ codec_class base64url_class
+
+cdef class Base64Encoder (_BaseEncoder):
+ """
+ Base64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 encoder.
+ """
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base64_class.encoder(flags, indent, maxline)
+
+cdef class Base64Decoder (_BaseDecoder):
+ """
+ Base64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 decoder.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base64_class.decoder(flags)
+
+cdef class File64Encoder (_BaseEncoder):
+ """
+ File64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 encoder, using `%' instead of `/', so encoded strings are safe as
+ filenames.
+ """
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = file64_class.encoder(flags, indent, maxline)
+
+cdef class File64Decoder (_BaseDecoder):
+ """
+ File64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 encoder, using `%' instead of `/', so encoded strings are safe as
+ filenames.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = file64_class.decoder(flags)
+
+cdef class Base64URLEncoder (_BaseEncoder):
+ """
+ Base64URLEncoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 encoder, using `-' and `_' instead of `+' and `/', so encoded
+ strings are safe as URL components.
+ """
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base64url_class.encoder(flags, indent, maxline)
+
+cdef class Base64URLDecoder (_BaseDecoder):
+ """
+ Base64URLDecoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base64 decoder, using `-' and `_' instead of `+' and `/', so encoded
+ strings are safe as URL components.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base64url_class.decoder(flags)
+
+###--------------------------------------------------------------------------
+### Base32.
+
+cdef extern from 'mLib/base32.h':
+ codec_class base32_class
+ codec_class base32hex_class
+
+cdef class Base32Encoder (_BaseEncoder):
+ """
+ Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base32 encoder.
+ """
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base32_class.encoder(flags, indent, maxline)
+
+cdef class Base32Decoder (_BaseDecoder):
+ """
+ Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base32 decoder.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base32_class.decoder(flags)
+
+cdef class Base32HexEncoder (_BaseEncoder):
+ """
+ Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base32 encoder, using digits and letters in ascending order, rather than
+ avoiding digits which visually resemble letters.
+ """
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base32hex_class.encoder(flags, indent, maxline)
+
+cdef class Base32HexDecoder (_BaseDecoder):
+ """
+ Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
+
+ Base32 decoder, using digits and letters in ascending order, rather than
+ avoiding digits which visually resemble letters.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base32hex_class.decoder(flags)
+
+###--------------------------------------------------------------------------
+### Hex.
+
+cdef extern from 'mLib/hex.h':
+ codec_class hex_class
+
+cdef class HexEncoder (_BaseEncoder):
+ """
+ HexEncoder([indent = '\\n'], [maxline = 72],
+ [flags = CDCF.IGNJUNK | CDCF.LOWERC])
+
+ Hexadecimal encoder.
+ """
+ def __init__(me, indent = '\n', maxline = 72,
+ flags = CDCF_IGNJUNK | CDCF_LOWERC):
+ me.c = hex_class.encoder(flags, indent, maxline)
+
+cdef class HexDecoder (_BaseDecoder):
+ """
+ HexDecoder([indent = '\\n'], [maxline = 72],
+ [flags = CDCF.IGNJUNK | CDCF.LOWERC])
+
+ Hexadecimal decoder.
+ """
+ def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC):
+ me.c = hex_class.decoder(flags)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Generic encoder/decoder
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef extern from 'mLib/%PREFIX%.h':
+ ctypedef struct %PREFIX%_ctx:
+ char *indent
+ int maxline
+ void _%PREFIX%_init "%PREFIX%_init"(%PREFIX%_ctx *b)
+ void _%PREFIX%_encode "%PREFIX%_encode"(%PREFIX%_ctx *b,
+ void *p, size_t sz, dstr *d)
+ void _%PREFIX%_decode"%PREFIX%_decode"(%PREFIX%_ctx *b,
+ void *p, size_t sz, dstr *d)
+
+cdef class %CLASS%Encode:
+ """
+ %CLASS%([indent = '\\n'], [maxline = 72])
+
+ Obsolete %CLASS% encoder.
+ """
+ cdef %PREFIX%_ctx ctx
+ def __cinit__(me, *hunoz, **hukairz):
+ _%PREFIX%_init(&me.ctx)
+ me.ctx.indent = NULL
+ def __init__(me, indent = '\n', maxline = 72):
+ if me.ctx.indent:
+ xfree(<void *>me.ctx.indent)
+ me.ctx.indent = xstrdup(indent)
+ me.ctx.maxline = maxline
+ def __dealloc__(me):
+ if me.ctx.indent:
+ xfree(<void *>me.ctx.indent)
+ property indent:
+ """E.indent -> INT: indent level for new lines"""
+ def __get__(me):
+ return me.ctx.indent
+ def __set__(me, indent):
+ if me.ctx.indent:
+ xfree(<void *>me.ctx.indent)
+ me.ctx.indent = xstrdup(indent)
+ property maxline:
+ """E.maxline -> INT: maximum length of line, or 0 to prevent splitting"""
+ def __get__(me):
+ return me.ctx.maxline
+ def __set__(me, maxline):
+ me.ctx.maxline = maxline
+ def encode(me, text):
+ """E.encode(IN) -> OUT: continue encoding"""
+ cdef void *p
+ cdef Py_ssize_t len
+ cdef dstr d
+ DCREATE(&d)
+ try:
+ PyObject_AsReadBuffer(text, <cvp *>&p, &len)
+ _%PREFIX%_encode(&me.ctx, p, len, &d)
+ rc = PyString_FromStringAndSize(d.buf, d.len)
+ finally:
+ dstr_destroy(&d)
+ return rc
+ def done(me):
+ """E.done() -> OUT: finish encoding, returning final output"""
+ cdef dstr d
+ DCREATE(&d)
+ try:
+ _%PREFIX%_encode(&me.ctx, NULL, 0, &d)
+ rc = PyString_FromStringAndSize(d.buf, d.len)
+ finally:
+ dstr_destroy(&d)
+ return rc
+
+def %PREFIX%_encode(text, *arg, **kw):
+ """%PREFIX%_encode(IN, [ARGS...]) -> OUT: %CLASS%-encode the string IN"""
+ e = %CLASS%Encode(*arg, **kw)
+ return e.encode(text) + e.done()
+
+cdef class %CLASS%Decode:
+ """
+ %CLASS%()
+
+ Obsolete %CLASS% decoder.
+ """
+ cdef %PREFIX%_ctx ctx
+ def __cinit__(me, *hunoz, **hukairz):
+ _%PREFIX%_init(&me.ctx)
+ me.ctx.indent = NULL
+ def decode(me, text):
+ """D.encode(IN) -> OUT: continue decoding"""
+ cdef void *p
+ cdef Py_ssize_t len
+ cdef dstr d
+ DCREATE(&d)
+ try:
+ PyObject_AsReadBuffer(text, <cvp *>&p, &len)
+ _%PREFIX%_decode(&me.ctx, p, len, &d)
+ rc = PyString_FromStringAndSize(d.buf, d.len)
+ finally:
+ dstr_destroy(&d)
+ return rc
+ def done(me):
+ """D.done() -> OUT: finish decoding, returning final output"""
+ cdef dstr d
+ DCREATE(&d)
+ try:
+ _%PREFIX%_decode(&me.ctx, NULL, 0, &d)
+ rc = PyString_FromStringAndSize(d.buf, d.len)
+ finally:
+ dstr_destroy(&d)
+ return rc
+
+def %PREFIX%_decode(text, *arg, **kw):
+ """%PREFIX%_decode(IN) -> OUT: %CLASS%-decode the string IN"""
+ d = %CLASS%Decode(*arg, **kw)
+ return d.decode(text) + d.done()
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Non-blocking connections
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice -----------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class SelConnect:
+ """
+ SelConnect(SK, [connectedproc = FUNC], [errorproc = FUNC])
+
+ When socket SK connects, call CONNECTEDPROC(); if connection fails, call
+ ERRORPROC(ERRNO, MESSAGE).
+
+ Attributes: C.socket, C.activep, C.connectedproc, C.errorproc.
+ """
+ cdef conn c
+ cdef int _activep
+ cdef readonly object socket
+ cdef _connected
+ cdef _error
+ def __cinit__(me, sk, connectedproc = None, errorproc = None,
+ *hunoz, **hukairz):
+ conn_fd(&me.c, &_sel, sk.fileno(), _connfunc, <void *>me)
+ me._activep = 1
+ me.socket = sk
+ me._connected = _checkcallable(connectedproc, 'connected proc')
+ me._error = _checkcallable(errorproc, 'error proc')
+ def __dealloc__(me):
+ if me._activep:
+ conn_kill(&me.c)
+ property activep:
+ """C.activep -> BOOL: is connection still in progress?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ property connectedproc:
+ """C.connectedproc -> FUNC: call FUNC() when connection completes"""
+ def __get__(me):
+ return me._connected
+ def __set__(me, proc):
+ me._connected = _checkcallable(proc, 'connected proc')
+ def __del__(me):
+ me._connected = None
+ property errorproc:
+ """
+ C.errorproc -> FUNC: call FUNC(ERRNO, MSG) if connection fails
+ """
+ def __get__(me):
+ return me._error
+ def __set__(me, proc):
+ me._error = _checkcallable(proc, 'error proc')
+ def __del__(me):
+ me._error = None
+ def kill(me):
+ """C.kill(): give up on connection"""
+ if not me._activep:
+ raise ValueError, 'already dead'
+ conn_kill(&me.c);
+ me._dead()
+ return me
+ cdef _dead(me):
+ me._activep = 0
+ me.dead()
+ def dead(me):
+ """C.dead(): called when connection completes or fails"""
+ pass
+ def connected(me):
+ """C.connected(): called when connection completes successfully"""
+ return _maybecall(me._connected, ())
+ def error(me, errno, strerror):
+ """C.error(ERRNO, MSG): called when connection fails"""
+ return _maybecall(me._error, ())
+
+cdef void _connfunc(int fd, void *arg):
+ cdef SelConnect c
+ c = <SelConnect>arg
+ c._dead()
+ if fd == -1:
+ c.socket = None
+ c.error(errno, strerror(errno))
+ else:
+ c.connected()
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Cyclic redundancy checker
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class CRC32:
+ """CRC32(): calculate CRC32 of a stream"""
+ cdef uint32 _a
+ def __cinit__(me, *hunoz, **hukairz):
+ me._a = 0
+ def __init__(me):
+ pass
+ def chunk(me, data):
+ """C.chunk(STR): process another chunk of input"""
+ cdef void *p
+ cdef Py_ssize_t n
+ PyObject_AsReadBuffer(data, <cvp *>&p, &n)
+ me._a = c_crc32(me._a, p, n)
+ return me
+ def done(me):
+ """C.done() -> INT: return CRC of data"""
+ return _u32(me._a)
+
+def crc32(data):
+ """crc32(STR) -> INT"""
+ cdef void *p
+ cdef Py_ssize_t n
+ cdef uint32 c
+ PyObject_AsReadBuffer(data, <cvp *>&p, &n)
+ c = c_crc32(0, p, n)
+ return _u32(c)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+files
+tmp
+substvars
+*.substvars
+*.debhelper
+*.log
+python-mlib
--- /dev/null
+mlib-python (1.1.1) experimental; urgency=medium
+
+ * Work around Pyrex bugs in exception handling (notably in _getfd).
+ * Fix variable-name typos in `fdflags', which has obviously been wrong
+ forever.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sun, 10 Sep 2017 11:31:09 +0100
+
+mlib-python (1.1.0) experimental; urgency=medium
+
+ * Lots of fixing for 64-bit targets.
+ * Add (rather terse) docstrings.
+ * Switch to `dh_python2' for packaging, to eliminate dependency on
+ `python-central'.
+ * Various bug fixes.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Wed, 16 Aug 2017 14:26:18 +0100
+
+mlib-python (1.0.5) experimental; urgency=low
+
+ * Fix Debian packaging.
+ * Support CDCF_IGNSPC flag in binary codecs.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Fri, 19 Feb 2016 08:52:39 +0000
+
+mlib-python (1.0.4) experimental; urgency=low
+
+ * Fix distribution arrangements. Apparently the release tarballs have
+ been hopelessly broken for ages and nobody noticed.
+ * Interface to newer binary encoding machinery.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Tue, 18 Jun 2013 09:53:24 +0100
+
+mlib-python (1.0.3) experimental; urgency=low
+
+ * Update for Python 2.7.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Wed, 09 Jan 2013 02:18:03 +0000
+
+mlib-python (1.0.2) experimental; urgency=low
+
+ * Fix some stupid bugs the compiler had been warning about for ages (but
+ got buried in the dross about Pyrex's code generator.
+ * Update __new__ methods to __cinit__ as prompted by Pyrex compiler.
+ * Overhaul Python build system.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sun, 04 Oct 2009 14:15:04 +0100
+
+mlib-python (1.0.1) experimental; urgency=low
+
+ * Switch to CDBS and support Python 2.6
+ * Support (glorious!) mdup function.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sun, 04 Oct 2009 00:32:29 +0100
+
+mlib-python (1.0.0) experimental; urgency=low
+
+ * Debianization!
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sun, 04 Oct 2009 00:31:21 +0100
--- /dev/null
+Source: mlib-python
+Section: python
+Priority: extra
+XS-Python-Version: >= 2.6, << 2.8
+Build-Depends: debhelper (>= 9), dh-python, pkg-config,
+ python (>= 2.6.6-3~), python-all-dev, python-pyrex,
+ mlib-dev (>= 2.2.2.1)
+Maintainer: Mark Wooding <mdw@distorted.org.uk>
+Standards-Version: 3.8.0
+
+Package: python-mlib
+Architecture: any
+XB-Python-Version: ${python:Versions}
+Depends: ${shlibs:Depends}, ${python:Depends}
+Provides: ${python:Provides}
+Description: A library of miscellaneous stuff
+ The mLib library provides various handy utilities, including
+ * yet another options parser, like GNU getopt but more so;
+ * a simple but efficient universal hashing family;
+ * a suite for writing event-driven select-based servers;
+ * a simple exception-handling system, based on longjmp;
+ * dynamically resizing strings and arrays;
+ * a resizing hashtable;
+ * base64 and hex encoding and decoding; and
+ * a simple background DNS resolver.
+ .
+ Not all of the features of mLib are available (or, indeed, very useful) in
+ Python. For example, Python has its own exception system, and different
+ ideas about how strings work.
--- /dev/null
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Copyright: 2005--2010, 2013, 2017 Straylight/Edgeware
+Upstream-Name: mLib-python
+Upstream-Contact: Mark Wooding <mdw@distorted.org.uk>
+Source: https://ftp.distorted.org.uk/pub/mdw/
+License: GPL-2.0+
+
+Files: *
+Copyright: 2005--2010, 2013, 2017 Straylight/Edgeware
+License: GPL-2.0+
+
+License: GPL-2.0+
+ mLib-python 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.
+ .
+ mLib-python 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 a copy of the GNU General Public License in
+ /usr/share/common-licenses/GPL; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+ .
+ On Debian systems, the full text of the GNU General Public License
+ version 2 can be found in the file `/usr/share/common-licenses/LGPL-2'.
--- /dev/null
+#! /usr/bin/make -f
+%:; dh $@ --parallel -Bdebian/build --with=python2
--- /dev/null
+### -*-pyrex-*-
+###
+### Basic definitions, used all over
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### C library.
+
+cdef extern from 'errno.h':
+ int errno
+ enum:
+ EINTR
+ EAGAIN
+cdef extern from 'limits.h':
+ enum:
+ LONG_MAX
+cdef extern from 'math.h':
+ double modf(double x, double *i)
+cdef extern from 'stddef.h':
+ ctypedef int size_t
+cdef extern from 'string.h':
+ void memcpy(void *p, void *q, size_t n)
+ char *strerror(int err)
+ size_t strlen(char *p)
+
+###--------------------------------------------------------------------------
+### Unix interface.
+
+cdef extern from 'sys/types.h':
+ pass
+cdef extern from 'sys/time.h':
+ struct timeval:
+ int tv_sec
+ int tv_usec
+
+cdef extern from 'sys/socket.h':
+ ctypedef int socklen_t
+ struct sockaddr:
+ int sa_family
+ enum:
+ AF_INET
+ int getsockname(int fd, sockaddr *pa, size_t *psz)
+ int getpeername(int fd, sockaddr *pa, size_t *psz)
+cdef extern from 'arpa/inet.h':
+ struct in_addr:
+ int s_addr
+ int inet_aton(char *rp, in_addr *ia)
+ char *inet_ntoa(in_addr ia)
+cdef extern from 'netinet/in.h':
+ struct sockaddr_in:
+ int sin_family
+ in_addr sin_addr
+ int sin_port
+ int htons(int x)
+ int htonl(int x)
+ int ntohs(int x)
+ int ntohl(int x)
+cdef extern from 'netdb.h':
+ struct hostent:
+ char *h_name
+ char **h_aliases
+ int h_addrtype
+ int h_length
+ char **h_addr_list
+ char *h_addr
+ int h_errno
+
+###--------------------------------------------------------------------------
+### Python.
+
+cdef extern from 'Python.h':
+
+ ctypedef struct PyObject:
+ pass
+ ctypedef struct PyTypeObject:
+ pass
+
+ object PyString_FromStringAndSize(char *p, Py_ssize_t len)
+ int PyString_AsStringAndSize(obj, char **p, Py_ssize_t *len) except -1
+ int PyObject_AsReadBuffer(obj, void **buf, Py_ssize_t *len) except -1
+ object PyInt_FromLong(long i)
+ object PyLong_FromUnsignedLong(unsigned long i)
+ char *PyString_AS_STRING(string)
+ int _PyString_Resize(PyObject **string, int size) except -1
+ void PyErr_Clear()
+
+ void Py_INCREF(PyObject *obj)
+ void Py_DECREF(PyObject *obj)
+
+###--------------------------------------------------------------------------
+### mLib basic stuff.
+
+cdef extern from 'mLib/alloc.h':
+ char *xstrdup(char *p)
+ void *xmalloc(size_t sz)
+ void xfree(void *p)
+
+cdef extern from 'mLib/bits.h':
+ ctypedef int uint32
+
+cdef extern from 'mLib/dstr.h':
+ ctypedef struct dstr:
+ char *buf
+ int len
+ void DCREATE(dstr *d)
+ void dstr_destroy(dstr *d)
+
+###--------------------------------------------------------------------------
+### CRC32.
+
+cdef extern from 'mLib/crc32.h':
+ uint32 c_crc32 "crc32" (uint32 a, void *p, int sz)
+
+###--------------------------------------------------------------------------
+### Universal hashing.
+
+cdef extern from 'mLib/unihash.h':
+ ctypedef struct unihash_info:
+ pass
+ void unihash_setkey(unihash_info *i, uint32 k)
+ uint32 UNIHASH_INIT(unihash_info *i)
+ uint32 unihash_hash(unihash_info *i, uint32 a, void *p, int sz)
+ unihash_info unihash_global
+
+###--------------------------------------------------------------------------
+### Symbol tables.
+
+cdef extern from 'mLib/sym.h':
+ ctypedef struct sym_table:
+ pass
+ ctypedef struct sym_base:
+ pass
+ ctypedef struct sym_iter:
+ pass
+ void sym_create(sym_table *t)
+ void sym_destroy(sym_table *t)
+ void *sym_find(sym_table *t, char *n, long l, int sz, unsigned *f)
+ void sym_remove(sym_table *t, void *b)
+ char *SYM_NAME(void *b)
+ int SYM_LEN(void *b)
+ void sym_mkiter(sym_iter *i, sym_table *t)
+ void *sym_next(sym_iter *i)
+
+###--------------------------------------------------------------------------
+### String utilities.
+
+cdef extern from 'mLib/str.h':
+ enum:
+ STRF_QUOTE
+ STRF_PREFIX
+ char *str_qword(char **pp, unsigned f)
+ size_t str_qsplit(char *p, char **v, size_t c, char **rest, unsigned f)
+ int str_matchx(char *p, char *s, unsigned f)
+ void str_sanitize(char *d, char *p, size_t sz)
+
+cdef extern from 'mLib/versioncmp.h':
+ int _versioncmp "versioncmp"(char *va, char *vb)
+
+###--------------------------------------------------------------------------
+### Form-urlencoding functions.
+
+cdef extern from 'mLib/url.h':
+ struct url_ectx:
+ unsigned f
+ struct url_dctx:
+ char *p
+ unsigned f
+ enum:
+ URLF_STRICT
+ URLF_LAX
+ URLF_SEMI
+ void url_initenc(url_ectx *ctx)
+ void url_enc(url_ectx *ctx, dstr *d, char *name, char *value)
+ void url_initdec(url_dctx *ctx, char *p)
+ int url_dec(url_dctx *ctx, dstr *n, dstr *v)
+
+###--------------------------------------------------------------------------
+### Atom stuff.
+
+## Atoms.
+##
+## Partly written in `real' C.
+cdef extern from 'atom.h':
+ ctypedef struct atom:
+ pass
+ ctypedef struct atom_iter:
+ pass
+ ctypedef struct atom_table:
+ pass
+ atom_table *ATOM_GLOBAL
+ void atom_mkiter(atom_iter *i, atom_table *t)
+ atom *atom_next(atom_iter *)
+ void atom_pysetup()
+ atom_pywrap(atom *a)
+ atom_pyintern(obj)
+ atom *ATOM_A(obj)
+ PyTypeObject atom_pytype
+
+## Association tables.
+cdef extern from 'mLib/assoc.h':
+ ctypedef struct assoc_table:
+ pass
+ ctypedef struct assoc_base:
+ pass
+ ctypedef struct assoc_iter:
+ pass
+ void assoc_create(assoc_table *t)
+ void assoc_destroy(assoc_table *t)
+ void *assoc_find(assoc_table *t, atom *a, int sz, unsigned *f)
+ void assoc_remove(assoc_table *t, void *b)
+ atom *ASSOC_ATOM(void *b)
+ void assoc_mkiter(assoc_iter *i, assoc_table *t)
+ void *assoc_next(assoc_iter *i)
+
+###--------------------------------------------------------------------------
+### Double-ended arrays.
+
+cdef extern from 'array.h':
+ void da_pysetup()
+ PyTypeObject da_pytype
+ PyTypeObject daiter_pytype
+
+###--------------------------------------------------------------------------
+### Line buffer.
+
+cdef extern from 'mLib/lbuf.h':
+ cdef struct lbuf:
+ int f
+ int delim
+ size_t sz
+ enum:
+ LBUF_ENABLE
+ _LBUF_CRLF "LBUF_CRLF"
+ _LBUF_STRICTCRLF "LBUF_STRICTCRLF"
+ void lbuf_flush(lbuf *b, char *p, size_t len)
+ void lbuf_close(lbuf *b)
+ size_t lbuf_free(lbuf *b, char **p)
+ void lbuf_setsize(lbuf *b, size_t sz)
+ void lbuf_enable(lbuf *b)
+ void lbuf_disable(lbuf *b)
+ void lbuf_init(lbuf *b,
+ void (*func)(char *s, size_t len, void *arg), void *arg)
+ void lbuf_destroy(lbuf *b)
+
+###--------------------------------------------------------------------------
+### Packet buffer.
+
+cdef extern from 'mLib/pkbuf.h':
+ ctypedef struct pkbuf:
+ int f
+ int want
+ enum:
+ PKBUF_ENABLE
+ void pkbuf_flush(pkbuf *pk, unsigned char *p, size_t len)
+ void pkbuf_close(pkbuf *pk)
+ size_t pkbuf_free(pkbuf *pk, unsigned char **p)
+ void pkbuf_want(pkbuf *pk, size_t sz)
+ void pkbuf_init(pkbuf *b,
+ void (*func)(unsigned char *s, size_t len,
+ pkbuf *pk, size_t *keep, void *arg),
+ void *arg)
+ void pkbuf_destroy(pkbuf *b)
+
+###--------------------------------------------------------------------------
+### Select stuff.
+
+## Basics.
+cdef extern from 'mLib/sel.h':
+ ctypedef struct sel_state:
+ pass
+ ctypedef struct sel_file:
+ int fd
+ ctypedef struct sel_timer:
+ pass
+ enum:
+ _SEL_READ "SEL_READ"
+ _SEL_WRITE "SEL_WRITE"
+ _SEL_EXC "SEL_EXC"
+ void sel_init(sel_state *s)
+ void sel_initfile(sel_state *s, sel_file *f, int fd, unsigned mode,
+ void (*func)(int fd, unsigned mode, void *arg),
+ void *arg)
+ void sel_force(sel_file *f)
+ void sel_addfile(sel_file *f)
+ void sel_rmfile(sel_file *f)
+ void sel_addtimer(sel_state *s, sel_timer *t, timeval *tv,
+ void (*func)(timeval *tv, void *arg),
+ void *arg)
+ void sel_rmtimer(sel_timer *t)
+ int sel_select(sel_state *s) except *
+
+### Non-blocking connection.
+cdef extern from 'mLib/conn.h':
+ ctypedef struct conn:
+ pass
+ int conn_fd(conn *c, sel_state *s, int fd,
+ void (*func)(int fd, void *arg), void *arg)
+ void conn_kill(conn *c)
+
+## Background name resolver.
+cdef extern from 'mLib/bres.h':
+ ctypedef struct bres_client:
+ pass
+ void bres_byname(bres_client *r, char *name,
+ void (*func)(hostent *h, void *arg), void *arg)
+ void bres_byaddr(bres_client *r, in_addr addr,
+ void (*func)(hostent *h, void *arg), void *arg)
+ void bres_abort(bres_client *r)
+ void bres_exec(char *null)
+ void bres_init(sel_state *s)
+
+## In-band signal handling.
+cdef extern from 'mLib/sig.h':
+ ctypedef struct sig:
+ pass
+ void sig_add(sig *s, int n, void (*func)(int n, void *arg), void *arg)
+ void sig_remove(sig *s)
+ void sig_init(sel_state *s)
+
+## Line buffer.
+cdef extern from 'mLib/selbuf.h':
+ ctypedef struct selbuf:
+ sel_file reader
+ lbuf b
+ void selbuf_enable(selbuf *b)
+ void selbuf_disable(selbuf *b)
+ void selbuf_setsize(selbuf *b, size_t sz)
+ void selbuf_init(selbuf *b, sel_state *s, int fd,
+ void (*func)(char *s, size_t len, void *arg), void *arg)
+ void selbuf_destroy(selbuf *b)
+
+## Packet buffer.
+cdef extern from 'mLib/selpk.h':
+ ctypedef struct selpk:
+ sel_file reader
+ pkbuf pk
+ void selpk_enable(selpk *b)
+ void selpk_disable(selpk *b)
+ void selpk_want(selpk *b, size_t sz)
+ void selpk_init(selpk *b, sel_state *s, int fd,
+ void (*func)(unsigned char *p, size_t n,
+ pkbuf *pk, size_t *keep, void *arg),
+ void *arg)
+ void selpk_destroy(selpk *b)
+
+## Ident client.
+cdef extern from 'mLib/ident.h':
+ ctypedef struct ident_request:
+ pass
+ enum:
+ IDENT_USERID
+ IDENT_ERROR
+ IDENT_BAD
+ struct ident_userid:
+ char *os
+ char *user
+ union ident_u:
+ ident_userid userid
+ char *error
+ ctypedef struct ident_reply:
+ int sport
+ int dport
+ int type
+ ident_u u
+ void ident(ident_request *rq, sel_state *s,
+ sockaddr_in *local, sockaddr_in *remote,
+ void (*func)(ident_reply *r, void *arg),
+ void *arg)
+ void ident_abort(ident_request *rq)
+
+###--------------------------------------------------------------------------
+### Error reporting.
+
+cdef extern from 'mLib/quis.h':
+ void _ego "ego"(char *prog)
+ char *_quis "quis"()
+
+cdef extern from 'mLib/report.h':
+ void _moan "moan"(char *f, char *msg)
+
+###--------------------------------------------------------------------------
+### File comparison.
+
+cdef extern from 'mLib/fwatch.h':
+ ctypedef struct fwatch:
+ pass
+ void fwatch_init(fwatch *f, char *name)
+ void fwatch_initfd(fwatch *f, int fd)
+ int fwatch_update(fwatch *f, char *name)
+ int fwatch_updatefd(fwatch *f, int fd)
+
+###--------------------------------------------------------------------------
+### File descriptor hacking.
+
+cdef extern from 'mLib/fdflags.h':
+ int _fdflags "fdflags"(int fd,
+ unsigned fbic, unsigned fxor,
+ unsigned fdbic, unsigned fdxor)
+
+cdef extern from 'mLib/fdpass.h':
+ int fdpass_send(int sock, int fd, void *p, size_t sz)
+ int fdpass_recv(int sock, int *fd, void *p, size_t sz)
+
+cdef extern from 'mLib/mdup.h':
+ ctypedef struct mdup_fd:
+ int cur
+ int want
+ int _mdup "mdup"(mdup_fd *v, size_t n)
+
+###--------------------------------------------------------------------------
+### Daemon utilities.
+
+cdef extern from 'mLib/daemonize.h':
+ int _daemonize "daemonize"()
+ void _detachtty "detachtty"()
+
+###--------------------------------------------------------------------------
+### Internal utilities.
+
+cdef extern from 'grim.h':
+ int PSIZEOF(void *x)
+ ctypedef void *cvp
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Messing with file descriptors
+###
+### (c) 2007 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+def fdflags(file,
+ unsigned fbic = 0, unsigned fxor = 0,
+ unsigned fdbic = 0, unsigned fdxor = 0):
+ """
+ fdflags(FILE, [fbic = 0], [fxor = 0], [fdbic = 0], [fdxor = 0])
+
+ Set fcntl(2) file and descriptor flags. If these are FL and FD, then
+ update:
+
+ * FL = (FL & ~FBIC) ^ FXOR
+ * FD = (FD & ~FDBIC) ^ FDXOR
+
+ FILE may be integer file descriptor or an object with `fileno' method.
+ """
+ cdef int rc
+ rc = _fdflags(_getfd(file), fbic, fxor, fdbic, fdxor)
+ if rc < 0:
+ _oserror()
+ return rc
+
+def fdsend(sock, file, buffer):
+ """
+ fdsend(SOCK, FILE, BUFFER) -> RC:
+ send FILE over Unix-domain socket SOCK, along with BUFFER
+ """
+ cdef void *p
+ cdef Py_ssize_t len
+ cdef int rc
+ PyObject_AsReadBuffer(buffer, <cvp *>&p, &len)
+ rc = fdpass_send(_getfd(sock), _getfd(file), p, len)
+ if rc < 0:
+ _oserror()
+ return rc
+
+def fdrecv(sock, unsigned size):
+ """
+ fdrecv(SOCK, SIZE) -> FD, BUFFER
+ receive file FD and BUFFER of length up to SIZE from Unix-domain SOCK
+ """
+ cdef void *p
+ cdef buf
+ cdef Py_ssize_t len
+ cdef PyObject *obj
+ cdef int fd
+ buf = PyString_FromStringAndSize(NULL, size)
+ p = PyString_AS_STRING(buf)
+ len = fdpass_recv(_getfd(sock), &fd, p, size)
+ if len < 0:
+ _oserror()
+ obj = <PyObject *>buf
+ _PyString_Resize(&obj, len)
+ return fd, <object>obj
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Watching files for changes
+###
+### (c) 2007 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class FWatch:
+ """
+ FWatch(FILE): watch FILE for changes
+
+ FILE may be a string, file descriptor, or an object with a `fileno' method.
+ """
+ cdef fwatch fw
+ cdef public file
+ def __cinit__(me, file):
+ me._init(file)
+ def __init__(me, file):
+ me._init(file)
+ cdef _init(me, file):
+ if isinstance(file, str):
+ fwatch_init(&me.fw, file)
+ else:
+ fwatch_initfd(&me.fw, _getfd(file))
+ me.file = file
+ def update(me):
+ """FW.update() -> RC: nonzero if the file has changed state"""
+ cdef int rc
+ if isinstance(me.file, str):
+ rc = fwatch_update(&me.fw, me.file)
+ else:
+ rc = fwatch_updatefd(&me.fw, _getfd(me.file))
+ return rc
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+/* -*-c-*-
+ *
+ * Grim hacks to support the Pyrex code
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Python interface to mLib.
+ *
+ * mLib/Python 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.
+ *
+ * mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GRIM_H
+#define GRIM_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <Python.h>
+
+/*----- Utilities ---------------------------------------------------------*/
+
+#define PSIZEOF(x) sizeof(*x)
+typedef const void *cvp;
+
+#define RETURN_OBJ(obj) do { Py_INCREF(obj); return (obj); } while (0)
+#define RETURN_ME RETURN_OBJ(me)
+#define RETURN_NONE RETURN_OBJ(Py_None)
+#define RETURN_NOTIMPL RETURN_OBJ(Py_NotImplemented)
+
+#define METH(func, doc) \
+ { #func, METHNAME(func), METH_VARARGS, doc },
+#define KWMETH(func, doc) \
+ { #func, (PyCFunction)METHNAME(func), \
+ METH_VARARGS | METH_KEYWORDS, doc },
+
+#define GET(func, doc) \
+ { #func, GETSETNAME(get, func), 0, doc },
+#define GETSET(func, doc) \
+ { #func, GETSETNAME(get, func), GETSETNAME(set, func), doc },
+
+#ifndef PySequence_Fast_ITEMS
+# define PySequence_Fast_ITEMS(o) \
+ (PyList_Check(o) ? &PyList_GET_ITEM(o, 0) : &PyTuple_GET_ITEM(o, 0))
+#endif
+
+#define FREEOBJ(obj) \
+ (((PyObject *)(obj))->ob_type->tp_free((PyObject *)(obj)))
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+### -*-pyrex-*-
+###
+### Ident client
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import socket
+
+cdef _inaddr_frompy(sockaddr_in *sin, addr):
+ cdef int port
+ if len(addr) != 2:
+ raise TypeError, 'want address/port pair'
+ a = addr[0]
+ if not inet_aton(a, &sin.sin_addr):
+ raise TypeError, 'bad IP address'
+ port = addr[1]
+ if not (0 <= port < 65536):
+ raise TypeError, 'port number out of range'
+ sin.sin_port = htons(port)
+
+cdef _inaddr_topy(sockaddr_in *sin):
+ return inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)
+
+cdef class SelIdentify:
+ """
+ SelIdentify(SK, [userproc = None], [bogusproc = None],
+ [badproc = None], [errorproc = None],)
+
+ Asynchronously enquire about remote user of socket SK.
+ """
+ cdef ident_request irq
+ cdef int _activep
+ cdef readonly localaddr
+ cdef readonly remoteaddr
+ cdef _user
+ cdef _bad
+ cdef _error
+ cdef _bogus
+ def __cinit__(me, sk, userproc = None, bogusproc = None,
+ badproc = None, errorproc = None, *hunoz, **hukairz):
+ cdef sockaddr_in s_in, s_out
+ cdef socklen_t sz_in, sz_out
+ cdef int fd
+ if typecheck(sk, socket.SocketType):
+ fd = sk.fileno()
+ sz_in = PSIZEOF(&s_in)
+ sz_out = PSIZEOF(&s_out)
+ if getsockname(fd, <sockaddr *>&s_in, &sz_in) or \
+ getpeername(fd, <sockaddr *>&s_out, &sz_out):
+ _oserror()
+ if s_in.sin_family != AF_INET or s_out.sin_family != AF_INET:
+ raise TypeError, 'must be internet socket'
+ elif len(sk) != 2:
+ raise TypeError, 'want pair of addresses'
+ else:
+ _inaddr_frompy(&s_in, sk[0])
+ _inaddr_frompy(&s_out, sk[1])
+ ident(&me.irq, &_sel, &s_in, &s_out, _identfunc, <void *>me)
+ me.localaddr = _inaddr_topy(&s_in)
+ me.remoteaddr = _inaddr_topy(&s_out)
+ me._activep = 1
+ me._user = _checkcallable(userproc, 'user proc')
+ me._bad = _checkcallable(badproc, 'bad proc')
+ me._error = _checkcallable(errorproc, 'error proc')
+ me._bogus = _checkcallable(bogusproc, 'bogus proc')
+ def __dealloc__(me):
+ if me._activep:
+ ident_abort(&me.irq)
+ property activep:
+ """I.activep -> BOOL: query still in progress?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ property userproc:
+ """I.userproc -> FUNC: call FUNC(OS, USER) if server replied"""
+ def __get__(me):
+ return me._user
+ def __set__(me, proc):
+ me._user = _checkcallable(proc, 'user proc')
+ def __del__(me):
+ me._user = None
+ property badproc:
+ """I.badproc -> FUNC: call FUNC() if server's reply was broken"""
+ def __get__(me):
+ return me._bad
+ def __set__(me, proc):
+ me._bad = _checkcallable(proc, 'bad proc')
+ def __del__(me):
+ me._bad = None
+ property errorproc:
+ """I.errorproc -> FUNC: call FUNC(ERR) if server reported error"""
+ def __get__(me):
+ return me._error
+ def __set__(me, proc):
+ me._error = _checkcallable(proc, 'error proc')
+ def __del__(me):
+ me._error = None
+ property bogusproc:
+ """I.bogusproc -> FUNC: call FUNC() on failure if no specific handler"""
+ def __get__(me):
+ return me._bogus
+ def __set__(me, proc):
+ me._bogus = _checkcallable(proc, 'bogus proc')
+ def __del__(me):
+ me._bogus = None
+ def kill(me):
+ """I.kill(): cancel ident query"""
+ if not me._activep:
+ raise ValueError, 'already disabled'
+ ident_abort(&me.irq)
+ me._dead()
+ def _dead(me):
+ me._activep = 0
+ me.dead()
+ def dead(me):
+ """I.dead(): called when operation completes or fails"""
+ pass
+ def user(me, os, user):
+ """I.user(OS, USER): called if server returns user name"""
+ return _maybecall(me._user, (os, user))
+ def bad(me):
+ """I.bad(): called if server's reply is invalid"""
+ if me._bad is not None:
+ return me._bad()
+ return me.bogus()
+ def error(me, error):
+ """I.error(ERR): called if server returns an error"""
+ if me._error is not None:
+ return me._error(error)
+ return me.bogus()
+ def bogus(me):
+ """I.bogus(): called on failure if there's no more specific handler"""
+ return _maybecall(me._bogus, ())
+
+cdef void _identfunc(ident_reply *i, void *arg):
+ cdef SelIdentify id
+ id = <SelIdentify>arg
+ id._dead()
+ if i.type == IDENT_BAD:
+ id.bad()
+ elif i.type == IDENT_ERROR:
+ id.error(i.u.error)
+ elif i.type == IDENT_USERID:
+ id.user(i.u.userid.os, i.u.userid.user)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Line buffering
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+LBUF_CRLF = _LBUF_CRLF
+LBUF_STRICTCRLF = _LBUF_STRICTCRLF
+
+cdef class LineBuffer:
+ """
+ LineBuffer([lineproc = None], [eofproc = None])
+
+ Split an incoming stream into lines.
+ """
+ cdef lbuf b
+ cdef _line
+ cdef _eof
+ def __cinit__(me, lineproc = None, eofproc = None, *hunoz, **hukairz):
+ lbuf_init(&me.b, _lbfunc, <void *>me)
+ me._line = _checkcallable(lineproc, 'line proc')
+ me._eof = _checkcallable(eofproc, 'eof proc')
+ def __dealloc__(me):
+ lbuf_destroy(&me.b)
+ property activep:
+ """LB.activep -> BOOL: is the buffer still active?"""
+ def __get__(me):
+ return _tobool(me.b.f & LBUF_ENABLE)
+ property delim:
+ """LB.delim -> CHAR | LBUF_...: line-end delimiter"""
+ def __get__(me):
+ if me.b.delim == _LBUF_CRLF or me.b.delim == _LBUF_STRICTCRLF:
+ return me.b.delim
+ else:
+ return chr(me.b.delim)
+ def __set__(me, d):
+ if d == _LBUF_CRLF or d == _LBUF_STRICTCRLF:
+ me.b.delim = d
+ else:
+ me.b.delim = ord(d)
+ property size:
+ """LB.size -> INT: buffer size limit"""
+ def __get__(me):
+ return me.b.sz
+ def __set__(me, sz):
+ if sz <= 0:
+ raise TypeError, 'size must be positive'
+ lbuf_setsize(&me.b, sz)
+ property lineproc:
+ """LB.lineproc -> FUNC: call FUNC(LINE) on each line"""
+ def __get__(me):
+ return me._line
+ def __set__(me, proc):
+ me._line = _checkcallable(proc, 'line proc')
+ def __del__(me):
+ me._line = None
+ property eofproc:
+ """LB.eofproc -> FUNC: call FUNC() at end-of-file"""
+ def __get__(me):
+ return me._eof
+ def __set__(me, proc):
+ me._eof = _checkcallable(proc, 'eof proc')
+ def __del__(me):
+ me._eof = None
+ def enable(me):
+ """LB.enable(): enable the buffer, allowing lines to be emitted"""
+ if me.b.f & LBUF_ENABLE:
+ raise ValueError, 'already enabled'
+ me.b.f = me.b.f | LBUF_ENABLE
+ me.enabled()
+ return me
+ def disable(me):
+ """LB.disable(): disable the buffer, suspending line emission"""
+ if not (me.b.f & LBUF_ENABLE):
+ raise ValueError, 'already disabled'
+ me.b.f = me.b.f & ~LBUF_ENABLE
+ me.disabled()
+ return me
+ def close(me):
+ """LB.close(): report the end of the input stream"""
+ if not (me.b.f & LBUF_ENABLE):
+ raise ValueError, 'buffer disabled'
+ lbuf_close(&me.b)
+ return me
+ property free:
+ """LB.free -> INT: amount of space remaining in buffer"""
+ def __get__(me):
+ cdef char *p
+ return lbuf_free(&me.b, &p)
+ def flush(me, str):
+ """LB.flush(STR) -> insert STR into the buffer and emit lines"""
+ cdef Py_ssize_t len
+ cdef char *p
+ cdef char *q
+ cdef size_t n
+ PyString_AsStringAndSize(str, &p, &len)
+ while len > 0:
+ n = lbuf_free(&me.b, &q)
+ if n > len:
+ n = len
+ memcpy(q, p, n)
+ p = p + n
+ len = len - n
+ if not (me.b.f & LBUF_ENABLE):
+ break
+ lbuf_flush(&me.b, q, n)
+ return PyString_FromStringAndSize(p, len)
+ def enabled(me):
+ """LB.enabled(): called when buffer is enabled"""
+ pass
+ def disabled(me):
+ """LB.disabled(): called when buffer is disabled"""
+ pass
+ def line(me, line):
+ """LB.line(LINE): called for each completed line"""
+ return _maybecall(me._line, (line,))
+ def eof(me):
+ """LB.eof(): called at end-of-file"""
+ return _maybecall(me._eof, ())
+
+cdef void _lbfunc(char *s, size_t n, void *arg):
+ cdef LineBuffer sb
+ sb = <LineBuffer>arg
+ if s is NULL:
+ sb.eof()
+ else:
+ sb.line(PyString_FromStringAndSize(s, n))
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Main driver for mLib module
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### External stuff.
+
+include 'defs.pxi'
+
+###--------------------------------------------------------------------------
+### Various facilities.
+
+## Internal utilities.
+include 'utils.pyx'
+
+## Hashing.
+include 'crc32.pyx'
+include 'unihash.pyx'
+
+## Data structures.
+include 'mapping.pyx'
+include 'sym.pyx'
+include 'atom.pyx'
+include 'assoc.pyx'
+
+## String utilities.
+include 'str.pyx'
+
+## Encodings.
+include 'codec.pyx'
+include 'base64.pyx'
+include 'base32.pyx'
+include 'hex.pyx'
+include 'url.pyx'
+
+## Error reporting.
+include 'report.pyx'
+
+## File utilities.
+include 'fwatch.pyx'
+include 'fdutils.pyx'
+include 'mdup.pyx'
+
+## Other useful stuff.
+include 'stuff.pyx'
+
+## Buffering.
+include 'lbuf.pyx'
+include 'pkbuf.pyx'
+
+## Select stuff.
+include 'sel-base.pyx'
+include 'sel-file.pyx'
+include 'sel-timer.pyx'
+include 'conn.pyx'
+include 'bres.pyx'
+include 'sig.pyx'
+include 'selbuf.pyx'
+include 'selpk.pyx'
+include 'ident.pyx'
+
+###--------------------------------------------------------------------------
+### Set-up stuff.
+
+cdef object _tyobj(PyTypeObject *ty):
+ cdef PyObject *obj
+ obj = <PyObject *>ty
+ Py_INCREF(obj)
+ return <object>obj
+
+da_pysetup()
+Array = _tyobj(&da_pytype)
+ArrayIter = _tyobj(&daiter_pytype)
+
+atom_pysetup()
+Atom = _tyobj(&atom_pytype)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Common mapping stuff
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class Mapping
+
+cdef class _MapIterator:
+ cdef void *_next(me):
+ return NULL
+
+cdef class Mapping:
+
+ ## Subclasses must implement these
+ cdef int _init(me) except -1:
+ raise TypeError, 'abstract class'
+ cdef void *_find(me, object key, unsigned *f) except NULL:
+ raise SystemError, 'unimplemented _find'
+ cdef object _key(me, void *e):
+ return None
+ cdef object _value(me, void *e):
+ return None
+ cdef void _setval(me, void *e, object val):
+ pass
+ cdef void _del(me, void *e):
+ pass
+ cdef _MapIterator _iter(me):
+ raise SystemError, 'unimplemented _iter'
+
+ ## Initialization
+ def __cinit__(me, *hunoz, **hukairz):
+ me._init()
+ def __init__(me, stuff = None, **kw):
+ me.update(stuff, kw)
+
+ ## Bulk update
+ def update(me, stuff = None, **kw):
+ """D.update([MAP], **KW): insert mappings from MAP and KW"""
+ cdef unsigned f
+ if stuff is None:
+ pass
+ elif hasattr(stuff, 'itemiter'):
+ for k, v in stuff.itemiter:
+ me._setval(me._find(k, &f), v)
+ elif hasattr(stuff, 'keys'):
+ for k in stuff.keys():
+ me._setval(me._find( k, &f), stuff[k])
+ else:
+ for k, v in stuff:
+ me._setval(me._find(k, &f), v)
+ for k, v in kw.iteritems():
+ me._setval(me._find(k, &f), v)
+ return me
+
+ ## Item access
+ def __getitem__(me, key):
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ raise KeyError, key
+ return me._value(e)
+ def __setitem__(me, key, value):
+ cdef unsigned f
+ me._setval(me._find(key, &f), value)
+ def __delitem__(me, key):
+ cdef void *e
+ cdef unsigned f
+ e = me._find(key, &f)
+ if not e:
+ raise KeyError, key
+ me._del(e)
+ def get(me, key, default = None):
+ """D.get(KEY, [default = None]) -> VALUE: value at KEY, or DEFAULT"""
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ return default
+ return me._value(e)
+ def setdefault(me, key, default = None):
+ """
+ D.setdefault(KEY, [default = None]) -> VALUE:
+ return value at key, or store DEFAULT at key and return that"""
+ cdef void *e
+ cdef unsigned f
+ e = me._find(key, &f)
+ if f:
+ return me._value(e)
+ else:
+ me._setval(e, default)
+ return default
+ def pop(me, key, default = None):
+ """
+ D.pop(KEY, [default = None]) -> VALUE:
+ return value at key or DEFAULT, and remove KEY"""
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ return default
+ rc = me._value(e)
+ me._del(e)
+ return rc
+ def popitem(me):
+ """D.popitem() -> KEY, VALUE: return and remove an association pair"""
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ e = i._next()
+ if not e:
+ raise ValueError, 'popitem(): table is empty'
+ return me._key(e), me._value(e)
+
+ ## Lists of items
+ cdef object _list(me, object (*func)(Mapping m, void *e)):
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ l = []
+ while 1:
+ e = i._next()
+ if not e:
+ break
+ l.append(func(me, e))
+ return l
+
+ def keys(me):
+ """D.keys() -> LIST: return a list of known keys"""
+ return me._list(_map_key)
+ def values(me):
+ """D.values() -> LIST: return a list of known values"""
+ return me._list(_map_value)
+ def items(me):
+ """D.values() -> LIST: return a list of known (KEY, VALUE) pairs"""
+ return me._list(_map_item)
+
+ def clear(me):
+ """D.clear(): remove all mappings"""
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ while 1:
+ e = i._next()
+ if not e:
+ break
+ me._del(e)
+ return me
+
+ ## Iteration
+ def __iter__(me):
+ return MapKeyIter(me)
+ def iterkeys(me):
+ """D.iterkeys() -> ITER: return iterator over keys"""
+ return MapKeyIter(me)
+ def itervalues(me):
+ """D.itervalues() -> ITER: return iterator over values"""
+ return MapValueIter(me)
+ def iteritems(me):
+ """D.iteritems() -> ITER: return iterator over (KEY, VALUE) pairs"""
+ return MapItemIter(me)
+
+cdef class MapIterBase:
+ cdef Mapping m
+ cdef object (*func)(Mapping m, void *e)
+ cdef _MapIterator i
+ cdef int _init(me) except -1:
+ raise TypeError, 'abstract class'
+ def __cinit__(me):
+ me.i = m._iter()
+ me._init()
+ def __iter__(me):
+ return me
+ def __next__(me):
+ cdef void *e
+ e = me.i._next()
+ if not e:
+ raise StopIteration
+ return me.func(me.m, e)
+cdef class MapKeyIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_key
+ return 0
+cdef class MapValueIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_value
+ return 0
+cdef class MapItemIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_item
+ return 0
+
+cdef object _map_key(Mapping m, void *e):
+ return m._key(e)
+cdef object _map_value(Mapping m, void *e):
+ return m._value(e)
+cdef object _map_item(Mapping m, void *e):
+ return m._key(e), m._value(e)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### File descriptor juggling
+###
+### (c) 2009 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+def mdup(v):
+ """
+ mdup(LIST) -> LIST:
+ LIST is a list (mutable sequence) of pairs (CUR, WANT). Duplicate each
+ CUR file descriptor as WANT (may be -1 to mean `don't care'), closing
+ original CUR. Works even if there are cycles. LIST is updated in place
+ with CUR reflecting the new file descriptors even on error. Returns the
+ same LIST on success.
+ """
+ cdef mdup_fd *vv
+ cdef size_t n
+ cdef int i
+ cdef int rc
+
+ n = len(v)
+ vv = <mdup_fd *>xmalloc(n * PSIZEOF(vv))
+ for 0 <= i < n:
+ vv[i].cur, vv[i].want = v[i]
+ rc = _mdup(vv, n)
+ for 0 <= i < n:
+ v[i] = vv[i].cur, vv[i].want
+ if rc < 0:
+ _oserror()
+ return v
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Packet buffering
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class PacketBuffer:
+ """
+ PacketBuffer([packetproc = None], [eofproc = None])
+
+ Split an incoming stream into packets.
+ """
+ cdef pkbuf pk
+ cdef _packet
+ cdef _eof
+ def __cinit__(me, packetproc = None, eofproc = None, *hunoz, **hukairz):
+ pkbuf_init(&me.pk, _pkfunc, <void *>me)
+ me._packet = _checkcallable(packetproc, 'packet proc')
+ me._eof = _checkcallable(eofproc, 'eof proc')
+ def __dealloc__(me):
+ pkbuf_destroy(&me.pk)
+ property activep:
+ """PK.activep -> BOOL: is the buffer still active?"""
+ def __get__(me):
+ return _tobool(me.pk.f & PKBUF_ENABLE)
+ property want:
+ """PK.want -> INT: size of next packet to return"""
+ def __get__(me):
+ return me.pk.want
+ def __set__(me, want):
+ if want <= 0:
+ raise TypeError, 'want must be positive'
+ pkbuf_want(&me.pk, pk)
+ property packetproc:
+ """PK.packetproc -> FUNC: call FUNC(PACKET) on each packet"""
+ def __get__(me):
+ return me._packet
+ def __set__(me, proc):
+ me._line = _checkcallable(proc, 'packet proc')
+ def __del__(me):
+ me._line = None
+ property eofproc:
+ """PK.eofproc -> FUNC: call FUNC() at end-of-file"""
+ def __get__(me):
+ return me._eof
+ def __set__(me, proc):
+ me._eof = _checkcallable(proc, 'eof proc')
+ def __del__(me):
+ me._eof = None
+ def enable(me):
+ """PK.enable(): enable the buffer, allowing packets to be emitted"""
+ if me.pk.f & PKBUF_ENABLE:
+ raise ValueError, 'already enabled'
+ me.pk.f = me.pk.f | PKBUF_ENABLE
+ me.enabled()
+ return me
+ def disable(me):
+ """PK.disable(): disable the buffer, suspending packet emission"""
+ if not (me.pk.f & PKBUF_ENABLE):
+ raise ValueError, 'already disabled'
+ me.pk.f = me.pk.f & ~PKBUF_ENABLE
+ me.disabled()
+ return me
+ def close(me):
+ """PK.close(): report the end of the input stream"""
+ if not (me.pk.f & PKBUF_ENABLE):
+ raise ValueError, 'buffer disabled'
+ pkbuf_close(&me.pk)
+ return me
+ property free:
+ """PK.free -> INT: amount of space remaining in buffer"""
+ def __get__(me):
+ cdef unsigned char *p
+ return pkbuf_free(&me.pk, &p)
+ def flush(me, str):
+ """PK.flush(STR) -> insert STR into the buffer and emit packets"""
+ cdef Py_ssize_t len
+ cdef unsigned char *p
+ cdef unsigned char *q
+ cdef size_t n
+ PyObject_AsReadBuffer(str, <cvp *>&p, &len)
+ while len > 0:
+ n = pkbuf_free(&me.pk, &q)
+ if n > len:
+ n = len
+ memcpy(q, p, n)
+ p = p + n
+ len = len - n
+ if not (me.pk.f & PKBUF_ENABLE):
+ break
+ pkbuf_flush(&me.pk, q, n)
+ return PyString_FromStringAndSize(<char *>p, len)
+ def enabled(me):
+ """PK.enabled(): called when buffer is enabled"""
+ pass
+ def disabled(me):
+ """PK.disabled(): called when buffer is disabled"""
+ pass
+ def packet(me, pk):
+ """PK.packet(PACKET): called for each completed packet"""
+ return _maybecall(me._packet, (pk,))
+ def eof(me):
+ """PK.eof(): called at end-of-file"""
+ return _maybecall(me._eof, ())
+
+cdef void _pkfunc(unsigned char *p, size_t n, pkbuf *pk,
+ size_t *keep, void *arg):
+ cdef PacketBuffer pb
+ cdef void *rp
+ cdef Py_ssize_t rn
+ pb = <PacketBuffer>arg
+ if p is NULL:
+ pb.eof()
+ else:
+ r = pb.packet(PyString_FromStringAndSize(<char *>p, n))
+ if r is not None:
+ PyObject_AsReadBuffer(r, <cvp *>&rp, &rn)
+ if rn > n:
+ raise ValueError, 'remaining buffer too large'
+ if rn:
+ memcpy(p + n - rn, rp, rn)
+ keep[0] = rn
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+;;; -*-emacs-lisp-*-
+
+(setq skel-alist
+ (append
+ '((author . "Straylight/Edgeware")
+ (licence-text . "[[gpl]]")
+ (full-title . "Pyke: the Python Kit for Extensions")
+ (program . "Pyke"))
+ skel-alist))
--- /dev/null
+### -*-pyrex-*-
+###
+### Error reporting and stuff
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+quis = '<UNNAMED>'
+cdef char *_progstring
+_progstring = NULL
+
+def ego(char *prog):
+ """ego(PROG): set program name"""
+ global quis, _progstring
+ if _progstring:
+ xfree(_progstring)
+ _progstring = xstrdup(prog)
+ _ego(_progstring)
+ quis = _quis()
+
+def moan(char *msg):
+ """moan(MSG): report a warning"""
+ _moan('%s', msg)
+def die(char *msg, rc = 126):
+ """die(MSG, [rc = 126]): report a fatal error and exit"""
+ _moan('%s', msg)
+ raise SystemExit, rc
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Select basic stuff
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef sel_state _sel
+
+def select():
+ """select(): wait for I/O and/or timeouts"""
+ if sel_select(&_sel) and errno != EINTR and errno != EAGAIN:
+ _oserror()
+
+sel_init(&_sel)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### File selectors
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+SEL_READ = _SEL_READ
+SEL_WRITE = _SEL_WRITE
+SEL_EXCEPT = _SEL_EXC
+
+cdef class SelFile:
+ """
+ SelFile(FILE, [mode = SEL_READ], [readyproc = None])
+
+ Register a file (or socket, or, ...) with the select loop.
+ """
+ cdef sel_file f
+ cdef int _activep
+ cdef readonly unsigned mode
+ cdef _readyfunc
+ def __cinit__(me, fd, int mode = SEL_READ, readyproc = None,
+ *hunoz, **hukairz):
+ if (mode != _SEL_READ and
+ mode != _SEL_WRITE and
+ mode != _SEL_EXC):
+ raise ValueError, 'bad select mode'
+ sel_initfile(&_sel, &me.f, _getfd(fd), mode, _filefunc, <void *>me)
+ me._activep = 0
+ me.mode = mode
+ me._readyfunc = _checkcallable(readyproc, 'ready proc')
+ def __dealloc__(me):
+ if me._activep:
+ sel_rmfile(&me.f)
+ property fd:
+ """SF.fd -> INT: the file descriptor"""
+ def __get__(me):
+ return me.f.fd
+ property activep:
+ """SF.activep -> BOOL: is the descriptor active?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ property readyproc:
+ """SF.readyproc -> FUNC: call FUNC() when file is ready for I/O"""
+ def __get__(me):
+ return me._readyfunc
+ def __set__(me, proc):
+ me._readyfunc = _checkcallable(proc, 'ready proc')
+ def __del__(me):
+ me._readyfunc = None
+ def enable(me):
+ """SF.enable(): enable waiting on file"""
+ if me._activep:
+ raise ValueError, 'already enabled'
+ sel_addfile(&me.f)
+ me._enabled()
+ return me
+ def disable(me):
+ """SF.disable(): disable waiting on file"""
+ if not me._activep:
+ raise ValueError, 'already disabled'
+ sel_rmfile(&me.f)
+ me._disabled()
+ return me
+ def force(me):
+ """SF.force(): artificially mark file as ready"""
+ sel_force(&me.f)
+ return me
+ cdef _enabled(me):
+ me._activep = 1
+ me.enabled()
+ cdef _disabled(me):
+ me._activep = 0
+ me.disabled()
+ def enabled(me):
+ """SF.enabled(): called when file is enabled"""
+ pass
+ def disabled(me):
+ """SF.disabled(): called when file is disabled"""
+ pass
+ def ready(me):
+ """SF.ready(): called when file is ready for I/O"""
+ return _maybecall(me._readyfunc, ())
+
+cdef void _filefunc(int fd, unsigned mode, void *arg):
+ cdef SelFile sf
+ sf = <SelFile>arg
+ sf.ready()
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Timer selectors
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef double _tvtofloat(timeval *tv):
+ return tv.tv_sec + (tv.tv_usec / 1000000)
+cdef void _floattotv(timeval *tv, double t):
+ cdef double s, us
+ us = modf(t, &s)
+ tv.tv_sec = <int>s
+ tv.tv_usec = <int>(us * 1000000)
+
+cdef class SelTimer:
+ """
+ SelTimer(WHEN, [timerproc = None])
+
+ Arrange to perform some action at time WHEN.
+ """
+ cdef sel_timer t
+ cdef int _activep
+ cdef readonly double time
+ cdef _timer
+ def __cinit__(me, double when, timerproc = None, *hunoz, **hukairz):
+ cdef timeval tv
+ _floattotv(&tv, when)
+ sel_addtimer(&_sel, &me.t, &tv, _timerfunc, <void *>me)
+ me._activep = 1
+ me.time = when
+ me._timer = _checkcallable(timerproc, 'timer proc')
+ def __dealloc__(me):
+ if me._activep:
+ sel_rmtimer(&me.t)
+ property activep:
+ """ST.activep -> BOOL: is the timer active?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ property timerproc:
+ """ST.timerproc -> FUNC: call FUNC() when the timer pops"""
+ def __get__(me):
+ return me._timer
+ def __set__(me, proc):
+ me._timer = _checkcallable(proc, 'timer proc')
+ def __del__(me):
+ me._timer = None
+ def kill(me):
+ """ST.kill(): deactivate timer permanently"""
+ if not me._activep:
+ raise ValueError, 'already dead'
+ sel_rmtimer(&me.t)
+ me._dead()
+ return me
+ cdef _dead(me):
+ me._activep = 0
+ me.dead()
+ def dead(me):
+ """ST.dead(): called when timer is deactivated"""
+ pass
+ def timer(me, now):
+ """ST.timer(NOW): called when the timer pops"""
+ return _maybecall(me._timer, ())
+
+cdef void _timerfunc(timeval *now, void *arg):
+ cdef SelTimer st
+ st = <SelTimer>arg
+ st._dead()
+ st.timer(_tvtofloat(now))
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Selecting line-buffers
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class SelLineBuffer:
+ """
+ SelLineBuffer(FILE, [lineproc = None], [eofproc = None])
+
+ Split an asynchronous stream into lines.
+ """
+ cdef selbuf b
+ cdef _line
+ cdef _eof
+ def __cinit__(me, fd, lineproc = None, eofproc = None, *hunoz, **hukairz):
+ selbuf_init(&me.b, &_sel, _getfd(fd), _selbfunc, <void *>me)
+ selbuf_disable(&me.b)
+ me._line = _checkcallable(lineproc, 'line proc')
+ me._eof = _checkcallable(eofproc, 'eof proc')
+ def __dealloc__(me):
+ selbuf_destroy(&me.b)
+ property activep:
+ """SLB.activep -> BOOL: is the buffer still active?"""
+ def __get__(me):
+ return _tobool(me.b.b.f & LBUF_ENABLE)
+ property fd:
+ """SLB.fd -> INT: the file descriptor"""
+ def __get__(me):
+ return me.b.reader.fd
+ property delim:
+ """SLB.delim -> CHAR | LBUF_...: line-end delimiter"""
+ def __get__(me):
+ if me.b.b.delim == _LBUF_CRLF or me.b.b.delim == _LBUF_STRICTCRLF:
+ return me.b.b.delim
+ else:
+ return chr(me.b.b.delim)
+ def __set__(me, d):
+ if d == _LBUF_CRLF or d == _LBUF_STRICTCRLF:
+ me.b.b.delim = d
+ else:
+ me.b.b.delim = ord(d)
+ property size:
+ """SLB.size -> INT: buffer size limit"""
+ def __get__(me):
+ return me.b.b.sz
+ def __set__(me, sz):
+ if sz <= 0:
+ raise TypeError, 'size must be positive'
+ selbuf_setsize(&me.b, sz)
+ property lineproc:
+ """SLB.lineproc -> FUNC: call FUNC(LINE) on each line"""
+ def __get__(me):
+ return me._line
+ def __set__(me, proc):
+ me._line = _checkcallable(proc, 'line proc')
+ def __del__(me):
+ me._line = None
+ property eofproc:
+ """SLB.eofproc -> FUNC: call FUNC() at end-of-file"""
+ def __get__(me):
+ return me._eof
+ def __set__(me, proc):
+ me._eof = _checkcallable(proc, 'eof proc')
+ def __del__(me):
+ me._eof = None
+ def enable(me):
+ """SLB.enable(): enable the buffer, allowing lines to be emitted"""
+ if me.b.b.f & LBUF_ENABLE:
+ raise ValueError, 'already enabled'
+ selbuf_enable(&me.b)
+ me.enabled()
+ return me
+ def disable(me):
+ """SLB.disable(): disable the buffer, suspending line emission"""
+ if not (me.b.b.f & LBUF_ENABLE):
+ raise ValueError, 'already disabled'
+ selbuf_disable(&me.b)
+ me.disabled()
+ return me
+ def enabled(me):
+ """SLB.enabled(): called when buffer is enabled"""
+ pass
+ def disabled(me):
+ """SLB.disabled(): called when buffer is disabled"""
+ pass
+ def line(me, line):
+ """SLB.line(LINE): called for each completed line"""
+ return _maybecall(me._line, (line,))
+ def eof(me):
+ """SLB.eof(): called at end-of-file"""
+ return _maybecall(me._eof, ())
+
+cdef void _selbfunc(char *s, size_t n, void *arg):
+ cdef SelLineBuffer sb
+ sb = <SelLineBuffer>arg
+ if s is NULL:
+ sb.eof()
+ else:
+ sb.line(PyString_FromStringAndSize(s, n))
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Selecting packet-buffer
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class SelPacketBuffer:
+ """
+ SelPacketBuffer(FILE, [packetproc = None], [eofproc = None])
+
+ Split an incoming stream into packets.
+ """
+ cdef selpk p
+ cdef _packet
+ cdef _eof
+ def __cinit__(me, fd, packetproc = None, eofproc = None, *hunoz, **hukairz):
+ selpk_init(&me.p, &_sel, _getfd(fd), _selpkfunc, <void *>me)
+ selpk_disable(&me.p)
+ me._packet = _checkcallable(packetproc, 'packet proc')
+ me._eof = _checkcallable(eofproc, 'eof proc')
+ def __dealloc__(me):
+ selpk_destroy(&me.p)
+ property activep:
+ """SPK.activep -> BOOL: is the buffer still active?"""
+ def __get__(me):
+ return _to_bool(me.p.pk.f & PKBUF_ENABLE)
+ property fd:
+ """SPK.fd -> INT: the file descriptor"""
+ def __get__(me):
+ return me.p.reader.fd
+ property want:
+ """SPK.want -> INT: size of next packet to return"""
+ def __get__(me):
+ return me.p.pk.want
+ def __set__(me, n):
+ if n <= 0:
+ raise TypeError, 'size must be positive'
+ selpk_want(&me.p, n)
+ property packetproc:
+ """SPK.packetproc -> FUNC: call FUNC(PACKET) on each packet"""
+ def __get__(me):
+ return me._packet
+ def __set__(me, proc):
+ me._packet = _checkcallable(proc, 'packet proc')
+ def __del__(me):
+ me._packet = None
+ property eofproc:
+ """SPK.eofproc -> FUNC: call FUNC() at end-of-file"""
+ def __get__(me):
+ return me._eof
+ def __set__(me, proc):
+ me._eof = _checkcallable(proc, 'eof proc')
+ def __del__(me):
+ me._eof = None
+ def enable(me):
+ """SPK.enable(): enable the buffer, allowing packets to be emitted"""
+ if me.p.pk.f & PKBUF_ENABLE:
+ raise ValueError, 'already enabled'
+ selpk_enable(&me.p)
+ me.enabled()
+ return me
+ def disable(me):
+ """SPK.disable(): disable the buffer, suspending packet emission"""
+ if not (me.p.pk.f & PKBUF_ENABLE):
+ raise ValueError, 'already disabled'
+ selpk_disable(&me.p)
+ me.disabled()
+ return me
+ def enabled(me):
+ """SPK.enabled(): called when buffer is enabled"""
+ pass
+ def disabled(me):
+ """SPK.disabled(): called when buffer is disabled"""
+ pass
+ def packet(me, pk):
+ """SPK.packet(PACKET): called for each completed packet"""
+ return _maybecall(me._packet, (pk,))
+ def eof(me):
+ """SPK.eof(): called at end-of-file"""
+ return _maybecall(me._eof, ())
+
+cdef void _selpkfunc(unsigned char *p, size_t n, pkbuf *pk,
+ size_t *keep, void *arg):
+ cdef SelPacketBuffer pb
+ cdef void *rp
+ cdef Py_ssize_t rn
+ pb = <SelPacketBuffer>arg
+ if p is NULL:
+ pb.eof()
+ else:
+ r = pb.packet(PyString_FromStringAndSize(<char *>p, n))
+ if r is not None:
+ PyObject_AsReadBuffer(r, <cvp *>&rp, &rn)
+ if rn > n:
+ raise ValueError, 'remaining buffer too large'
+ if rn:
+ memcpy(p + n - rn, rp, rn)
+ keep[0] = rn
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+#! /usr/bin/python
+
+import distutils.core as DC
+import Pyrex.Distutils as PXD
+import mdwsetup as MS
+
+MS.pkg_config('mLib', '2.1.0')
+
+mLib = DC.Extension('mLib', ['mLib.pyx', 'atom-base.c', 'array.c'],
+ ##extra_compile_args = ['-O0'],
+ include_dirs = MS.uniquify(MS.INCLUDEDIRS),
+ library_dirs = MS.uniquify(MS.LIBDIRS),
+ libraries = MS.uniquify(MS.LIBS))
+
+MS.setup(name = 'mLib-python',
+ description = 'Python interface to mLib utilities library',
+ author = 'Straylight/Edgeware',
+ author_email = 'mdw@distorted.org.uk',
+ license = 'GNU General Public License',
+ ext_modules = [mLib],
+ genfiles = [MS.Derive('base64.pyx', 'codec.pyx.in',
+ {'CLASS': 'Base64', 'PREFIX': 'base64'}),
+ MS.Derive('base32.pyx', 'codec.pyx.in',
+ {'CLASS': 'Base32', 'PREFIX': 'base32'}),
+ MS.Derive('hex.pyx', 'codec.pyx.in',
+ {'CLASS': 'Hex', 'PREFIX': 'hex'})],
+ cleanfiles = ['mLib.c'],
+ cmdclass = { 'build_ext': PXD.build_ext })
--- /dev/null
+### -*-pyrex-*-
+###
+### In-band signals
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import signal
+
+cdef class SelSignal:
+ """
+ SelSignal(SIG, [signalledproc = None])
+
+ Collect signals from the event loop.
+ """
+ cdef sig s
+ cdef int _activep
+ cdef readonly int signal
+ cdef _signalled
+ def __cinit__(me, int sig, signalledproc = None, *hunoz, **hukairz):
+ if sig < 0 or sig >= signal.NSIG:
+ raise ValueError, 'signal number out of range'
+ me.signal = sig
+ me._signalled = _checkcallable(signalledproc, 'signalled proc')
+ me._activep = 0
+ def __dealloc__(me):
+ if me._activep:
+ sig_remove(&me.s)
+ property activep:
+ """SS.activep -> BOOL: is the handler still active?"""
+ def __get__(me):
+ return _tobool(me._activep)
+ property signalledproc:
+ """SS.signalledproc -> FUNC: call FUNC() when the signal is received"""
+ def __get__(me):
+ return me._signalled
+ def __set__(me, proc):
+ me._signalled = _checkcallable(proc, 'signalled proc')
+ def __del__(me):
+ me._signalled = None
+ def enable(me):
+ """SS.enable(): enable the handler"""
+ if me._activep:
+ raise ValueError, 'already enabled'
+ sig_add(&me.s, me.signal, _sigfunc, <void *>me)
+ me._enabled()
+ return me
+ def disable(me):
+ """SS.disable(): disable the handler"""
+ if not me._activep:
+ raise ValueError, 'already disabled'
+ sig_remove(&me.s)
+ me._disabled()
+ return me
+ cdef _enabled(me):
+ me._activep = 1
+ me.enabled()
+ cdef _disabled(me):
+ me._activep = 0
+ me.disabled()
+ def enabled(me):
+ """SS.enabled(): called when handler is enabled"""
+ pass
+ def disabled(me):
+ """SS.disabled(): called when handler is disabled"""
+ pass
+ def signalled(me):
+ """SS.signalled(): called when the signal is received"""
+ return _maybecall(me._signalled, ())
+
+cdef void _sigfunc(int sig, void *arg):
+ cdef SelSignal s
+ s = <SelSignal>arg
+ s.signalled()
+
+sig_init(&_sel)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### String utilities
+###
+### (c) 2006 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+def word(char *p, quotep = False):
+ """word(STR, [quotep = False]) -> WORD, REST"""
+ cdef unsigned f
+ cdef char *op
+ cdef char *pp
+ cdef char *q
+ cdef object w
+ cdef object r
+
+ f = 0
+ if quotep:
+ f = f | STRF_QUOTE
+ pp = op = xstrdup(p)
+ q = str_qword(&pp, f)
+ if q is NULL:
+ w = None
+ else:
+ w = q
+ if pp is NULL:
+ r = ''
+ else:
+ r = pp
+ xfree(op)
+ return w, r
+
+def split(char *p, int n = -1, quotep = False):
+ """split(STR, [n = -1], [quotep = False]) -> WORDS, REST"""
+ cdef unsigned f
+ cdef char *op
+ cdef char *pp
+ cdef char *q
+ cdef object l
+ cdef object r
+
+ f = 0
+ if quotep:
+ f = f | STRF_QUOTE
+ l = []
+ op = pp = xstrdup(p)
+ while n != 0:
+ q = str_qword(&pp, f)
+ if q is NULL:
+ break
+ l.append(q)
+ if n > 0:
+ n = n - 1
+ if pp is NULL:
+ r = ''
+ else:
+ r = pp
+ xfree(op)
+ return l, r
+
+def match(char *p, char *s, prefixp = False):
+ """match(PAT, STR, [prefixp = False]) -> BOOL"""
+ cdef unsigned f
+
+ f = 0
+ if prefixp:
+ f = f | STRF_PREFIX
+ return _tobool(str_matchx(p, s, f))
+
+def sanitize(char *p, int n = -1):
+ """sanitize(STR, [n = -1]) -> STR"""
+ cdef char *buf
+ cdef object d
+
+ if n < 0:
+ n = strlen(p)
+ buf = <char *>xmalloc(n + 1)
+ str_sanitize(buf, p, n + 1)
+ d = buf
+ xfree(buf)
+ return d
+
+def versioncmp(char *va, char *vb):
+ """versioncmp(V0, V1) -> -1 | 0 | +1"""
+ return _versioncmp(va, vb)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Various small things
+###
+### (c) 2007 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+def detachtty():
+ """detachtty(): detach from terminal and fork"""
+ _detachtty()
+
+def daemonize():
+ """daemonize(): become a daemon"""
+ if _daemonize():
+ _oserror()
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Symbol table, using universal hashing
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef struct _sym_entry:
+ sym_base _b
+ PyObject *v
+
+cdef class SymTable (Mapping):
+ """
+ SymTable([DICT], **KW)
+
+ A mapping keyed by strings.
+ """
+ cdef sym_table _t
+ cdef int _init(me) except -1:
+ sym_create(&me._t)
+ return 0
+ cdef void *_find(me, object key, unsigned *f) except NULL:
+ cdef void *p
+ cdef Py_ssize_t n
+ cdef _sym_entry *e
+ PyObject_AsReadBuffer(key, <cvp *>&p, &n)
+ if f:
+ f[0] = 0
+ e = <_sym_entry *>sym_find(&me._t, <char *>p, n, PSIZEOF(e), f)
+ if not f[0]:
+ e.v = NULL
+ else:
+ e = <_sym_entry *>sym_find(&me._t, <char *>p, n, 0, NULL)
+ return <void *>e
+ cdef object _key(me, void *e):
+ return PyString_FromStringAndSize(SYM_NAME(e), SYM_LEN(e))
+ cdef object _value(me, void *e):
+ cdef _sym_entry *ee
+ ee = <_sym_entry *>e
+ Py_INCREF(ee.v)
+ return <object>ee.v
+ cdef void _setval(me, void *e, object val):
+ cdef _sym_entry *ee
+ ee = <_sym_entry *>e
+ if ee.v:
+ Py_DECREF(ee.v)
+ ee.v = <PyObject *>v
+ Py_INCREF(ee.v)
+ cdef void _del(me, void *e):
+ cdef _sym_entry *ee
+ ee = <_sym_entry *>e
+ if ee.v:
+ Py_DECREF(ee.v)
+ sym_remove(&me._t, <void *>ee)
+ cdef _MapIterator _iter(me):
+ return _SymIter(me)
+
+cdef class _SymIter (_MapIterator):
+ cdef SymTable t
+ cdef sym_iter i
+ def __cinit__(me, SymTable t not None):
+ me.t = t
+ sym_mkiter(&me.i, &me.t._t)
+ cdef void *_next(me):
+ return sym_next(&me.i)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Universal hashing interface
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+def setglobalkey(uint32 k):
+ """setglobalkey(K): set global hash key"""
+ unihash_setkey(&unihash_global, k)
+
+cdef class Key:
+ """Key(K): universal hashing key"""
+ cdef unihash_info _i
+ cdef uint32 _k
+ def __cinit__(me, uint32 k):
+ unihash_setkey(&me._i, k)
+ me._k = k
+ property k:
+ """K.k -> INT: the key value"""
+ def __get__(me):
+ return _u32(me._k)
+
+cdef class Unihash:
+ """Unihash([key = None]): universal hashing context"""
+ cdef uint32 _a
+ cdef readonly Key key
+ cdef unihash_info *_i
+ def __cinit__(me, key = None):
+ cdef Key k
+ me.key = key
+ if key is None:
+ me._i = &unihash_global
+ else:
+ k = key
+ me._i = &k._i
+ me._a = UNIHASH_INIT(me._i)
+ def chunk(me, data):
+ """U.chunk(STR): hash the STR"""
+ cdef void *p
+ cdef Py_ssize_t n
+ PyObject_AsReadBuffer(data, <cvp *>&p, &n)
+ me._a = unihash_hash(me._i, me._a, p, n)
+ def done(me):
+ """U.done() -> INT: the hash of the data"""
+ return _u32(me._a)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Form-urlencoding functions
+###
+### (c) 2006 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class URLEncode:
+ """URLEncode([strictp = False], [laxp = False], [semip = False])"""
+ cdef url_ectx ctx
+ cdef dstr d
+
+ def __cinit__(me, *hunoz, **hukairz):
+ url_initenc(&me.ctx)
+ DCREATE(&me.d)
+ def __init__(me, strictp = False, laxp = False, semip = False):
+ cdef unsigned f
+ f = 0
+ if strictp:
+ f = f | URLF_STRICT
+ if laxp:
+ f = f | URLF_LAX
+ if semip:
+ f = f | URLF_SEMI
+ me.ctx.f = f
+ def encode(me, char *name, char *value):
+ """UE.encode(NAME, VALUE): encode a key/value pair"""
+ url_enc(&me.ctx, &me.d, name, value)
+ return me
+ property result:
+ """UE.result -> STR: the encoded string"""
+ def __get__(me):
+ return PyString_FromStringAndSize(me.d.buf, me.d.len)
+ property strictp:
+ """UE.strictp -> BOOL: strictly escape non-alphanumerics?"""
+ def __get__(me):
+ return _tobool(me.ctx.f & URLF_STRICT)
+ def __set__(me, val):
+ if val:
+ me.ctx.f = me.ctx.f | URLF_STRICT
+ else:
+ me.ctx.f = me.ctx.f & ~URLF_STRICT
+ property laxp:
+ """UE.laxp -> BOOL: only escape obviously unsafe characters?"""
+ def __get__(me):
+ return _tobool(me.ctx.f & URLF_LAX)
+ def __set__(me, val):
+ if val:
+ me.ctx.f = me.ctx.f | URLF_LAX
+ else:
+ me.ctx.f = me.ctx.f & ~URLF_LAX
+ property semip:
+ """UE.semip -> BOOL: separate key/value pairs with semicolons?"""
+ def __get__(me):
+ return _tobool(me.ctx.f & URLF_SEMI)
+ def __set__(me, val):
+ if val:
+ me.ctx.f = me.ctx.f | URLF_SEMI
+ else:
+ me.ctx.f = me.ctx.f & ~URLF_SEMI
+ def __del__(me):
+ dstr_destroy(&me.d)
+
+cdef class URLDecode:
+ """URLDecode(STR, [semip = False]): iterator over (KEY, VALUE) pairs"""
+ cdef url_dctx ctx
+ cdef char *p
+
+ def __cinit__(me, *hunoz, **hukairz):
+ me.p = xstrdup('')
+ url_initdec(&me.ctx, me.p)
+ def __init__(me, char *string, semip = False):
+ cdef unsigned f
+ f = 0
+ if semip:
+ f = f | URLF_SEMI
+ xfree(me.p)
+ me.p = xstrdup(string)
+ me.ctx.p = me.p
+ me.ctx.f = f
+ def __iter__(me):
+ return me
+ def __next__(me):
+ cdef dstr n
+ cdef dstr v
+ cdef object nn
+ cdef object vv
+ cdef int anyp
+ DCREATE(&n)
+ DCREATE(&v)
+ anyp = url_dec(&me.ctx, &n, &v)
+ if anyp:
+ nn = PyString_FromStringAndSize(n.buf, n.len)
+ vv = PyString_FromStringAndSize(v.buf, v.len)
+ dstr_destroy(&n)
+ dstr_destroy(&v)
+ if not anyp:
+ raise StopIteration
+ return nn, vv
+ property semip:
+ """UD.semip -> BOOL: key/value pairs separated with semicolons?"""
+ def __get__(me):
+ return _tobool(me.ctx.f & URLF_SEMI)
+ def __set__(me, val):
+ if val:
+ me.ctx.f = me.ctx.f | URLF_SEMI
+ else:
+ me.ctx.f = me.ctx.f & ~URLF_SEMI
+ def __del__(me):
+ xfree(me.p)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-pyrex-*-
+###
+### Miscellaneous support gubbins
+###
+### (c) 2005 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to mLib.
+###
+### mLib/Python 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.
+###
+### mLib/Python 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 mLib/Python; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef object _u32(uint32 x):
+ if x <= LONG_MAX:
+ return PyInt_FromLong(x)
+ else:
+ return PyLong_FromUnsignedLong(x)
+
+cdef object _oserror():
+ raise OSError, (errno, strerror(errno))
+
+cdef object _tobool(int i):
+ if i:
+ return True
+ else:
+ return False
+
+cdef int _getfd(object fdobj):
+ try:
+ fd = int(fdobj)
+ except TypeError:
+ PyErr_Clear()
+ fd = fdobj.fileno()
+ return fd
+
+cdef object _checkcallable(f, what):
+ if f is not None and not callable(f):
+ raise TypeError, '%s must be callable' % what
+ return f
+
+cdef object _maybecall(f, args):
+ if f is None:
+ return None
+ return f(*args)
+
+###----- That's all, folks --------------------------------------------------