Browse Source

Rudimentary implementation of Python term module.

Stefano Cossu 3 years ago
parent
commit
c5b3dde882
3 changed files with 192 additions and 7 deletions
  1. 181 0
      cpython/termmodule.c
  2. 9 4
      include/term.h
  3. 2 3
      src/term.c

+ 181 - 0
cpython/termmodule.c

@@ -0,0 +1,181 @@
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "term.h"
+
+
+typedef struct {
+    PyObject_HEAD
+    LSUP_Term * ob_struct;
+} TermObject;
+
+static PyModuleDef termmodule = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "term",
+    .m_doc = "RDF term module.",
+    .m_size = -1,
+};
+
+
+static int
+Term_init (TermObject *self, PyObject *args, PyObject *kwargs)
+{
+    LSUP_term_type term_type;
+    char *data = NULL, *datatype = NULL, *lang = NULL;
+
+    static char *kwlist[] = {"data", "datatype", "lang", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords (
+            args, kwargs, "bs|ss", kwlist,
+            &term_type, &data, &datatype, &lang))
+        return -1;
+
+    self->ob_struct = LSUP_term_new (term_type, data, datatype, lang);
+    if (!self->ob_struct) {
+        PyErr_SetString (PyExc_ValueError, "Could not create term.");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void
+Term_dealloc (TermObject *self)
+{
+    LSUP_term_free (self->ob_struct);
+    Py_TYPE (self)->tp_free ((PyObject *) self);
+}
+
+
+static PyObject *
+Term_get_type (TermObject *self)
+{
+    PyObject *type = PyLong_FromSize_t ((size_t)self->ob_struct->type);
+    Py_INCREF (type);
+
+    return type;
+}
+
+
+static PyObject *
+Term_get_data (TermObject *self)
+{
+    PyObject *data = PyUnicode_FromString (self->ob_struct->data);
+    Py_INCREF (data);
+
+    return data;
+}
+
+
+static PyObject *
+Term_get_datatype (TermObject *self)
+{
+    if (!self->ob_struct->datatype) Py_RETURN_NONE;
+
+    PyObject *datatype = PyUnicode_FromString (self->ob_struct->datatype);
+    Py_INCREF (datatype);
+
+    return datatype;
+}
+
+static PyObject *
+Term_get_lang (TermObject *self)
+{
+    if (
+            !self->ob_struct->datatype || !self->ob_struct->lang ||
+            strlen (self->ob_struct->lang) == 0)
+        Py_RETURN_NONE;
+
+    PyObject *lang = PyUnicode_FromString (self->ob_struct->lang);
+    Py_INCREF (lang);
+
+    return lang;
+}
+
+
+static PyGetSetDef Term_getsetters[] = {
+    {"type", (getter) Term_get_type, NULL, "Term type.", NULL},
+    {"data", (getter) Term_get_data, NULL, "Term data.", NULL},
+    {
+        "datatype", (getter) Term_get_datatype,
+        NULL, "Literal term data type.", NULL
+    },
+    {
+        "lang", (getter) Term_get_lang,
+        NULL, "Literal term language tag.", NULL
+    },
+    {NULL}
+};
+
+
+static PyTypeObject TermType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    .tp_name = "term.Term",
+    .tp_doc = "RDF term",
+    .tp_basicsize = sizeof(TermObject),
+    .tp_itemsize = 0,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_new = PyType_GenericNew,
+    .tp_init = (initproc) Term_init,
+    .tp_dealloc = (destructor) Term_dealloc,
+    .tp_getset = Term_getsetters,
+};
+
+
+static PyObject *
+Term_richcmp (PyObject *obj1, PyObject *obj2, int op)
+{
+    PyObject *result = NULL;
+
+    if (
+        ! PyObject_TypeCheck (obj1, &TermType) ||
+        ! PyObject_TypeCheck (obj2, &TermType)
+    ) return NULL;
+
+    int c = 0;
+    LSUP_Term *t1 = ((TermObject *) obj1)->ob_struct;
+    LSUP_Term *t2 = ((TermObject *) obj2)->ob_struct;
+
+    switch (op) {
+        case Py_LT: result = Py_NotImplemented; break;
+        case Py_LE: result = Py_NotImplemented; break;
+        case Py_EQ: c = LSUP_term_equals (t1, t2); break;
+        case Py_NE: c = ! LSUP_term_equals (t1, t2); break;
+        case Py_GT: result = Py_NotImplemented; break;
+        case Py_GE: result = Py_NotImplemented; break;
+    }
+
+    if (!result) result = c ? Py_True : Py_False;
+
+    Py_INCREF(result);
+    return result;
+ }
+
+
+
+PyMODINIT_FUNC
+PyInit_term(void)
+{
+    if (PyType_Ready (&TermType) < 0) return NULL;
+
+    PyObject *m = PyModule_Create(&termmodule);
+    if (m == NULL) return NULL;
+
+#define ENTRY(a, b) \
+    if (PyModule_AddIntConstant (m, "TERM_" #a, b) < 0) return NULL;
+    TTYPE_TABLE
+#undef ENTRY
+
+    TermType.tp_richcompare = Term_richcmp;
+
+    Py_INCREF(&TermType);
+    if (PyModule_AddObject(m, "Term", (PyObject *) &TermType) < 0) {
+        Py_DECREF(&TermType);
+        Py_DECREF(m);
+        return NULL;
+    }
+
+    return m;
+}

+ 9 - 4
include/term.h

@@ -28,11 +28,16 @@
 typedef XXH64_hash_t LSUP_TermHash64;
 typedef char langtag[LANG_SIZE];
 
+#define TTYPE_TABLE \
+    ENTRY (UNDEFINED,     0) \
+    ENTRY (URI,           1) \
+    ENTRY (BNODE,         2) \
+    ENTRY (LITERAL,       3)
+
 typedef enum LSUP_term_type {
-    LSUP_TERM_UNDEFINED,
-    LSUP_TERM_URI,
-    LSUP_TERM_BNODE,
-    LSUP_TERM_LITERAL
+#define ENTRY(a, b) LSUP_TERM_##a = b,
+    TTYPE_TABLE
+#undef ENTRY
 } LSUP_term_type;
 
 typedef struct LSUP_Term {

+ 2 - 3
src/term.c

@@ -161,12 +161,11 @@ LSUP_term_init(
 LSUP_rc
 LSUP_term_serialize (const LSUP_Term *term, LSUP_Buffer *sterm)
 {
-    size_t size, data_len, datatype_len,
-           data_idx, datatype_idx, lang_idx;
+    size_t size, data_len, datatype_len = 0,
+           data_idx = 1, datatype_idx = 0, lang_idx = 0;
 
     if (UNLIKELY (term == NULL)) return LSUP_NOACTION;
 
-    data_idx = 1;
     data_len = strlen (term->data) + 1;
 
     size = data_idx + data_len;