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

Reply via email to