return nl;
}
+int irc_line_cmp(const struct irc_line *a, const struct irc_line *b)
+{
+ int i;
+ int ret;
+
+ if (a->origin != NULL && b->origin == NULL)
+ return 1;
+
+ if (a->origin == NULL && b->origin != NULL)
+ return -1;
+
+ if (a->origin == NULL && b->origin == NULL)
+ ret = 0;
+ else
+ ret = strcmp(a->origin, b->origin);
+ if (ret != 0)
+ return ret;
+
+ for (i = 0; i < MIN(a->argc, b->argc); i++) {
+ ret = strcmp(a->args[i], b->args[i]);
+ if (ret != 0)
+ return ret;
+ }
+
+ return a->argc - b->argc;
+}
G_MODULE_EXPORT struct irc_line *line_prefix_time(const struct irc_line *l, time_t t);
#define irc_line_respcode(l) (((l)->argc == 0)?0:atoi((l)->args[0]))
+G_MODULE_EXPORT int irc_line_cmp(const struct irc_line *a, const struct irc_line *b);
+
#endif /* __CTRLPROXY_LINE_H__ */
G_MODULE_EXPORT struct linestack_context *create_linestack(const char *name, gboolean truncate, const char *basedir, const struct irc_network_state *);
G_MODULE_EXPORT void free_linestack_context(struct linestack_context *);
+G_MODULE_EXPORT gboolean linestack_read_entry(struct linestack_context *nd,
+ guint64 i,
+ struct irc_line **line,
+ time_t *time
+ );
+
+
#endif /* __CTRLPROXY_LINESTACK_H__ */
{ NULL }
};
+static int py_line_cmp(PyLineObject *a, PyLineObject *b)
+{
+ return irc_line_cmp(a->line, b->line);
+}
+
PyTypeObject PyLineType = {
.tp_name = "Line",
.tp_new = py_line_new,
.tp_doc = "A RFC2459-compatible line.",
.tp_getset = py_line_getsetters,
.tp_as_sequence = &py_line_sequence,
+ .tp_compare = (cmpfunc)py_line_cmp,
};
struct irc_line *PyObject_AsLine(PyObject *obj)
if (PyType_Ready(&PyLinestackType) < 0)
return;
+ if (PyType_Ready(&PyLinestackIterType) < 0)
+ return;
+
if (PyType_Ready(&PyChannelModeDictType) < 0)
return;
PyModule_AddObject(m, "Transport", (PyObject *)&PyTransportType);
Py_INCREF(&PyLinestackType);
PyModule_AddObject(m, "Linestack", (PyObject *)&PyLinestackType);
+ Py_INCREF(&PyLinestackIterType);
PyModule_AddIntConstant(m, "TO_SERVER", TO_SERVER);
PyModule_AddIntConstant(m, "FROM_SERVER", FROM_SERVER);
}
PyObject *parent;
} PyLinestackObject;
PyTypeObject PyLinestackType;
+PyTypeObject PyLinestackIterType;
/* GList iterator */
PyObject *py_g_list_iter(GList *list, PyObject *parent, PyObject *(*converter) (PyObject *parent, void *));
Py_RETURN_NONE;
}
+typedef struct {
+ PyObject_HEAD
+ PyLinestackObject *parent;
+ guint64 from, to;
+} PyLinestackIterObject;
+
+static int py_linestack_iter_dealloc(PyLinestackIterObject *self)
+{
+ Py_DECREF(self->parent);
+ PyObject_Del(self);
+ return 0;
+}
+
+static PyObject *py_linestack_iter_next(PyLinestackIterObject *self)
+{
+ time_t time;
+ struct irc_line *line = NULL;
+ gboolean ret;
+ PyLineObject *py_line;
+ PyObject *py_ret;
+ if (self->from == self->to) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ ret = linestack_read_entry(self->parent->linestack, self->from,
+ &line, &time);
+ if (ret == FALSE) {
+ PyErr_SetNone(PyExc_RuntimeError);
+ return NULL;
+ }
+
+ py_line = PyObject_New(PyLineObject, &PyLineType);
+ py_line->line = line;
+
+ py_ret = Py_BuildValue("(Nl)", py_line, time);
+
+ self->from++;
+ return py_ret;
+}
+
+PyTypeObject PyLinestackIterType = {
+ .tp_name = "LinestackIter",
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_basicsize = sizeof(PyLinestackIterObject),
+ .tp_iter = PyObject_SelfIter,
+ .tp_iternext = (iternextfunc)py_linestack_iter_next,
+ .tp_dealloc = (destructor)py_linestack_iter_dealloc,
+};
+
+static PyObject *py_linestack_traverse(PyLinestackObject *self, PyObject *args)
+{
+ PyLinestackIterObject *ret;
+ ret = PyObject_New(PyLinestackIterObject, &PyLinestackIterType);
+ if (ret == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ Py_INCREF(self);
+ ret->parent = self;
+
+ if (!PyArg_ParseTuple(args, "LL", &ret->from, &ret->to)) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ return (PyObject *)ret;
+}
+
static PyMethodDef py_linestack_methods[] = {
{ "insert_line", (PyCFunction)py_linestack_insert_line,
METH_VARARGS, "Insert line" },
METH_NOARGS, "Get marker" },
{ "send", (PyCFunction)py_linestack_send, METH_VARARGS,
"Send" },
+ { "traverse", (PyCFunction)py_linestack_traverse, METH_VARARGS,
+ "Traverse" },
{ NULL }
};
state2 = self.get_state()
ls.replay(state2, m, ls.get_marker())
self.assertEquals(["#bla"], state2.channels.keys())
+
+ def test_traverse(self):
+ state = self.get_state()
+ ls = irc.Linestack("insert_line", True, self.get_basedir(), state)
+ m1 = ls.get_marker()
+ ls.insert_line(":somebody!some@host JOIN #bla", irc.FROM_SERVER, state)
+ ls.insert_line(":somebody!some@host PRIVMSG #bla :BAR!",
+ irc.FROM_SERVER, state)
+ m2 = ls.get_marker()
+ self.assertEquals([irc.Line(":somebody!some@host JOIN #bla"), irc.Line(":somebody!some@host PRIVMSG #bla :BAR!")], [l for (l, t) in ls.traverse(m1, m2)])