Pārlūkot izejas kodu

Triple module; split module and object code for cross-include.

Stefano Cossu 3 gadi atpakaļ
vecāks
revīzija
efa3810477
9 mainītis faili ar 338 papildinājumiem un 40 dzēšanām
  1. 42 0
      cpython/term_mod.c
  2. 15 38
      cpython/term_obj.h
  3. 37 0
      cpython/triple_mod.c
  4. 141 0
      cpython/triple_obj.h
  5. 12 0
      include/buffer.h
  6. 2 1
      include/triple.h
  7. 54 0
      setup.py
  8. 33 0
      src/buffer.c
  9. 2 1
      src/term.c

+ 42 - 0
cpython/term_mod.c

@@ -0,0 +1,42 @@
+#ifndef _PY_TERM_MOD_H
+#define _PY_TERM_MOD_H
+
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+
+#include "term_obj.h"
+
+
+PyModuleDef term_mod = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "term",
+    .m_doc = "RDF term module.",
+    .m_size = -1,
+};
+
+
+PyMODINIT_FUNC
+PyInit_term(void)
+{
+    if (PyType_Ready (&TermType) < 0) return NULL;
+
+    PyObject *m = PyModule_Create(&term_mod);
+    if (m == NULL) return NULL;
+
+#define ENTRY(a, b) \
+    if (PyModule_AddIntConstant (m, "TERM_" #a, b) < 0) return NULL;
+    TTYPE_TABLE
+#undef ENTRY
+
+    Py_INCREF(&TermType);
+    if (PyModule_AddObject(m, "Term", (PyObject *) &TermType) < 0) {
+        Py_DECREF(&TermType);
+        Py_DECREF(m);
+        return NULL;
+    }
+
+    return m;
+}
+
+#endif

+ 15 - 38
cpython/termmodule.c → cpython/term_obj.h

@@ -1,3 +1,6 @@
+#ifndef _PY_TERM_OBJ_H
+#define _PY_TERM_OBJ_H
+
 #define PY_SSIZE_T_CLEAN
 
 #include <Python.h>
@@ -11,28 +14,21 @@ typedef struct {
     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;
+    unsigned char term_type;
     char *data = NULL, *datatype = NULL, *lang = NULL;
 
-    static char *kwlist[] = {"data", "datatype", "lang", NULL};
+    static char *kwlist[] = {"", "", "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);
+    self->ob_struct = LSUP_term_new ((LSUP_term_type)term_type, data, datatype, lang);
     if (!self->ob_struct) {
         PyErr_SetString (PyExc_ValueError, "Could not create term.");
         return -1;
@@ -52,7 +48,7 @@ Term_dealloc (TermObject *self)
 static PyObject *
 Term_get_type (TermObject *self)
 {
-    PyObject *type = PyLong_FromSize_t ((size_t)self->ob_struct->type);
+    PyObject *type = PyLong_FromLong (self->ob_struct->type);
     Py_INCREF (type);
 
     return type;
@@ -110,7 +106,11 @@ static PyGetSetDef Term_getsetters[] = {
 };
 
 
-static PyTypeObject TermType = {
+static PyObject *
+Term_richcmp (PyObject *obj1, PyObject *obj2, int op);
+
+
+PyTypeObject TermType = {
     PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = "term.Term",
     .tp_doc = "RDF term",
@@ -121,6 +121,7 @@ static PyTypeObject TermType = {
     .tp_init = (initproc) Term_init,
     .tp_dealloc = (destructor) Term_dealloc,
     .tp_getset = Term_getsetters,
+    .tp_richcompare = Term_richcmp,
 };
 
 
@@ -153,29 +154,5 @@ Term_richcmp (PyObject *obj1, PyObject *obj2, int op)
     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;
-}
+// END _PY_TERM_OBJ_H
+#endif

+ 37 - 0
cpython/triple_mod.c

@@ -0,0 +1,37 @@
+#ifndef _PY_TRIPLE_MOD_H
+#define _PY_TRIPLE_MOD_H
+
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+
+#include "triple_obj.h"
+
+
+PyModuleDef triple_mod = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "triple",
+    .m_doc = "RDF triple module.",
+    .m_size = -1,
+};
+
+
+PyMODINIT_FUNC
+PyInit_triple(void)
+{
+    if (PyType_Ready (&TripleType) < 0) return NULL;
+
+    PyObject *m = PyModule_Create(&triple_mod);
+    if (m == NULL) return NULL;
+
+    Py_INCREF(&TripleType);
+    if (PyModule_AddObject(m, "Triple", (PyObject *) &TripleType) < 0) {
+        Py_DECREF(&TripleType);
+        Py_DECREF(m);
+        return NULL;
+    }
+
+    return m;
+}
+
+#endif

+ 141 - 0
cpython/triple_obj.h

@@ -0,0 +1,141 @@
+#ifndef _PY_TRIPLE_OBJ_H
+#define _PY_TRIPLE_OBJ_H
+
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "triple.h"
+#include "term_obj.h"
+
+
+typedef struct {
+    PyObject_HEAD
+    LSUP_Triple * ob_struct;
+    TermObject *s;
+    TermObject *p;
+    TermObject *o;
+} TripleObject;
+
+
+static int
+Triple_init (TripleObject *self, PyObject *args)
+{
+    TermObject *s = NULL, *p = NULL, *o = NULL, *tmp;
+
+    if (! PyArg_ParseTuple (
+    /*
+                args, "O!O!O!", &s, &TermType,
+                &p, &TermType, &o, &TermType))
+    */
+                args, "OOO", &s, &p, &o))
+        return -1;
+
+    // TODO check for null s, p, o
+    if (
+        PyObject_TypeCheck (s, &TermType) ||
+        PyObject_TypeCheck (p, &TermType) ||
+        PyObject_TypeCheck (o, &TermType)
+    ) return -1;
+
+    tmp = self->s;
+    Py_INCREF(s);
+    self->s = s;
+    Py_XDECREF(tmp);
+
+    tmp = self->p;
+    Py_INCREF(p);
+    self->p = p;
+    Py_XDECREF(tmp);
+
+    tmp = self->o;
+    Py_INCREF(o);
+    self->o = o;
+    Py_XDECREF(tmp);
+
+    self->ob_struct = LSUP_triple_new (
+            s->ob_struct, p->ob_struct, o->ob_struct);
+    if (!self->ob_struct) {
+        PyErr_SetString (PyExc_ValueError, "Could not create triple.");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static void
+Triple_dealloc (TripleObject *self)
+{
+    Py_XDECREF(self->s);
+    Py_XDECREF(self->p);
+    Py_XDECREF(self->o);
+    free (self->ob_struct); // Term pointers were allocated independently.
+    Py_TYPE (self)->tp_free ((PyObject *) self);
+}
+
+
+static PyMemberDef Triple_members[] = {
+    {"s", T_OBJECT_EX, offsetof(TripleObject, s), 0, "Triple subject,"},
+    {"p", T_OBJECT_EX, offsetof(TripleObject, p), 0, "Triple predicate."},
+    {"o", T_OBJECT_EX, offsetof(TripleObject, o), 0, "Triple object."},
+    {NULL}
+};
+
+
+static PyObject *
+Triple_richcmp (PyObject *obj1, PyObject *obj2, int op);
+
+
+PyTypeObject TripleType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    .tp_name = "triple.Triple",
+    .tp_doc = "RDF triple",
+    .tp_basicsize = sizeof(TripleObject),
+    .tp_itemsize = 0,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_new = PyType_GenericNew,
+    .tp_init = (initproc) Triple_init,
+    .tp_dealloc = (destructor) Triple_dealloc,
+    .tp_members = Triple_members,
+    .tp_richcompare = Triple_richcmp,
+};
+
+
+static PyObject *
+Triple_richcmp (PyObject *obj1, PyObject *obj2, int op)
+{
+    PyObject *result = NULL;
+
+    if (
+        ! PyObject_TypeCheck (obj1, &TripleType) ||
+        ! PyObject_TypeCheck (obj2, &TripleType)
+    ) return NULL;
+
+    int c = 0;
+    LSUP_Triple *t1 = ((TripleObject *) obj1)->ob_struct;
+    LSUP_Triple *t2 = ((TripleObject *) 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->s, t2->s) &&
+                            LSUP_term_equals (t1->p, t2->p) &&
+                            LSUP_term_equals (t1->o, t2->o)); break;
+        case Py_NE: c = (!
+                            LSUP_term_equals (t1->s, t2->s) &&
+                            LSUP_term_equals (t1->p, t2->p) &&
+                            LSUP_term_equals (t1->o, t2->o)); 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;
+ }
+
+#endif

+ 12 - 0
include/buffer.h

@@ -90,6 +90,18 @@ void LSUP_buffer_free (LSUP_Buffer *buf);
 void LSUP_buffer_print (const LSUP_Buffer *buf);
 
 
+/** @brief Format a buffer into anb ASCII string.
+ *
+ * The string has non-printable characters escaped as "\xNN".
+ *
+ * @param buf[in] Buffer to convert.
+ *
+ * @return Formatted string. It must be freed with free().
+ */
+char *
+LSUP_buffer_as_str (const LSUP_Buffer *buf);
+
+
 /** @brief Compare two buffers.
  *
  * The return value is the same as memcmp.

+ 2 - 1
include/triple.h

@@ -44,7 +44,8 @@ LSUP_striple_new_from_triple (const LSUP_Triple *spo);
 
 /** @brief Initialize internal term pointers in a heap-allocated triple.
  *
- * The triple must be freed with #LSUP_triple_free().
+ * NOTE: the term structures are not copied. If the triple is freed with
+ * #LSUP_triple_free(), the originally provided terms are freed too.
  *
  * @param spo[in] Triple pointer to initialize.
  */

+ 54 - 0
setup.py

@@ -0,0 +1,54 @@
+# from glob import glob
+from os import path
+from setuptools import Extension, setup
+
+
+ROOT_DIR = path.dirname(path.realpath(__file__))
+MOD_DIR = path.join(ROOT_DIR, 'cpython')
+SRC_DIR = path.join(ROOT_DIR, 'src')
+INCL_DIR = path.join(ROOT_DIR, 'include')
+EXT_DIR = path.join(ROOT_DIR, 'ext')
+
+sources = (
+    # glob(path.join(SRC_DIR, '*.c')) +
+    # glob(path.join(MOD_DIR, '*.c')) +
+    [
+        path.join(EXT_DIR, 'xxHash', 'xxhash.c'),
+        path.join(EXT_DIR, 'openldap', 'libraries', 'liblmdb', 'mdb.c'),
+        path.join(EXT_DIR, 'openldap', 'libraries', 'liblmdb', 'midl.c'),
+    ]
+)
+
+compile_args = ['-std=c99', '-DDEBUG', '-g3']
+
+setup(
+    name="lsup_rdf",
+    version="1.0a1",
+    ext_modules=[
+        Extension(
+            "lsup_rdf.term",
+            [
+                path.join(EXT_DIR, 'xxHash', 'xxhash.c'),
+                path.join(SRC_DIR, 'buffer.c'),
+                path.join(SRC_DIR, 'term.c'),
+                path.join(MOD_DIR, 'term_mod.c'),
+            ],
+            include_dirs=[INCL_DIR],
+            libraries=['uuid'],
+            extra_compile_args=compile_args,
+        ),
+        Extension(
+            "lsup_rdf.triple",
+            [
+                path.join(EXT_DIR, 'xxHash', 'xxhash.c'),
+                path.join(SRC_DIR, 'buffer.c'),
+                path.join(SRC_DIR, 'term.c'),
+                path.join(SRC_DIR, 'triple.c'),
+                path.join(MOD_DIR, 'triple_mod.c'),
+            ],
+            include_dirs=[INCL_DIR],
+            libraries=['uuid'],
+            extra_compile_args=compile_args,
+        ),
+    ],
+)

+ 33 - 0
src/buffer.c

@@ -41,6 +41,39 @@ void LSUP_buffer_print (const LSUP_Buffer *buf)
 }
 
 
+char *
+LSUP_buffer_as_str (const LSUP_Buffer *buf)
+{
+    size_t i, str_size = 1; // terminating NUL
+
+    // Calculate alloc size first.
+    for (i = 0; i < buf->size; i++) {
+        char chr = ((char*)buf->addr)[i];
+        if (isprint (chr)) str_size ++;
+        else str_size += 4; // 4 characters for ASCII representation (\xNN).
+    }
+
+    char *cstr = malloc (str_size);
+
+    size_t cur = 0; // Position in target string.
+    for (i = 0; i < str_size - 1; i++) {
+        char chr = ((char*)buf->addr)[i];
+
+        if (isprint (chr)) {
+            cstr[cur] = chr;
+            cur ++;
+        } else {
+            sprintf (cstr + cur, "\\x%02x", chr);
+            cur += 4;
+        }
+    }
+
+    cstr[str_size - 1] = 0; // terminating NUL.
+
+    return cstr;
+}
+
+
 void LSUP_buffer_done (LSUP_Buffer *buf)
 {
     if (LIKELY (buf)) free (buf->addr);

+ 2 - 1
src/term.c

@@ -81,7 +81,8 @@ LSUP_term_init(
     // Validate URI.
     if (term->type == LSUP_TERM_URI) {
         if (UNLIKELY (!ptn_init)) {
-            assert (regcomp (&ptn, URI_REGEX_STR, REG_EXTENDED) == 0);
+            int rc = regcomp (&ptn, URI_REGEX_STR, REG_EXTENDED);
+            if (rc != 0) return LSUP_ERROR;
             ptn_init = true;
             atexit (term_cleanup);
         }