xmlrw.c

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

doxygen