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   GWEN_SyncIo_AddFlags(sio,
00287                        GWEN_SYNCIO_FILE_FLAGS_READ | GWEN_SYNCIO_FILE_FLAGS_WRITE |
00288                        GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE);
00289   rv=GWEN_SyncIo_Connect(sio);
00290   if (rv<0) {
00291     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00292     GWEN_SyncIo_free(sio);
00293     return rv;
00294   }
00295 
00296   /* create context and io layers */
00297   ctx=GWEN_XmlCtxStore_new(NULL, flags);
00298 
00299   /* write data to stream */
00300   rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
00301   if (rv<0) {
00302     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00303     GWEN_SyncIo_Disconnect(sio);
00304     GWEN_SyncIo_free(sio);
00305     GWEN_XmlCtx_free(ctx);
00306     return rv;
00307   }
00308 
00309   /* close file */
00310   GWEN_SyncIo_Disconnect(sio);
00311   GWEN_SyncIo_free(sio);
00312 
00313   GWEN_XmlCtx_free(ctx);
00314 
00315   return 0;
00316 }
00317 
00318 
00319 
00320 int GWEN_XMLNode_toBuffer(const GWEN_XMLNODE *n, GWEN_BUFFER *buf, uint32_t flags){
00321   GWEN_XML_CONTEXT *ctx;
00322   GWEN_SYNCIO *sio;
00323   int rv;
00324 
00325   sio=GWEN_SyncIo_Memory_new(buf, 0);
00326 
00327   /* create context and io layers */
00328   ctx=GWEN_XmlCtxStore_new(NULL, flags);
00329 
00330   /* write data to stream */
00331   rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
00332   if (rv<0) {
00333     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00334     GWEN_SyncIo_free(sio);
00335     GWEN_XmlCtx_free(ctx);
00336     return rv;
00337   }
00338 
00339   GWEN_SyncIo_free(sio);
00340 
00341   GWEN_XmlCtx_free(ctx);
00342 
00343   return 0;
00344 }
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 int GWEN_XML__ReadData(GWEN_XML_CONTEXT *ctx,
00354                        GWEN_FAST_BUFFER *fb,
00355                        GWEN_UNUSED uint32_t flags){
00356   int chr;
00357   unsigned char uc;
00358   GWEN_BUFFER *dbuf;
00359 
00360   dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00361 
00362   for (;;) {
00363     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00364     if (chr<0) {
00365       if (chr==GWEN_ERROR_EOF)
00366         break;
00367       else {
00368         GWEN_Buffer_free(dbuf);
00369         return chr;
00370       }
00371     }
00372 
00373     uc=(unsigned char) chr;
00374     if (uc=='<')
00375       break;
00376     fb->bufferReadPos++;
00377     GWEN_Buffer_AppendByte(dbuf, uc);
00378   }
00379 
00380   if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00381     int rv;
00382     const char *s;
00383 
00384     s=GWEN_Buffer_GetStart(dbuf);
00385     if (*s) {
00386       rv=GWEN_XmlCtx_AddData(ctx, s);
00387       if (rv) {
00388         GWEN_Buffer_free(dbuf);
00389         return rv;
00390       }
00391     }
00392   }
00393   GWEN_Buffer_free(dbuf);
00394 
00395   return 0;
00396 }
00397 
00398 
00399 
00400 int GWEN_XML__ReadTag(GWEN_XML_CONTEXT *ctx,
00401                       GWEN_FAST_BUFFER *fb,
00402                       GWEN_UNUSED uint32_t flags,
00403                       GWEN_BUFFER *dbuf){
00404   int chr;
00405   unsigned char uc=0;
00406   int rv;
00407 
00408   /* skip blanks */
00409   for (;;) {
00410     GWEN_FASTBUFFER_READBYTE(fb, chr);
00411     if (chr<0) {
00412       return chr;
00413     }
00414     uc=(unsigned char) chr;
00415     if (uc>32)
00416       break;
00417   }
00418 
00419   if (uc=='/') {
00420     /* read end tag */
00421     GWEN_Buffer_AppendByte(dbuf, uc);
00422     for (;;) {
00423       GWEN_FASTBUFFER_READBYTE(fb, chr);
00424       if (chr<0) {
00425         return chr;
00426       }
00427       uc=(unsigned char) chr;
00428       if (uc=='>' || uc<33)
00429         break;
00430 
00431       GWEN_Buffer_AppendByte(dbuf, uc);
00432     }
00433 
00434     rv=GWEN_XmlCtx_StartTag(ctx, GWEN_Buffer_GetStart(dbuf));
00435     if (rv) {
00436       return rv;
00437     }
00438     if (uc!='>') {
00439       for (;;) {
00440         /* skip blanks, expect '>' */
00441         GWEN_FASTBUFFER_READBYTE(fb, chr);
00442         if (chr<0) {
00443           return chr;
00444         }
00445         uc=(unsigned char) chr;
00446         if (uc>32)
00447           break;
00448       }
00449     }
00450     if (uc!='>') {
00451       DBG_ERROR(GWEN_LOGDOMAIN, "Unexpected character");
00452       return GWEN_ERROR_BAD_DATA;
00453     }
00454 
00455     /* tag finished */
00456     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00457     if (rv) {
00458       return rv;
00459     }
00460     return 0;
00461   }
00462   else if (uc=='!') {
00463     /* check for comment */
00464     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00465     if (chr<0) {
00466       return chr;
00467     }
00468     uc=(unsigned char) chr;
00469     if (uc=='-') {
00470       fb->bufferReadPos++;
00471       GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00472       if (chr<0) {
00473         return chr;
00474       }
00475       uc=(unsigned char) chr;
00476       if (uc=='-') {
00477         GWEN_BUFFER *cbuf;
00478 
00479         /* found comment */
00480         fb->bufferReadPos++;
00481         cbuf=GWEN_Buffer_new(0, 256, 0, 1);
00482         for (;;) {
00483           GWEN_FASTBUFFER_READBYTE(fb, chr);
00484           if (chr<0) {
00485             GWEN_Buffer_free(cbuf);
00486             return chr;
00487           }
00488           uc=(unsigned char) chr;
00489           GWEN_Buffer_AppendByte(cbuf, uc);
00490           if (GWEN_Buffer_GetUsedBytes(cbuf)>2) {
00491             char *p;
00492 
00493             p=GWEN_Buffer_GetStart(cbuf);
00494             p+=GWEN_Buffer_GetUsedBytes(cbuf)-3;
00495             if (strcmp(p, "-->")==0) {
00496               *p=0;
00497               rv=GWEN_XmlCtx_AddComment(ctx, GWEN_Buffer_GetStart(cbuf));
00498               if (rv) {
00499                 GWEN_Buffer_free(cbuf);
00500                 return rv;
00501               }
00502               GWEN_Buffer_free(cbuf);
00503               return 0;
00504             }
00505           }
00506         }
00507       }
00508       else {
00509         GWEN_Buffer_AppendString(dbuf, "!-");
00510       }
00511     }
00512     else
00513       uc='!';
00514   }
00515 
00516   /* read name */
00517   for (;;) {
00518     if (uc==' ' || uc=='>' || uc=='/')
00519       break;
00520     else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00521       unsigned char fc;
00522 
00523       fc=*GWEN_Buffer_GetStart(dbuf);
00524       if ((fc=='!' && uc=='!') || (fc=='?' && uc=='?')) {
00525         GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00526         if (chr<0) {
00527           return chr;
00528         }
00529         uc=(unsigned char) chr;
00530         if (uc=='>') {
00531           fb->bufferReadPos++;
00532           break;
00533         }
00534       }
00535     }
00536 
00537     GWEN_Buffer_AppendByte(dbuf, uc);
00538 
00539     GWEN_FASTBUFFER_READBYTE(fb, chr);
00540     if (chr<0) {
00541       if (chr==GWEN_ERROR_EOF) {
00542         return chr;
00543       }
00544       else {
00545         return chr;
00546       }
00547     }
00548 
00549     uc=(unsigned char) chr;
00550   }
00551 
00552   /* tag started */
00553   if (GWEN_Buffer_GetUsedBytes(dbuf)==0) {
00554     DBG_ERROR(GWEN_LOGDOMAIN, "Element name missing");
00555     return GWEN_ERROR_BAD_DATA;
00556   }
00557 
00558   rv=GWEN_XmlCtx_StartTag(ctx, GWEN_Buffer_GetStart(dbuf));
00559   if (rv) {
00560     return rv;
00561   }
00562 
00563   if (uc=='/' || uc=='?' || uc=='!') {
00564     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00565     if (chr<0) {
00566       return chr;
00567     }
00568     uc=(unsigned char) chr;
00569     if (uc=='>') {
00570       fb->bufferReadPos++;
00571       rv=GWEN_XmlCtx_EndTag(ctx, 1);
00572       if (rv) {
00573         return rv;
00574       }
00575       /* tag finished */
00576       return 0;
00577     }
00578   }
00579 
00580   if (uc=='>') {
00581     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00582     if (rv) {
00583       return rv;
00584     }
00585     /* tag finished */
00586     return 0;
00587   }
00588 
00589   /* read attributes */
00590   for (;;) {
00591     GWEN_BUFFER *nbuf;
00592     GWEN_BUFFER *vbuf=NULL;
00593 
00594     nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00595 
00596     /* skip blanks */
00597     for (;;) {
00598       GWEN_FASTBUFFER_READBYTE(fb, chr);
00599       if (chr<0) {
00600         GWEN_Buffer_free(nbuf);
00601         return chr;
00602       }
00603       uc=(unsigned char) chr;
00604       if (uc>32)
00605         break;
00606     }
00607 
00608     /* read attribute name */
00609     for (;;) {
00610       if (uc=='/' || uc=='!' || uc=='?' || uc=='=' || uc=='>')
00611         break;
00612       GWEN_Buffer_AppendByte(nbuf, uc);
00613 
00614       GWEN_FASTBUFFER_READBYTE(fb, chr);
00615       if (chr<0) {
00616         GWEN_Buffer_free(nbuf);
00617         return chr;
00618       }
00619       uc=(unsigned char) chr;
00620     }
00621 
00622     if (GWEN_Buffer_GetUsedBytes(nbuf)) {
00623       if (uc=='=') {
00624         /* read attribute value if there is an equation mark */
00625         int inQuote=0;
00626   
00627         vbuf=GWEN_Buffer_new(0, 256, 0, 1);
00628         for (;;) {
00629           GWEN_FASTBUFFER_READBYTE(fb, chr);
00630           if (chr<0) {
00631             GWEN_Buffer_free(nbuf);
00632             return chr;
00633           }
00634           uc=(unsigned char) chr;
00635           if (uc=='"') {
00636             if (inQuote) {
00637               inQuote=0;
00638               break;
00639             }
00640             else
00641               inQuote=1;
00642           }
00643           else {
00644             if (!inQuote) {
00645               if (uc=='>' || uc<33)
00646                 break;
00647               else if (uc=='<') {
00648                 DBG_ERROR(GWEN_LOGDOMAIN,
00649                           "Nested element definitions");
00650                 GWEN_Buffer_free(vbuf);
00651                 GWEN_Buffer_free(nbuf);
00652                 return GWEN_ERROR_BAD_DATA;
00653               }
00654               else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
00655                 if (uc=='/' || uc=='!' || uc=='?') {
00656                   unsigned char tc;
00657 
00658                   GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00659                   if (chr<0) {
00660                     GWEN_Buffer_free(vbuf);
00661                     GWEN_Buffer_free(nbuf);
00662                     return chr;
00663                   }
00664                   tc=(unsigned char) chr;
00665                   if (tc=='>') {
00666                     break;
00667                   }
00668                 }
00669               }
00670             }
00671             GWEN_Buffer_AppendByte(vbuf, uc);
00672           }
00673         }
00674         if (inQuote) {
00675           DBG_ERROR(GWEN_LOGDOMAIN, "No matching number of quote chars");
00676           GWEN_Buffer_free(vbuf);
00677           GWEN_Buffer_free(nbuf);
00678           return GWEN_ERROR_BAD_DATA;
00679         }
00680 
00681         if (GWEN_Buffer_GetUsedBytes(vbuf)==0) {
00682           GWEN_Buffer_free(vbuf);
00683           vbuf=NULL;
00684         }
00685       }
00686       rv=GWEN_XmlCtx_AddAttr(ctx,
00687                              GWEN_Buffer_GetStart(nbuf),
00688                              vbuf?GWEN_Buffer_GetStart(vbuf):NULL);
00689       if (rv) {
00690         GWEN_Buffer_free(vbuf);
00691         GWEN_Buffer_free(nbuf);
00692         return rv;
00693       }
00694     }
00695 
00696     GWEN_Buffer_free(vbuf);
00697     GWEN_Buffer_free(nbuf);
00698 
00699     if (uc=='>' || uc=='?' || uc=='!' || uc=='/')
00700       break;
00701   }
00702 
00703   if (uc=='?' || uc=='!' || uc=='/') {
00704     unsigned char ucsave=uc;
00705 
00706     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00707     if (chr<0) {
00708       return chr;
00709     }
00710     uc=(unsigned char) chr;
00711     if (uc=='>') {
00712       DBG_VERBOUS(GWEN_LOGDOMAIN, "Ending tag [%s]", GWEN_Buffer_GetStart(dbuf));
00713       fb->bufferReadPos++;
00714       rv=GWEN_XmlCtx_EndTag(ctx, 1);
00715       if (rv) {
00716         return rv;
00717       }
00718       /* tag finished */
00719       return 0;
00720     }
00721     else {
00722       DBG_ERROR(GWEN_LOGDOMAIN,
00723                 "Got an unexpected character here (after %02x[%c]): %02x[%c], "
00724                 "maybe the text contains unescaped XML characters?",
00725                 ucsave, ucsave, uc, uc);
00726     }
00727   }
00728   else if (uc=='>') {
00729     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00730     if (rv) {
00731       return rv;
00732     }
00733     /* tag finished */
00734     return 0;
00735   }
00736 
00737   DBG_ERROR(GWEN_LOGDOMAIN,
00738             "Internal error: Should never reach this point");
00739   return GWEN_ERROR_INTERNAL;
00740 }
00741 
00742 
00743 
00744 
00745 int GWEN_XML_ReadFromFastBuffer(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb){
00746   int oks=0;
00747   int startingDepth;
00748   GWEN_BUFFER *workBuf;
00749 
00750   startingDepth=GWEN_XmlCtx_GetDepth(ctx);
00751 
00752   workBuf=GWEN_Buffer_new(0, 256, 0, 1);
00753   GWEN_XmlCtx_ResetFinishedElement(ctx);
00754   for (;;) {
00755     int rv;
00756 
00757     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00758     if (rv<0) {
00759       if (rv!=GWEN_ERROR_EOF || !oks) {
00760         DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d), after reading %d bytes",
00761                   rv, (int) GWEN_FastBuffer_GetBytesRead(fb));
00762         GWEN_Buffer_free(workBuf);
00763         return rv;
00764       }
00765       GWEN_Buffer_free(workBuf);
00766       return 0;
00767     }
00768 
00769     rv=GWEN_XML__ReadData(ctx, fb, GWEN_XmlCtx_GetFlags(ctx));
00770     if (rv) {
00771       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00772       GWEN_Buffer_free(workBuf);
00773       return rv;
00774     }
00775     oks=1;
00776 
00777     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00778     if (rv<0) {
00779       if (rv!=GWEN_ERROR_EOF || !oks ||
00780           (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth)) {
00781         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00782         GWEN_Buffer_free(workBuf);
00783         return rv;
00784       }
00785       GWEN_Buffer_free(workBuf);
00786       return 0;
00787     }
00788     else if (rv=='<') {
00789       fb->bufferReadPos++;
00790       rv=GWEN_XML__ReadTag(ctx, fb, GWEN_XmlCtx_GetFlags(ctx), workBuf);
00791       if (rv) {
00792         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00793         GWEN_Buffer_free(workBuf);
00794         return rv;
00795       }
00796       GWEN_Buffer_Reset(workBuf);
00797       oks=1;
00798     }
00799 
00800     if (GWEN_XmlCtx_GetFinishedElement(ctx) &&
00801         GWEN_XmlCtx_GetDepth(ctx)==startingDepth)
00802       break;
00803   }
00804 
00805   if (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth) {
00806     DBG_ERROR(GWEN_LOGDOMAIN,
00807               "Not on same level where we started...(%d!=%d)",
00808               GWEN_XmlCtx_GetDepth(ctx), startingDepth);
00809   }
00810   GWEN_Buffer_free(workBuf);
00811 
00812   return 0;
00813 }
00814 
00815 
00816 
00817 int GWEN_XML__ReadAllFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio){
00818   GWEN_FAST_BUFFER *fb;
00819   int oks=0;
00820 
00821   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE, sio);
00822   assert(fb);
00823   for (;;) {
00824     int rv;
00825 
00826     rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00827     if (rv<0) {
00828       if (rv==GWEN_ERROR_EOF && oks)
00829         break;
00830       else {
00831         DBG_INFO(GWEN_LOGDOMAIN, "here");
00832         GWEN_FastBuffer_free(fb);
00833         return rv;
00834       }
00835     }
00836     oks=1;
00837   }
00838 
00839   GWEN_FastBuffer_free(fb);
00840   return 0;
00841 }
00842 
00843 
00844 
00845 int GWEN_XMLContext_ReadFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio){
00846 #if 0
00847   GWEN_FAST_BUFFER *fb;
00848   int rv;
00849 
00850   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE, sio);
00851   assert(fb);
00852   rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00853   if (rv) {
00854     DBG_INFO(GWEN_LOGDOMAIN, "here");
00855     GWEN_FastBuffer_free(fb);
00856     return rv;
00857   }
00858 
00859   GWEN_FastBuffer_free(fb);
00860   return 0;
00861 #else
00862   int rv;
00863 
00864   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00865   if (rv<0) {
00866     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00867     return rv;
00868   }
00869 
00870   return rv;
00871 #endif
00872 }
00873 
00874 
00875 
00876 int GWEN_XMLContext_ReadFromFile(GWEN_XML_CONTEXT *ctx, const char *fname) {
00877   GWEN_SYNCIO *sio;
00878   int rv;
00879 
00880   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00881   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00882   rv=GWEN_SyncIo_Connect(sio);
00883   if (rv<0) {
00884     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00885     GWEN_SyncIo_free(sio);
00886     return rv;
00887   }
00888 
00889   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00890   if (rv<0) {
00891     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00892     GWEN_SyncIo_Disconnect(sio);
00893     GWEN_SyncIo_free(sio);
00894     return rv;
00895   }
00896 
00897   GWEN_SyncIo_Disconnect(sio);
00898   GWEN_SyncIo_free(sio);
00899 
00900   return 0;
00901 }
00902 
00903 
00904 
00905 int GWEN_XMLContext_ReadFromString(GWEN_XML_CONTEXT *ctx, const char *text) {
00906   if (text && *text) {
00907     GWEN_SYNCIO *sio;
00908     int rv;
00909     GWEN_BUFFER *tbuf;
00910     int i;
00911 
00912     i=strlen(text)+1;
00913     tbuf=GWEN_Buffer_new((char*)text, i, i, 0);
00914     /* static buffer, don't resize */
00915     GWEN_Buffer_SubMode(tbuf, GWEN_BUFFER_MODE_DYNAMIC);
00916     GWEN_Buffer_AddMode(tbuf, GWEN_BUFFER_MODE_READONLY);
00917     sio=GWEN_SyncIo_Memory_new(tbuf, 0);
00918 
00919     rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00920     if (rv<0) {
00921       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00922       GWEN_SyncIo_free(sio);
00923       GWEN_Buffer_free(tbuf);
00924       return rv;
00925     }
00926 
00927     GWEN_SyncIo_free(sio);
00928     GWEN_Buffer_free(tbuf);
00929   }
00930   return 0;
00931 }
00932 
00933 
00934 
00935 
00936 int GWEN_XML_ReadFile(GWEN_XMLNODE *n, const char *filepath, uint32_t flags) {
00937   GWEN_XML_CONTEXT *ctx;
00938   GWEN_SYNCIO *sio;
00939   int rv;
00940 
00941   sio=GWEN_SyncIo_File_new(filepath, GWEN_SyncIo_File_CreationMode_OpenExisting);
00942   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00943   rv=GWEN_SyncIo_Connect(sio);
00944   if (rv<0) {
00945     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00946     GWEN_SyncIo_free(sio);
00947     return rv;
00948   }
00949 
00950   ctx=GWEN_XmlCtxStore_new(n, flags);
00951   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00952   if (rv<0) {
00953     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00954     GWEN_SyncIo_Disconnect(sio);
00955     GWEN_SyncIo_free(sio);
00956     GWEN_XmlCtx_free(ctx);
00957     return rv;
00958   }
00959 
00960   GWEN_SyncIo_Disconnect(sio);
00961   GWEN_SyncIo_free(sio);
00962 
00963   GWEN_XmlCtx_free(ctx);
00964 
00965   return 0;
00966 }
00967 
00968 
00969 
00970 GWEN_XMLNODE *GWEN_XMLNode_fromString(const char *s, int len, uint32_t flags) {
00971 #if 0
00972   GWEN_XML_CONTEXT *ctx;
00973   GWEN_SYNCIO *sio;
00974   GWEN_XMLNODE *n;
00975   int rv;
00976 
00977   if (len==0)
00978     len=strlen(s);
00979   sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*)s, len);
00980 
00981   n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "doc");
00982   ctx=GWEN_XmlCtxStore_new(n, flags);
00983   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
00984   if (rv<0) {
00985     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00986     GWEN_SyncIo_free(sio);
00987     GWEN_XmlCtx_free(ctx);
00988     GWEN_XMLNode_free(n);
00989     return NULL;
00990   }
00991 
00992   GWEN_SyncIo_free(sio);
00993 
00994   GWEN_XmlCtx_free(ctx);
00995 
00996   return n;
00997 #else
00998   GWEN_XML_CONTEXT *ctx;
00999   GWEN_SYNCIO *sio;
01000   GWEN_XMLNODE *n;
01001   int rv;
01002   GWEN_BUFFER *tbuf;
01003 
01004   tbuf=GWEN_Buffer_new((char*)s, len, len, 0);
01005   /* static buffer, don't resize */
01006   GWEN_Buffer_SubMode(tbuf, GWEN_BUFFER_MODE_DYNAMIC);
01007   GWEN_Buffer_AddMode(tbuf, GWEN_BUFFER_MODE_READONLY);
01008   sio=GWEN_SyncIo_Memory_new(tbuf, 0);
01009 
01010   n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "doc");
01011   ctx=GWEN_XmlCtxStore_new(n, flags);
01012   rv=GWEN_XML__ReadAllFromIo(ctx, sio);
01013   if (rv<0) {
01014     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01015     GWEN_XmlCtx_free(ctx);
01016     GWEN_XMLNode_free(n);
01017     GWEN_SyncIo_free(sio);
01018     GWEN_Buffer_free(tbuf);
01019     return NULL;
01020   }
01021 
01022   GWEN_XmlCtx_free(ctx);
01023   GWEN_SyncIo_free(sio);
01024   GWEN_Buffer_free(tbuf);
01025 
01026   return n;
01027 #endif
01028 }
01029 
01030 
01031 
01032