gwenhywfar  4.99.25rc9
xmlrw.c
Go to the documentation of this file.
1 /***************************************************************************
2  copyright : (C) 2007-2010 by Martin Preuss
3  email : martin@libchipcard.de
4 
5  ***************************************************************************
6  * *
7  * This library is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU Lesser General Public *
9  * License as published by the Free Software Foundation; either *
10  * version 2.1 of the License, or (at your option) any later version. *
11  * *
12  * This library is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15  * Lesser General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU Lesser General Public *
18  * License along with this library; if not, write to the Free Software *
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20  * MA 02111-1307 USA *
21  * *
22  ***************************************************************************/
23 
24 
25 /* this file is included from xml.c */
26 
27 
28 
30  GWEN_FAST_BUFFER *fb,
31  uint32_t flags,
32  const char *encoding,
33  unsigned int ind)
34 {
36  GWEN_XMLNODE *c;
37  GWEN_BUFFER *buf;
38  int i;
39  int simpleTag;
40  int rv;
41 
42 #define CHECK_ERROR(rv) \
43  if (rv<0) {\
44  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);\
45  GWEN_Buffer_free(buf);\
46  return rv;\
47  }
48 
49  assert(n);
50 
51  buf=GWEN_Buffer_new(0, 256, 0, 1);
52  simpleTag=0;
53  if (n->type==GWEN_XMLNodeTypeTag) {
54  if (!(flags & GWEN_XML_FLAGS_SIMPLE)) {
55  if (flags & GWEN_XML_FLAGS_INDENT) {
56  for (i=0; i<ind; i++) {
57  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
58  CHECK_ERROR(rv);
59  }
60  }
61  }
62 
63  if (n->data) {
64  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, '<');
65  CHECK_ERROR(rv);
66  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
67  CHECK_ERROR(rv);
68  }
69  else {
70  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "<UNKNOWN", -1);
71  CHECK_ERROR(rv);
72  }
73 
76 
77  ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
78  while (ns) {
79  const char *name;
80  const char *url;
81 
84  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
85  CHECK_ERROR(rv);
86  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "xmlns", -1);
87  CHECK_ERROR(rv);
88  if (name && *name) {
89  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, ":", -1);
90  CHECK_ERROR(rv);
91  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, name, -1);
92  CHECK_ERROR(rv);
93  }
94  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "=\"", -1);
95  CHECK_ERROR(rv);
96  if (url) {
97  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, url, -1);
98  CHECK_ERROR(rv);
99  }
100  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "\"", -1);
101  CHECK_ERROR(rv);
102 
104  }
105  }
106 
107  p=n->properties;
108  while (p) {
109  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
110  CHECK_ERROR(rv);
111  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, p->name, -1);
112  CHECK_ERROR(rv);
113  if (p->value) {
114  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "=\"", -1);
115  CHECK_ERROR(rv);
116  rv=GWEN_Text_ConvertCharset("UTF-8", encoding,
117  p->value, strlen(p->value), buf);
118  CHECK_ERROR(rv);
120  CHECK_ERROR(rv);
121  GWEN_Buffer_Reset(buf);
122  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "\"", -1);
123  CHECK_ERROR(rv);
124  }
125  p=p->next;
126  }
127 
128  if (n->data) {
129  if (n->data[0]=='?') {
130  simpleTag=1;
131  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, '?');
132  CHECK_ERROR(rv);
133  }
134  else if (n->data[0]=='!') {
135  simpleTag=1;
136  }
137  }
138 
139  if (flags & GWEN_XML_FLAGS_SIMPLE) {
140  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, ">", -1);
141  }
142  else {
143  GWEN_FASTBUFFER_WRITELINE(fb, rv, ">");
144  }
145  CHECK_ERROR(rv);
146  if (!simpleTag) {
148  while (c) {
149  rv=GWEN_XMLNode__WriteToStream(c, fb, flags, encoding, ind+2);
150  CHECK_ERROR(rv);
151  c=GWEN_XMLNode_Next(c);
152  }
153 
154  if (!(flags & GWEN_XML_FLAGS_SIMPLE)) {
155  if (flags & GWEN_XML_FLAGS_INDENT) {
156  for (i=0; i<ind; i++) {
157  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
158  CHECK_ERROR(rv);
159  }
160  }
161  }
162  if (n->data) {
163  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "</", -1);
164  CHECK_ERROR(rv);
165  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, n->data, -1);
166  CHECK_ERROR(rv);
167  if (flags & GWEN_XML_FLAGS_SIMPLE) {
168  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, ">", -1);
169  }
170  else {
171  GWEN_FASTBUFFER_WRITELINE(fb, rv, ">");
172  }
173  CHECK_ERROR(rv);
174  }
175  else {
176  GWEN_FASTBUFFER_WRITELINE(fb, rv, "</UNKNOWN>");
177  CHECK_ERROR(rv);
178  }
179  }
180  }
181  else if (n->type==GWEN_XMLNodeTypeData) {
182  if (n->data) {
183  if (!(flags & GWEN_XML_FLAGS_SIMPLE)) {
184  if (flags & GWEN_XML_FLAGS_INDENT) {
185  for (i=0; i<ind; i++) {
186  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
187  CHECK_ERROR(rv);
188  }
189  }
190  }
191 
192  rv=GWEN_Text_ConvertCharset("UTF-8", encoding,
193  n->data, strlen(n->data), buf);
194  CHECK_ERROR(rv);
196  CHECK_ERROR(rv);
197  GWEN_Buffer_Reset(buf);
198  if (!(flags & GWEN_XML_FLAGS_SIMPLE)) {
199  GWEN_FASTBUFFER_WRITELINE(fb, rv, "");
200  CHECK_ERROR(rv);
201  }
202  }
203  }
204  else if (n->type==GWEN_XMLNodeTypeComment) {
205  if (flags & GWEN_XML_FLAGS_HANDLE_COMMENTS) {
206  if (flags & GWEN_XML_FLAGS_INDENT) {
207  for (i=0; i<ind; i++) {
208  GWEN_FASTBUFFER_WRITEBYTE(fb, rv, ' ');
209  CHECK_ERROR(rv);
210  }
211  }
212 
213  GWEN_FASTBUFFER_WRITEFORCED(fb, rv, "<!--", -1);
214  CHECK_ERROR(rv);
215  if (n->data) {
216  rv=GWEN_Text_ConvertCharset("UTF-8", encoding,
217  n->data, strlen(n->data), buf);
218  CHECK_ERROR(rv);
220  CHECK_ERROR(rv);
221  GWEN_Buffer_Reset(buf);
222  }
223  GWEN_FASTBUFFER_WRITELINE(fb, rv, "-->");
224  CHECK_ERROR(rv);
225  }
226  }
227  else {
228  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown tag type (%d)", n->type);
229  }
230 
231  GWEN_Buffer_free(buf);
232  return 0;
233 #undef CHECK_ERROR
234 }
235 
236 
237 
239  GWEN_XML_CONTEXT *ctx,
240  GWEN_SYNCIO *sio)
241 {
242  const GWEN_XMLNODE *nn;
243  const GWEN_XMLNODE *nchild;
244  const GWEN_XMLNODE *nheader;
245  uint32_t flags;
246  GWEN_FAST_BUFFER *fb;
247  int rv;
248 
249  flags=GWEN_XmlCtx_GetFlags(ctx);
250  nchild=GWEN_XMLNode_GetChild(n);
251  nheader=GWEN_XMLNode_GetHeader(n);
252 
253  fb=GWEN_FastBuffer_new(512, sio);
254 
255  if (nheader && (flags & GWEN_XML_FLAGS_HANDLE_HEADERS)) {
256 
257  nn=nheader;
258  while (nn) {
259  const GWEN_XMLNODE *next;
260 
261  rv=GWEN_XMLNode__WriteToStream(nn, fb, flags,
262  GWEN_XmlCtx_GetEncoding(ctx), 0);
263  if (rv<0) {
264  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
266  return rv;
267  }
268  next=GWEN_XMLNode_Next(nn);
269  if (next) {
270  int err;
271 
272  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
273  if (err<0) {
274  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
276  return err;
277  }
278  }
279  if (strcmp(GWEN_XMLNode_GetData(nn), "?xml")==0) {
280  const char *encoding;
281 
282  encoding=GWEN_XMLNode_GetProperty(nn, "encoding", NULL);
283  if (encoding) {
284  if (strcasecmp(encoding, "UTF-8")==0 ||
285  strcasecmp(encoding, "UTF8")==0)
286  encoding=NULL;
287  GWEN_XmlCtx_SetEncoding(ctx, encoding);
288  }
289  }
290 
291  nn=next;
292  }
293 
294  if (nchild) {
295  int err;
296 
297  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
298  if (err<0) {
299  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
301  return err;
302  }
303  }
304  }
305 
306  nn=nchild;
307  while (nn) {
308  const GWEN_XMLNODE *next;
309 
310  if (GWEN_XMLNode__WriteToStream(nn, fb, flags,
311  GWEN_XmlCtx_GetEncoding(ctx), 0))
312  return -1;
313  next=GWEN_XMLNode_Next(nn);
314  if (next) {
315  int err;
316 
317  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
318  if (err<0) {
319  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
321  return err;
322  }
323  }
324 
325  nn=next;
326  } /* while */
327 
328  GWEN_FASTBUFFER_FLUSH(fb, rv);
329  if (rv<0) {
330  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
332  return rv;
333  }
335 
336  return 0;
337 }
338 
339 
340 
342  const char *fname,
343  uint32_t flags)
344 {
345  GWEN_XML_CONTEXT *ctx;
346  GWEN_SYNCIO *sio;
347  int rv;
348 
353  rv=GWEN_SyncIo_Connect(sio);
354  if (rv<0) {
355  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
356  GWEN_SyncIo_free(sio);
357  return rv;
358  }
359 
360  /* create context and io layers */
361  ctx=GWEN_XmlCtxStore_new(NULL, flags);
362 
363  /* write data to stream */
364  rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
365  if (rv<0) {
366  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
368  GWEN_SyncIo_free(sio);
369  GWEN_XmlCtx_free(ctx);
370  return rv;
371  }
372 
373  /* close file */
375  GWEN_SyncIo_free(sio);
376 
377  GWEN_XmlCtx_free(ctx);
378 
379  return 0;
380 }
381 
382 
383 
384 int GWEN_XMLNode_toBuffer(const GWEN_XMLNODE *n, GWEN_BUFFER *buf, uint32_t flags)
385 {
386  GWEN_XML_CONTEXT *ctx;
387  GWEN_SYNCIO *sio;
388  int rv;
389 
390  sio=GWEN_SyncIo_Memory_new(buf, 0);
391 
392  /* create context and io layers */
393  ctx=GWEN_XmlCtxStore_new(NULL, flags);
394 
395  /* write data to stream */
396  rv=GWEN_XMLNode_WriteToStream(n, ctx, sio);
397  if (rv<0) {
398  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
399  GWEN_SyncIo_free(sio);
400  GWEN_XmlCtx_free(ctx);
401  return rv;
402  }
403 
404  GWEN_SyncIo_free(sio);
405 
406  GWEN_XmlCtx_free(ctx);
407 
408  return 0;
409 }
410 
411 
412 
413 
414 
415 
416 
417 
419  GWEN_FAST_BUFFER *fb,
420  GWEN_UNUSED uint32_t flags)
421 {
422  int chr;
423  unsigned char uc;
424  GWEN_BUFFER *dbuf;
425 
426  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
427 
428  for (;;) {
429  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
430  if (chr<0) {
431  if (chr==GWEN_ERROR_EOF)
432  break;
433  else {
434  GWEN_Buffer_free(dbuf);
435  return chr;
436  }
437  }
438 
439  uc=(unsigned char) chr;
440  if (uc=='<')
441  break;
442  fb->bufferReadPos++;
443  GWEN_Buffer_AppendByte(dbuf, uc);
444  }
445 
446  if (GWEN_Buffer_GetUsedBytes(dbuf)) {
447  int rv;
448  uint32_t len;
449  char *s;
450 
451  len=GWEN_Buffer_GetUsedBytes(dbuf);
452  s=strdup(GWEN_Buffer_GetStart(dbuf));
453  assert(s);
454  GWEN_Buffer_Reset(dbuf);
456  s, len, dbuf);
457  free(s);
458  if (rv) {
459  GWEN_Buffer_free(dbuf);
460  return rv;
461  }
462  s=GWEN_Buffer_GetStart(dbuf);
463  if (*s) {
464  rv=GWEN_XmlCtx_AddData(ctx, s);
465  if (rv) {
466  GWEN_Buffer_free(dbuf);
467  return rv;
468  }
469  }
470  }
471  GWEN_Buffer_free(dbuf);
472 
473  return 0;
474 }
475 
476 
477 
479  GWEN_FAST_BUFFER *fb,
480  GWEN_UNUSED uint32_t flags,
481  GWEN_BUFFER *dbuf)
482 {
483  int chr;
484  unsigned char uc=0;
485  int rv;
486 
487  /* skip blanks */
488  for (;;) {
489  GWEN_FASTBUFFER_READBYTE(fb, chr);
490  if (chr<0) {
491  return chr;
492  }
493  uc=(unsigned char) chr;
494  if (uc>32)
495  break;
496  }
497 
498  if (uc=='/') {
499  /* read end tag */
500  GWEN_Buffer_AppendByte(dbuf, uc);
501  for (;;) {
502  GWEN_FASTBUFFER_READBYTE(fb, chr);
503  if (chr<0) {
504  return chr;
505  }
506  uc=(unsigned char) chr;
507  if (uc=='>' || uc<33)
508  break;
509 
510  GWEN_Buffer_AppendByte(dbuf, uc);
511  }
512 
514  if (rv) {
515  return rv;
516  }
517  if (uc!='>') {
518  for (;;) {
519  /* skip blanks, expect '>' */
520  GWEN_FASTBUFFER_READBYTE(fb, chr);
521  if (chr<0) {
522  return chr;
523  }
524  uc=(unsigned char) chr;
525  if (uc>32)
526  break;
527  }
528  }
529  if (uc!='>') {
530  DBG_ERROR(GWEN_LOGDOMAIN, "Unexpected character");
531  DBG_ERROR(GWEN_LOGDOMAIN, "Data so far:");
532  GWEN_Buffer_Dump(dbuf, 2);
533 
534  return GWEN_ERROR_BAD_DATA;
535  }
536 
537  /* tag finished */
538  rv=GWEN_XmlCtx_EndTag(ctx, 0);
539  if (rv) {
540  return rv;
541  }
542  return 0;
543  }
544  else if (uc=='!') {
545  /* check for comment */
546  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
547  if (chr<0) {
548  return chr;
549  }
550  uc=(unsigned char) chr;
551  if (uc=='-') {
552  fb->bufferReadPos++;
553  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
554  if (chr<0) {
555  return chr;
556  }
557  uc=(unsigned char) chr;
558  if (uc=='-') {
559  GWEN_BUFFER *cbuf;
560 
561  /* found comment */
562  fb->bufferReadPos++;
563  cbuf=GWEN_Buffer_new(0, 256, 0, 1);
564  for (;;) {
565  GWEN_FASTBUFFER_READBYTE(fb, chr);
566  if (chr<0) {
567  GWEN_Buffer_free(cbuf);
568  return chr;
569  }
570  uc=(unsigned char) chr;
571  GWEN_Buffer_AppendByte(cbuf, uc);
572  if (GWEN_Buffer_GetUsedBytes(cbuf)>2) {
573  char *p;
574 
575  p=GWEN_Buffer_GetStart(cbuf);
576  p+=GWEN_Buffer_GetUsedBytes(cbuf)-3;
577  if (strcmp(p, "-->")==0) {
578  uint32_t len;
579 
580  *p=0;
581  len=GWEN_Buffer_GetUsedBytes(cbuf)-3;
582  p=strdup(GWEN_Buffer_GetStart(cbuf));
583  assert(p);
584  GWEN_Buffer_Reset(cbuf);
586  p, len, cbuf);
587  free(p);
588  if (rv) {
589  GWEN_Buffer_free(cbuf);
590  return rv;
591  }
593  if (rv) {
594  GWEN_Buffer_free(cbuf);
595  return rv;
596  }
597  GWEN_Buffer_free(cbuf);
598  return 0;
599  }
600  }
601  }
602  }
603  else {
604  GWEN_Buffer_AppendString(dbuf, "!-");
605  }
606  }
607  else
608  uc='!';
609  }
610 
611  /* read name */
612  for (;;) {
613  if (uc==' ' || uc=='>' || uc=='/')
614  break;
615  else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
616  unsigned char fc;
617 
618  fc=*GWEN_Buffer_GetStart(dbuf);
619  if ((fc=='!' && uc=='!') || (fc=='?' && uc=='?')) {
620  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
621  if (chr<0) {
622  return chr;
623  }
624  uc=(unsigned char) chr;
625  if (uc=='>') {
626  fb->bufferReadPos++;
627  break;
628  }
629  }
630  }
631 
632  GWEN_Buffer_AppendByte(dbuf, uc);
633 
634  GWEN_FASTBUFFER_READBYTE(fb, chr);
635  if (chr<0) {
636  if (chr==GWEN_ERROR_EOF) {
637  return chr;
638  }
639  else {
640  return chr;
641  }
642  }
643 
644  uc=(unsigned char) chr;
645  }
646 
647  /* tag started */
648  if (GWEN_Buffer_GetUsedBytes(dbuf)==0) {
649  DBG_ERROR(GWEN_LOGDOMAIN, "Element name missing");
650  return GWEN_ERROR_BAD_DATA;
651  }
652 
654  if (rv) {
655  return rv;
656  }
657 
658  if (uc=='/' || uc=='?' || uc=='!') {
659  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
660  if (chr<0) {
661  return chr;
662  }
663  uc=(unsigned char) chr;
664  if (uc=='>') {
665  fb->bufferReadPos++;
666  rv=GWEN_XmlCtx_EndTag(ctx, 1);
667  if (rv) {
668  return rv;
669  }
670  /* tag finished */
671  return 0;
672  }
673  }
674 
675  if (uc=='>') {
676  rv=GWEN_XmlCtx_EndTag(ctx, 0);
677  if (rv) {
678  return rv;
679  }
680  /* tag finished */
681  return 0;
682  }
683 
684  /* read attributes */
685  for (;;) {
686  GWEN_BUFFER *nbuf;
687  GWEN_BUFFER *vbuf=NULL;
688 
689  nbuf=GWEN_Buffer_new(0, 256, 0, 1);
690 
691  /* skip blanks */
692  for (;;) {
693  GWEN_FASTBUFFER_READBYTE(fb, chr);
694  if (chr<0) {
695  GWEN_Buffer_free(nbuf);
696  return chr;
697  }
698  uc=(unsigned char) chr;
699  if (uc>32)
700  break;
701  }
702 
703  /* read attribute name */
704  for (;;) {
705  if (uc=='/' || uc=='!' || uc=='?' || uc=='=' || uc=='>')
706  break;
707  GWEN_Buffer_AppendByte(nbuf, uc);
708 
709  GWEN_FASTBUFFER_READBYTE(fb, chr);
710  if (chr<0) {
711  GWEN_Buffer_free(nbuf);
712  return chr;
713  }
714  uc=(unsigned char) chr;
715  }
716 
717  if (GWEN_Buffer_GetUsedBytes(nbuf)) {
718  if (uc=='=') {
719  /* read attribute value if there is an equation mark */
720  int inQuote=0;
721  uint32_t len;
722 
723  vbuf=GWEN_Buffer_new(0, 256, 0, 1);
724  for (;;) {
725  GWEN_FASTBUFFER_READBYTE(fb, chr);
726  if (chr<0) {
727  GWEN_Buffer_free(nbuf);
728  return chr;
729  }
730  uc=(unsigned char) chr;
731  if (uc=='"') {
732  if (inQuote) {
733  inQuote=0;
734  break;
735  }
736  else
737  inQuote=1;
738  }
739  else {
740  if (!inQuote) {
741  if (uc=='>' || uc<33)
742  break;
743  else if (uc=='<') {
745  "Nested element definitions");
746  GWEN_Buffer_free(vbuf);
747  GWEN_Buffer_free(nbuf);
748  return GWEN_ERROR_BAD_DATA;
749  }
750  else if (GWEN_Buffer_GetUsedBytes(dbuf)) {
751  if (uc=='/' || uc=='!' || uc=='?') {
752  unsigned char tc;
753 
754  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
755  if (chr<0) {
756  GWEN_Buffer_free(vbuf);
757  GWEN_Buffer_free(nbuf);
758  return chr;
759  }
760  tc=(unsigned char) chr;
761  if (tc=='>') {
762  break;
763  }
764  }
765  }
766  }
767  GWEN_Buffer_AppendByte(vbuf, uc);
768  }
769  }
770  if (inQuote) {
771  DBG_ERROR(GWEN_LOGDOMAIN, "No matching number of quote chars");
772  GWEN_Buffer_free(vbuf);
773  GWEN_Buffer_free(nbuf);
774  return GWEN_ERROR_BAD_DATA;
775  }
776 
777  len=GWEN_Buffer_GetUsedBytes(vbuf);
778  if (len==0) {
779  GWEN_Buffer_free(vbuf);
780  vbuf=NULL;
781  }
782  else {
783  char *s;
784 
785  s=strdup(GWEN_Buffer_GetStart(vbuf));
786  GWEN_Buffer_Reset(vbuf);
788  s, len, vbuf);
789  free(s);
790  if (rv) {
791  GWEN_Buffer_free(vbuf);
792  GWEN_Buffer_free(nbuf);
793  return rv;
794  }
795  }
796  }
797  rv=GWEN_XmlCtx_AddAttr(ctx,
798  GWEN_Buffer_GetStart(nbuf),
799  vbuf?GWEN_Buffer_GetStart(vbuf):NULL);
800  if (rv) {
801  GWEN_Buffer_free(vbuf);
802  GWEN_Buffer_free(nbuf);
803  return rv;
804  }
805  }
806 
807  GWEN_Buffer_free(vbuf);
808  GWEN_Buffer_free(nbuf);
809 
810  if (uc=='>' || uc=='?' || uc=='!' || uc=='/')
811  break;
812  }
813 
814  if (uc=='?' || uc=='!' || uc=='/') {
815  unsigned char ucsave=uc;
816 
817  GWEN_FASTBUFFER_PEEKBYTE(fb, chr);
818  if (chr<0) {
819  return chr;
820  }
821  uc=(unsigned char) chr;
822  if (uc=='>') {
823  DBG_VERBOUS(GWEN_LOGDOMAIN, "Ending tag [%s]", GWEN_Buffer_GetStart(dbuf));
824  fb->bufferReadPos++;
825  rv=GWEN_XmlCtx_EndTag(ctx, 1);
826  if (rv) {
827  return rv;
828  }
829  /* tag finished */
830  return 0;
831  }
832  else {
834  "Got an unexpected character here (after %02x[%c]): %02x[%c], "
835  "maybe the text contains unescaped XML characters?",
836  ucsave, ucsave, uc, uc);
837  }
838  }
839  else if (uc=='>') {
840  rv=GWEN_XmlCtx_EndTag(ctx, 0);
841  if (rv) {
842  return rv;
843  }
844  /* tag finished */
845  return 0;
846  }
847 
849  "Internal error: Should never reach this point");
850  return GWEN_ERROR_INTERNAL;
851 }
852 
853 
854 
855 
857 {
858  int oks=0;
859  int startingDepth;
860  GWEN_BUFFER *workBuf;
861 
862  startingDepth=GWEN_XmlCtx_GetDepth(ctx);
863 
864  workBuf=GWEN_Buffer_new(0, 256, 0, 1);
866  for (;;) {
867  int rv;
868 
869  GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
870  if (rv<0) {
871  if (rv!=GWEN_ERROR_EOF || !oks) {
872  DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d), after reading %d bytes",
873  rv, (int) GWEN_FastBuffer_GetBytesRead(fb));
874  GWEN_Buffer_free(workBuf);
875  return rv;
876  }
877  GWEN_Buffer_free(workBuf);
878  return 0;
879  }
880 
881  rv=GWEN_XML__ReadData(ctx, fb, GWEN_XmlCtx_GetFlags(ctx));
882  if (rv) {
883  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
884  GWEN_Buffer_free(workBuf);
885  return rv;
886  }
887  oks=1;
888 
889  GWEN_FASTBUFFER_PEEKBYTE(fb, rv);
890  if (rv<0) {
891  if (rv!=GWEN_ERROR_EOF || !oks ||
892  (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth)) {
893  DBG_INFO(GWEN_LOGDOMAIN, "here (rv=%d, oks=%d, depth=%d, startingDepth=%d)",
894  rv, oks, GWEN_XmlCtx_GetDepth(ctx), startingDepth);
895  GWEN_Buffer_free(workBuf);
896  return rv;
897  }
898  GWEN_Buffer_free(workBuf);
899  return 0;
900  }
901  else if (rv=='<') {
902  fb->bufferReadPos++;
903  rv=GWEN_XML__ReadTag(ctx, fb, GWEN_XmlCtx_GetFlags(ctx), workBuf);
904  if (rv) {
905  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
906  GWEN_Buffer_free(workBuf);
907  return rv;
908  }
909  GWEN_Buffer_Reset(workBuf);
910  oks=1;
911  }
912 
914  GWEN_XmlCtx_GetDepth(ctx)==startingDepth) {
915  DBG_INFO(GWEN_LOGDOMAIN, "Finished element at depth %d", GWEN_XmlCtx_GetDepth(ctx));
916  break;
917  }
918  }
919 
920  if (GWEN_XmlCtx_GetDepth(ctx)!=startingDepth) {
922  "Not on same level where we started...(%d!=%d)",
923  GWEN_XmlCtx_GetDepth(ctx), startingDepth);
924  }
925  GWEN_Buffer_free(workBuf);
926 
927  return 0;
928 }
929 
930 
931 
933 {
934  GWEN_FAST_BUFFER *fb;
935  int oks=0;
936 
938  assert(fb);
939  for (;;) {
940  int rv;
941 
942  rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
943  if (rv<0) {
944  if (rv==GWEN_ERROR_EOF && oks)
945  break;
946  else {
947  DBG_INFO(GWEN_LOGDOMAIN, "here (rv=%d, oks=%d)", rv, oks);
949  return rv;
950  }
951  }
952  oks=1;
953  }
954 
956  return 0;
957 }
958 
959 
960 
962 {
963 #if 0
964  GWEN_FAST_BUFFER *fb;
965  int rv;
966 
968  assert(fb);
969  rv=GWEN_XML_ReadFromFastBuffer(ctx, fb);
970  if (rv) {
971  DBG_INFO(GWEN_LOGDOMAIN, "here");
973  return rv;
974  }
975 
977  return 0;
978 #else
979  int rv;
980 
981  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
982  if (rv<0) {
983  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
984  return rv;
985  }
986 
987  return rv;
988 #endif
989 }
990 
991 
992 
993 int GWEN_XMLContext_ReadFromFile(GWEN_XML_CONTEXT *ctx, const char *fname)
994 {
995  GWEN_SYNCIO *sio;
996  int rv;
997 
1000  rv=GWEN_SyncIo_Connect(sio);
1001  if (rv<0) {
1002  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1003  GWEN_SyncIo_free(sio);
1004  return rv;
1005  }
1006 
1007  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
1008  if (rv<0) {
1009  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1011  GWEN_SyncIo_free(sio);
1012  return rv;
1013  }
1014 
1016  GWEN_SyncIo_free(sio);
1017 
1018  return 0;
1019 }
1020 
1021 
1022 
1024 {
1025  if (text && *text) {
1026  GWEN_SYNCIO *sio;
1027  int rv;
1028  GWEN_BUFFER *tbuf;
1029  int i;
1030 
1031  i=strlen(text)+1;
1032  tbuf=GWEN_Buffer_new((char *)text, i, i, 0);
1033  /* static buffer, don't resize */
1036  sio=GWEN_SyncIo_Memory_new(tbuf, 0);
1037 
1038  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
1039  if (rv<0) {
1040  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1041  GWEN_SyncIo_free(sio);
1042  GWEN_Buffer_free(tbuf);
1043  return rv;
1044  }
1045 
1046  GWEN_SyncIo_free(sio);
1047  GWEN_Buffer_free(tbuf);
1048  }
1049  return 0;
1050 }
1051 
1052 
1053 
1054 
1055 int GWEN_XML_ReadFile(GWEN_XMLNODE *n, const char *filepath, uint32_t flags)
1056 {
1057  GWEN_XML_CONTEXT *ctx;
1058  GWEN_SYNCIO *sio;
1059  int rv;
1060 
1063  rv=GWEN_SyncIo_Connect(sio);
1064  if (rv<0) {
1065  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1066  GWEN_SyncIo_free(sio);
1067  return rv;
1068  }
1069 
1070  ctx=GWEN_XmlCtxStore_new(n, flags);
1071  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
1072  if (rv<0) {
1073  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1075  GWEN_SyncIo_free(sio);
1076  GWEN_XmlCtx_free(ctx);
1077  return rv;
1078  }
1079 
1081  GWEN_SyncIo_free(sio);
1082 
1083  GWEN_XmlCtx_free(ctx);
1084 
1085  return 0;
1086 }
1087 
1088 
1089 
1090 GWEN_XMLNODE *GWEN_XMLNode_fromString(const char *s, int len, uint32_t flags)
1091 {
1092 #if 0
1093  GWEN_XML_CONTEXT *ctx;
1094  GWEN_SYNCIO *sio;
1095  GWEN_XMLNODE *n;
1096  int rv;
1097 
1098  if (len==0)
1099  len=strlen(s);
1100  sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t *)s, len);
1101 
1103  ctx=GWEN_XmlCtxStore_new(n, flags);
1104  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
1105  if (rv<0) {
1106  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1107  GWEN_SyncIo_free(sio);
1108  GWEN_XmlCtx_free(ctx);
1109  GWEN_XMLNode_free(n);
1110  return NULL;
1111  }
1112 
1113  GWEN_SyncIo_free(sio);
1114 
1115  GWEN_XmlCtx_free(ctx);
1116 
1117  return n;
1118 #else
1119  GWEN_XML_CONTEXT *ctx;
1120  GWEN_SYNCIO *sio;
1121  GWEN_XMLNODE *n;
1122  int rv;
1123  GWEN_BUFFER *tbuf;
1124 
1125  tbuf=GWEN_Buffer_new((char *)s, len, len, 0);
1126  /* static buffer, don't resize */
1129  sio=GWEN_SyncIo_Memory_new(tbuf, 0);
1130 
1132  ctx=GWEN_XmlCtxStore_new(n, flags);
1133  rv=GWEN_XML__ReadAllFromIo(ctx, sio);
1134  if (rv<0) {
1135  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1136  GWEN_XmlCtx_free(ctx);
1137  GWEN_XMLNode_free(n);
1138  GWEN_SyncIo_free(sio);
1139  GWEN_Buffer_free(tbuf);
1140  return NULL;
1141  }
1142 
1143  GWEN_XmlCtx_free(ctx);
1144  GWEN_SyncIo_free(sio);
1145  GWEN_Buffer_free(tbuf);
1146 
1147  return n;
1148 #endif
1149 }
1150 
1151 
1152 
1153 
GWEN_XMLNODE * GWEN_XMLNode_GetHeader(const GWEN_XMLNODE *n)
Definition: xml.c:1283
int GWEN_XML__ReadData(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb, GWEN_UNUSED uint32_t flags)
Definition: xmlrw.c:418
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
#define CHECK_ERROR(rv)
struct GWEN_XMLNODE_NAMESPACE GWEN_XMLNODE_NAMESPACE
Definition: xml.h:150
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition: syncio.c:97
int GWEN_XMLNode_toBuffer(const GWEN_XMLNODE *n, GWEN_BUFFER *buf, uint32_t flags)
Definition: xmlrw.c:384
#define GWEN_SYNCIO_FILE_FLAGS_WRITE
Definition: syncio_file.h:54
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:282
#define GWEN_SYNCIO_FILE_FLAGS_READ
Definition: syncio_file.h:53
#define GWEN_XML_FLAGS_SIMPLE
Definition: xml.h:89
const char * GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name, const char *defaultValue)
Definition: xml.c:239
const char * GWEN_XMLNode_NameSpace_GetName(const GWEN_XMLNODE_NAMESPACE *ns)
Definition: xml.c:1992
struct GWEN__XMLPROPERTY GWEN_XMLPROPERTY
Definition: xml_l.h:37
uint32_t GWEN_FastBuffer_GetBytesRead(const GWEN_FAST_BUFFER *fb)
Definition: fastbuffer.c:202
const char * GWEN_XMLNode_NameSpace_GetUrl(const GWEN_XMLNODE_NAMESPACE *ns)
Definition: xml.c:2000
#define NULL
Definition: binreloc.c:297
#define GWEN_SYNCIO_FILE_FLAGS_UREAD
Definition: syncio_file.h:58
void GWEN_XmlCtx_ResetFinishedElement(GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:187
int GWEN_Text_ConvertCharset(const char *fromCharset, const char *toCharset, const char *text, int len, GWEN_BUFFER *tbuf)
Definition: text.c:2015
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:217
int GWEN_XmlCtx_AddAttr(GWEN_XML_CONTEXT *ctx, const char *attrName, const char *attrData)
Definition: xmlctx.c:349
int GWEN_XML_ReadFile(GWEN_XMLNODE *n, const char *filepath, uint32_t flags)
Definition: xmlrw.c:1055
int GWEN_XmlCtx_StartTag(GWEN_XML_CONTEXT *ctx, const char *tagName)
Definition: xmlctx.c:293
#define GWEN_FASTBUFFER_PEEKBYTE(fb, var)
Definition: fastbuffer.h:74
void GWEN_FastBuffer_free(GWEN_FAST_BUFFER *fb)
Definition: fastbuffer.c:46
#define GWEN_LOGDOMAIN
Definition: logger.h:35
int GWEN_XMLNode_WriteToStream(const GWEN_XMLNODE *n, GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio)
Definition: xmlrw.c:238
int GWEN_XmlCtx_GetDepth(const GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:136
GWEN_XMLNODE * GWEN_XMLNode_new(GWEN_XMLNODE_TYPE t, const char *data)
Definition: xml.c:144
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:655
uint32_t GWEN_XmlCtx_GetFinishedElement(const GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:171
uint32_t bufferReadPos
Definition: fastbuffer.h:32
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:719
#define GWEN_FASTBUFFER_FLUSH(fb, var)
Definition: fastbuffer.h:162
GWEN_XMLNODE * GWEN_XMLNode_GetChild(const GWEN_XMLNODE *n)
Definition: xml.c:409
void GWEN_XmlCtx_free(GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:67
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
int GWEN_XmlCtx_EndTag(GWEN_XML_CONTEXT *ctx, int closing)
Definition: xmlctx.c:307
void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:210
GWEN_SYNCIO * GWEN_SyncIo_Memory_new(GWEN_BUFFER *buffer, int take)
Definition: syncio_memory.c:50
int GWEN_XmlCtx_AddData(GWEN_XML_CONTEXT *ctx, const char *data)
Definition: xmlctx.c:321
void GWEN_XmlCtx_SetEncoding(GWEN_XML_CONTEXT *ctx, const char *encoding)
Definition: xmlctx.c:118
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:209
#define GWEN_XML_BUFFERSIZE
Definition: xml.c:60
int GWEN_XML_ReadFromFastBuffer(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb)
Definition: xmlrw.c:856
int GWEN_XMLNode__WriteToStream(const GWEN_XMLNODE *n, GWEN_FAST_BUFFER *fb, uint32_t flags, const char *encoding, unsigned int ind)
Definition: xmlrw.c:29
int GWEN_XMLContext_ReadFromFile(GWEN_XML_CONTEXT *ctx, const char *fname)
Definition: xmlrw.c:993
int GWEN_XML__ReadTag(GWEN_XML_CONTEXT *ctx, GWEN_FAST_BUFFER *fb, GWEN_UNUSED uint32_t flags, GWEN_BUFFER *dbuf)
Definition: xmlrw.c:478
GWEN_XMLNODE * GWEN_XMLNode_Next(const GWEN_XMLNODE *n)
Definition: xml.c:465
#define GWEN_BUFFER_MODE_DYNAMIC
Definition: buffer.h:69
void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:203
GWEN_XML_CONTEXT * GWEN_XmlCtxStore_new(GWEN_XMLNODE *n, uint32_t flags)
Definition: xmlctx.c:371
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:399
#define GWEN_SYNCIO_FILE_FLAGS_UWRITE
Definition: syncio_file.h:59
GWEN_XMLNODE * GWEN_XMLNode_fromString(const char *s, int len, uint32_t flags)
Definition: xmlrw.c:1090
GWEN_SYNCIO * GWEN_SyncIo_Memory_fromBuffer(const uint8_t *buffer, int size)
Definition: syncio_memory.c:78
int GWEN_XMLNode_WriteFile(const GWEN_XMLNODE *n, const char *fname, uint32_t flags)
Definition: xmlrw.c:341
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:85
void GWEN_XMLNode_free(GWEN_XMLNODE *n)
Definition: xml.c:160
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition: syncio.c:78
void GWEN_SyncIo_AddFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:179
#define GWEN_XML_FLAGS_HANDLE_COMMENTS
Definition: xml.h:60
#define GWEN_FASTBUFFER_READBYTE(fb, var)
Definition: fastbuffer.h:103
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
uint32_t GWEN_XmlCtx_GetFlags(const GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:94
#define GWEN_ERROR_EOF
Definition: error.h:96
int GWEN_XML__ReadAllFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio)
Definition: xmlrw.c:932
const char * GWEN_XMLNode_GetData(const GWEN_XMLNODE *n)
Definition: xml.c:370
#define GWEN_FASTBUFFER_WRITEFORCED(fb, var, p, len)
Definition: fastbuffer.h:377
int GWEN_XMLContext_ReadFromString(GWEN_XML_CONTEXT *ctx, const char *text)
Definition: xmlrw.c:1023
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:109
int GWEN_XMLContext_ReadFromIo(GWEN_XML_CONTEXT *ctx, GWEN_SYNCIO *sio)
Definition: xmlrw.c:961
#define GWEN_FASTBUFFER_WRITEBYTE(fb, var, chr)
Definition: fastbuffer.h:134
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:178
int GWEN_XmlCtx_AddComment(GWEN_XML_CONTEXT *ctx, const char *data)
Definition: xmlctx.c:335
#define GWEN_XML_FLAGS_INDENT
Definition: xml.h:66
const char * GWEN_XmlCtx_GetEncoding(const GWEN_XML_CONTEXT *ctx)
Definition: xmlctx.c:110
#define GWEN_BUFFER_MODE_READONLY
Definition: buffer.h:72
#define GWEN_XML_FLAGS_HANDLE_HEADERS
Definition: xml.h:94
GWENHYWFAR_API GWEN_SYNCIO * GWEN_SyncIo_File_new(const char *path, GWEN_SYNCIO_FILE_CREATIONMODE cm)
#define GWEN_FASTBUFFER_WRITELINE(fb, var, p)
Definition: fastbuffer.h:407
#define GWEN_XML_FLAGS_HANDLE_NAMESPACES
Definition: xml.h:105
#define GWEN_ERROR_INTERNAL
Definition: error.h:125
GWEN_XMLNODE_NAMESPACE * GWEN_XMLNode_NameSpace_List_Next(const GWEN_XMLNODE_NAMESPACE *element)
GWEN_FAST_BUFFER * GWEN_FastBuffer_new(uint32_t bsize, GWEN_SYNCIO *io)
Definition: fastbuffer.c:27
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:149
struct GWEN_XML_CONTEXT GWEN_XML_CONTEXT
Definition: xmlctx.h:39
#define GWEN_UNUSED
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1062
GWEN_XMLNODE_NAMESPACE * GWEN_XMLNode_NameSpace_List_First(const GWEN_XMLNODE_NAMESPACE_LIST *l)