libzypp  11.13.5
Reader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 extern "C"
13 {
14 #include <libxml/xmlreader.h>
15 #include <libxml/xmlerror.h>
16 }
17 
18 #include <iostream>
19 
20 #include "zypp/base/LogControl.h"
21 #include "zypp/base/LogTools.h"
22 #include "zypp/base/Exception.h"
23 #include "zypp/base/String.h"
24 
25 #include "zypp/parser/xml/Reader.h"
26 
27 using std::endl;
28 
30 namespace zypp
31 {
32 
33  namespace xml
34  {
35 
37  namespace
38  {
39 
40  int ioread( void * context_r, char * buffer_r, int bufferLen_r )
41  {
42  if ( context_r && buffer_r )
43  {
44  return reinterpret_cast<InputStream *>(context_r)
45  ->stream().read( buffer_r, bufferLen_r ).gcount();
46  }
47  INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl;
48  return -1;
49  }
50 
51  int ioclose( void * /*context_r*/ )
52  { return 0; }
53 
54 
55  std::list<std::string> structuredErrors;
56  void structuredErrorFunc( void * userData, xmlErrorPtr error )
57  {
58  if ( error )
59  {
60  // error->message is NL terminated
61  std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
62  str::stripSuffix( error->message, "\n" ).c_str() ) );
63  structuredErrors.push_back( err );
64  WAR << err << endl;
65  }
66 #if 0
67  if ( error )
68  {
69 #define X(m) SEC << " " << #m << "\t" << error->m << endl
70 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
71  X(domain);
72  X(code);
73  XS(message);
74  X(level);
75  XS(file);
76  X(line);
77  XS(str1);
78  XS(str2);
79  XS(str3);
80  X(int1);
81  X(int2);
82  X(ctxt);
83  X(node);
84 #undef X
85 #undef XS
86  }
87 #endif
88  }
89 
90  struct ParseException : public Exception
91  {
92  ParseException()
93  : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
94  {
95  for_( it, structuredErrors.begin(), --structuredErrors.end() )
96  addHistory( *it );
97  }
98  };
99 
101  } // namespace
103 
105  //
106  // METHOD NAME : Reader::Reader
107  // METHOD TYPE : Constructor
108  //
109  Reader::Reader( const InputStream & stream_r,
110  const Validate & validate_r )
111  : _stream( stream_r )
112  , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
113  stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
114  , _node( _reader )
115  {
116  MIL << "Start Parsing " << _stream << endl;
117  if ( ! _reader || ! stream_r.stream().good() )
118  ZYPP_THROW( Exception( "Bad input stream" ) );
119  // set error handler
120  // TODO: Fix using a global lastStructuredError string is not reentrant.
121  structuredErrors.clear();
122  xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
123  // TODO: set validation
124 
125  // advance to 1st node
126  nextNode();
127  }
128 
130  //
131  // METHOD NAME : Reader::~Reader
132  // METHOD TYPE : Destructor
133  //
135  {
136  if ( _reader )
137  {
138  xmlFreeTextReader( _reader );
139  }
140  MIL << "Done Parsing " << _stream << endl;
141  }
142 
144  {
145  if ( ! _node.isEmptyElement() )
146  {
147  if ( nextNode() )
148  {
149  if ( _node.nodeType() == XML_READER_TYPE_TEXT )
150  {
151  return _node.value();
152  }
153  }
154  }
155  return XmlString();
156  }
157 
159  //
160  // METHOD NAME : Reader::nextNode
161  // METHOD TYPE : bool
162  //
164  {
165  int ret = xmlTextReaderRead( _reader );
166  if ( ret == 1 )
167  {
168  return true;
169  }
170  xmlTextReaderClose( _reader );
171  if ( ret != 0 )
172  {
173  ZYPP_THROW( ParseException() );
174  }
175  return false;
176  }
177 
179  //
180  // METHOD NAME : Reader::nextNodeAttribute
181  // METHOD TYPE : bool
182  //
184  {
185  int ret = xmlTextReaderMoveToNextAttribute( _reader );
186  if ( ret == 1 )
187  {
188  return true;
189  }
190  if ( ret != 0 )
191  {
192  ZYPP_THROW( ParseException() );
193  }
194  return false;
195  }
196 
198  //
199  // METHOD NAME : Reader::close
200  // METHOD TYPE : void
201  //
203  {
204  if ( _reader )
205  {
206  xmlTextReaderClose( _reader );
207  }
208  }
209 
211  //
212  // METHOD NAME : Reader::seekToNode
213  // METHOD TYPE : bool
214  //
215  bool Reader::seekToNode( int depth_r, const std::string & name_r )
216  {
217  do
218  {
219  if ( _node.depth() == depth_r
220  && _node.name() == name_r
221  && _node.nodeType() == XML_READER_TYPE_ELEMENT )
222  {
223  break;
224  }
225  } while( nextNode() );
226 
227  return ! atEnd();
228  }
229 
231  //
232  // METHOD NAME : Reader::seekToEndNode
233  // METHOD TYPE : bool
234  //
235  bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
236  {
237  // Empty element has no separate end node: <node/>
238  do
239  {
240  if ( _node.depth() == depth_r
241  && _node.name() == name_r
242  && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
243  || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
244  && _node.isEmptyElement() ) ) )
245  {
246  break;
247  }
248  } while( nextNode() );
249 
250  return ! atEnd();
251  }
252 
254  } // namespace xml
257 } // namespace zypp