libzypp 17.31.23
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
23
24using std::endl;
25
27namespace 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 //
132 {
133 if ( _reader )
134 {
135 xmlFreeTextReader( _reader );
136 }
137 MIL << "Done Parsing " << _stream << endl;
138 }
139
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 //
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 //
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 //
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
Base class for Exception.
Definition: Exception.h:146
Helper to create and pass std::istream.
Definition: inputstream.h:57
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
xmlTextReader based interface to iterate xml streams.
Definition: Reader.h:96
bool seekToEndNode(int depth_r, const std::string &name_r)
Definition: Reader.cc:232
XmlString nodeText()
If the current node is not empty, advances the reader to the next node, and returns the value.
Definition: Reader.cc:140
bool nextNodeAttribute()
Definition: Reader.cc:180
~Reader()
Dtor.
Definition: Reader.cc:131
bool seekToNode(int depth_r, const std::string &name_r)
Definition: Reader.cc:212
bool nextNode()
Definition: Reader.cc:160
xmlChar * wrapper.
Definition: XmlString.h:41
#define X(T)
Definition: Arch.h:361
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:1048
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
xmlTextReader document validation.
Definition: Reader.h:38
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97
#define INT
Definition: Logger.h:100