#ifndef _PY_TERM_OBJ_H #define _PY_TERM_OBJ_H #define PY_SSIZE_T_CLEAN #include #include #include "term.h" #include "py_namespace.h" typedef struct { PyObject_HEAD LSUP_Term * ob_struct; } TermObject; static int Term_init (TermObject *self, PyObject *args, PyObject *kwargs) { unsigned char term_type; char *data = NULL, *datatype = NULL, *lang = NULL; static char *kwlist[] = {"", "", "datatype", "lang", NULL}; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "bs|zz", kwlist, &term_type, &data, &datatype, &lang)) return -1; if (datatype) { LSUP_Term *dtype_uri = LSUP_term_new ( LSUP_TERM_IRIREF, datatype, NULL); self->ob_struct = LSUP_term_new ( (LSUP_TermType) term_type, data, dtype_uri); } else { self->ob_struct = LSUP_term_new ( (LSUP_TermType) term_type, data, lang); } if (!self->ob_struct) { PyErr_SetString (PyExc_ValueError, "Could not create term."); return -1; } return 0; } static int Term_iriref_init (TermObject *self, PyObject *args, PyObject *kwargs) { char *data = NULL; NSMapObject *nsm = NULL; static char *kwlist[] = {"data", "nsm", NULL}; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "|sO", kwlist, &data, &nsm)) return -1; if (nsm && !PyObject_TypeCheck (nsm, &NSMapType)) { PyErr_SetString (PyExc_TypeError, "nsm is not a NSMap type."); return -1; } self->ob_struct = LSUP_iriref_new ( data, (nsm ? nsm->ob_struct : NULL)); if (!self->ob_struct) { PyErr_SetString (PyExc_ValueError, "Could not create term."); return -1; } return 0; } static int Term_literal_init (TermObject *self, PyObject *args, PyObject *kwargs) { char *data = NULL, *datatype = NULL, *lang = NULL; static char *kwlist[] = {"", "datatype", "lang", NULL}; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "s|zz", kwlist, &data, &datatype, &lang)) return -1; if (lang) self->ob_struct = LSUP_lt_literal_new (data, lang); else { LSUP_Term *dtype = (datatype) ? LSUP_iriref_new (datatype, NULL) : NULL; self->ob_struct = LSUP_literal_new (data, dtype); } if (!self->ob_struct) { PyErr_SetString (PyExc_ValueError, "Could not create term."); return -1; } return 0; } static int Term_bnode_init (TermObject *self, PyObject *args, PyObject *kwargs) { char *data; static char *kwlist[] = {"data", NULL}; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|s", kwlist, &data)) return -1; self->ob_struct = LSUP_term_new (LSUP_TERM_BNODE, data, NULL); 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, void *closure) { return PyLong_FromLong (self->ob_struct->type); } static PyObject * Term_get_data (TermObject *self, void *closure) { return PyUnicode_FromString (self->ob_struct->data); } static PyObject * Term_iriref_get_nsm (TermObject *self, void *closure) { LSUP_Term *term = self->ob_struct; if (!LSUP_IS_IRI(term)) Py_RETURN_NONE; LSUP_NSMap *nsm = LSUP_iriref_nsm (term); if (!nsm) Py_RETURN_NONE; NSMapObject *nsm_obj = PyObject_New (NSMapObject, &NSMapType); if (UNLIKELY (!nsm_obj)) return PyErr_NoMemory(); nsm_obj->ob_struct = nsm; Py_INCREF (nsm_obj); return (PyObject *) nsm_obj; } static PyObject * Term_iriref_get_prefix (TermObject *self, void *closure) { LSUP_Term *term = self->ob_struct; if (! LSUP_IS_IRI (term)) Py_RETURN_NONE; return PyUnicode_FromString (LSUP_iriref_prefix (term)); } static PyObject * Term_iriref_get_path (TermObject *self, void *closure) { LSUP_Term *term = self->ob_struct; if (! LSUP_IS_IRI (term)) Py_RETURN_NONE; return PyUnicode_FromString (LSUP_iriref_path (term)); } static PyObject * Term_iriref_get_frag (TermObject *self, void *closure) { LSUP_Term *term = self->ob_struct; if (! LSUP_IS_IRI (term)) Py_RETURN_NONE; return PyUnicode_FromString (LSUP_iriref_frag (term)); } static PyObject * Term_lit_get_datatype (TermObject *self, void *closure) { if (!self->ob_struct->datatype) Py_RETURN_NONE; char *dtype_data = self->ob_struct->type == LSUP_TERM_LT_LITERAL ? DEFAULT_DTYPE : self->ob_struct->datatype->data; TermObject *datatype = (TermObject *) Py_TYPE (self)->tp_alloc ( Py_TYPE (self), 0); if (!datatype) return PyErr_NoMemory(); datatype->ob_struct = LSUP_iriref_new (dtype_data, NULL); Py_INCREF (datatype); return (PyObject *) datatype; } static PyObject * Term_lit_get_lang (TermObject *self, void *closure) { if ( self->ob_struct->type != LSUP_TERM_LT_LITERAL || self->ob_struct->lang[0] == '\0') Py_RETURN_NONE; return PyUnicode_FromString (self->ob_struct->lang); } static PyGetSetDef Term_getsetters[] = { {"_type", (getter) Term_get_type, NULL, "Term type.", NULL}, {"_data", (getter) Term_get_data, NULL, "Term data.", NULL}, { "_nsm", (getter) Term_iriref_get_nsm, NULL, "IRI ref namespace map.", NULL }, { "_prefix", (getter) Term_iriref_get_prefix, NULL, "IRI ref prefix.", NULL }, { "_path", (getter) Term_iriref_get_path, NULL, "IRI ref path after prefix.", NULL }, { "_frag", (getter) Term_iriref_get_frag, NULL, "IRI ref fragment.", NULL }, { "_datatype", (getter) Term_lit_get_datatype, NULL, "Literal term data type.", NULL }, { "_lang", (getter) Term_lit_get_lang, NULL, "Literal term language tag.", NULL }, {NULL} }; static PyGetSetDef IRIRef_getsetters[] = { {"data", (getter) Term_get_data, NULL, "IRI string.", NULL}, { "nsm", (getter) Term_iriref_get_nsm, NULL, "Namespace map.", NULL }, { "prefix", (getter) Term_iriref_get_prefix, NULL, "IRI ref prefix.", NULL }, { "path", (getter) Term_iriref_get_path, NULL, "IRI ref path after prefix.", NULL }, { "frag", (getter) Term_iriref_get_frag, NULL, "IRI ref fragment.", NULL }, {NULL} }; static PyGetSetDef Literal_getsetters[] = { {"data", (getter) Term_get_data, NULL, "Literal data.", NULL}, { "datatype", (getter) Term_lit_get_datatype, NULL, "Data type.", NULL }, { "lang", (getter) Term_lit_get_lang, NULL, "Language tag.", NULL }, {NULL} }; static PyGetSetDef BNode_getsetters[] = { {"data", (getter) Term_get_data, NULL, "Blank node label.", NULL}, {NULL} }; static PyObject * Term_repr (TermObject *term_obj) { LSUP_Term *term = term_obj->ob_struct; char *term_repr_ptn = "<%s @%p> '%s'"; char *term_nt; if (UNLIKELY (nt_codec.encode_term (term, NULL, &term_nt) != LSUP_OK)) { PyErr_SetString (PyExc_ValueError, "Error serializing term."); return NULL; } char *term_repr = malloc ( strlen (term_repr_ptn) + strlen (term_nt) + strlen (term_obj->tp_name) + 32); // 32 for pointer address + NUL if (UNLIKELY (!term_repr)) return PyErr_NoMemory; sprintf ( term_repr, term_repr_ptn, term_obj->tp_name, term->obj, term_nt); PyObject *result = PyUnicode_FromString (term_repr); free (term_repr); if (UNLIKELY (!result)) return PyErr_NoMemory; Py_INCREF (result); return result; } static PyObject * Term_str (PyObject *term_obj) { LSUP_Term *term = term_obj->ob_struct; PyObject *result = PyUnicode_FromString (term->data); if (UNLIKELY (!result)) return PyErr_NoMemory; Py_INCREF (result); return result; } static PyObject * Term_richcmp (PyObject *obj1, PyObject *obj2, int op); static Py_hash_t Term_hash (PyObject *self) { return LSUP_term_hash (((TermObject *)self)->ob_struct); } 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_repr = Term_repr, .tp_str = Term_str, .tp_getset = Term_getsetters, .tp_richcompare = Term_richcmp, .tp_hash = Term_hash, }; PyTypeObject IRIRefType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "term.IRIRef", .tp_doc = "RDF IRI reference.", .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_base = &TermType, .tp_init = (initproc) Term_iriref_init, .tp_getset = IRIRef_getsetters, }; PyTypeObject LiteralType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "term.Literal", .tp_doc = "RDF Literal.", .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_base = &TermType, .tp_init = (initproc) Term_literal_init, .tp_getset = Literal_getsetters, }; PyTypeObject BNodeType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "term.BNode", .tp_doc = "RDF Blanbk Node.", .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_base = &TermType, .tp_init = (initproc) Term_bnode_init, .tp_getset = BNode_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; } PyObject * build_term (LSUP_Term *t) { log_trace ("Building term: %s", t->data); PyTypeObject *term_obj_type; PyObject *term_args; switch (t->type) { case LSUP_TERM_IRIREF: term_obj_type = &IRIRefType; term_args = Py_BuildValue ("(s)", t->data); break; case LSUP_TERM_NS_IRIREF: term_obj_type = &IRIRefType; term_args = Py_BuildValue ("sO", t->data, LSUP_iriref_nsm (t)); break; case LSUP_TERM_BNODE: term_obj_type = &BNodeType; term_args = Py_BuildValue ("(s)", t->data); break; case LSUP_TERM_LITERAL: term_obj_type = &LiteralType; term_args = Py_BuildValue ("sz", t->data, t->datatype->data, NULL); break; case LSUP_TERM_LT_LITERAL: term_obj_type = &LiteralType; term_args = Py_BuildValue ("sz", t->data, NULL, t->lang); break; default: return NULL; } if (UNLIKELY (!term_args)) return NULL; PyObject *t_obj = PyObject_CallObject ( (PyObject *)term_obj_type, term_args); Py_DECREF (term_args); if (UNLIKELY (!t_obj)) return NULL; return t_obj; } // END _PY_TERM_OBJ_H #endif