Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TXMLEngine.cxx
Go to the documentation of this file.
1// @(#)root/xml:$Id: 1bd040ac1c03c58bcad15b5206d602680a831c0a $
2// Author: Sergey Linev 10.05.2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//________________________________________________________________________
13//
14// TXMLEngine class is used to write and read ROOT XML files - TXMLFile.
15// It does not conform to complete xml standard and cannot be used
16// as parser for arbitrary XML files. For such cases TXMLParser should
17// be used. This class was introduced to exclude dependency from
18// external libraries (like libxml2) and improve speed / memory consumption.
19//
20//________________________________________________________________________
21
22#include "TXMLEngine.h"
23
24#include "TString.h"
25#include "TNamed.h"
26#include "TObjArray.h"
27#include "strlcpy.h"
28#include "snprintf.h"
29
30#include <fstream>
31#include <cstdlib>
32#include <cstring>
33
35
36struct SXmlAttr_t {
38 // after structure itself memory for attribute name is preserved
39 // if first byte is 0, this is special attribute
40 static inline char *Name(void *arg) { return (char *)arg + sizeof(SXmlAttr_t); }
41};
42
44 kXML_NODE = 1, // normal node with children
45 kXML_COMMENT = 2, // comment (stored as value of node fName)
46 kXML_PI_NODE = 3, // processing instructions node (like <?name attr="" ?>
47 kXML_RAWLINE = 4, // just one line of xml code
48 kXML_CONTENT = 5 // node content, can appear many times in between of normal nodes
49};
50
51struct SXmlNode_t {
52 EXmlNodeType fType; // this is node type - node, comment, processing instruction and so on
53 SXmlAttr_t *fAttr; // first attribute
54 SXmlAttr_t *fNs; // name space definition (if any)
55 SXmlNode_t *fNext; // next node on the same level of hierarchy
56 SXmlNode_t *fChild; // first child node
57 SXmlNode_t *fLastChild; // last child node
58 SXmlNode_t *fParent; // parent node
59 // consequent bytes after structure are node name
60 // if first byte is 0, next is node content
61 static inline char *Name(void *arg) { return (char *)arg + sizeof(SXmlNode_t); }
62};
63
64struct SXmlDoc_t {
66 char *fDtdName;
67 char *fDtdRoot;
68};
69
71protected:
72 std::ostream *fOut{nullptr};
73 TString *fOutStr{nullptr};
74 char *fBuf{nullptr};
75 char *fCurrent{nullptr};
76 char *fMaxAddr{nullptr};
77 char *fLimitAddr{nullptr};
78
79public:
80 TXMLOutputStream(const char *filename, Int_t bufsize = 20000)
81 {
82 fOut = new std::ofstream(filename);
83 fOutStr = nullptr;
84 Init(bufsize);
85 }
86
87 TXMLOutputStream(TString *outstr, Int_t bufsize = 20000)
88 {
89 fOut = nullptr;
90 fOutStr = outstr;
91 Init(bufsize);
92 }
93
94 void Init(Int_t bufsize)
95 {
96 fBuf = (char *)malloc(bufsize);
97 fCurrent = fBuf;
98 fMaxAddr = fBuf + bufsize;
99 fLimitAddr = fBuf + int(bufsize * 0.75);
100 }
101
103 {
104 if (fCurrent != fBuf)
106 delete fOut;
107 free(fBuf);
108 }
109
111 {
112 if (fCurrent != fBuf) {
113 if (fOut)
114 fOut->write(fBuf, fCurrent - fBuf);
115 else if (fOutStr)
117 }
118 fCurrent = fBuf;
119 }
120
121 void OutputChar(char symb)
122 {
123 if (fOut)
124 fOut->put(symb);
125 else if (fOutStr)
126 fOutStr->Append(symb);
127 }
128
129 void Write(const char *str)
130 {
131 int len = strlen(str);
132 if (fCurrent + len >= fMaxAddr) {
134 if (fOut)
135 fOut->write(str, len);
136 else if (fOutStr)
137 fOutStr->Append(str, len);
138 } else {
139 while (*str)
140 *fCurrent++ = *str++;
141 if (fCurrent > fLimitAddr)
143 }
144 }
145
146 void Put(char symb, Int_t cnt = 1)
147 {
148 if (fCurrent + cnt >= fMaxAddr)
150 if (fCurrent + cnt >= fMaxAddr) {
151 for (int n = 0; n < cnt; n++)
152 OutputChar(symb);
153 } else {
154 for (int n = 0; n < cnt; n++)
155 *fCurrent++ = symb;
156 if (fCurrent > fLimitAddr)
158 }
159 }
160};
161
162class TXMLEntity : public TNamed {
163 Bool_t fSystem; //! is system (file)
164public:
166 TXMLEntity(const TString &name, const TString &value, Bool_t sys) : TNamed(name, value), fSystem(sys) {}
167 Bool_t IsSystem() const { return fSystem; }
168};
169
171protected:
172 std::istream *fInp;
173 const char *fInpStr;
175
176 char *fBuf;
178
179 char *fMaxAddr;
181
184
185 TObjArray fEntities; //! array of TXMLEntity
186
187public:
188 char *fCurrent;
189
190 ////////////////////////////////////////////////////////////////////////////
191 /// constructor
192
193 TXMLInputStream(Bool_t isfilename, const char *filename, Int_t ibufsize)
194 : fInp(nullptr), fInpStr(nullptr), fInpStrLen(0), fBuf(nullptr), fBufSize(0), fMaxAddr(nullptr), fLimitAddr(nullptr), fTotalPos(0),
195 fCurrentLine(0), fEntities(), fCurrent(nullptr)
196 {
197 if (isfilename) {
198 fInp = new std::ifstream(filename);
199 fInpStr = nullptr;
200 fInpStrLen = 0;
201 } else {
202 fInp = nullptr;
204 fInpStrLen = !filename ? 0 : strlen(filename);
205 }
206
207 fBufSize = ibufsize;
208 fBuf = (char *)malloc(fBufSize);
209
210 fCurrent = nullptr;
211 fMaxAddr = nullptr;
212
213 int len = DoRead(fBuf, fBufSize);
214 fCurrent = fBuf;
215 fMaxAddr = fBuf + len;
216 fLimitAddr = fBuf + int(len * 0.75);
217
218 fTotalPos = 0;
219 fCurrentLine = 1;
220
222 }
223
224 ////////////////////////////////////////////////////////////////////////////
225 /// destructor
226
228 {
229 delete fInp;
230 fInp = nullptr;
231 free(fBuf);
232 fBuf = nullptr;
233 }
234
235 ////////////////////////////////////////////////////////////////////////////
236 /// return true if end of file is achieved
237
238 inline Bool_t EndOfFile() { return fInp ? fInp->eof() : (fInpStrLen <= 0); }
239
240 ////////////////////////////////////////////////////////////////////////////
241 /// return true if end of file and all data from buffer are processed
242
243 inline Bool_t EndOfStream() { return EndOfFile() && (fCurrent >= fMaxAddr); }
244
245 ////////////////////////////////////////////////////////////////////////////
246 /// Add new entity
247
248 void AddEntity(TXMLEntity *ent) { fEntities.Add(ent); }
249
250 ////////////////////////////////////////////////////////////////////////////
251 /// Returns number of entity
252
253 Int_t NumEntities() const { return fEntities.GetLast() + 1; }
254
255 ////////////////////////////////////////////////////////////////////////////
256 /// Search for the entity
257
258 TXMLEntity *FindEntity(const char *beg, Int_t len)
259 {
260 if (len <= 0)
261 return nullptr;
262 for (Int_t n = 0; n <= fEntities.GetLast(); n++) {
263 TXMLEntity *entity = (TXMLEntity *)fEntities[n];
264 if ((Int_t)strlen(entity->GetName()) != len)
265 continue;
266 if (strncmp(beg, entity->GetName(), len) == 0)
267 return entity;
268 }
269 return nullptr;
270 }
271
272 ////////////////////////////////////////////////////////////////////////////
273 /// Read new data into buffer
274
275 int DoRead(char *buf, int maxsize)
276 {
277 if (EndOfFile())
278 return 0;
279
280 int resultsize = 0;
281 if (fInp) {
282 fInp->get(buf, maxsize, 0);
283 resultsize = strlen(buf);
284 } else {
285 resultsize = strlcpy(buf, fInpStr, maxsize);
286 if (resultsize >= maxsize)
287 resultsize = maxsize - 1;
288 fInpStr += resultsize;
289 fInpStrLen -= resultsize;
290 }
291 return resultsize;
292 }
293
294 ////////////////////////////////////////////////////////////////////////////
295 /// Allocate more data for the buffer, preserving content
296
297 Bool_t ExpandStream(char *&curr)
298 {
299 if (EndOfFile())
300 return kFALSE;
301 fBufSize *= 2;
302 int curlength = fMaxAddr - fBuf;
303 char *newbuf = (char *)realloc(fBuf, fBufSize);
304 if (!newbuf)
305 return kFALSE;
306
307 fMaxAddr = newbuf + (fMaxAddr - fBuf);
308 fCurrent = newbuf + (fCurrent - fBuf);
309 fLimitAddr = newbuf + (fLimitAddr - fBuf);
310 curr = newbuf + (curr - fBuf);
311 fBuf = newbuf;
312
313 int len = DoRead(fMaxAddr, fBufSize - curlength);
314 if (len == 0)
315 return kFALSE;
316 fMaxAddr += len;
317 fLimitAddr += int(len * 0.75);
318 return kTRUE;
319 }
320
321 ////////////////////////////////////////////////////////////////////////////
322 /// read next portion of data from the stream in the buffer
323
325 {
326 if (fCurrent < fLimitAddr)
327 return kTRUE; // everything ok, can continue
328 if (EndOfFile())
329 return kTRUE;
330 int rest_len = fMaxAddr - fCurrent;
331 memmove(fBuf, fCurrent, rest_len);
332 int read_len = DoRead(fBuf + rest_len, fBufSize - rest_len);
333
334 fCurrent = fBuf;
335 fMaxAddr = fBuf + rest_len + read_len;
336 fLimitAddr = fBuf + int((rest_len + read_len) * 0.75);
337 return kTRUE;
338 }
339
340 ////////////////////////////////////////////////////////////////////////////
341 /// returns absolute byte position in the stream
342
344
345 ////////////////////////////////////////////////////////////////////////////
346 /// returns current line number in the input stream
347
349
350 ////////////////////////////////////////////////////////////////////////////
351 /// shift current position on provided number of symbol
352
354 {
355 for (int n = 0; n < sz; n++) {
356 if (*fCurrent == 10)
357 fCurrentLine++;
358 if (fCurrent >= fLimitAddr) {
359 ShiftStream();
360 if (fCurrent >= fMaxAddr)
361 return kFALSE;
362 }
363 fCurrent++;
364 }
365 fTotalPos += sz;
366 return kTRUE;
367 }
368
369 ////////////////////////////////////////////////////////////////////////////
370 /// Skip spaces at the current position
371
373 {
374 while (fCurrent < fMaxAddr) {
375 char symb = *fCurrent;
376 if ((symb > 26) && (symb != ' '))
377 return kTRUE;
378
379 if (!ShiftCurrent())
380 return kFALSE;
381
382 if (tillendl && (symb == 10))
383 return kTRUE;
384 }
385 return kFALSE;
386 }
387
388 /////////////////////////////////////////////////////////////
389 /// Check if in current position we see specified string
390
391 Bool_t CheckFor(const char *str)
392 {
393 int len = strlen(str);
394 char *curr = fCurrent;
395 while (curr + len > fMaxAddr) {
396 if (!ExpandStream(curr))
397 return kFALSE;
398 }
399 while (*str != 0)
400 if (*str++ != *curr++)
401 return kFALSE;
402 return ShiftCurrent(len);
403 }
404
405 /////////////////////////////////////////////////////////////////////
406 /// Search for specified string in the stream
407 /// return number of symbols before string was found, -1 if error
408
409 Int_t SearchFor(const char *str)
410 {
411 int len = strlen(str);
412
413 char *curr = fCurrent;
414
415 while(true) {
416 while (curr + len > fMaxAddr)
417 if (!ExpandStream(curr))
418 return -1;
419 const char *chk0 = curr;
420 const char *chk = str;
421 Bool_t find = kTRUE;
422 while (*chk != 0)
423 if (*chk++ != *chk0++) {
424 find = kFALSE;
425 break;
426 }
427 // if string found, shift to the next symbol after string
428 if (find)
429 return curr - fCurrent;
430 curr++;
431 }
432 return -1;
433 }
434
435 ////////////////////////////////////////////////////////////////////////////
436 /// returns true if symbol can be used as starting in the node name
437
438 inline Bool_t GoodStartSymbol(unsigned char symb)
439 {
440 return (((symb >= 'a') && (symb <= 'z')) || ((symb >= 'A') && (symb <= 'Z')) || (symb == '_') ||
441 ((symb >= 0xc0) && (symb <= 0xd6)) || ((symb >= 0xd8) && (symb <= 0xf6)) || (symb > 0xf8));
442 }
443
444 ////////////////////////////////////////////////////////////////////////////
445 /// locate identifier in the stream, returns length of the identifier (or 0 if fails)
446
448 {
449 unsigned char symb = (unsigned char)*fCurrent;
450
451 Bool_t ok = GoodStartSymbol(symb);
452 if (!ok)
453 return 0;
454
455 char *curr = fCurrent;
456
457 do {
458 curr++;
459 if (curr >= fMaxAddr)
460 if (!ExpandStream(curr))
461 return 0;
462 symb = (unsigned char)*curr;
463 ok = GoodStartSymbol(symb) || ((symb >= '0') && (symb <= '9')) || (symb == ':') || (symb == '-') ||
464 (symb == '.') || (symb == 0xb7);
465 if (!ok)
466 return curr - fCurrent;
467 } while (curr < fMaxAddr);
468 return 0;
469 }
470
471 ////////////////////////////////////////////////////////////////////////////
472 /// locate node content, returns length (or -1 if fails)
473
475 {
476 char *curr = fCurrent;
477 while (curr < fMaxAddr) {
478 char symb = *curr;
479 if (symb == '<')
480 return curr - fCurrent;
481 curr++;
482 if (curr >= fMaxAddr)
483 if (!ExpandStream(curr))
484 return -1;
485 }
486 return -1;
487 }
488
489 ////////////////////////////////////////////////////////////////////////////
490 /// locate attribute value, returns length (or 0 if fails)
491
492 Int_t LocateValue(unsigned curr_offset, bool withequalsign = true)
493 {
494 char *curr = fCurrent + curr_offset;
495 if (curr >= fMaxAddr)
496 if (!ExpandStream(curr))
497 return 0;
498 if (withequalsign) {
499 if (*curr != '=')
500 return 0;
501 curr++;
502 if (curr >= fMaxAddr)
503 if (!ExpandStream(curr))
504 return 0;
505 }
506 if ((*curr != '\"') && (*curr != '\''))
507 return 0;
508 char quote = *curr;
509 do {
510 curr++;
511 if (curr >= fMaxAddr)
512 if (!ExpandStream(curr))
513 return 0;
514 if (*curr == quote)
515 return curr - (fCurrent + curr_offset) + 1;
516 } while (curr < fMaxAddr);
517 return 0;
518 }
519};
520
521////////////////////////////////////////////////////////////////////////////////
522/// default (normal) constructor of TXMLEngine class
523
525{
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// destructor for TXMLEngine object
531
533{
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// checks if node has attribute of specified name
538
540{
541 if (!xmlnode || !name)
542 return kFALSE;
543 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
544 while (attr) {
545 if (strcmp(SXmlAttr_t::Name(attr), name) == 0)
546 return kTRUE;
547 attr = attr->fNext;
548 }
549 return kFALSE;
550}
551
552////////////////////////////////////////////////////////////////////////////////
553/// returns value of attribute for xmlnode
554
555const char *TXMLEngine::GetAttr(XMLNodePointer_t xmlnode, const char *name)
556{
557 if (!xmlnode)
558 return nullptr;
559 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
560 while (attr) {
561 if (strcmp(SXmlAttr_t::Name(attr), name) == 0)
562 return SXmlAttr_t::Name(attr) + strlen(name) + 1;
563 attr = attr->fNext;
564 }
565 return nullptr;
566}
567
568////////////////////////////////////////////////////////////////////////////////
569/// returns value of attribute as integer
570
572{
573 if (!xmlnode)
574 return 0;
575 Int_t res = 0;
576 const char *attr = GetAttr(xmlnode, name);
577 if (attr)
578 sscanf(attr, "%d", &res);
579 return res;
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// creates new attribute for xmlnode,
584/// namespaces are not supported for attributes
585
587{
588 if (!xmlnode)
589 return nullptr;
590
591 int namelen = name ? strlen(name) : 0;
592 int valuelen = value ? strlen(value) : 0;
593 SXmlAttr_t *attr = (SXmlAttr_t *)AllocateAttr(namelen, valuelen, xmlnode);
594
595 char *attrname = SXmlAttr_t::Name(attr);
596 if (namelen > 0)
597 strncpy(attrname, name, namelen + 1);
598 else
599 *attrname = 0;
600 attrname += (namelen + 1);
601 if (valuelen > 0)
602 strncpy(attrname, value, valuelen + 1);
603 else
604 *attrname = 0;
605
606 return (XMLAttrPointer_t)attr;
607}
608
609////////////////////////////////////////////////////////////////////////////////
610/// create node attribute with integer value
611
613{
614 char sbuf[30];
615 snprintf(sbuf, 30, "%d", value);
616 return NewAttr(xmlnode, nullptr, name, sbuf);
617}
618
619////////////////////////////////////////////////////////////////////////////////
620/// remove attribute from xmlnode
621
623{
624 if (!xmlnode)
625 return;
626 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
627 SXmlAttr_t *prev = nullptr;
628 while (attr) {
629 if (strcmp(SXmlAttr_t::Name(attr), name) == 0) {
630 if (prev)
631 prev->fNext = attr->fNext;
632 else
633 ((SXmlNode_t *)xmlnode)->fAttr = attr->fNext;
634 // fNumNodes--;
635 free(attr);
636 return;
637 }
638
639 prev = attr;
640 attr = attr->fNext;
641 }
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Free all attributes of the node
646
648{
649 if (!xmlnode)
650 return;
651
652 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
653 SXmlAttr_t *attr = node->fAttr;
654 while (attr) {
655 SXmlAttr_t *next = attr->fNext;
656 free(attr);
657 attr = next;
658 }
659 node->fAttr = nullptr;
660}
661
662////////////////////////////////////////////////////////////////////////////////
663/// return first attribute in the list, namespace (if exists) will be skipped
664
666{
667 if (!xmlnode)
668 return nullptr;
669 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
670
671 SXmlAttr_t *attr = node->fAttr;
672 if (attr && (node->fNs == attr))
673 attr = attr->fNext;
674
675 return (XMLAttrPointer_t)attr;
676}
677
678////////////////////////////////////////////////////////////////////////////////
679/// return next attribute in the list
680
682{
683 if (!xmlattr)
684 return nullptr;
685
686 return (XMLAttrPointer_t)((SXmlAttr_t *)xmlattr)->fNext;
687}
688
689////////////////////////////////////////////////////////////////////////////////
690/// return name of the attribute
691
693{
694 if (!xmlattr)
695 return nullptr;
696
697 return SXmlAttr_t::Name(xmlattr);
698}
699
700////////////////////////////////////////////////////////////////////////////////
701/// return value of attribute
702
704{
705 if (!xmlattr)
706 return nullptr;
707
708 const char *attrname = SXmlAttr_t::Name(xmlattr);
709 return attrname + strlen(attrname) + 1;
710}
711
712////////////////////////////////////////////////////////////////////////////////
713/// create new child element for parent node
714
715XMLNodePointer_t TXMLEngine::NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content)
716{
717 int namelen = name ? strlen(name) : 0;
718
719 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(namelen, parent);
720
721 if (namelen > 0)
722 strncpy(SXmlNode_t::Name(node), name, namelen + 1);
723 else
724 *SXmlNode_t::Name(node) = 0;
725
726 node->fNs = (SXmlAttr_t *)ns;
727 int contlen = content ? strlen(content) : 0;
728 if (contlen > 0) {
729 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(contlen, node);
730 contnode->fType = kXML_CONTENT; // indicate that we creating content node
731 strncpy(SXmlNode_t::Name(contnode), content, contlen + 1);
732 }
733
734 return (XMLNodePointer_t)node;
735}
736
737////////////////////////////////////////////////////////////////////////////////
738/// create namespace attribute for xmlnode.
739/// namespace attribute will be always the first in list of node attributes
740
741XMLNsPointer_t TXMLEngine::NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name)
742{
743 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
744 if (!name)
745 name = SXmlNode_t::Name(node);
746 int namelen = strlen(name);
747 char *nsname = new char[namelen + 7];
748 snprintf(nsname, namelen + 7, "xmlns:%s", name);
749
750 SXmlAttr_t *first = node->fAttr;
751 node->fAttr = nullptr;
752
753 SXmlAttr_t *nsattr = (SXmlAttr_t *)NewAttr(xmlnode, nullptr, nsname, reference);
754
755 node->fAttr = nsattr;
756 nsattr->fNext = first;
757
758 node->fNs = nsattr;
759 delete[] nsname;
760 return (XMLNsPointer_t)nsattr;
761}
762
763////////////////////////////////////////////////////////////////////////////////
764/// return namespace attribute (if exists)
765
767{
768 if (!xmlnode)
769 return nullptr;
770 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
771
772 return (XMLNsPointer_t)node->fNs;
773}
774
775////////////////////////////////////////////////////////////////////////////////
776/// return name id of namespace
777
779{
780 const char *nsname = GetAttrName((XMLAttrPointer_t)ns);
781
782 if (nsname && (strncmp(nsname, "xmlns:", 6) == 0))
783 nsname += 6;
784
785 return nsname;
786}
787
788////////////////////////////////////////////////////////////////////////////////
789/// return reference id of namespace
790
792{
793 return GetAttrValue((XMLAttrPointer_t)ns);
794}
795
796////////////////////////////////////////////////////////////////////////////////
797/// add child element to xmlnode
798
800{
801 if (!parent || !child)
802 return;
803 SXmlNode_t *pnode = (SXmlNode_t *)parent;
804 SXmlNode_t *cnode = (SXmlNode_t *)child;
805
806 if (cnode->fParent)
808
809 cnode->fParent = pnode;
810 if (!pnode->fLastChild) {
811 pnode->fChild = cnode;
812 pnode->fLastChild = cnode;
813 } else {
814 // SXmlNode_t* ch = pnode->fChild;
815 // while (ch->fNext!=0) ch=ch->fNext;
816 pnode->fLastChild->fNext = cnode;
817 pnode->fLastChild = cnode;
818 }
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// add node as first child
823
825{
826 if (!parent || !child)
827 return;
828 SXmlNode_t *pnode = (SXmlNode_t *)parent;
829 SXmlNode_t *cnode = (SXmlNode_t *)child;
830
831 if (cnode->fParent)
833
834 cnode->fParent = pnode;
835
836 cnode->fNext = pnode->fChild;
837 pnode->fChild = cnode;
838
839 if (!pnode->fLastChild)
840 pnode->fLastChild = cnode;
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// Insert new child node after already existing node
845
847{
848 if (!afternode) {
849 AddChild(parent, child);
850 return;
851 }
852
853 SXmlNode_t *pnode = (SXmlNode_t *)parent;
854 SXmlNode_t *cnode = (SXmlNode_t *)child;
855 SXmlNode_t *anode = (SXmlNode_t *)afternode;
856
857 if (anode->fParent != pnode) {
858 Error("InsertChildAfter", "Specified afternode is not in childs list of parent node");
859 AddChild(parent, child);
860 return;
861 }
862
863 if (cnode->fParent)
865
866 cnode->fParent = pnode;
867
868 cnode->fNext = anode->fNext;
869 anode->fNext = cnode;
870
871 if (pnode->fLastChild == anode)
872 pnode->fLastChild = cnode;
873}
874
875////////////////////////////////////////////////////////////////////////////////
876/// Adds comment line to the node
877
878Bool_t TXMLEngine::AddComment(XMLNodePointer_t xmlnode, const char *comment)
879{
880 if (!xmlnode || !comment)
881 return kFALSE;
882
883 int commentlen = strlen(comment);
884
885 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(commentlen, xmlnode);
886 node->fType = kXML_COMMENT;
887 strncpy(SXmlNode_t::Name(node), comment, commentlen + 1);
888
889 return kTRUE;
890}
891
892////////////////////////////////////////////////////////////////////////////////
893/// add comment line to the top of the document
894
896{
897 if (!xmldoc)
898 return kFALSE;
899
900 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
901 UnlinkNode(rootnode);
902
903 Bool_t res = AddComment(((SXmlDoc_t *)xmldoc)->fRootNode, comment);
904
905 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
906
907 return res;
908}
909
910////////////////////////////////////////////////////////////////////////////////
911/// Add just line into xml file
912/// Line should has correct xml syntax that later it can be decoded by xml parser
913/// For instance, it can be comment or processing instructions
914
916{
917 if (!xmlnode || !line)
918 return kFALSE;
919
920 int linelen = strlen(line);
921 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(linelen, xmlnode);
922 node->fType = kXML_RAWLINE;
923 strncpy(SXmlNode_t::Name(node), line, linelen + 1);
924
925 return kTRUE;
926}
927
928////////////////////////////////////////////////////////////////////////////////
929/// Add just line on the top of xml document
930/// Line should has correct xml syntax that later it can be decoded by xml parser
931
933{
934 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
935 UnlinkNode(rootnode);
936
937 Bool_t res = AddRawLine(((SXmlDoc_t *)xmldoc)->fRootNode, line);
938
939 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
940
941 return res;
942}
943
944////////////////////////////////////////////////////////////////////////////////
945/// Adds style sheet definition to the specified node
946/// Creates <?xml-stylesheet alternate="yes" title="compact" href="small-base.css" type="text/css"?>
947/// Attributes href and type must be supplied,
948/// other attributes: title, alternate, media, charset are optional
949/// if alternate==0, attribute alternate="no" will be created,
950/// if alternate>0, attribute alternate="yes"
951/// if alternate<0, attribute will not be created
952
953Bool_t TXMLEngine::AddStyleSheet(XMLNodePointer_t xmlnode, const char *href, const char *type, const char *title,
954 int alternate, const char *media, const char *charset)
955{
956 if (!xmlnode || !href || !type)
957 return kFALSE;
958
959 const char *nodename = "xml-stylesheet";
960 int nodenamelen = strlen(nodename);
961
962 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(nodenamelen, xmlnode);
963 node->fType = kXML_PI_NODE;
964 strncpy(SXmlNode_t::Name(node), nodename, nodenamelen + 1);
965
966 if (alternate >= 0)
967 NewAttr(node, nullptr, "alternate", (alternate > 0) ? "yes" : "no");
968
969 if (title)
970 NewAttr(node, nullptr, "title", title);
971
972 NewAttr(node, nullptr, "href", href);
973 NewAttr(node, nullptr, "type", type);
974
975 if (media)
976 NewAttr(node, nullptr, "media", media);
977 if (charset)
978 NewAttr(node, nullptr, "charset", charset);
979
980 return kTRUE;
981}
982
983////////////////////////////////////////////////////////////////////////////////
984/// Add style sheet definition on the top of document
985
986Bool_t TXMLEngine::AddDocStyleSheet(XMLDocPointer_t xmldoc, const char *href, const char *type, const char *title,
987 int alternate, const char *media, const char *charset)
988{
989 if (!xmldoc)
990 return kFALSE;
991
992 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
993 UnlinkNode(rootnode);
994
995 Bool_t res = AddStyleSheet(((SXmlDoc_t *)xmldoc)->fRootNode, href, type, title, alternate, media, charset);
996
997 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
998
999 return res;
1000}
1001
1002////////////////////////////////////////////////////////////////////////////////
1003/// unlink (detach) xmlnode from parent
1004
1006{
1007 if (!xmlnode)
1008 return;
1009
1010 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1011 SXmlNode_t *parent = node->fParent;
1012
1013 if (!parent)
1014 return;
1015
1016 if (parent->fChild == node) {
1017 parent->fChild = node->fNext;
1018 if (parent->fLastChild == node)
1019 parent->fLastChild = node->fNext;
1020 } else {
1021 SXmlNode_t *ch = parent->fChild;
1022 while (ch->fNext != node)
1023 ch = ch->fNext;
1024 ch->fNext = node->fNext;
1025 if (parent->fLastChild == node)
1026 parent->fLastChild = ch;
1027 }
1028
1029 node->fParent = nullptr;
1030 node->fNext = nullptr;
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// release all memory, allocated from this node and
1035/// destroys node itself
1036
1038{
1039 if (!xmlnode)
1040 return;
1041 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1042
1043 SXmlNode_t *child = node->fChild;
1044 while (child) {
1045 SXmlNode_t *next = child->fNext;
1047 child = next;
1048 }
1049
1050 SXmlAttr_t *attr = node->fAttr;
1051 while (attr) {
1052 SXmlAttr_t *next = attr->fNext;
1053 // fNumNodes--;
1054 free(attr);
1055 attr = next;
1056 }
1057
1058 free(node);
1059
1060 // fNumNodes--;
1061}
1062
1063////////////////////////////////////////////////////////////////////////////////
1064/// combined operation. Unlink node and free used memory
1065
1067{
1068 UnlinkNode(xmlnode);
1069 FreeNode(xmlnode);
1070}
1071
1072////////////////////////////////////////////////////////////////////////////////
1073/// returns name of xmlnode
1074
1076{
1077 return !xmlnode ? nullptr : SXmlNode_t::Name(xmlnode);
1078}
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// get contents (if any) of xmlnode
1082
1084{
1085 if (!xmlnode)
1086 return nullptr;
1087 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1088 if (!node->fChild)
1089 return nullptr;
1090
1091 if (node->fChild->fType != kXML_CONTENT)
1092 return nullptr;
1093
1094 return SXmlNode_t::Name(node->fChild);
1095}
1096
1097////////////////////////////////////////////////////////////////////////////////
1098/// set content of the xmlnode
1099/// if old node content was exists, it will be replaced
1100
1101void TXMLEngine::SetNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len)
1102{
1103 if (!xmlnode)
1104 return;
1105 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1106 if (node->fChild && (node->fChild->fType == kXML_CONTENT))
1108
1109 if (!content)
1110 return;
1111 if (len <= 0)
1112 len = strlen(content);
1113
1114 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(len, nullptr);
1115 char *nameptr = SXmlNode_t::Name(contnode);
1116 contnode->fType = kXML_CONTENT;
1117 strncpy(nameptr, content, len);
1118 nameptr += len;
1119 *nameptr = 0; // here we add padding 0 to get normal string
1120
1121 AddChildFirst(xmlnode, (XMLNodePointer_t)contnode);
1122}
1123
1124////////////////////////////////////////////////////////////////////////////////
1125/// add new content of the xmlnode
1126/// old content will be preserved, one could mix content with child nodes
1127
1128void TXMLEngine::AddNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len)
1129{
1130 if (!xmlnode || !content)
1131 return;
1132 if (len <= 0)
1133 len = strlen(content);
1134
1135 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(len, xmlnode);
1136 char *nameptr = SXmlNode_t::Name(contnode);
1137 contnode->fType = kXML_CONTENT;
1138 strncpy(nameptr, content, len);
1139 nameptr += len;
1140 *nameptr = 0; // here we add padding 0 to get normal string
1141}
1142
1143////////////////////////////////////////////////////////////////////////////////
1144/// returns first child of xmlnode
1145
1147{
1148 XMLNodePointer_t res = !xmlnode ? nullptr : ((SXmlNode_t *)xmlnode)->fChild;
1149 // skip content(s) node, if specified
1150 if (realnode && res && (((SXmlNode_t *)res)->fType != kXML_NODE))
1151 ShiftToNext(res, kTRUE);
1152 return res;
1153}
1154
1155////////////////////////////////////////////////////////////////////////////////
1156/// returns parent of xmlnode
1157
1159{
1160 return !xmlnode ? nullptr : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fParent;
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// return next to xmlnode node
1165/// if realnode==kTRUE, any special nodes in between will be skipped
1166
1168{
1169 do {
1170 xmlnode = !xmlnode ? nullptr : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fNext;
1171 if (!xmlnode || !realnode)
1172 return xmlnode;
1173 } while (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1174
1175 return xmlnode;
1176}
1177
1178////////////////////////////////////////////////////////////////////////////////
1179/// shifts specified node to next
1180/// if realnode==kTRUE, any special nodes in between will be skipped
1181
1183{
1184 do {
1185 xmlnode = !xmlnode ? nullptr : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fNext;
1186 if (!xmlnode || !realnode)
1187 return;
1188 } while (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1189}
1190
1191////////////////////////////////////////////////////////////////////////////////
1192/// return kTRUE is this is normal xmlnode
1193
1195{
1196 return !xmlnode ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_NODE);
1197}
1198
1199////////////////////////////////////////////////////////////////////////////////
1200/// return kTRUE is this is node with special data like comments to data processing instructions
1201
1203{
1204 return !xmlnode ? kTRUE : (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1205}
1206
1207////////////////////////////////////////////////////////////////////////////////
1208/// return kTRUE is this is special node with content
1209
1211{
1212 return !xmlnode ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_CONTENT);
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// return kTRUE is this is special node with content
1217
1219{
1220 return !xmlnode ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_COMMENT);
1221}
1222
1223////////////////////////////////////////////////////////////////////////////////
1224/// Skip all current empty nodes and locate on first "true" node
1225
1227{
1228 if (IsEmptyNode(xmlnode))
1229 ShiftToNext(xmlnode);
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// remove all children node from xmlnode
1234
1236{
1237 if (!xmlnode)
1238 return;
1239 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1240
1241 SXmlNode_t *child = node->fChild;
1242 while (child) {
1243 SXmlNode_t *next = child->fNext;
1245 child = next;
1246 }
1247
1248 node->fChild = nullptr;
1249 node->fLastChild = nullptr;
1250}
1251
1252////////////////////////////////////////////////////////////////////////////////
1253/// creates new xml document with provided version
1254
1256{
1257 SXmlDoc_t *doc = new SXmlDoc_t;
1258 doc->fRootNode = (SXmlNode_t *)NewChild(nullptr, nullptr, "??DummyTopNode??", nullptr);
1259
1260 if (version) {
1261 XMLNodePointer_t vernode = NewChild((XMLNodePointer_t)doc->fRootNode, nullptr, "xml");
1262 ((SXmlNode_t *)vernode)->fType = kXML_PI_NODE;
1263 NewAttr(vernode, nullptr, "version", version);
1264 }
1265
1266 doc->fDtdName = nullptr;
1267 doc->fDtdRoot = nullptr;
1268 return (XMLDocPointer_t)doc;
1269}
1270
1271////////////////////////////////////////////////////////////////////////////////
1272/// assigns dtd filename to document
1273
1274void TXMLEngine::AssignDtd(XMLDocPointer_t xmldoc, const char *dtdname, const char *rootname)
1275{
1276 if (!xmldoc)
1277 return;
1278 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1279 delete[] doc->fDtdName;
1280 doc->fDtdName = Makestr(dtdname);
1281 delete[] doc->fDtdRoot;
1282 doc->fDtdRoot = Makestr(rootname);
1283}
1284
1285////////////////////////////////////////////////////////////////////////////////
1286/// frees allocated document data and deletes document itself
1287
1289{
1290 if (!xmldoc)
1291 return;
1292 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1294 delete[] doc->fDtdName;
1295 delete[] doc->fDtdRoot;
1296 delete doc;
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// store document content to file
1301/// if layout<=0, no any spaces or newlines will be placed between
1302/// xmlnodes. Xml file will have minimum size, but non-readable structure
1303/// if (layout>0) each node will be started from new line,
1304/// and number of spaces will correspond to structure depth.
1305
1306void TXMLEngine::SaveDoc(XMLDocPointer_t xmldoc, const char *filename, Int_t layout)
1307{
1308 if (!xmldoc)
1309 return;
1310
1311 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1312
1313 TXMLOutputStream out(filename, 100000);
1314
1316
1317 do {
1318 SaveNode(child, &out, layout, 0);
1320 } while (child);
1321}
1322
1323////////////////////////////////////////////////////////////////////////////////
1324/// set main (root) node for document
1325
1327{
1328 if (!xmldoc)
1329 return;
1330
1331 FreeNode(DocGetRootElement(xmldoc));
1332
1333 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, xmlnode);
1334}
1335
1336////////////////////////////////////////////////////////////////////////////////
1337/// returns root node of document
1338
1340{
1341 if (!xmldoc)
1342 return nullptr;
1343
1344 XMLNodePointer_t xmlnode = (XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode;
1345
1346 // typically first child of XML document is version
1347 // therefore just skip it when returning root node of document
1348 return GetChild(xmlnode, kTRUE);
1349}
1350
1351////////////////////////////////////////////////////////////////////////////////
1352/// Parses content of file and tries to produce xml structures.
1353/// The maxbuf argument specifies the max size of the XML file to be
1354/// parsed. The default value is 100000.
1355
1357{
1358 if (!filename || !*filename)
1359 return nullptr;
1360 if (maxbuf < 100000)
1361 maxbuf = 100000;
1362 TXMLInputStream inp(true, filename, maxbuf);
1363 return ParseStream(&inp);
1364}
1365
1366////////////////////////////////////////////////////////////////////////////////
1367/// parses content of string and tries to produce xml structures
1368
1370{
1371 if (!xmlstring || !*xmlstring)
1372 return nullptr;
1373 TXMLInputStream inp(false, xmlstring, 100000);
1374 return ParseStream(&inp);
1375}
1376
1377////////////////////////////////////////////////////////////////////////////////
1378/// parses content of the stream and tries to produce xml structures
1379
1381{
1382 if (!inp)
1383 return nullptr;
1384
1385 XMLDocPointer_t xmldoc = NewDoc(nullptr);
1386
1387 Bool_t success = false;
1388
1389 Int_t resvalue = 0;
1390
1391 do {
1392 ReadNode(((SXmlDoc_t *)xmldoc)->fRootNode, inp, resvalue);
1393
1394 if (resvalue != 2)
1395 break;
1396
1397 // coverity[unchecked_value] at this place result of SkipSpaces() doesn't matter - either file is finished (false)
1398 // or there is some more nodes to analyse (true)
1399 if (!inp->EndOfStream())
1400 inp->SkipSpaces();
1401
1402 if (inp->EndOfStream()) {
1403 success = true;
1404 break;
1405 }
1406 } while (true);
1407
1408 if (!success) {
1409 DisplayError(resvalue, inp->CurrentLine());
1410 FreeDoc(xmldoc);
1411 return nullptr;
1412 }
1413
1414 return xmldoc;
1415}
1416
1417////////////////////////////////////////////////////////////////////////////////
1418/// check that first node is xml processing instruction with correct xml version number
1419
1421{
1422 if (!xmldoc)
1423 return kFALSE;
1424
1425 XMLNodePointer_t vernode = GetChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, kFALSE);
1426 if (!vernode)
1427 return kFALSE;
1428
1429 if (((SXmlNode_t *)vernode)->fType != kXML_PI_NODE)
1430 return kFALSE;
1431 if (strcmp(GetNodeName(vernode), "xml") != 0)
1432 return kFALSE;
1433
1434 const char *value = GetAttr(vernode, "version");
1435 if (!value)
1436 return kFALSE;
1437 if (!version)
1438 version = "1.0";
1439
1440 return strcmp(version, value) == 0;
1441}
1442
1443////////////////////////////////////////////////////////////////////////////////
1444/// convert single xmlnode (and its child node) to string
1445/// if layout<=0, no any spaces or newlines will be placed between
1446/// xmlnodes. Xml file will have minimum size, but non-readable structure
1447/// if (layout>0) each node will be started from new line,
1448/// and number of spaces will correspond to structure depth.
1449
1451{
1452 if (!res || !xmlnode)
1453 return;
1454
1455 TXMLOutputStream out(res, 10000);
1456
1457 SaveNode(xmlnode, &out, layout, 0);
1458}
1459
1460////////////////////////////////////////////////////////////////////////////////
1461/// read single xmlnode from provided string
1462
1464{
1465 if (!src)
1466 return nullptr;
1467
1468 TXMLInputStream inp(false, src, 10000);
1469
1470 Int_t resvalue;
1471
1472 XMLNodePointer_t xmlnode = ReadNode(nullptr, &inp, resvalue);
1473
1474 if (resvalue <= 0) {
1475 DisplayError(resvalue, inp.CurrentLine());
1476 FreeNode(xmlnode);
1477 return nullptr;
1478 }
1479
1480 return xmlnode;
1481}
1482
1483////////////////////////////////////////////////////////////////////////////////
1484/// creates char* variable with copy of provided string
1485
1486char *TXMLEngine::Makestr(const char *str)
1487{
1488 if (!str)
1489 return nullptr;
1490 int len = strlen(str);
1491 if (len == 0)
1492 return nullptr;
1493 char *res = new char[len + 1];
1494 strncpy(res, str, len + 1);
1495 return res;
1496}
1497
1498////////////////////////////////////////////////////////////////////////////////
1499/// creates char* variable with copy of len symbols from provided string
1500
1501char *TXMLEngine::Makenstr(const char *str, int len)
1502{
1503 if (!str || (len == 0))
1504 return nullptr;
1505 char *res = new char[len + 1];
1506 strncpy(res, str, len);
1507 *(res + len) = 0;
1508 return res;
1509}
1510
1511////////////////////////////////////////////////////////////////////////////////
1512/// Allocates new xml node with specified name length
1513
1515{
1516 // fNumNodes++;
1517
1518 SXmlNode_t *node = (SXmlNode_t *)malloc(sizeof(SXmlNode_t) + namelen + 1);
1519
1520 node->fType = kXML_NODE;
1521 node->fParent = nullptr;
1522 node->fNs = nullptr;
1523 node->fAttr = nullptr;
1524 node->fChild = nullptr;
1525 node->fLastChild = nullptr;
1526 node->fNext = nullptr;
1527
1528 if (parent)
1529 AddChild(parent, (XMLNodePointer_t)node);
1530
1531 return (XMLNodePointer_t)node;
1532}
1533
1534////////////////////////////////////////////////////////////////////////////////
1535/// Allocate new attribute with specified name length and value length
1536
1538{
1539 // fNumNodes++;
1540
1541 SXmlAttr_t *attr = (SXmlAttr_t *)malloc(sizeof(SXmlAttr_t) + namelen + 1 + valuelen + 1);
1542
1543 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1544
1545 attr->fNext = nullptr;
1546
1547 if (!node->fAttr) {
1548 node->fAttr = attr;
1549 } else {
1550 SXmlAttr_t *d = node->fAttr;
1551 while (d->fNext)
1552 d = d->fNext;
1553 d->fNext = attr;
1554 }
1555
1556 return (XMLAttrPointer_t)attr;
1557}
1558
1559////////////////////////////////////////////////////////////////////////////////
1560/// define if namespace of that name exists for xmlnode
1561
1563{
1564 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1565 while (node) {
1566 if (node->fNs) {
1567 const char *nsname = SXmlAttr_t::Name(node->fNs) + 6;
1568 if (strcmp(nsname, name) == 0)
1569 return node->fNs;
1570 }
1571 node = node->fParent;
1572 }
1573 return nullptr;
1574}
1575
1576////////////////////////////////////////////////////////////////////////////////
1577/// removes namespace extension of nodename
1578
1580{
1581 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1582 if (!node)
1583 return;
1584 char *colon = strchr(SXmlNode_t::Name(node), ':');
1585 if (!colon)
1586 return;
1587
1588 char *copyname = SXmlNode_t::Name(node);
1589
1590 while (*colon != 0)
1591 *(copyname++) = *(++colon);
1592}
1593
1594////////////////////////////////////////////////////////////////////////////////
1595/// unpack special symbols, used in xml syntax to code characters
1596/// these symbols: '<' - &lt, '>' - &gt, '&' - &amp, '"' - &quot, ''' - &apos
1597
1598void TXMLEngine::UnpackSpecialCharacters(char *target, const char *source, int srclen)
1599{
1600 while (srclen > 0) {
1601 if (*source == '&') {
1602 if ((srclen > 3) && (*(source + 1) == 'l') && (*(source + 2) == 't') && (*(source + 3) == ';')) {
1603 *target++ = '<';
1604 source += 4;
1605 srclen -= 4;
1606 } else if ((srclen > 3) && (*(source + 1) == 'g') && (*(source + 2) == 't') && (*(source + 3) == ';')) {
1607 *target++ = '>';
1608 source += 4;
1609 srclen -= 4;
1610 } else if ((srclen > 4) && (*(source + 1) == 'a') && (*(source + 2) == 'm') && (*(source + 3) == 'p') &&
1611 (*(source + 4) == ';')) {
1612 *target++ = '&';
1613 source += 5;
1614 srclen -= 5;
1615 } else if ((srclen > 5) && (*(source + 1) == 'q') && (*(source + 2) == 'u') && (*(source + 3) == 'o') &&
1616 (*(source + 4) == 't') && (*(source + 5) == ';')) {
1617 *target++ = '\"';
1618 source += 6;
1619 srclen -= 6;
1620 } else if ((srclen > 5) && (*(source + 1) == 'a') && (*(source + 2) == 'p') && (*(source + 3) == 'o') &&
1621 (*(source + 4) == 's') && (*(source + 5) == ';')) {
1622 *target++ = '\'';
1623 source += 6;
1624 srclen -= 6;
1625 } else {
1626 *target++ = *source++;
1627 srclen--;
1628 }
1629 } else {
1630 *target++ = *source++;
1631 srclen--;
1632 }
1633 }
1634 *target = 0;
1635}
1636
1637////////////////////////////////////////////////////////////////////////////////
1638/// output value to output stream
1639/// if symbols '<' '&' '>' '"' ''' appears in the string, they
1640/// will be encoded to appropriate xml symbols: &lt, &amp, &gt, &quot, &apos
1641
1643{
1644 if (!value)
1645 return;
1646
1647 char *last = value;
1648 char *find = nullptr;
1649 while ((find = strpbrk(last, "<&>\"")) != nullptr) {
1650 char symb = *find;
1651 *find = 0;
1652 out->Write(last);
1653 *find = symb;
1654 last = find + 1;
1655 if (symb == '<')
1656 out->Write("&lt;");
1657 else if (symb == '>')
1658 out->Write("&gt;");
1659 else if (symb == '&')
1660 out->Write("&amp;");
1661 else if (symb == '\'')
1662 out->Write("&apos;");
1663 else
1664 out->Write("&quot;");
1665 }
1666 if (*last != 0)
1667 out->Write(last);
1668}
1669
1670////////////////////////////////////////////////////////////////////////////////
1671/// stream data of xmlnode to output
1672
1674{
1675 if (!xmlnode)
1676 return;
1677 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1678
1679 Bool_t issingleline = (node->fChild == nullptr);
1680
1681 if (layout > 0)
1682 out->Put(' ', level);
1683
1684 if (node->fType == kXML_COMMENT) {
1685 out->Write("<!--");
1686 out->Write(SXmlNode_t::Name(node));
1687 out->Write("-->");
1688 if (layout > 0)
1689 out->Put('\n');
1690 return;
1691 } else if (node->fType == kXML_RAWLINE) {
1692 out->Write(SXmlNode_t::Name(node));
1693 if (layout > 0)
1694 out->Put('\n');
1695 return;
1696 } else if (node->fType == kXML_CONTENT) {
1697 out->Write(SXmlNode_t::Name(node));
1698 if (layout > 0)
1699 out->Put('\n');
1700 return;
1701 }
1702
1703 out->Put('<');
1704 if (node->fType == kXML_PI_NODE)
1705 out->Put('?');
1706
1707 // we suppose that ns is always first attribute
1708 if (node->fNs && (node->fNs != node->fAttr)) {
1709 out->Write(SXmlAttr_t::Name(node->fNs) + 6);
1710 out->Put(':');
1711 }
1712 out->Write(SXmlNode_t::Name(node));
1713
1714 SXmlAttr_t *attr = node->fAttr;
1715 while (attr) {
1716 out->Put(' ');
1717 char *attrname = SXmlAttr_t::Name(attr);
1718 out->Write(attrname);
1719 out->Write("=\"");
1720 attrname += strlen(attrname) + 1;
1721 OutputValue(attrname, out);
1722 out->Put('\"');
1723 attr = attr->fNext;
1724 }
1725
1726 // if single line, close node with "/>" and return
1727 if (issingleline) {
1728 if (node->fType == kXML_PI_NODE)
1729 out->Write("?>");
1730 else
1731 out->Write("/>");
1732 if (layout > 0)
1733 out->Put('\n');
1734 return;
1735 }
1736
1737 out->Put('>');
1738
1739 SXmlNode_t *child = node->fChild;
1740
1741 if (child && (child->fType == kXML_CONTENT) && !child->fNext) {
1742 // special case when single content node is exists
1743 out->Write(SXmlNode_t::Name(child));
1744 } else {
1745 if (layout > 0)
1746 out->Put('\n');
1747 while (child) {
1748 SaveNode((XMLNodePointer_t)child, out, layout, level + 2);
1749 child = child->fNext;
1750 }
1751 // add starting spaces before closing node
1752 if (layout > 0)
1753 out->Put(' ', level);
1754 }
1755
1756 out->Write("</");
1757 // we suppose that ns is always first attribute
1758 if (node->fNs && (node->fNs != node->fAttr)) {
1759 out->Write(SXmlAttr_t::Name(node->fNs) + 6);
1760 out->Put(':');
1761 }
1762 out->Write(SXmlNode_t::Name(node));
1763 out->Put('>');
1764 if (layout > 0)
1765 out->Put('\n');
1766}
1767
1768////////////////////////////////////////////////////////////////////////////////
1769/// Tries to construct xml node from input stream. Node should be
1770/// child of xmlparent node or it can be closing tag of xmlparent.
1771/// resvalue <= 0 if error
1772/// resvalue == 1 if this is endnode of parent
1773/// resvalue == 2 if this is child
1774
1776{
1777 resvalue = 0;
1778
1779 if (!inp)
1780 return nullptr;
1781
1782 if (!inp->SkipSpaces()) {
1783 resvalue = -1;
1784 return nullptr;
1785 }
1786 SXmlNode_t *parent = (SXmlNode_t *)xmlparent;
1787
1788 SXmlNode_t *node = nullptr;
1789
1790 // process comments before we start to analyse any node symbols
1791 while (inp->CheckFor("<!--")) {
1792 Int_t commentlen = inp->SearchFor("-->");
1793 if (commentlen < 0) {
1794 resvalue = -10;
1795 return nullptr;
1796 }
1797
1798 if (!fSkipComments) {
1799 node = (SXmlNode_t *)AllocateNode(commentlen, xmlparent);
1800 char *nameptr = SXmlNode_t::Name(node);
1801 node->fType = kXML_COMMENT;
1802 strncpy(nameptr, inp->fCurrent, commentlen); // here copy only content, there is no padding 0 at the end
1803 nameptr += commentlen;
1804 *nameptr = 0; // here we add padding 0 to get normal string
1805 }
1806
1807 if (!inp->ShiftCurrent(commentlen + 3)) {
1808 resvalue = -1;
1809 return node;
1810 }
1811 if (!inp->SkipSpaces() && !inp->EndOfStream()) {
1812 resvalue = -1;
1813 return node;
1814 }
1815
1816 resvalue = 2;
1817 return node;
1818 }
1819
1820 if (*inp->fCurrent != '<') {
1821 // here should be reading of element content
1822 // now one can have content at any place of the node, also after childs
1823 if (!parent) {
1824 resvalue = -2;
1825 return nullptr;
1826 }
1827 int contlen = inp->LocateContent();
1828 if (contlen < 0)
1829 return nullptr;
1830
1831 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(contlen, xmlparent);
1832 contnode->fType = kXML_CONTENT;
1833 char *contptr = SXmlNode_t::Name(contnode);
1834 UnpackSpecialCharacters(contptr, inp->fCurrent, contlen);
1835 if (!inp->ShiftCurrent(contlen))
1836 return nullptr;
1837
1838 if (inp->NumEntities() <= 0) {
1839 resvalue = 2;
1840 return contnode;
1841 }
1842
1843 // analyze content on possible includes only when ENTITY was specified for document
1844
1845 const char *beg = nullptr, *lastentity = nullptr, *curr = contptr;
1846
1847 while (*curr != 0) {
1848 if (!beg && (*curr == '&'))
1849 beg = curr;
1850 if (!beg || (*curr != ';')) {
1851 curr++;
1852 continue;
1853 }
1854
1855 TXMLEntity *entity = inp->FindEntity(beg + 1, curr - beg - 1);
1856
1857 if (entity) {
1858
1859 if (!lastentity) {
1860 lastentity = contptr;
1861 UnlinkNode(contnode);
1862 }
1863
1864 if (lastentity != beg)
1865 AddNodeContent(xmlparent, lastentity, beg - lastentity);
1866
1867 if (entity->IsSystem()) {
1868 XMLDocPointer_t entitydoc = ParseFile(entity->GetTitle());
1869 if (!entitydoc) {
1870 resvalue = -14;
1871 return contnode;
1872 }
1873
1874 XMLNodePointer_t topnode = DocGetRootElement(entitydoc);
1875
1876 while (topnode) {
1877 XMLNodePointer_t currnode = topnode;
1878 ShiftToNext(topnode, false);
1879 UnlinkNode(currnode);
1880 AddChild(xmlparent, currnode);
1881 }
1882 } else {
1883 AddNodeContent(xmlparent, entity->GetTitle());
1884 }
1885 }
1886
1887 beg = nullptr;
1888 curr++;
1889
1890 lastentity = curr;
1891 }
1892
1893 if (lastentity) {
1894 // add rest part of the content
1895 if (strlen(lastentity) > 0)
1896 AddNodeContent(xmlparent, lastentity);
1897 // do not forget to cleanup content node
1898 FreeNode(contnode);
1899 contnode = nullptr;
1900 }
1901
1902 resvalue = 2;
1903 return contnode;
1904 } else {
1905 // skip "<" symbol
1906 if (!inp->ShiftCurrent())
1907 return nullptr;
1908 }
1909
1910 if (*inp->fCurrent == '/') {
1911 // this is a starting of closing node
1912 if (!inp->ShiftCurrent())
1913 return nullptr;
1914 if (!inp->SkipSpaces())
1915 return nullptr;
1916 Int_t len = inp->LocateIdentifier();
1917 if (len <= 0) {
1918 resvalue = -3;
1919 return nullptr;
1920 }
1921
1922 if (!parent) {
1923 resvalue = -4;
1924 return nullptr;
1925 }
1926
1927 if (strncmp(SXmlNode_t::Name(parent), inp->fCurrent, len) != 0) {
1928 resvalue = -5;
1929 return nullptr;
1930 }
1931
1932 if (!inp->ShiftCurrent(len))
1933 return nullptr;
1934
1935 if (!inp->SkipSpaces())
1936 return nullptr;
1937 if (*inp->fCurrent != '>')
1938 return nullptr;
1939 if (!inp->ShiftCurrent())
1940 return nullptr;
1941
1942 if (parent->fNs)
1944
1945 inp->SkipSpaces(kTRUE); // locate start of next string
1946 resvalue = 1;
1947 return nullptr;
1948 }
1949
1950 if (*inp->fCurrent == '!') {
1951 // this is start of DTD reading, only limited number of features are supported
1952 if (!inp->ShiftCurrent())
1953 return nullptr;
1954 if (!inp->CheckFor("DOCTYPE")) {
1955 resvalue = -12;
1956 return nullptr;
1957 }
1958 if (!inp->SkipSpaces()) {
1959 resvalue = -13;
1960 return nullptr;
1961 }
1962
1963 // now skip name of the root element - it is not verified at all
1964 Int_t len = inp->LocateIdentifier();
1965 if (len <= 0) {
1966 resvalue = -13;
1967 return nullptr;
1968 }
1969 if (!inp->ShiftCurrent(len)) {
1970 resvalue = -13;
1971 return nullptr;
1972 }
1973 if (!inp->SkipSpaces()) {
1974 resvalue = -13;
1975 return nullptr;
1976 }
1977
1978 // this is start of reading ENTITIES
1979 if (inp->CheckFor("[")) {
1980 if (!inp->SkipSpaces())
1981 return nullptr;
1982 while (true) {
1983 if (inp->CheckFor("<!ENTITY")) {
1984 // process ENTITY from DTD
1985 if (!inp->SkipSpaces()) {
1986 resvalue = -13;
1987 return nullptr;
1988 }
1989 Int_t namelen = inp->LocateIdentifier();
1990 if (namelen <= 0) {
1991 resvalue = -13;
1992 return nullptr;
1993 }
1994 TString entity_name(inp->fCurrent, namelen);
1995 if (!inp->ShiftCurrent(namelen)) {
1996 resvalue = -13;
1997 return nullptr;
1998 }
1999 if (!inp->SkipSpaces()) {
2000 resvalue = -13;
2001 return nullptr;
2002 }
2003 Bool_t is_system = kFALSE;
2004 if (inp->CheckFor("SYSTEM")) {
2005 if (!inp->SkipSpaces()) {
2006 resvalue = -13;
2007 return nullptr;
2008 }
2009 is_system = kTRUE;
2010 }
2011
2012 Int_t valuelen = inp->LocateValue(0, false);
2013 if (valuelen < 2) {
2014 resvalue = -13;
2015 return nullptr;
2016 }
2017
2018 TString entity_value(inp->fCurrent + 1, valuelen - 2);
2019
2020 if (!inp->ShiftCurrent(valuelen)) {
2021 resvalue = -13;
2022 return nullptr;
2023 }
2024 inp->SkipSpaces();
2025 if (*inp->fCurrent != '>') {
2026 resvalue = -13;
2027 return nullptr;
2028 }
2029 if (!inp->ShiftCurrent()) {
2030 resvalue = -13;
2031 return nullptr;
2032 }
2033 inp->SkipSpaces();
2034
2035 inp->AddEntity(new TXMLEntity(entity_name, entity_value, is_system));
2036 continue;
2037 }
2038
2039 if (inp->CheckFor("<!ELEMENT")) {
2040 // process ELEMENT from DTD - dummy at the moment
2041 if (!inp->SkipSpaces()) {
2042 resvalue = -13;
2043 return nullptr;
2044 }
2045 Int_t namelen = inp->LocateIdentifier();
2046 if (namelen <= 0) {
2047 resvalue = -13;
2048 return nullptr;
2049 }
2050
2051 if (!inp->ShiftCurrent(namelen)) {
2052 resvalue = -13;
2053 return nullptr;
2054 }
2055 if (!inp->SkipSpaces()) {
2056 resvalue = -13;
2057 return nullptr;
2058 }
2059
2060 if (!inp->CheckFor("(")) {
2061 resvalue = -13;
2062 return nullptr;
2063 }
2064 if (inp->SearchFor(")") <= 0) {
2065 resvalue = -13;
2066 return nullptr;
2067 }
2068
2069 inp->SkipSpaces();
2070 if (*inp->fCurrent != '>') {
2071 resvalue = -13;
2072 return nullptr;
2073 }
2074 if (!inp->ShiftCurrent()) {
2075 resvalue = -13;
2076 return nullptr;
2077 }
2078 inp->SkipSpaces();
2079
2080 continue;
2081 }
2082
2083 break;
2084 }
2085
2086 if (!inp->CheckFor("]")) {
2087 resvalue = -13;
2088 return nullptr;
2089 }
2090 }
2091 inp->SkipSpaces();
2092 if (!inp->CheckFor(">")) {
2093 resvalue = -13;
2094 return nullptr;
2095 }
2096
2097 resvalue = 2;
2098 return node;
2099 }
2100
2101 EXmlNodeType nodetype = kXML_NODE;
2102 Bool_t canhaschildren = true;
2103 char endsymbol = '/';
2104
2105 // this is case of processing instructions node
2106 if (*inp->fCurrent == '?') {
2107 if (!inp->ShiftCurrent())
2108 return nullptr;
2109 nodetype = kXML_PI_NODE;
2110 canhaschildren = false;
2111 endsymbol = '?';
2112 }
2113
2114 if (!inp->SkipSpaces())
2115 return nullptr;
2116 Int_t len = inp->LocateIdentifier();
2117 if (len <= 0)
2118 return nullptr;
2119 node = (SXmlNode_t *)AllocateNode(len, xmlparent);
2120 char *nameptr = SXmlNode_t::Name(node);
2121 node->fType = nodetype;
2122
2123 strncpy(nameptr, inp->fCurrent, len); // here copied content without padding 0
2124 nameptr += len;
2125 *nameptr = 0; // add 0 to the end
2126
2127 char *colon = strchr(SXmlNode_t::Name(node), ':');
2128 if (colon && parent) {
2129 *colon = 0;
2130 node->fNs = (SXmlAttr_t *)FindNs(xmlparent, SXmlNode_t::Name(node));
2131 *colon = ':';
2132 }
2133
2134 if (!inp->ShiftCurrent(len))
2135 return nullptr;
2136
2137 do {
2138 if (!inp->SkipSpaces())
2139 return nullptr;
2140
2141 char nextsymb = *inp->fCurrent;
2142
2143 if (nextsymb == endsymbol) { // this is end of short node like <node ... />
2144 if (!inp->ShiftCurrent())
2145 return nullptr;
2146 if (*inp->fCurrent == '>') {
2147 if (!inp->ShiftCurrent())
2148 return nullptr;
2149
2150 if (node->fNs)
2152
2153 inp->SkipSpaces(kTRUE); // locate start of next string
2154 resvalue = 2;
2155 return node;
2156 } else
2157 return nullptr;
2158 } else if (nextsymb == '>') { // this is end of parent node, lets find all children
2159 if (!canhaschildren) {
2160 resvalue = -11;
2161 return nullptr;
2162 }
2163
2164 if (!inp->ShiftCurrent())
2165 return nullptr;
2166
2167 do {
2168 ReadNode(node, inp, resvalue);
2169 } while (resvalue == 2);
2170
2171 if (resvalue == 1) {
2172 resvalue = 2;
2173 return node;
2174 } else
2175 return nullptr;
2176 } else {
2177 Int_t attrlen = inp->LocateIdentifier();
2178 if (attrlen <= 0) {
2179 resvalue = -6;
2180 return nullptr;
2181 }
2182
2183 int valuelen = inp->LocateValue(attrlen, true);
2184 if (valuelen < 3) {
2185 resvalue = -7;
2186 return nullptr;
2187 }
2188
2189 SXmlAttr_t *attr = (SXmlAttr_t *)AllocateAttr(attrlen, valuelen - 3, (XMLNodePointer_t)node);
2190
2191 char *attrname = SXmlAttr_t::Name(attr);
2192 strncpy(attrname, inp->fCurrent, attrlen);
2193 attrname += attrlen;
2194 *attrname = 0;
2195 attrname++;
2196 UnpackSpecialCharacters(attrname, inp->fCurrent + attrlen + 2, valuelen - 3);
2197
2198 if (!inp->ShiftCurrent(attrlen + valuelen))
2199 return nullptr;
2200
2201 attrname = SXmlAttr_t::Name(attr);
2202
2203 if ((strlen(attrname) > 6) && (strstr(attrname, "xmlns:") == attrname)) {
2204 if (strcmp(SXmlNode_t::Name(node), attrname + 6) != 0) {
2205 resvalue = -8;
2206 // return nullptr;
2207 }
2208 if (node->fNs) {
2209 resvalue = -9;
2210 // return nullptr;
2211 }
2212 node->fNs = attr;
2213 }
2214 }
2215 } while (true);
2216
2217 return nullptr;
2218}
2219
2220////////////////////////////////////////////////////////////////////////////////
2221/// Displays xml parsing error
2222
2223void TXMLEngine::DisplayError(Int_t error, Int_t linenumber)
2224{
2225 switch (error) {
2226 case -14: Error("ParseFile", "Error include external XML file at line %d", linenumber); break;
2227 case -13: Error("ParseFile", "Error processing DTD part of XML file at line %d", linenumber); break;
2228 case -12: Error("ParseFile", "DOCTYPE missing after <! at line %d", linenumber); break;
2229 case -11:
2230 Error("ParseFile", "Node cannot be closed with > symbol at line %d, for instance <?xml ... ?> node", linenumber);
2231 break;
2232 case -10:
2233 Error("ParseFile", "Error in xml comments definition at line %d, must be <!-- comments -->", linenumber);
2234 break;
2235 case -9: Error("ParseFile", "Multiple namespace definitions not allowed, line %d", linenumber); break;
2236 case -8: Error("ParseFile", "Invalid namespace specification, line %d", linenumber); break;
2237 case -7: Error("ParseFile", "Invalid attribute value, line %d", linenumber); break;
2238 case -6: Error("ParseFile", "Invalid identifier for node attribute, line %d", linenumber); break;
2239 case -5: Error("ParseFile", "Mismatch between open and close nodes, line %d", linenumber); break;
2240 case -4: Error("ParseFile", "Unexpected close node, line %d", linenumber); break;
2241 case -3: Error("ParseFile", "Valid identifier for close node is missing, line %d", linenumber); break;
2242 case -2: Error("ParseFile", "No multiple content entries allowed, line %d", linenumber); break;
2243 case -1: Error("ParseFile", "Unexpected end of xml file"); break;
2244 default: Error("ParseFile", "XML syntax error at line %d", linenumber); break;
2245 }
2246}
#define d(i)
Definition RSha256.hxx:102
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
EXmlNodeType
@ kXML_COMMENT
@ kXML_PI_NODE
@ kXML_NODE
@ kXML_RAWLINE
@ kXML_CONTENT
void * XMLNodePointer_t
Definition TXMLEngine.h:17
void * XMLNsPointer_t
Definition TXMLEngine.h:18
void * XMLDocPointer_t
Definition TXMLEngine.h:20
void * XMLAttrPointer_t
Definition TXMLEngine.h:19
#define realloc
Definition civetweb.c:1538
#define free
Definition civetweb.c:1539
#define snprintf
Definition civetweb.c:1540
#define malloc
Definition civetweb.c:1536
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:31
Int_t GetLast() const override
Return index of last object in array.
void Add(TObject *obj) override
Definition TObjArray.h:68
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
Basic string class.
Definition TString.h:139
TString & Append(const char *cs)
Definition TString.h:572
Bool_t AddRawLine(XMLNodePointer_t parent, const char *line)
Add just line into xml file Line should has correct xml syntax that later it can be decoded by xml pa...
XMLNodePointer_t AllocateNode(int namelen, XMLNodePointer_t parent)
Allocates new xml node with specified name length.
const char * GetNSName(XMLNsPointer_t ns)
return name id of namespace
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=nullptr)
create new child element for parent node
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode, Bool_t realnode=kTRUE)
returns first child of xmlnode
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
creates new attribute for xmlnode, namespaces are not supported for attributes
void SaveSingleNode(XMLNodePointer_t xmlnode, TString *res, Int_t layout=1)
convert single xmlnode (and its child node) to string if layout<=0, no any spaces or newlines will be...
void SaveDoc(XMLDocPointer_t xmldoc, const char *filename, Int_t layout=1)
store document content to file if layout<=0, no any spaces or newlines will be placed between xmlnode...
void DisplayError(Int_t error, Int_t linenumber)
Displays xml parsing error.
Bool_t AddComment(XMLNodePointer_t parent, const char *comment)
Adds comment line to the node.
void CleanNode(XMLNodePointer_t xmlnode)
remove all children node from xmlnode
void UnlinkNode(XMLNodePointer_t node)
unlink (detach) xmlnode from parent
void AssignDtd(XMLDocPointer_t xmldoc, const char *dtdname, const char *rootname)
assigns dtd filename to document
void FreeDoc(XMLDocPointer_t xmldoc)
frees allocated document data and deletes document itself
XMLNodePointer_t DocGetRootElement(XMLDocPointer_t xmldoc)
returns root node of document
void AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
add child element to xmlnode
Bool_t AddStyleSheet(XMLNodePointer_t parent, const char *href, const char *type="text/css", const char *title=nullptr, int alternate=-1, const char *media=nullptr, const char *charset=nullptr)
Adds style sheet definition to the specified node Creates <?xml-stylesheet alternate="yes" title="com...
XMLAttrPointer_t NewIntAttr(XMLNodePointer_t xmlnode, const char *name, Int_t value)
create node attribute with integer value
Bool_t AddDocComment(XMLDocPointer_t xmldoc, const char *comment)
add comment line to the top of the document
~TXMLEngine() override
destructor for TXMLEngine object
void AddNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len=0)
add new content of the xmlnode old content will be preserved, one could mix content with child nodes
Bool_t HasAttr(XMLNodePointer_t xmlnode, const char *name)
checks if node has attribute of specified name
char * Makestr(const char *str)
creates char* variable with copy of provided string
Bool_t IsXmlNode(XMLNodePointer_t xmlnode)
return kTRUE is this is normal xmlnode
void SaveNode(XMLNodePointer_t xmlnode, TXMLOutputStream *out, Int_t layout, Int_t level)
stream data of xmlnode to output
Bool_t IsContentNode(XMLNodePointer_t xmlnode)
return kTRUE is this is special node with content
XMLAttrPointer_t GetNextAttr(XMLAttrPointer_t xmlattr)
return next attribute in the list
XMLDocPointer_t ParseStream(TXMLInputStream *input)
parses content of the stream and tries to produce xml structures
XMLNodePointer_t ReadSingleNode(const char *src)
read single xmlnode from provided string
const char * GetNSReference(XMLNsPointer_t ns)
return reference id of namespace
char * Makenstr(const char *start, int len)
creates char* variable with copy of len symbols from provided string
Bool_t ValidateVersion(XMLDocPointer_t doc, const char *version=nullptr)
check that first node is xml processing instruction with correct xml version number
void SetNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len=0)
set content of the xmlnode if old node content was exists, it will be replaced
const char * GetNodeContent(XMLNodePointer_t xmlnode)
get contents (if any) of xmlnode
XMLNsPointer_t GetNS(XMLNodePointer_t xmlnode)
return namespace attribute (if exists)
Bool_t IsEmptyNode(XMLNodePointer_t xmlnode)
return kTRUE is this is node with special data like comments to data processing instructions
Bool_t IsCommentNode(XMLNodePointer_t xmlnode)
return kTRUE is this is special node with content
const char * GetAttrName(XMLAttrPointer_t xmlattr)
return name of the attribute
XMLAttrPointer_t GetFirstAttr(XMLNodePointer_t xmlnode)
return first attribute in the list, namespace (if exists) will be skipped
const char * GetNodeName(XMLNodePointer_t xmlnode)
returns name of xmlnode
Bool_t AddDocRawLine(XMLDocPointer_t xmldoc, const char *line)
Add just line on the top of xml document Line should has correct xml syntax that later it can be deco...
XMLNodePointer_t ReadNode(XMLNodePointer_t xmlparent, TXMLInputStream *inp, Int_t &resvalue)
Tries to construct xml node from input stream.
void FreeAttr(XMLNodePointer_t xmlnode, const char *name)
remove attribute from xmlnode
void OutputValue(char *value, TXMLOutputStream *out)
output value to output stream if symbols '<' '&' '>' '"' ''' appears in the string,...
const char * GetAttr(XMLNodePointer_t xmlnode, const char *name)
returns value of attribute for xmlnode
void AddChildAfter(XMLNodePointer_t parent, XMLNodePointer_t child, XMLNodePointer_t afternode)
Insert new child node after already existing node.
Bool_t AddDocStyleSheet(XMLDocPointer_t xmldoc, const char *href, const char *type="text/css", const char *title=nullptr, int alternate=-1, const char *media=nullptr, const char *charset=nullptr)
Add style sheet definition on the top of document.
XMLNsPointer_t NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name=nullptr)
create namespace attribute for xmlnode.
Bool_t fSkipComments
Definition TXMLEngine.h:42
Int_t GetIntAttr(XMLNodePointer_t node, const char *name)
returns value of attribute as integer
XMLDocPointer_t NewDoc(const char *version="1.0")
creates new xml document with provided version
XMLNsPointer_t FindNs(XMLNodePointer_t xmlnode, const char *nsname)
define if namespace of that name exists for xmlnode
void UnlinkFreeNode(XMLNodePointer_t xmlnode)
combined operation. Unlink node and free used memory
XMLDocPointer_t ParseFile(const char *filename, Int_t maxbuf=100000)
Parses content of file and tries to produce xml structures.
TXMLEngine()
if true, do not create comments nodes in document during parsing
XMLAttrPointer_t AllocateAttr(int namelen, int valuelen, XMLNodePointer_t xmlnode)
Allocate new attribute with specified name length and value length.
void TruncateNsExtension(XMLNodePointer_t xmlnode)
removes namespace extension of nodename
void UnpackSpecialCharacters(char *target, const char *source, int srclen)
unpack special symbols, used in xml syntax to code characters these symbols: '<' - &lt,...
void FreeAllAttr(XMLNodePointer_t xmlnode)
Free all attributes of the node.
XMLDocPointer_t ParseString(const char *xmlstring)
parses content of string and tries to produce xml structures
void FreeNode(XMLNodePointer_t xmlnode)
release all memory, allocated from this node and destroys node itself
const char * GetAttrValue(XMLAttrPointer_t xmlattr)
return value of attribute
XMLNodePointer_t GetNext(XMLNodePointer_t xmlnode, Bool_t realnode=kTRUE)
return next to xmlnode node if realnode==kTRUE, any special nodes in between will be skipped
void SkipEmpty(XMLNodePointer_t &xmlnode)
Skip all current empty nodes and locate on first "true" node.
void ShiftToNext(XMLNodePointer_t &xmlnode, Bool_t realnode=kTRUE)
shifts specified node to next if realnode==kTRUE, any special nodes in between will be skipped
void DocSetRootElement(XMLDocPointer_t xmldoc, XMLNodePointer_t xmlnode)
set main (root) node for document
XMLNodePointer_t GetParent(XMLNodePointer_t xmlnode)
returns parent of xmlnode
void AddChildFirst(XMLNodePointer_t parent, XMLNodePointer_t child)
add node as first child
TXMLEntity(const TString &name, const TString &value, Bool_t sys)
Bool_t fSystem
Bool_t IsSystem() const
TXMLEntity()
is system (file)
const char * fInpStr
Bool_t CheckFor(const char *str)
Check if in current position we see specified string.
std::istream * fInp
Int_t SearchFor(const char *str)
Search for specified string in the stream return number of symbols before string was found,...
Bool_t GoodStartSymbol(unsigned char symb)
returns true if symbol can be used as starting in the node name
Bool_t EndOfStream()
return true if end of file and all data from buffer are processed
Bool_t ExpandStream(char *&curr)
Allocate more data for the buffer, preserving content.
Bool_t EndOfFile()
return true if end of file is achieved
Int_t LocateIdentifier()
locate identifier in the stream, returns length of the identifier (or 0 if fails)
TXMLInputStream(Bool_t isfilename, const char *filename, Int_t ibufsize)
constructor
Int_t CurrentLine()
returns current line number in the input stream
void AddEntity(TXMLEntity *ent)
Add new entity.
Bool_t ShiftCurrent(Int_t sz=1)
shift current position on provided number of symbol
TXMLEntity * FindEntity(const char *beg, Int_t len)
Search for the entity.
Bool_t SkipSpaces(Bool_t tillendl=kFALSE)
Skip spaces at the current position.
Int_t NumEntities() const
Returns number of entity.
int DoRead(char *buf, int maxsize)
Read new data into buffer.
virtual ~TXMLInputStream()
destructor
Int_t LocateValue(unsigned curr_offset, bool withequalsign=true)
locate attribute value, returns length (or 0 if fails)
Int_t TotalPos()
returns absolute byte position in the stream
Int_t LocateContent()
locate node content, returns length (or -1 if fails)
TObjArray fEntities
Bool_t ShiftStream()
read next portion of data from the stream in the buffer
char * fCurrent
array of TXMLEntity
TXMLOutputStream(TString *outstr, Int_t bufsize=20000)
void OutputChar(char symb)
void Put(char symb, Int_t cnt=1)
std::ostream * fOut
TString * fOutStr
void Write(const char *str)
TXMLOutputStream(const char *filename, Int_t bufsize=20000)
void Init(Int_t bufsize)
virtual ~TXMLOutputStream()
TLine * line
const Int_t n
Definition legend1.C:16
SXmlAttr_t * fNext
static char * Name(void *arg)
SXmlNode_t * fRootNode
char * fDtdName
char * fDtdRoot
EXmlNodeType fType
static char * Name(void *arg)
SXmlNode_t * fNext
SXmlNode_t * fChild
SXmlAttr_t * fNs
SXmlNode_t * fLastChild
SXmlNode_t * fParent
SXmlAttr_t * fAttr