Author: ArcRiley Date: 2009-03-03 23:34:50 -0500 (Tue, 03 Mar 2009) New Revision: 1541
Modified: trunk/concordance/include/concordance.h trunk/concordance/src/_core/__init__.c trunk/concordance/src/_core/step.c trunk/concordance/src/sockets/Client.c Log: a ton of work on XML callback support: * no longer requires Python to reparse XML * callback message type support * lacks some cleanup and execution code Modified: trunk/concordance/include/concordance.h =================================================================== --- trunk/concordance/include/concordance.h 2009-03-04 04:34:46 UTC (rev 1540) +++ trunk/concordance/include/concordance.h 2009-03-04 04:34:50 UTC (rev 1541) @@ -50,16 +50,63 @@ } concordGlobals; typedef struct { - guint major; - guint minor; + guint major; + guint minor; } concordVersion; +typedef struct { + gint type; /* type 0 */ +} concordMsg; typedef struct { - PyObject* self; - gchar* method; - GAsyncQueue* returnQueue; /* callback return queue */ - GString* message; -} concordQueueMsg; + gint type; /* type CONCORD_MT_XMLSTART */ + PyObject* tree; /* cElementTree.TreeBuilder */ + gpointer data; + const XML_Char* name; + const XML_Char** atts; +} concordMsg_xmlStart; +typedef struct { + gint type; /* type CONCORD_MT_XMLEND */ + PyObject* tree; /* cElementTree.TreeBuilder */ + const XML_Char* name; +} concordMsg_xmlEnd; + +typedef struct { + gint type; /* type CONCORD_MT_XMLCHARDATA */ + PyObject* tree; /* cElementTree.TreeBuilder */ + const XML_Char* str; + gint str_len; +} concordMsg_xmlCharData; + +typedef struct { + gint type; /* type CONCORD_MT_XMLCHARDATA */ + PyObject* tree; /* cElementTree.TreeBuilder */ + PyObject* self; /* self for callback method */ + gpointer data; /* pointer to session data */ + GAsyncQueue* retn; /* callback queue input */ +} concordMsg_xmlClose; + +typedef struct { + gint type; /* type CONCORD_MT_XMLCHARDATA */ + gpointer data; /* pointer to session data */ + GString* mesg; /* UTF8 string with XML data */ +} concordMsg_xmlReturn; + +typedef struct { + gint type; /* type CONCORD_MT_SASLPASSWORD */ + gpointer data; +} concordMsg_saslPassword; + + +enum concordMsgType { + CONCORD_MT_NONE = 0, + CONCORD_MT_XMLSTART, /* for _xmlStart handler */ + CONCORD_MT_XMLEND, /* for _xmlEnd handler */ + CONCORD_MT_XMLCHARDATA, /* for _xmlCharData handler */ + CONCORD_MT_XMLCLOSE, /* last xml msg for a stanza */ + CONCORD_MT_XMLRETURN, /* xml output for a session */ + CONCORD_MT_SASLPASSWORD, /* for GSASL_PASSWORD handler */ +}; + #endif Modified: trunk/concordance/src/_core/__init__.c =================================================================== --- trunk/concordance/src/_core/__init__.c 2009-03-04 04:34:46 UTC (rev 1540) +++ trunk/concordance/src/_core/__init__.c 2009-03-04 04:34:50 UTC (rev 1541) @@ -117,6 +117,7 @@ */ globals->queueCall = g_async_queue_new(); + /* launch _core_loop thread GThread* g_thread_create (GThreadFunc func, Modified: trunk/concordance/src/_core/step.c =================================================================== --- trunk/concordance/src/_core/step.c 2009-03-04 04:34:46 UTC (rev 1540) +++ trunk/concordance/src/_core/step.c 2009-03-04 04:34:50 UTC (rev 1541) @@ -21,26 +21,20 @@ #include "concordance._core.h" -static void -_freeQueue(concordQueueMsg* msg) { - /* free message struct and it's members +#define BREAKNULL {err = 1; break;} - gchar* g_string_free (GString *string, - gboolean free_segment); - void g_free (gpointer mem); - */ - g_free(msg->method); - g_string_free(msg->message, TRUE); - g_free(msg); -} - PyObject* concordStep() { /*\ cdef : \*/ + gint i; + gint err = 0; PyObject* output; - concordQueueMsg* popped; + concordMsg* pmsg; GTimeVal popEnd; + PyObject* temp; + PyObject* atts; + PyObject* attr; /* calculate end time to wait for next callback, 0.5 seconds ahead @@ -57,14 +51,14 @@ GTimeVal *end_time); */ Py_BEGIN_ALLOW_THREADS - popped = g_async_queue_timed_pop(globals->queueCall, &popEnd); + pmsg = g_async_queue_timed_pop(globals->queueCall, &popEnd); Py_END_ALLOW_THREADS /* return if the pop call timed out */ - if (!popped) - return; + if (!pmsg) + Py_RETURN_NONE; - /* call our handler method + /* call the appropriate Python method PyObject* PyObject_CallMethod (PyObject *o, char *method, @@ -82,69 +76,144 @@ Convert a C string and its length to a Python unicode object. If the C string pointer is NULL, the length is ignored and None is returned. */ - output = PyEval_CallMethod(popped->self, popped->method, "OU#", - popped->self, - popped->message->str, - popped->message->len); - if (!output) { - /* free message struct and exit here if callback raised an error */ - _freeQueue(popped); - return; - } + switch (pmsg->type) { + case CONCORD_MT_XMLSTART : { /*\ + cdef : \*/ + concordMsg_xmlStart* msg = (concordMsg_xmlStart*) pmsg; + + /* create a TreeBuilder if one wasn't provided */ + if (!msg->tree) { + if (!(temp = PyImport_ImportModule("xml.etree.cElementTree"))) + BREAKNULL + msg->tree = PyEval_CallMethod(temp, "TreeBuilder", ""); + Py_DECREF(temp); + if (!msg->tree) + BREAKNULL + } - /* if output is None, decref it, free message struct, and continue */ - if (output == Py_None) { - Py_DECREF(output); - _freeQueue(popped); - return; - } + /* generate attribute dict */ + atts = PyDict_New(); + if (!atts) + BREAKNULL + for (i=0; msg->atts[i]; i+=2) { + attr = PyUnicode_FromString(msg->atts[i+1]); + PyDict_SetItemString(atts, msg->atts[i], attr); + Py_DECREF(attr); + } - /* ensure output is PyUnicode_Type (since it's not None) + /* add element to tree - int PyUnicode_Check (PyObject *o); - */ - if (!PyUnicode_Check(output)) { - /* free whatever was returned and raise an error + decref return value since we don't want/need it yet. + */ + Py_DECREF(PyEval_CallMethod(msg->tree, "start", "UO", msg->name, attr)); - void Py_DECREF (PyObject *o); - void PyErr_SetString (PyObject *type, - const char *message); - */ - Py_DECREF(output); - _freeQueue(popped); - PyErr_SetString(PyExc_TypeError, - "handle must return a Unicode string or None"); - return NULL; - } + /* remove local reference to attr dict */ + Py_DECREF(attr); + break; + } - /* only use output when non-empty + case CONCORD_MT_XMLEND : { /*\ + cdef : \*/ + concordMsg_xmlEnd* msg = (concordMsg_xmlEnd*) pmsg; - Py_ssize_t PyUnicode_GetSize (PyObject *unicode); - */ - if (PyUnicode_GetSize(output)) { - /* convert unicode to utf8, reusing popped->message for response + /* end element in tree */ + temp = PyEval_CallMethod(msg->tree, "end", "U", msg->name); + if (!temp) + BREAKNULL - GString* g_string_assign (GString *string, - const gchar *rval); - */ - popped->message = g_string_assign(popped->message, - concordPyUnicodeToUTF8(output)); + /* decref return value since we don't want/need it yet */ + Py_DECREF(temp); + break; + } - /* send response with the included self-addressed stamped envelope + case CONCORD_MT_XMLCHARDATA : { /*\ + cdef : \*/ + concordMsg_xmlCharData* msg = (concordMsg_xmlCharData*) pmsg; + + /* pass character data to tree */ + temp = PyEval_CallMethod(msg->tree, "data", "U#", msg->str, msg->str_len); + if (!temp) + BREAKNULL + + /* decref return value since we don't want/need it yet.*/ + Py_DECREF(temp); + break; + } + + case CONCORD_MT_XMLCLOSE : { /*\ + cdef : \*/ + concordMsg_xmlClose* msg = (concordMsg_xmlClose*) pmsg; + + /* get root element from TreeBuilder's close */ + temp = PyEval_CallMethod(msg->tree, "close", ""); + if (!temp) + break; + + output = PyEval_CallMethod(msg->self, "xml", "O", temp); + if (!output) + BREAKNULL + + /* if output is None, decref it, free message struct, and return */ + if (output == Py_None) { + Py_DECREF(output); + break; + } + + /* if a unicode string was returned */ + if (PyUnicode_Check(output)) { /*\ + cdef : \*/ + concordMsg_xmlReturn* ret; + + /* only use output when non-empty + + Py_ssize_t PyUnicode_GetSize (PyObject *unicode); + */ + if (!PyUnicode_GetSize(output)) { + Py_DECREF(output); + break; + } + + /* build return message */ + ret = (concordMsg_xmlReturn*) g_malloc(sizeof(concordMsg_xmlReturn)); + ret->type = CONCORD_MT_XMLRETURN; + ret->data = msg->data; + ret->mesg = g_string_new(concordPyUnicodeToUTF8(output)); + + /* push return message onto return queue */ + g_async_queue_push(msg->retn, ret); + + Py_DECREF(output); + break; + } + + /* unknown output type - raise error */ + Py_DECREF(output); + PyErr_SetString(PyExc_TypeError, "bad return type from XML handler"); + BREAKNULL + } - void g_async_queue_push (GAsyncQueue *queue, - gpointer data); - */ - g_async_queue_push(popped->returnQueue, popped); + default : + PyErr_SetString(PyExc_LookupError, "unknown message type"); + BREAKNULL } - else - /* free message struct since we didn't use it */ - _freeQueue(popped); - /* free the output object + /* free message struct and it's members - void Py_DECREF (PyObject *o); + void g_free (gpointer mem); */ - Py_DECREF(output); + switch (pmsg->type) { + case CONCORD_MT_XMLSTART : + + break; + case CONCORD_MT_XMLEND : + break; + case CONCORD_MT_XMLCHARDATA : + break; + } + + /* return either NULL or None depending on BREAKNULL or break; */ + if (err) + return NULL; + Py_RETURN_NONE; } Modified: trunk/concordance/src/sockets/Client.c =================================================================== --- trunk/concordance/src/sockets/Client.c 2009-03-04 04:34:46 UTC (rev 1540) +++ trunk/concordance/src/sockets/Client.c 2009-03-04 04:34:50 UTC (rev 1541) @@ -40,6 +40,7 @@ _pySASL(PyObject* s) { /*\ cdef : \*/ socketsClient_Object* self = (socketsSocket_Object*) s; + return NULL; } @@ -157,7 +158,7 @@ (XML_Parser parser, XML_CharacterDataHandler); */ - session->pars = XML_ParserCreateNS(NULL, 32); /* space is separator*/ + session->pars = XML_ParserCreateNS(NULL, 125); /* "}" is the separator*/ XML_SetUserData(session->pars, session); XML_SetElementHandler(session->pars, _xmlStart, _xmlEnd); XML_SetCharacterDataHandler(session->pars, _xmlCharData); @@ -644,7 +645,7 @@ const gchar *delimiter, gint max_tokens); */ - element = g_strsplit(name, " ", 2); + element = g_strsplit(name, "}", 2); switch (session->depth) { /* match element by depth, namespace, and finally element name @@ -796,7 +797,7 @@ const gchar *delimiter, gint max_tokens); */ - element = g_strsplit(name, " ", 2); + element = g_strsplit(name, "}", 2); switch (session->depth) { case 0 : { _______________________________________________ PySoy-SVN mailing list PySoy-SVN@pysoy.org http://www.pysoy.org/mailman/listinfo/pysoy-svn