libzypp: zypp/parser/xml/Reader.cc Source File

libzypp 17.25.10

Reader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <libxml/xmlreader.h>
13 #include <libxml/xmlerror.h>
14
15 #include <iostream>
16
17 #include <zypp/base/LogControl.h>
18 #include <zypp/base/LogTools.h>
19 #include <zypp/base/Exception.h>
20 #include <zypp/base/String.h>
21
22 #include <zypp/parser/xml/Reader.h>
23
24 using std::endl;
25
27 namespace zypp
28 {
30 namespace xml
31 {
32
34 namespace
35 {
36
37 int ioread( void * context_r, char * buffer_r, int bufferLen_r )
38 {
39 if ( context_r && buffer_r )
40 {
41 return reinterpret_cast<InputStream *>(context_r)
42 ->stream().read( buffer_r, bufferLen_r ).gcount();
43 }
44 INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl;
45 return -1;
46 }
47
48 int ioclose( void * /*context_r*/ )
49 { return 0; }
50
51
52 std::list<std::string> structuredErrors;
53 void structuredErrorFunc( void * userData, xmlErrorPtr error )
54 {
55 if ( error )
56 {
57 // error->message is NL terminated
58 std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
59 str::stripSuffix( error->message, "\n" ).c_str() ) );
60 structuredErrors.push_back( err );
61 WAR << err << endl;
62 }
63 #if 0
64 if ( error )
65 {
66 #define X(m) SEC << " " << #m << "\t" << error->m << endl
67 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
68 X(domain);
69 X(code);
70 XS(message);
71 X(level);
72 XS(file);
73 X(line);
74 XS(str1);
75 XS(str2);
76 XS(str3);
77 X(int1);
78 X(int2);
79 X(ctxt);
80 X(node);
81 #undef X
82 #undef XS
83 }
84 #endif
85 }
86
87 struct ParseException : public Exception
88 {
89 ParseException()
90 : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
91 {
92 for_( it, structuredErrors.begin(), --structuredErrors.end() )
93 addHistory( *it );
94 }
95 };
96
98 } // namespace
100
102 //
103 // METHOD NAME : Reader::Reader
104 // METHOD TYPE : Constructor
105 //
106 Reader::Reader( const InputStream & stream_r,
107 const Validate & validate_r )
108 : _stream( stream_r )
109 , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
110 stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
111 , _node( _reader )
112 {
113 MIL << "Start Parsing " << _stream << endl;
114 if ( ! _reader || ! stream_r.stream().good() )
115 ZYPP_THROW( Exception( "Bad input stream" ) );
116 // set error handler
117 // TODO: Fix using a global lastStructuredError string is not reentrant.
118 structuredErrors.clear();
119 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
120 // TODO: set validation
121
122 // advance to 1st node
123 nextNode();
124 }
125
127 //
128 // METHOD NAME : Reader::~Reader
129 // METHOD TYPE : Destructor
130 //
131 Reader::~Reader()
132 {
133 if ( _reader )
134 {
135 xmlFreeTextReader( _reader );
136 }
137 MIL << "Done Parsing " << _stream << endl;
138 }
139
140 XmlString Reader::nodeText()
141 {
142 if ( ! _node.isEmptyElement() )
143 {
144 if ( nextNode() )
145 {
146 if ( _node.nodeType() == XML_READER_TYPE_TEXT )
147 {
148 return _node.value();
149 }
150 }
151 }
152 return XmlString();
153 }
154
156 //
157 // METHOD NAME : Reader::nextNode
158 // METHOD TYPE : bool
159 //
160 bool Reader::nextNode()
161 {
162 int ret = xmlTextReaderRead( _reader );
163 if ( ret == 1 )
164 {
165 return true;
166 }
167 xmlTextReaderClose( _reader );
168 if ( ret != 0 )
169 {
170 ZYPP_THROW( ParseException() );
171 }
172 return false;
173 }
174
176 //
177 // METHOD NAME : Reader::nextNodeAttribute
178 // METHOD TYPE : bool
179 //
180 bool Reader::nextNodeAttribute()
181 {
182 int ret = xmlTextReaderMoveToNextAttribute( _reader );
183 if ( ret == 1 )
184 {
185 return true;
186 }
187 if ( ret != 0 )
188 {
189 ZYPP_THROW( ParseException() );
190 }
191 return false;
192 }
193
195 //
196 // METHOD NAME : Reader::close
197 // METHOD TYPE : void
198 //
199 void Reader::close()
200 {
201 if ( _reader )
202 {
203 xmlTextReaderClose( _reader );
204 }
205 }
206
208 //
209 // METHOD NAME : Reader::seekToNode
210 // METHOD TYPE : bool
211 //
212 bool Reader::seekToNode( int depth_r, const std::string & name_r )
213 {
214 do
215 {
216 if ( _node.depth() == depth_r
217 && _node.name() == name_r
218 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
219 {
220 break;
221 }
222 } while( nextNode() );
223
224 return ! atEnd();
225 }
226
228 //
229 // METHOD NAME : Reader::seekToEndNode
230 // METHOD TYPE : bool
231 //
232 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
233 {
234 // Empty element has no separate end node: <node/>
235 do
236 {
237 if ( _node.depth() == depth_r
238 && _node.name() == name_r
239 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
240 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
241 && _node.isEmptyElement() ) ) )
242 {
243 break;
244 }
245 } while( nextNode() );
246
247 return ! atEnd();
248 }
249
251 } // namespace xml
254 } // namespace zypp
for_
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
Exception.h
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
LogControl.h
LogTools.h
MIL
#define MIL
Definition: Logger.h:91
WAR
#define WAR
Definition: Logger.h:92
INT
#define INT
Definition: Logger.h:95
Reader.h
String.h
zypp::Exception
Base class for Exception.
Definition: Exception.h:146
zypp::InputStream
Helper to create and pass std::istream.
Definition: InputStream.h:57
zypp::filesystem::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
zypp::xml::Reader
xmlTextReader based interface to iterate xml streams.
Definition: Reader.h:96
zypp::xml::Reader::seekToEndNode
bool seekToEndNode(int depth_r, const std::string &name_r)
Definition: Reader.cc:232
zypp::xml::Reader::nodeText
XmlString nodeText()
If the current node is not empty, advances the reader to the next node, and returns the value.
Definition: Reader.cc:140
zypp::xml::Reader::nextNodeAttribute
bool nextNodeAttribute()
Definition: Reader.cc:180
zypp::xml::Reader::close
void close()
Definition: Reader.cc:199
zypp::xml::Reader::~Reader
~Reader()
Dtor.
Definition: Reader.cc:131
zypp::xml::Reader::seekToNode
bool seekToNode(int depth_r, const std::string &name_r)
Definition: Reader.cc:212
zypp::xml::Reader::nextNode
bool nextNode()
Definition: Reader.cc:160
zypp::xml::XmlString
xmlChar * wrapper.
Definition: XmlString.h:41
X
#define X(T)
std
Definition: Arch.h:348
zypp::str::stripSuffix
std::string stripSuffix(const C_Str &str_r, const C_Str &suffix_r)
Strip a suffix_r from str_r and return the resulting string.
Definition: String.h:1044
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
zypp::xmlout::node
std::ostream & node(std::ostream &out_r, const std::string &name_r, Node::Attr attr_r)
Definition: Xml.h:203
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::asString
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
Definition: DefaultIntegral.h:98
zypp::xml::Validate
xmlTextReader document validation.
Definition: Reader.h:38