|
@@ -7,9 +7,69 @@
|
|
#include <structmember.h>
|
|
#include <structmember.h>
|
|
|
|
|
|
#include "graph.h"
|
|
#include "graph.h"
|
|
|
|
+#include "codec_nt.h"
|
|
#include "py_triple.h"
|
|
#include "py_triple.h"
|
|
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * String iterator for codec output.
|
|
|
|
+ *
|
|
|
|
+ * Yields one string (one or more lines) at a time.
|
|
|
|
+ */
|
|
|
|
+typedef struct {
|
|
|
|
+ PyObject_HEAD
|
|
|
|
+ LSUP_CodecIterator *it;
|
|
|
|
+ char *line;
|
|
|
|
+} StringIteratorObject;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+StringIterator_dealloc (StringIteratorObject *it_obj)
|
|
|
|
+{ it_obj->it->codec->encode_graph_done (it_obj->it); }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static PyObject *
|
|
|
|
+StringIterator_next (StringIteratorObject *it_obj)
|
|
|
|
+{
|
|
|
|
+ unsigned char *rdf_str;
|
|
|
|
+ LSUP_rc rc = it_obj->it->codec->encode_graph_iter (it_obj->it, &rdf_str);
|
|
|
|
+ if (rc != LSUP_OK) {
|
|
|
|
+ if (rc != LSUP_END)
|
|
|
|
+ PyErr_SetString (PyExc_ValueError, "Error encoding graph.");
|
|
|
|
+
|
|
|
|
+ // If not an error, this raises StopIteration.
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ PyObject *rdf_obj = PyUnicode_FromString ((char*)rdf_str);
|
|
|
|
+ if (UNLIKELY (!rdf_obj)) return NULL;
|
|
|
|
+
|
|
|
|
+ Py_INCREF (rdf_obj);
|
|
|
|
+ return (rdf_obj);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * String iterator type.
|
|
|
|
+ *
|
|
|
|
+ * Objects of this type are never generated from Python code, rather from
|
|
|
|
+ * Graph_encode, hence the type has no special new or init function.
|
|
|
|
+ */
|
|
|
|
+PyTypeObject StringIteratorType = {
|
|
|
|
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
|
|
|
+ .tp_name = "graph.StringIterator",
|
|
|
|
+ .tp_basicsize = sizeof (StringIteratorObject),
|
|
|
|
+ .tp_itemsize = 0,
|
|
|
|
+ .tp_flags = Py_TPFLAGS_DEFAULT,
|
|
|
|
+ .tp_dealloc = (destructor) StringIterator_dealloc,
|
|
|
|
+ .tp_iter = PyObject_SelfIter,
|
|
|
|
+ .tp_iternext = (iternextfunc)StringIterator_next,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Graph stuff.
|
|
|
|
+ */
|
|
|
|
+
|
|
typedef struct {
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
PyObject_HEAD
|
|
LSUP_Graph *ob_struct;
|
|
LSUP_Graph *ob_struct;
|
|
@@ -73,6 +133,7 @@ static PyGetSetDef Graph_getsetters[] = {
|
|
{NULL}
|
|
{NULL}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+
|
|
static PyObject *
|
|
static PyObject *
|
|
Graph_copy (PyTypeObject *cls, PyObject *src)
|
|
Graph_copy (PyTypeObject *cls, PyObject *src)
|
|
{
|
|
{
|
|
@@ -88,6 +149,44 @@ Graph_copy (PyTypeObject *cls, PyObject *src)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+static PyObject *
|
|
|
|
+Graph_new_from_rdf (PyTypeObject *cls, PyObject *args)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ Py_buffer *buf;
|
|
|
|
+ const char *type;
|
|
|
|
+ if (! PyArg_ParseTuple (args, "s*s", &buf, &type)) return NULL;
|
|
|
|
+
|
|
|
|
+ GraphObject *res = (GraphObject *) cls->tp_alloc(cls, 0);
|
|
|
|
+ if (!res) goto fail;
|
|
|
|
+
|
|
|
|
+ const LSUP_Codec *codec;
|
|
|
|
+ if (strcmp(type, "nt") == 0) codec = &nt_codec;
|
|
|
|
+ // TODO other codecs here.
|
|
|
|
+ else {
|
|
|
|
+ PyErr_SetString (PyExc_ValueError, "Unsupported codec.");
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ size_t ct;
|
|
|
|
+ char *err;
|
|
|
|
+ codec->decode_graph (buf->buf, &res->ob_struct, &ct, &err);
|
|
|
|
+
|
|
|
|
+ TRACE ("Decoded %lu triples.\n", ct);
|
|
|
|
+ if (!UNLIKELY (err)) goto fail;
|
|
|
|
+
|
|
|
|
+ PyBuffer_Release (buf);
|
|
|
|
+ Py_INCREF(res);
|
|
|
|
+
|
|
|
|
+ return (PyObject *) res;
|
|
|
|
+
|
|
|
|
+fail:
|
|
|
|
+ PyBuffer_Release (buf);
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static PyObject *
|
|
static PyObject *
|
|
Graph_richcmp (PyObject *self, PyObject *other, int op)
|
|
Graph_richcmp (PyObject *self, PyObject *other, int op)
|
|
{
|
|
{
|
|
@@ -135,7 +234,7 @@ Graph_add (PyObject *self, PyObject *triples)
|
|
PyObject *trp_obj = NULL;
|
|
PyObject *trp_obj = NULL;
|
|
int rc = 0;
|
|
int rc = 0;
|
|
size_t i;
|
|
size_t i;
|
|
- LSUP_SerTriple *sspo = STRP_DUMMY;
|
|
|
|
|
|
+ LSUP_SerTriple *sspo = LSUP_striple_new (BUF_DUMMY, BUF_DUMMY, BUF_DUMMY);
|
|
LSUP_GraphIterator *it = LSUP_graph_add_init (
|
|
LSUP_GraphIterator *it = LSUP_graph_add_init (
|
|
((GraphObject *)self)->ob_struct);
|
|
((GraphObject *)self)->ob_struct);
|
|
|
|
|
|
@@ -173,11 +272,14 @@ finalize:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+// TODO
|
|
static int Graph_remove (PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
static int Graph_remove (PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
{
|
|
{
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+// TODO
|
|
static PyObject *Graph_lookup (
|
|
static PyObject *Graph_lookup (
|
|
PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
{
|
|
{
|
|
@@ -185,8 +287,43 @@ static PyObject *Graph_lookup (
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+static PyObject *
|
|
|
|
+Graph_encode (PyObject *self, PyObject *args)
|
|
|
|
+{
|
|
|
|
+ char *type;
|
|
|
|
+
|
|
|
|
+ if (! PyArg_ParseTuple (args, "s", &type)) return NULL;
|
|
|
|
+
|
|
|
|
+ const LSUP_Codec *codec;
|
|
|
|
+ if (strcmp(type, "nt") == 0) codec = &nt_codec;
|
|
|
|
+ // TODO other codecs here.
|
|
|
|
+ else {
|
|
|
|
+ PyErr_SetString (PyExc_ValueError, "Unsupported codec.");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ LSUP_CodecIterator *it = codec->encode_graph_init (
|
|
|
|
+ ((GraphObject *)self)->ob_struct);
|
|
|
|
+
|
|
|
|
+ // Initialize the generator object.
|
|
|
|
+ //StringIteratorType *it_type;
|
|
|
|
+ StringIteratorObject *it_obj = PyObject_New (
|
|
|
|
+ StringIteratorObject, &StringIteratorType);
|
|
|
|
+ if (!it_obj) return NULL;
|
|
|
|
+
|
|
|
|
+ it_obj->it = it;
|
|
|
|
+
|
|
|
|
+ Py_INCREF (it_obj);
|
|
|
|
+ return (PyObject *)it_obj;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static PyMethodDef Graph_methods[] = {
|
|
static PyMethodDef Graph_methods[] = {
|
|
{"copy", (PyCFunction) Graph_copy, METH_CLASS, "Copy a graph."},
|
|
{"copy", (PyCFunction) Graph_copy, METH_CLASS, "Copy a graph."},
|
|
|
|
+ {
|
|
|
|
+ "from_rdf", (PyCFunction) Graph_new_from_rdf, METH_CLASS,
|
|
|
|
+ "Create a graph from a RDF file."
|
|
|
|
+ },
|
|
{"add", (PyCFunction) Graph_add, METH_O, "Add triples to a graph."},
|
|
{"add", (PyCFunction) Graph_add, METH_O, "Add triples to a graph."},
|
|
{
|
|
{
|
|
"remove", (PyCFunction) Graph_remove, METH_VARARGS,
|
|
"remove", (PyCFunction) Graph_remove, METH_VARARGS,
|
|
@@ -196,6 +333,10 @@ static PyMethodDef Graph_methods[] = {
|
|
"lookup", (PyCFunction) Graph_lookup, METH_VARARGS,
|
|
"lookup", (PyCFunction) Graph_lookup, METH_VARARGS,
|
|
"Look triples in a graph by matching a pattern."
|
|
"Look triples in a graph by matching a pattern."
|
|
},
|
|
},
|
|
|
|
+ {
|
|
|
|
+ "to_rdf", (PyCFunction) Graph_encode, METH_VARARGS,
|
|
|
|
+ "Encode a graph into a RDF byte buffer."
|
|
|
|
+ },
|
|
{NULL},
|
|
{NULL},
|
|
};
|
|
};
|
|
|
|
|
|
@@ -253,19 +394,19 @@ static PySequenceMethods Graph_seq_methods = {
|
|
|
|
|
|
PyTypeObject GraphType = {
|
|
PyTypeObject GraphType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
- .tp_name = "graph.Graph",
|
|
|
|
- .tp_doc = "RDF graph",
|
|
|
|
- .tp_basicsize = sizeof (GraphObject),
|
|
|
|
- .tp_itemsize = 0,
|
|
|
|
- .tp_flags = Py_TPFLAGS_DEFAULT,
|
|
|
|
- .tp_new = PyType_GenericNew,
|
|
|
|
- .tp_init = (initproc) Graph_init,
|
|
|
|
- .tp_dealloc = (destructor) Graph_dealloc,
|
|
|
|
- .tp_getset = Graph_getsetters,
|
|
|
|
- .tp_methods = Graph_methods,
|
|
|
|
- .tp_richcompare = (richcmpfunc) Graph_richcmp,
|
|
|
|
- .tp_as_number = &Graph_number_methods,
|
|
|
|
- .tp_as_sequence = &Graph_seq_methods,
|
|
|
|
|
|
+ .tp_name = "graph.Graph",
|
|
|
|
+ .tp_doc = "RDF graph",
|
|
|
|
+ .tp_basicsize = sizeof (GraphObject),
|
|
|
|
+ .tp_itemsize = 0,
|
|
|
|
+ .tp_flags = Py_TPFLAGS_DEFAULT,
|
|
|
|
+ .tp_new = PyType_GenericNew,
|
|
|
|
+ .tp_init = (initproc) Graph_init,
|
|
|
|
+ .tp_dealloc = (destructor) Graph_dealloc,
|
|
|
|
+ .tp_getset = Graph_getsetters,
|
|
|
|
+ .tp_methods = Graph_methods,
|
|
|
|
+ .tp_richcompare = (richcmpfunc) Graph_richcmp,
|
|
|
|
+ .tp_as_number = &Graph_number_methods,
|
|
|
|
+ .tp_as_sequence = &Graph_seq_methods,
|
|
};
|
|
};
|
|
|
|
|
|
#endif
|
|
#endif
|