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

libzypp 17.38.11

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-core/base/LogControl.h>
18#include <zypp-core/base/LogTools.h>
19#include <zypp-core/base/Exception.h>
20#include <zypp-core/base/String.h>
21
22#include <zypp/parser/xml/Reader.h>
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 << ' ' << static_cast<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#if LIBXML_VERSION >= 21200
54 void structuredErrorFunc( void * userData, const xmlError * error )
55#else
56 void structuredErrorFunc( void * userData, xmlError * error )
57#endif
58 {
59 if ( error )
60 {
61 // error->message is NL terminated
62 std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
63 str::stripSuffix( error->message, "\n" ).c_str() ) );
64 structuredErrors.push_back( err );
65 WAR << err << endl;
66 }
67 }
68
69 struct ParseException : public Exception
70 {
71 ParseException()
72 : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
73 {
74 for_( it, structuredErrors.begin(), --structuredErrors.end() )
75 addHistory( *it );
76 }
77 };
78
80 } // namespace
82
84 //
85 // METHOD NAME : Reader::Reader
86 // METHOD TYPE : Constructor
87 //
88 Reader::Reader( const InputStream & stream_r,
89 const Validate & validate_r )
90 : _stream( stream_r )
91 , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
92 stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
93 , _node( _reader )
94 {
95 MIL << "Start Parsing " << _stream << endl;
96 if ( ! _reader || stream_r.stream().bad() )
97 ZYPP_THROW( Exception( "Bad input stream" ) );
98 // set error handler
99 // TODO: Fix using a global lastStructuredError string is not reentrant.
100 structuredErrors.clear();
101 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
102 // TODO: set validation
103
104 // advance to 1st node
105 nextNode();
106 }
107
109 //
110 // METHOD NAME : Reader::~Reader
111 // METHOD TYPE : Destructor
112 //
113 Reader::~Reader()
114 {
115 if ( _reader )
116 {
117 xmlFreeTextReader( _reader );
118 }
119 MIL << "Done Parsing " << _stream << endl;
120 }
121
122 XmlString Reader::nodeText()
123 {
124 if ( ! _node.isEmptyElement() )
125 {
126 if ( nextNode() )
127 {
128 if ( _node.nodeType() == XML_READER_TYPE_TEXT )
129 {
130 return _node.value();
131 }
132 }
133 }
134 return XmlString();
135 }
136
138 //
139 // METHOD NAME : Reader::nextNode
140 // METHOD TYPE : bool
141 //
142 bool Reader::nextNode()
143 {
144 int ret = xmlTextReaderRead( _reader );
145 if ( ret == 1 )
146 {
147 return true;
148 }
149 xmlTextReaderClose( _reader );
150 if ( ret != 0 )
151 {
152 ZYPP_THROW( ParseException() );
153 }
154 return false;
155 }
156
158 //
159 // METHOD NAME : Reader::nextNodeAttribute
160 // METHOD TYPE : bool
161 //
162 bool Reader::nextNodeAttribute()
163 {
164 int ret = xmlTextReaderMoveToNextAttribute( _reader );
165 if ( ret == 1 )
166 {
167 return true;
168 }
169 if ( ret != 0 )
170 {
171 ZYPP_THROW( ParseException() );
172 }
173 return false;
174 }
175
177 //
178 // METHOD NAME : Reader::close
179 // METHOD TYPE : void
180 //
181 void Reader::close()
182 {
183 if ( _reader )
184 {
185 xmlTextReaderClose( _reader );
186 }
187 }
188
190 //
191 // METHOD NAME : Reader::seekToNode
192 // METHOD TYPE : bool
193 //
194 bool Reader::seekToNode( int depth_r, const std::string & name_r )
195 {
196 do
197 {
198 if ( _node.depth() == depth_r
199 && _node.name() == name_r
200 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
201 {
202 break;
203 }
204 } while( nextNode() );
205
206 return ! atEnd();
207 }
208
210 //
211 // METHOD NAME : Reader::seekToEndNode
212 // METHOD TYPE : bool
213 //
214 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
215 {
216 // Empty element has no separate end node: <node/>
217 do
218 {
219 if ( _node.depth() == depth_r
220 && _node.name() == name_r
221 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
222 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
223 && _node.isEmptyElement() ) ) )
224 {
225 break;
226 }
227 } while( nextNode() );
228
229 return ! atEnd();
230 }
231
233 } // namespace xml
236} // namespace zypp
for_
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
Exception.h
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
LogControl.h
LogTools.h
MIL
#define MIL
Definition Logger.h:103
WAR
#define WAR
Definition Logger.h:104
INT
#define INT
Definition Logger.h:107
Reader.h
String.h
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::InputStream
Helper to create and pass std::istream.
Definition inputstream.h:57
zypp::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition Pathname.h:137
zypp::xml::Reader::seekToEndNode
bool seekToEndNode(int depth_r, const std::string &name_r)
Definition Reader.cc:214
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:122
zypp::xml::Reader::nextNodeAttribute
bool nextNodeAttribute()
Definition Reader.cc:162
zypp::xml::Reader::close
void close()
Definition Reader.cc:181
zypp::xml::Reader::_stream
InputStream _stream
Definition Reader.h:191
zypp::xml::Reader::_reader
xmlTextReaderPtr _reader
Definition Reader.h:192
zypp::xml::Reader::~Reader
~Reader()
Dtor.
Definition Reader.cc:113
zypp::xml::Reader::Reader
Reader(const InputStream &stream_r, const Validate &validate_r=Validate::none())
Ctor.
Definition Reader.cc:88
zypp::xml::Reader::seekToNode
bool seekToNode(int depth_r, const std::string &name_r)
Definition Reader.cc:194
zypp::xml::Reader::nextNode
bool nextNode()
Definition Reader.cc:142
zypp::xml::Reader::atEnd
bool atEnd() const
Definition Reader.h:128
zypp::xml::Reader::_node
Node _node
Definition Reader.h:193
zypp::xml::XmlString
xmlChar * wrapper.
Definition XmlString.h:41
ztui::ProgressEnd::error
@ error
Definition Out.h:45
zypp::sat::empty
bool empty() const
Whether neither idents nor provides are set.
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:1118
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::xml
Definition libxmlfwd.cc:22
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::asString
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
Definition Patch.cc:122
zypp::xml::Validate
xmlTextReader document validation.
Definition Reader.h:38