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     unsigned char ucsave=uc;
00748 
00749     GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
00750     if (chr<0) {
00751       GWEN_Buffer_free(dbuf);
00752       return chr;
00753     }
00754     uc=(unsigned char) chr;
00755     if (uc=='>') {
00756       DBG_VERBOUS(GWEN_LOGDOMAIN, "Ending tag [%s]", GWEN_Buffer_GetStart(dbuf));
00757       fb->bufferReadPos++;
00758       rv=GWEN_XmlCtx_EndTag(ctx, 1);
00759       if (rv) {
00760         GWEN_Buffer_free(dbuf);
00761         return rv;
00762       }
00763       GWEN_Buffer_free(dbuf);
00764       /* tag finished */
00765       return 0;
00766     }
00767     else {
00768       DBG_ERROR(GWEN_LOGDOMAIN,
00769                 "Got an unexpected character here (after %02x[%c]): %02x[%c], "
00770                 "maybe the text contains unescaped XML characters?",
00771                 ucsave, ucsave, uc, uc);
00772     }
00773   }
00774   else if (uc=='>') {
00775     rv=GWEN_XmlCtx_EndTag(ctx, 0);
00776     if (rv) {
00777       GWEN_Buffer_free(dbuf);
00778       return rv;
00779     }
00780     GWEN_Buffer_free(dbuf);
00781     /* tag finished */
00782     return 0;
00783   }
00784 
00785   DBG_ERROR(GWEN_LOGDOMAIN,
00786             "Internal error: Should never reach this point");
00787   GWEN_Buffer_free(dbuf);
00788   return GWEN_ERROR_INTERNAL;
00789 }
00790 
00791 
00792 
00793 
00794 int GWEN_XML_ReadFromFastBuffer(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb){
00795   int oks=0;
00796   int startingDepth;
00797 
00798   startingDepth=GWEN_XmlCtx_GetDepth(ctx);
00799 
00800   GWEN_XmlCtx_ResetFinishedElement(ctx);
00801   for (;;) {
00802     int rv;
00803 
00804     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00805     if (rv<0) {
00806       if (rv!=GWEN_ERROR_EOF || !oks) {
00807         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00808         return rv;
00809       }
00810       return 0;
00811     }
00812 
00813     rv=GWEN_XML__ReadData(ctx, fb, GWEN_XmlCtx_GetFlags(ctx));
00814     if (rv) {
00815       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00816       return rv;
00817     }
00818     oks=1;
00819 
00820     GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
00821     if (rv<0) {
00822       if (rv!=GWEN_ERROR_EOF || !oks ||
00823           (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth)) {
00824         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00825         return rv;
00826       }
00827       return 0;
00828     }
00829     else if (rv=='<') {
00830       fb->bufferReadPos++;
00831       rv=GWEN_XML__ReadTag(ctx, fb, GWEN_XmlCtx_GetFlags(ctx));
00832       if (rv) {
00833         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00834         return rv;
00835       }
00836       oks=1;
00837     }
00838 
00839     if (GWEN_XmlCtx_GetFinishedElement(ctx) &&
00840         GWEN_XmlCtx_GetDepth(ctx)==startingDepth)
00841       break;
00842   }
00843 
00844   if (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth) {
00845     DBG_ERROR(GWEN_LOGDOMAIN,
00846               "Not on same level where we started...(%d!=%d)",
00847               GWEN_XmlCtx_GetDepth(ctx), startingDepth);
00848   }
00849 
00850   return 0;
00851 }
00852 
00853 
00854 
00855 int GWEN_XML__ReadAllFromIo(GWEN_XML_CONTEXT *ctx, GWEN_IO_LAYER *io){
00856   GWEN_FAST_BUFFER *fb;
00857   int oks=0;
00858 
00859   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE,
00860                          io,
00861                          GWEN_XmlCtx_GetGuiId(ctx),
00862                          GWEN_XmlCtx_GetTimeout(ctx));
00863   assert(fb);
00864   for (;;) {
00865     int rv;
00866 
00867     rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00868     if (rv<0) {
00869       if (rv==GWEN_ERROR_EOF && oks)
00870         break;
00871       else {
00872         DBG_INFO(GWEN_LOGDOMAIN, "here");
00873         GWEN_FastBuffer_free(fb);
00874         return rv;
00875       }
00876     }
00877     oks=1;
00878   }
00879 
00880   GWEN_FastBuffer_free(fb);
00881   return 0;
00882 }
00883 
00884 
00885 
00886 int GWEN_XML_ReadFromIo(GWEN_XML_CONTEXT *ctx, GWEN_IO_LAYER *io){
00887   GWEN_FAST_BUFFER *fb;
00888   int rv;
00889 
00890   fb=GWEN_FastBuffer_new(GWEN_XML_BUFFERSIZE,
00891                          io,
00892                          GWEN_XmlCtx_GetGuiId(ctx),
00893                          GWEN_XmlCtx_GetTimeout(ctx));
00894   assert(fb);
00895   rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
00896   if (rv) {
00897     DBG_INFO(GWEN_LOGDOMAIN, "here");
00898     GWEN_FastBuffer_free(fb);
00899     return rv;
00900   }
00901 
00902   GWEN_FastBuffer_free(fb);
00903   return 0;
00904 }
00905 
00906 
00907 
00908 
00909 int GWEN_XML_ReadFile(GWEN_XMLNODE *n, const char *filepath, uint32_t flags) {
00910   GWEN_XML_CONTEXT *ctx;
00911   GWEN_IO_LAYER *io;
00912   int fd;
00913   int rv;
00914 
00915   fd=open(filepath, O_RDONLY);
00916   if (fd==-1) {
00917     DBG_ERROR(0, "open(%s): %s", filepath, strerror(errno));
00918     return GWEN_ERROR_IO;
00919   }
00920 
00921   ctx=GWEN_XmlCtxStore_new(n, flags, 0, 10000);
00922   io=GWEN_Io_LayerFile_new(fd, -1);
00923   GWEN_Io_Manager_RegisterLayer(io);
00924 
00925   rv=GWEN_XML__ReadAllFromIo(ctx, io);
00926   if (rv<0) {
00927     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00928     GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
00929     GWEN_Io_Layer_free(io);
00930     GWEN_XmlCtx_free(ctx);
00931     return rv;
00932   }
00933 
00934   GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
00935 
00936   GWEN_Io_Layer_free(io);
00937   GWEN_XmlCtx_free(ctx);
00938 
00939   return 0;
00940 }
00941 
00942 
00943 
00944 GWEN_XMLNODE *GWEN_XMLNode_fromString(const char *s, int len, uint32_t flags) {
00945   GWEN_XML_CONTEXT *ctx;
00946   GWEN_IO_LAYER *io;
00947   GWEN_XMLNODE *n;
00948   int rv;
00949 
00950   n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "doc");
00951   ctx=GWEN_XmlCtxStore_new(n, flags, 0, 10000);
00952   io=GWEN_Io_LayerMemory_fromString((const uint8_t*)s, len);
00953   GWEN_Io_Manager_RegisterLayer(io);
00954 
00955   rv=GWEN_XML__ReadAllFromIo(ctx, io);
00956   if (rv<0) {
00957     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00958     GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
00959     GWEN_Io_Layer_free(io);
00960     GWEN_XmlCtx_free(ctx);
00961     GWEN_XMLNode_free(n);
00962     return NULL;
00963   }
00964 
00965   GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
00966 
00967   GWEN_Io_Layer_free(io);
00968   GWEN_XmlCtx_free(ctx);
00969 
00970   return n;
00971 }
00972 
00973 
00974 
00975 
Generated on Mon Jul 5 22:51:15 2010 for gwenhywfar by  doxygen 1.6.3