XRootD
Loading...
Searching...
No Matches
XrdXmlRdrTiny.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d X m l R d r T i n y . c c */
4/* */
5/* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cctype>
31#include <cstdlib>
32#include <cstring>
33#include <unistd.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <iostream>
37
38#include "XrdSys/XrdSysE2T.hh"
39#include "tinyxml.h"
41
42/******************************************************************************/
43/* L o c a l D e f i n i t i o n s */
44/******************************************************************************/
45
46namespace
47{
48// Develop a sane enum structure of xml node types
49//
50enum XmlNodeType {ntNone = TiXmlNode::TINYXML_UNKNOWN,
51 ntElmBeg = TiXmlNode::TINYXML_ELEMENT,
52 ntElmEnd = -1,
53 ntText = TiXmlNode::TINYXML_TEXT,
54 ntCmt = TiXmlNode::TINYXML_COMMENT,
55 ntDoc = TiXmlNode::TINYXML_DOCUMENT,
56 ntXMLDcl = TiXmlNode::TINYXML_DECLARATION
57 };
58
59/******************************************************************************/
60/* X m l N o d e N a m e */
61/******************************************************************************/
62
63const char *NodeName(int ntype)
64{
65 switch(ntype)
66 {case ntNone: return "isNode "; break;
67 case ntElmBeg: return "isElmBeg"; break;
68 case ntText: return "isText "; break;
69 case ntCmt: return "isCmt "; break;
70 case ntDoc: return "isDoc "; break;
71 case ntElmEnd: return "isElmEnd"; break;
72 case ntXMLDcl: return "isXMLDcl"; break;
73 default: break;
74 };
75 return "???";
76}
77}
78
79/******************************************************************************/
80/* C o n s t r c u t o r # 1 */
81/******************************************************************************/
82
83XrdXmlRdrTiny::XrdXmlRdrTiny(bool &aOK, const char *fname, const char *enc) : reader(0) // make sure the pointer is nil initialized otherwise if stat fails the destructor segfaults
84{
85 struct stat Stat;
86 const char *etext;
87
88// Initialize the standard values
89//
90 curNode = 0;
91 curElem = 0;
92 elmNode = 0;
93 eCode = 0;
94 *eText = 0;
95 debug = getenv("XrdXmlDEBUG") != 0;
96
97// Make sure this file exists
98//
99 if (stat(fname, &Stat))
100 {eCode = errno;
101 snprintf(eText,sizeof(eText),"%s opening %s", XrdSysE2T(errno), fname);
102 aOK = false;
103 return;
104 }
105
106// Get a file reader
107//
108 reader = new TiXmlDocument(fname);
109 if (reader->LoadFile())
110 {curNode = (TiXmlNode *)reader;
111 curElem = 0;
112 elmNode = curNode;
113 aOK = true;
114 } else {
115 if (!(etext = reader->ErrorDesc()) || *etext)
116 {if ((eCode = errno)) etext = XrdSysE2T(errno);
117 else etext = "Unknown error";
118 }
119 snprintf(eText,sizeof(eText),"%s opening %s", etext, fname);
120 eCode = EINVAL;
121 aOK = false;
122 }
123}
124
125/******************************************************************************/
126/* D e s t r u c t o r */
127/******************************************************************************/
128
130{
131
132// Tear down the reader
133//
134 if (reader)
135 {
136 delete reader;
137 reader = 0;
138 }
139}
140
141/******************************************************************************/
142/* Private: D e b u g */
143/******************************************************************************/
144
145void XrdXmlRdrTiny::Debug(const char *hdr, const char *want, const char *have,
146 const char *scope, int nType)
147{
148 char buff[512];
149
150// Format the message
151//
152 snprintf(buff,sizeof(buff),"%s %s scope: %s want: %s have: %s\n",
153 hdr,NodeName(nType),scope,want,have);
154 std::cerr <<buff <<std::flush;
155}
156
157/******************************************************************************/
158/* G e t A t t r i b u t e s */
159/******************************************************************************/
160
161bool XrdXmlRdrTiny::GetAttributes(const char **aname, char **aval)
162{
163 const char *value;
164 int i = 0;
165 bool found = false;
166
167// If we are not at the begining of an element, this is a sequence error
168//
169 if (!curElem)
170 {snprintf(eText, sizeof(eText),
171 "Element not fetched when seeking attribute %s",aname[0]);
172 eCode = EILSEQ;
173 return false;
174 }
175
176// Find all the requested attributes
177//
178 while(aname[i])
179 {if ((value = curElem->Attribute(aname[i])))
180 {if (aval[i]) free(aval[i]);
181 aval[i] = strdup(value);
182 found = true;
183 }
184 i++;
185 }
186
187// All done
188//
189 return found;
190}
191
192/******************************************************************************/
193/* G e t E l e m e n t */
194/******************************************************************************/
195
196int XrdXmlRdrTiny::GetElement(const char **ename, bool reqd)
197{
198 TiXmlNode *theChild;
199 const char *name = (curNode ? curNode->Value() : 0);
200 int i;
201
202// If we are positioned either at the current node or the last node we returned
203// Complain if that is not the case.
204//
205 if (*ename[0])
206 {if (name && strcmp(name, ename[0]))
207 {if (curElem && !strcmp(elmNode->Value(),ename[0])) curNode = elmNode;
208 else {snprintf(eText, sizeof(eText),
209 "Current context '%s' does not match stated scope '%s'",
210 (name ? name : ""), ename[0]);
211 eCode = EILSEQ;
212 return false;
213 }
214 }
215 }
216
217// Sequence to the next node at appropriate level.
218//
219 if (curNode == elmNode ) theChild = curNode->FirstChild();
220 else if (elmNode) theChild = elmNode->NextSibling();
221 else theChild = curNode->NextSibling();
222
223
224// Scan over to the first wanted element
225//
226 while(theChild)
227 {if ((name = theChild->Value()) && theChild->Type() == ntElmBeg)
228 {i = 1;
229 while(ename[i] && strcmp(name, ename[i])) i++;
230 if (ename[i])
231 {if (debug) Debug("getelem:",ename[i],name,ename[0],ntElmBeg);
232 curElem = theChild->ToElement();
233 elmNode = theChild;
234 return i;
235 }
236 }
237 theChild = theChild->NextSibling();
238 }
239
240// We didn't find any wanted tag here in this scope. Transition to the element's
241// parent we finished the tag
242//
243 if (debug) Debug("getelem:",ename[1],ename[0],ename[0],ntElmEnd);
244 elmNode = curNode;
245 curNode = curNode->Parent();
246 curElem = 0;
247 return 0;
248
249// This is an error if this element was required
250//
251 if (reqd)
252 {snprintf(eText,sizeof(eText),"Required element '%s' not found in '%s'",
253 (ename[1] ? ename[1] : "???"), ename[0]);
254 eCode = ESRCH;
255 }
256 return 0;
257}
258
259/******************************************************************************/
260/* G e t T e x t */
261/******************************************************************************/
262
263char *XrdXmlRdrTiny::GetText(const char *ename, bool reqd)
264{
265 const char *value;
266 char *sP;
267
268// If we are not at the begining of an element, this is a sequence error
269//
270 if (!curElem)
271 {snprintf(eText, sizeof(eText),
272 "Illegal position seeking text for tag %s",ename);
273 eCode = EILSEQ;
274 return 0;
275 }
276
277// Get the text associated with element (simple text only)
278//
279 value = curElem->GetText();
280
281// We did not find a value. If not required return.
282//
283 if (value || !reqd)
284 {if (!value) return 0;
285 sP = strdup(value);
286 return sP;
287 }
288
289// Create error message
290//
291 snprintf(eText, sizeof(eText), "Required %s tag value not found", ename);
292 eCode = ENOMSG;
293 return 0;
294}
295
296/******************************************************************************/
297/* I n i t */
298/******************************************************************************/
299
300bool XrdXmlRdrTiny::Init() {return true;}
struct stat Stat
Definition XrdCks.cc:49
#define stat(a, b)
Definition XrdPosix.hh:96
bool Debug
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
XrdXmlRdrTiny(bool &aOK, const char *fname, const char *enc=0)
Constructor & Destructor.
virtual bool GetAttributes(const char **aname, char **aval)
virtual int GetElement(const char **ename, bool reqd=false)
virtual char * GetText(const char *ename, bool reqd=false)
static bool Init()
virtual ~XrdXmlRdrTiny()