gwenhywfar 4.0.3

xmlrw.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  copyright   : (C) 2007-2010 by Martin Preuss
00003  email       : martin@libchipcard.de
00004 
00005  ***************************************************************************
00006  *                                                                         *
00007  *   This library is free software; you can redistribute it and/or         *
00008  *   modify it under the terms of the GNU Lesser General Public            *
00009  *   License as published by the Free Software Foundation; either          *
00010  *   version 2.1 of the License, or (at your option) any later version.    *
00011  *                                                                         *
00012  *   This library is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00015  *   Lesser General Public License for more details.                       *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Lesser General Public      *
00018  *   License along with this library; if not, write to the Free Software   *
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00020  *   MA  02111-1307  USA                                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 
00025 /* this file is included from xml.c */
00026 
00027 
00028 
00029 int GWEN_XMLNode__WriteToStream(const GWEN_XMLNODE *n,
00030                                 GWEN_FAST_BUFFER *fb,
00031                                 uint32_t flags,
00032                                 unsigned int ind) {
00033   GWEN_XMLPROPERTY *p;
00034   GWEN_XMLNODE *c;
00035   int i;
00036   int simpleTag;
00037   int rv;
00038 
00039 #define CHECK_ERROR(rv) \
00040   if (rv<0) {\
00041     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);\
00042     return rv;\
00043   }
00044 
00045   assert(n);
00046 
00047   if (flags & GWEN_XML_FLAGS_INDENT) {
00048     for(i=0; i<ind; i++) {
00049       GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
00050       CHECK_ERROR(rv);
00051     }
00052   }
00053 
00054   simpleTag=0;
00055   if (n->type==GWEN_XMLNodeTypeTag) {
00056     if (n->data) {
00057       GWEN_FASTBUFFER_WRITEBYTE(fb, rv, '<');
00058       CHECK_ERROR(rv);
00059       GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
00060       CHECK_ERROR(rv);
00061     }
00062     else {
00063       GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "<UNKNOWN", -1);
00064       CHECK_ERROR(rv);
00065     }
00066 
00067     if (flags & GWEN_XML_FLAGS_HANDLE_NAMESPACES) {
00068       GWEN_XMLNODE_NAMESPACE *ns;
00069 
00070       ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
00071       while(ns) {
00072         const char *name;
00073         const char *url;
00074 
00075         name=GWEN_XMLNode_NameSpace_GetName(ns);
00076         url=GWEN_XMLNode_NameSpace_GetUrl(ns);
00077         GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
00078         CHECK_ERROR(rv);
00079         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "xmlns", -1);
00080         CHECK_ERROR(rv);
00081         if (name) {
00082           GWEN_FASTBUFFER_WRITEFORCED(fb, rv, ":", -1);
00083           CHECK_ERROR(rv);
00084           GWEN_FASTBUFFER_WRITEFORCED(fb, rv, name, -1);
00085           CHECK_ERROR(rv);
00086         }
00087         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "=\"", -1);
00088         CHECK_ERROR(rv);
00089         if (url) {
00090           GWEN_FASTBUFFER_WRITEFORCED(fb, rv, url, -1);
00091           CHECK_ERROR(rv);
00092         }
00093         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "\"", -1);
00094         CHECK_ERROR(rv);
00095 
00096         ns=GWEN_XMLNode_NameSpace_List_Next(ns);
00097       }
00098     }
00099 
00100     p=n->properties;
00101     while (p) {
00102       GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
00103       CHECK_ERROR(rv);
00104       GWEN_FASTBUFFER_WRITEFORCED(fb, rv, p->name, -1);
00105       CHECK_ERROR(rv);
00106       if (p->value) {
00107         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "=\"", -1);
00108         CHECK_ERROR(rv);
00109         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, p->value, -1);
00110         CHECK_ERROR(rv);
00111         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "\"", -1);
00112         CHECK_ERROR(rv);
00113       }
00114       p=p->next;
00115     }
00116 
00117     if (n->data) {
00118       if (n->data[0]=='?') {
00119         simpleTag=1;
00120         GWEN_FASTBUFFER_WRITEBYTE(fb, rv, '?');
00121         CHECK_ERROR(rv);
00122       }
00123       else if (n->data[0]=='!') {
00124         simpleTag=1;
00125       }
00126     }
00127 
00128     GWEN_FASTBUFFER_WRITELINE(fb, rv, ">");
00129     CHECK_ERROR(rv);
00130     if (!simpleTag) {
00131       c=GWEN_XMLNode_GetChild(n);
00132       while(c) {
00133         rv=GWEN_XMLNode__WriteToStream(c, fb, flags, ind+2);
00134         CHECK_ERROR(rv);
00135         c=GWEN_XMLNode_Next(c);
00136       }
00137       if (flags & GWEN_XML_FLAGS_INDENT) {
00138         for(i=0; i<ind; i++) {
00139           GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
00140           CHECK_ERROR(rv);
00141         }
00142       }
00143       if (n->data) {
00144         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "</", -1);
00145         CHECK_ERROR(rv);
00146         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
00147         CHECK_ERROR(rv);
00148         GWEN_FASTBUFFER_WRITELINE(fb, rv, ">");
00149         CHECK_ERROR(rv);
00150       }
00151       else {
00152         GWEN_FASTBUFFER_WRITELINE(fb, rv, "</UNKNOWN>");
00153         CHECK_ERROR(rv);
00154       }
00155     }
00156   }
00157   else if (n->type==GWEN_XMLNodeTypeData) {
00158     if (n->data) {
00159       GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
00160       CHECK_ERROR(rv);
00161       GWEN_FASTBUFFER_WRITELINE(fb, rv, "");
00162       CHECK_ERROR(rv);
00163     }
00164   }
00165   else if (n->type==GWEN_XMLNodeTypeComment) {
00166     if (flags & GWEN_XML_FLAGS_HANDLE_COMMENTS) {
00167       GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "<!--", -1);
00168       CHECK_ERROR(rv);
00169       if (n->data) {
00170         GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
00171         CHECK_ERROR(rv);
00172       }
00173       GWEN_FASTBUFFER_WRITELINE(fb, rv, "-->");
00174       CHECK_ERROR(rv);
00175     }
00176   }
00177   else {
00178     DBG_ERROR(GWEN_LOGDOMAIN, "Unknown tag type (%d)", n->type);
00179   }
00180 
00181   return 0;
00182 #undef CHECK_ERROR
00183 }
00184 
00185 
00186 
00187 int GWEN_XMLNode_WriteToStream(const GWEN_XMLNODE *n,
00188                                GWEN_XML_CONTEXT *ctx,
00189                                GWEN_SYNCIO *sio){
00190   const GWEN_XMLNODE *nn;
00191   const GWEN_XMLNODE *nchild;
00192   const GWEN_XMLNODE *nheader;
00193   uint32_t flags;
00194   GWEN_FAST_BUFFER *fb;
00195   int rv;
00196 
00197   flags=GWEN_XmlCtx_GetFlags(ctx);
00198   nchild=GWEN_XMLNode_GetChild(n);
00199   nheader=GWEN_XMLNode_GetHeader(n);
00200 
00201   fb=GWEN_FastBuffer_new(512, sio);
00202 
00203   if (nheader && (flags & GWEN_XML_FLAGS_HANDLE_HEADERS)) {
00204     uint32_t lflags;
00205 
00206     lflags=flags & ~GWEN_XML_FLAGS_HANDLE_HEADERS;
00207     nn=nheader;
00208     while(nn) {
00209       const GWEN_XMLNODE *next;
00210 
00211       rv=GWEN_XMLNode__WriteToStream(nn, fb, GWEN_XmlCtx_GetFlags(ctx), 0);
00212       if (rv<0) {
00213         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00214         GWEN_FastBuffer_free(fb);
00215         return rv;
00216       }
00217       next=GWEN_XMLNode_Next(nn);
00218       if (next) {
00219         int err;
00220 
00221         GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00222         if (err<0) {
00223           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00224           GWEN_FastBuffer_free(fb);
00225           return err;
00226         }
00227       }
00228 
00229       nn=next;
00230     }
00231 
00232     if (nchild) {
00233       int err;
00234 
00235       GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00236       if (err<0) {
00237         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00238         GWEN_FastBuffer_free(fb);
00239         return err;
00240       }
00241     }
00242   }
00243 
00244   nn=nchild;
00245   while(nn) {
00246     const GWEN_XMLNODE *next;
00247 
00248     if (GWEN_XMLNode__WriteToStream(nn, fb, GWEN_XmlCtx_GetFlags(ctx), 0))
00249       return -1;
00250     next=GWEN_XMLNode_Next(nn);
00251     if (next) {
00252       int err;
00253 
00254       GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00255       if (err<0) {
00256         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00257         GWEN_FastBuffer_free(fb);
00258         return err;
00259       }
00260     }
00261 
00262     nn=next;
00263   } /* while */
00264 
00265   GWEN_FASTBUFFER_FLUSH(fb, rv);
00266   if (rv<0) {
00267     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00268     GWEN_FastBuffer_free(fb);
00269     return rv;
00270   }
00271   GWEN_FastBuffer_free(fb);
00272 
00273   return 0;
00274 }
00275 
00276 
00277 
00278 int GWEN_XMLNode_WriteFile(const GWEN_XMLNODE *n,
00279                            const char *fname,
00280                            uint32_t flags){
00281   GWEN_XML_CONTEXT *ctx;
00282   GWEN_SYNCIO *sio;
00283   int rv;
00284 
00285   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateAlways);
00286   rv=GWEN_SyncIo_Connect(sio);
00287   if (rv<0) {
00288     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00289     GWEN_SyncIo_free(sio);
00290     return rv;
00291   }
00292 
00293   /* create context and io layers */
00294   ctx=GWEN_XmlCtxStore_new(NULL, flags);
00295 
00296   /* write data to stream */
00297   rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
00298   if (rv<0) {
00299     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00300     GWEN_SyncIo_Disconnect(sio);
00301     GWEN_SyncIo_free(sio);
00302     GWEN_XmlCtx_free(ctx);
00303     return rv;
00304   }
00305 
00306   /* close file */
00307   GWEN_SyncIo_Disconnect(sio);
00308   GWEN_SyncIo_free(sio);
00309 
00310   GWEN_XmlCtx_free(ctx);
00311 
00312   return 0;
00313 }
00314 
00315 
00316 
00317 int GWEN_XMLNode_toBuffer(const GWEN_XMLNODE *n, GWEN_BUFFER *buf, uint32_t flags){
00318   GWEN_XML_CONTEXT *ctx;
00319   GWEN_SYNCIO *sio;
00320   int rv;
00321 
00322   sio=GWEN_SyncIo_Memory_new(buf, 0);
00323 
00324   /* create context and io layers */
00325   ctx=GWEN_XmlCtxStore_new(NULL, flags);
00326 
00327   /* write data to stream */
00328   rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
00329   if (rv<0) {
00330     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00331     GWEN_SyncIo_free(sio);
00332     GWEN_XmlCtx_free(ctx);
00333     return rv;
00334   }
00335 
00336   GWEN_SyncIo_free(sio);
00337 
00338   GWEN_XmlCtx_free(ctx);
00339 
00340   return 0;
00341 }
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 int GWEN_XML__ReadData(GWEN_XML_CONTEXT *ctx,
00351                        GWEN_FAST_BUFFER *fb,
00352                        GWEN_UNUSED uint32_t flags){
00353   int chr;
00354   unsigned char uc;
00355   GWEN_BUFFER *dbuf;
00356 
00357   dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00358 
00359   for (;;) {
00360     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00361     if (chr<0) {
00362       if (chr==GWEN_ERROR_EOF)
00363         break;
00364       else {
00365         GWEN_Buffer_free(dbuf);
00366         return chr;
00367       }
00368     }
00369 
00370     uc=(unsigned char) chr;
00371     if (uc=='<')
00372       break;
00373     fb->bufferReadPos++;
00374     GWEN_Buffer_AppendByte(dbuf, uc);
00375   }
00376 
00377   if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00378     int rv;
00379     const char *s;
00380 
00381     s=GWEN_Buffer_GetStart(dbuf);
00382     if (*s) {
00383       rv=GWEN_XmlCtx_AddData(ctx, s);
00384       if (rv) {
00385         GWEN_Buffer_free(dbuf);
00386         return rv;
00387       }
00388     }
00389   }
00390   GWEN_Buffer_free(dbuf);
00391 
00392   return 0;
00393 }
00394 
00395 
00396 
00397 int GWEN_XML__ReadTag(GWEN_XML_CONTEXT *ctx,
00398                       GWEN_FAST_BUFFER *fb,
00399                       GWEN_UNUSED uint32_t flags,
00400                       GWEN_BUFFER *dbuf){
00401   int chr;
00402   unsigned char uc=0;
00403   int rv;
00404 
00405   /* skip blanks */
00406   for (;;) {
00407     GWEN_FASTBUFFER_READBYTE(fb, chr);
00408     if (chr<0) {
00409       return chr;
00410     }
00411     uc=(unsigned char) chr;
00412     if (uc>32)
00413       break;
00414   }
00415 
00416   if (uc=='/') {
00417     /* read end tag */
00418     GWEN_Buffer_AppendByte(dbuf, uc);
00419     for (;;) {
00420       GWEN_FASTBUFFER_READBYTE(fb, chr);
00421       if (chr<0) {
00422         return chr;
00423       }
00424       uc=(unsigned char) chr;
00425       if (uc=='>' || uc<33)
00426         break;
00427 
00428       GWEN_Buffer_AppendByte(dbuf, uc);
00429     }
00430 
00431     rv=GWEN_XmlCtx_StartTag(ctx, GWEN_Buffer_GetStart(dbuf));
00432     if (rv) {
00433       return rv;
00434     }
00435     if (uc!='>') {
00436       for (;;) {
00437         /* skip blanks, expect '>' */
00438         GWEN_FASTBUFFER_READBYTE(fb, chr);
00439         if (chr<0) {
00440           return chr;
00441         }
00442         uc=(unsigned char) chr;
00443         if (uc>32)
00444           break;
00445       }
00446     }
00447     if (uc!='>') {
00448       DBG_ERROR(GWEN_LOGDOMAIN, "Unexpected character");
00449       return GWEN_ERROR_BAD_DATA;
00450     }
00451 
00452     /* tag finished */
00453     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00454     if (rv) {
00455       return rv;
00456     }
00457     return 0;
00458   }
00459   else if (uc=='!') {
00460     /* check for comment */
00461     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00462     if (chr<0) {
00463       return chr;
00464     }
00465     uc=(unsigned char) chr;
00466     if (uc=='-') {
00467       fb->bufferReadPos++;
00468       GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00469       if (chr<0) {
00470         return chr;
00471       }
00472       uc=(unsigned char) chr;
00473       if (uc=='-') {
00474         GWEN_BUFFER *cbuf;
00475 
00476         /* found comment */
00477         fb->bufferReadPos++;
00478         cbuf=GWEN_Buffer_new(0, 256, 0, 1);
00479         for (;;) {
00480           GWEN_FASTBUFFER_READBYTE(fb, chr);
00481           if (chr<0) {
00482             GWEN_Buffer_free(cbuf);
00483             return chr;
00484           }
00485           uc=(unsigned char) chr;
00486           GWEN_Buffer_AppendByte(cbuf, uc);
00487           if (GWEN_Buffer_GetUsedBytes(cbuf)>2) {
00488             char *p;
00489 
00490             p=GWEN_Buffer_GetStart(cbuf);
00491             p+=GWEN_Buffer_GetUsedBytes(cbuf)-3;
00492             if (strcmp(p, "-->")==0) {
00493               *p=0;
00494               rv=GWEN_XmlCtx_AddComment(ctx, GWEN_Buffer_GetStart(cbuf));
00495               if (rv) {
00496                 GWEN_Buffer_free(cbuf);
00497                 return rv;
00498               }
00499               GWEN_Buffer_free(cbuf);
00500               return 0;
00501             }
00502           }
00503         }
00504       }
00505       else {
00506         GWEN_Buffer_AppendString(dbuf, "!-");
00507       }
00508     }
00509     else
00510       uc='!';
00511   }
00512 
00513   /* read name */
00514   for (;;) {
00515     if (uc==' ' || uc=='>' || uc=='/')
00516       break;
00517     else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00518       unsigned char fc;
00519 
00520       fc=*GWEN_Buffer_GetStart(dbuf);
00521       if ((fc=='!' && uc=='!') || (fc=='?' && uc=='?')) {
00522         GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00523         if (chr<0) {
00524           return chr;
00525         }
00526         uc=(unsigned char) chr;
00527         if (uc=='>') {
00528           fb->bufferReadPos++;
00529           break;
00530         }
00531       }
00532     }
00533 
00534     GWEN_Buffer_AppendByte(dbuf, uc);
00535 
00536     GWEN_FASTBUFFER_READBYTE(fb, chr);
00537     if (chr<0) {
00538       if (chr==GWEN_ERROR_EOF) {
00539         return chr;
00540       }
00541       else {
00542         return chr;
00543       }
00544     }
00545 
00546     uc=(unsigned char) chr;
00547   }
00548 
00549   /* tag started */
00550   if (GWEN_Buffer_GetUsedBytes(dbuf)==0) {
00551     DBG_ERROR(GWEN_LOGDOMAIN, "Element name missing");
00552     return GWEN_ERROR_BAD_DATA;
00553   }
00554 
00555   rv=GWEN_XmlCtx_StartTag(ctx, GWEN_Buffer_GetStart(dbuf));
00556   if (rv) {
00557     return rv;
00558   }
00559 
00560   if (uc=='/' || uc=='?' || uc=='!') {
00561     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00562     if (chr<0) {
00563       return chr;
00564     }
00565     uc=(unsigned char) chr;
00566     if (uc=='>') {
00567       fb->bufferReadPos++;
00568       rv=GWEN_XmlCtx_EndTag(ctx, 1);
00569       if (rv) {
00570         return rv;
00571       }
00572       /* tag finished */
00573       return 0;
00574     }
00575   }
00576 
00577   if (uc=='>') {
00578     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00579     if (rv) {
00580       return rv;
00581     }
00582     /* tag finished */
00583     return 0;
00584   }
00585 
00586   /* read attributes */
00587   for (;;) {
00588     GWEN_BUFFER *nbuf;
00589     GWEN_BUFFER *vbuf=NULL;
00590 
00591     nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00592 
00593     /* skip blanks */
00594     for (;;) {
00595       GWEN_FASTBUFFER_READBYTE(fb, chr);
00596       if (chr<0) {
00597         GWEN_Buffer_free(nbuf);
00598         return chr;
00599       }
00600       uc=(unsigned char) chr;
00601       if (uc>32)
00602         break;
00603     }
00604 
00605     /* read attribute name */
00606     for (;;) {
00607       if (uc=='/' || uc=='!' || uc=='?' || uc=='=' || uc=='>')
00608         break;
00609       GWEN_Buffer_AppendByte(nbuf, uc);
00610 
00611       GWEN_FASTBUFFER_READBYTE(fb, chr);
00612       if (chr<0) {
00613         GWEN_Buffer_free(nbuf);
00614         return chr;
00615       }
00616       uc=(unsigned char) chr;
00617     }
00618 
00619     if (GWEN_Buffer_GetUsedBytes(nbuf)) {
00620       if (uc=='=') {
00621         /* read attribute value if there is an equation mark */
00622         int inQuote=0;
00623   
00624         vbuf=GWEN_Buffer_new(0, 256, 0, 1);
00625         for (;;) {
00626           GWEN_FASTBUFFER_READBYTE(fb, chr);
00627           if (chr<0) {
00628             GWEN_Buffer_free(nbuf);
00629             return chr;
00630           }
00631           uc=(unsigned char) chr;
00632           if (uc=='"') {
00633             if (inQuote) {
00634               inQuote=0;
00635               break;
00636             }
00637             else
00638               inQuote=1;
00639           }
00640           else {
00641             if (!inQuote) {
00642               if (uc=='>' || uc<33)
00643                 break;
00644               else if (uc=='<') {
00645                 DBG_ERROR(GWEN_LOGDOMAIN,
00646                           "Nested element definitions");
00647                 GWEN_Buffer_free(vbuf);
00648                 GWEN_Buffer_free(nbuf);
00649                 return GWEN_ERROR_BAD_DATA;
00650               }
00651               else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00652                 if (uc=='/' || uc=='!' || uc=='?') {
00653                   unsigned char tc;
00654 
00655                   GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00656                   if (chr<0) {
00657                     GWEN_Buffer_free(vbuf);
00658                     GWEN_Buffer_free(nbuf);
00659                     return chr;
00660                   }
00661                   tc=(unsigned char) chr;
00662                   if (tc=='>') {
00663                     break;
00664                   }
00665                 }
00666               }
00667             }
00668             GWEN_Buffer_AppendByte(vbuf, uc);
00669           }
00670         }
00671         if (inQuote) {
00672           DBG_ERROR(GWEN_LOGDOMAIN, "No matching number of quote chars");
00673           GWEN_Buffer_free(vbuf);
00674           GWEN_Buffer_free(nbuf);
00675           return GWEN_ERROR_BAD_DATA;
00676         }
00677 
00678         if (GWEN_Buffer_GetUsedBytes(vbuf)==0) {
00679           GWEN_Buffer_free(vbuf);
00680           vbuf=NULL;
00681         }
00682       }
00683       rv=GWEN_XmlCtx_AddAttr(ctx,
00684                              GWEN_Buffer_GetStart(nbuf),
00685                              vbuf?GWEN_Buffer_GetStart(vbuf):NULL);
00686       if (rv) {
00687         GWEN_Buffer_free(vbuf);
00688         GWEN_Buffer_free(nbuf);
00689         return rv;
00690       }
00691     }
00692 
00693     GWEN_Buffer_free(vbuf);
00694     GWEN_Buffer_free(nbuf);
00695 
00696     if (uc=='>' || uc=='?' || uc=='!' || uc=='/')
00697       break;
00698   }
00699 
00700   if (uc=='?' || uc=='!' || uc=='/') {
00701     unsigned char ucsave=uc;
00702 
00703     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00704     if (chr<0) {
00705       return chr;
00706     }
00707     uc=(unsigned char) chr;
00708     if (uc=='>') {
00709       DBG_VERBOUS(GWEN_LOGDOMAIN, "Ending tag [%s]", GWEN_Buffer_GetStart(dbuf));
00710       fb->bufferReadPos++;
00711       rv=GWEN_XmlCtx_EndTag(ctx, 1);
00712       if (rv) {
00713         return rv;
00714       }
00715       /* tag finished */
00716       return 0;
00717     }
00718     else {
00719       DBG_ERROR(GWEN_LOGDOMAIN,
00720                 "Got an unexpected character here (after %02x[%c]): %02x[%c], "
00721                 "maybe the text contains unescaped XML characters?",
00722                 ucsave, ucsave, uc, uc);
00723     }
00724   }
00725   else if (uc=='>') {
00726     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00727     if (rv) {
00728       return rv;
00729     }
00730     /* tag finished */
00731     return 0;
00732   }
00733 
00734   DBG_ERROR(GWEN_LOGDOMAIN,
00735             "Internal error: Should never reach this point");
00736   return GWEN_ERROR_INTERNAL;
00737 }
00738 
00739 
00740 
00741 
00742 int GWEN_XML_ReadFromFastBuffer(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb){
00743   int oks=0;
00744   int startingDepth;
00745   GWEN_BUFFER *workBuf;
00746 
00747   startingDepth=GWEN_XmlCtx_GetDepth(ctx);
00748 
00749   workBuf=GWEN_Buffer_new(0, 256, 0, 1);
00750   GWEN_XmlCtx_ResetFinishedElement(ctx);
00751   for (;;) {
00752     int rv;
00753 
00754     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00755     if (rv<0) {
00756       if (rv!=GWEN_ERROR_EOF || !oks) {
00757         DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d), after reading %d bytes",
00758                   rv, (int) GWEN_FastBuffer_GetBytesRead(fb));
00759         GWEN_Buffer_free(workBuf);
00760         return rv;
00761       }
00762       GWEN_Buffer_free(workBuf);
00763       return 0;
00764     }
00765 
00766     rv=GWEN_XML__ReadData(ctx, fb, GWEN_XmlCtx_GetFlags(ctx));
00767     if (rv) {
00768       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00769       GWEN_Buffer_free(workBuf);
00770       return rv;
00771     }
00772     oks=1;
00773 
00774     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00775     if (rv<0) {
00776       if (rv!=GWEN_ERROR_EOF || !oks ||
00777           (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth)) {
00778         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00779         GWEN_Buffer_free(workBuf);
00780         return rv;
00781       }
00782       return 0;
00783     }
00784     else if (rv=='<') {
00785       fb->bufferReadPos++;
00786       rv=GWEN_XML__ReadTag(ctx, fb, GWEN_XmlCtx_GetFlags(ctx), workBuf);
00787       if (rv) {
00788         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00789         GWEN_Buffer_free(workBuf);
00790         return rv;
00791       }
00792       GWEN_Buffer_Reset(workBuf);
00793       oks=1;
00794     }
00795 
00796     if (GWEN_XmlCtx_GetFinishedElement(ctx) &&
00797         GWEN_XmlCtx_GetDepth(ctx)==startingDepth)
00798       break;
00799   }
00800 
00801   if (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth) {
00802     DBG_ERROR(GWEN_LOGDOMAIN,
00803               "Not on same level where we started...(%d!=%d)",
00804               GWEN_XmlCtx_GetDepth(ctx), startingDepth);
00805   }
00806   GWEN_Buffer_free(workBuf);
00807 
00808   return 0;
00809 }
00810 
00811 
00812 
00813 int GWEN_XML__ReadAllFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio){
00814   GWEN_FAST_BUFFER *fb;
00815   int oks=0;
00816 
00817   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE, sio);
00818   assert(fb);
00819   for (;;) {
00820     int rv;
00821 
00822     rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00823     if (rv<0) {
00824       if (rv==GWEN_ERROR_EOF && oks)
00825         break;
00826       else {
00827         DBG_INFO(GWEN_LOGDOMAIN, "here");
00828         GWEN_FastBuffer_free(fb);
00829         return rv;
00830       }
00831     }
00832     oks=1;
00833   }
00834 
00835   GWEN_FastBuffer_free(fb);
00836   return 0;
00837 }
00838 
00839 
00840 
00841 int GWEN_XMLContext_ReadFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio){
00842 #if 0
00843   GWEN_FAST_BUFFER *fb;
00844   int rv;
00845 
00846   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE, sio);
00847   assert(fb);
00848   rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00849   if (rv) {
00850     DBG_INFO(GWEN_LOGDOMAIN, "here");
00851     GWEN_FastBuffer_free(fb);
00852     return rv;
00853   }
00854 
00855   GWEN_FastBuffer_free(fb);
00856   return 0;
00857 #else
00858   int rv;
00859 
00860   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00861   if (rv<0) {
00862     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00863     return rv;
00864   }
00865 
00866   return rv;
00867 #endif
00868 }
00869 
00870 
00871 
00872 int GWEN_XMLContext_ReadFromFile(GWEN_XML_CONTEXT *ctx, const char *fname) {
00873   GWEN_SYNCIO *sio;
00874   int rv;
00875 
00876   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00877   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00878   rv=GWEN_SyncIo_Connect(sio);
00879   if (rv<0) {
00880     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00881     GWEN_SyncIo_free(sio);
00882     return rv;
00883   }
00884 
00885   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00886   if (rv<0) {
00887     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00888     GWEN_SyncIo_Disconnect(sio);
00889     GWEN_SyncIo_free(sio);
00890     return rv;
00891   }
00892 
00893   GWEN_SyncIo_Disconnect(sio);
00894   GWEN_SyncIo_free(sio);
00895 
00896   return 0;
00897 }
00898 
00899 
00900 
00901 int GWEN_XMLContext_ReadFromString(GWEN_XML_CONTEXT *ctx, const char *text) {
00902   if (text && *text) {
00903     GWEN_SYNCIO *sio;
00904     int rv;
00905     GWEN_BUFFER *tbuf;
00906     int i;
00907 
00908     i=strlen(text)+1;
00909     tbuf=GWEN_Buffer_new((char*)text, i, i, 0);
00910     /* static buffer, don't resize */
00911     GWEN_Buffer_SubMode(tbuf, GWEN_BUFFER_MODE_DYNAMIC);
00912     GWEN_Buffer_AddMode(tbuf, GWEN_BUFFER_MODE_READONLY);
00913     sio=GWEN_SyncIo_Memory_new(tbuf, 0);
00914 
00915     rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00916     if (rv<0) {
00917       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00918       GWEN_SyncIo_free(sio);
00919       GWEN_Buffer_free(tbuf);
00920       return rv;
00921     }
00922 
00923     GWEN_SyncIo_free(sio);
00924     GWEN_Buffer_free(tbuf);
00925   }
00926   return 0;
00927 }
00928 
00929 
00930 
00931 
00932 int GWEN_XML_ReadFile(GWEN_XMLNODE *n, const char *filepath, uint32_t flags) {
00933   GWEN_XML_CONTEXT *ctx;
00934   GWEN_SYNCIO *sio;
00935   int rv;
00936 
00937   sio=GWEN_SyncIo_File_new(filepath, GWEN_SyncIo_File_CreationMode_OpenExisting);
00938   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00939   rv=GWEN_SyncIo_Connect(sio);
00940   if (rv<0) {
00941     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00942     GWEN_SyncIo_free(sio);
00943     return rv;
00944   }
00945 
00946   ctx=GWEN_XmlCtxStore_new(n, flags);
00947   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00948   if (rv<0) {
00949     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00950     GWEN_SyncIo_Disconnect(sio);
00951     GWEN_SyncIo_free(sio);
00952     GWEN_XmlCtx_free(ctx);
00953     return rv;
00954   }
00955 
00956   GWEN_SyncIo_Disconnect(sio);
00957   GWEN_SyncIo_free(sio);
00958 
00959   GWEN_XmlCtx_free(ctx);
00960 
00961   return 0;
00962 }
00963 
00964 
00965 
00966 GWEN_XMLNODE *GWEN_XMLNode_fromString(const char *s, int len, uint32_t flags) {
00967 #if 0
00968   GWEN_XML_CONTEXT *ctx;
00969   GWEN_SYNCIO *sio;
00970   GWEN_XMLNODE *n;
00971   int rv;
00972 
00973   if (len==0)
00974     len=strlen(s);
00975   sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*)s, len);
00976 
00977   n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "doc");
00978   ctx=GWEN_XmlCtxStore_new(n, flags);
00979   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00980   if (rv<0) {
00981     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00982     GWEN_SyncIo_free(sio);
00983     GWEN_XmlCtx_free(ctx);
00984     GWEN_XMLNode_free(n);
00985     return NULL;
00986   }
00987 
00988   GWEN_SyncIo_free(sio);
00989 
00990   GWEN_XmlCtx_free(ctx);
00991 
00992   return n;
00993 #else
00994   GWEN_XML_CONTEXT *ctx;
00995   GWEN_SYNCIO *sio;
00996   GWEN_XMLNODE *n;
00997   int rv;
00998   GWEN_BUFFER *tbuf;
00999 
01000   tbuf=GWEN_Buffer_new((char*)s, len, len, 0);
01001   /* static buffer, don't resize */
01002   GWEN_Buffer_SubMode(tbuf, GWEN_BUFFER_MODE_DYNAMIC);
01003   GWEN_Buffer_AddMode(tbuf, GWEN_BUFFER_MODE_READONLY);
01004   sio=GWEN_SyncIo_Memory_new(tbuf, 0);
01005 
01006   n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "doc");
01007   ctx=GWEN_XmlCtxStore_new(n, flags);
01008   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
01009   if (rv<0) {
01010     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01011     GWEN_XmlCtx_free(ctx);
01012     GWEN_XMLNode_free(n);
01013     GWEN_SyncIo_free(sio);
01014     GWEN_Buffer_free(tbuf);
01015     return NULL;
01016   }
01017 
01018   GWEN_XmlCtx_free(ctx);
01019   GWEN_SyncIo_free(sio);
01020   GWEN_Buffer_free(tbuf);
01021 
01022   return n;
01023 #endif
01024 }
01025 
01026 
01027 
01028