NSVD Reader  0.0.1
expat.hpp
Go to the documentation of this file.
1 
8 /*
9  * These codes are licensed under CC0.
10  * http://creativecommons.org/publicdomain/zero/1.0/
11  */
12 /*
13  Expat license is the same as the MIT/X Consortium license.
14  */
15 
16 #ifndef __NODAMUSHI_SVD_EXPAT_HPP__
17 #define __NODAMUSHI_SVD_EXPAT_HPP__
18 
20 # include <expat.h>
21 # include <cstdio>
22 namespace nodamushi{
23 namespace svd{
24 
25 
26 //-----------------------------------------------------------
27 // Expat parser handlers
28 //-----------------------------------------------------------
29 namespace expat_handler{
30 
31 template<typename P>
32 void add_child(
33  P* ptr, // expat_svd_reader* or stream_reader_element*
34  const XML_Char *name,const XML_Char **attributes)
35 {
36  auto& e = ptr->add_child(std::string(name));
37  while(attributes!=nullptr){
38  const XML_Char* n = *attributes;
39  if(n == nullptr) break;
40  attributes++;
41  const XML_Char* v = *attributes;
42  if(v == nullptr) break;
43  attributes++;
44  e.add_attribute(std::string(n),std::string(v));
45  }
46 }
47 
48 template<typename UD>
49 void XMLCALL element_start(
50  void *user_data, // UD*
51  const XML_Char *name,const XML_Char **attributes)
52 {
53  UD* ptr= reinterpret_cast<UD*>(user_data);
54  auto* c = ptr->get_active_open_element();
55  if(c == nullptr)add_child(ptr,name,attributes);
56  else add_child(c,name,attributes);
57 }
58 
59 template<typename UD>
60 void XMLCALL element_end(
61  void *user_data,// UD*
62  const XML_Char *name)
63 {
64  UD* ptr= reinterpret_cast<UD*>(user_data);
65  auto* c = ptr->get_active_open_element();
66  if(c!=nullptr){
67  //TODO name check
68  c->close();
69  }
70 }
71 
72 
73 template<typename UD>
74 void XMLCALL element_char(
75  void *user_data,// UD*
76  const XML_Char *data,int len)
77 {
78  UD* ptr= reinterpret_cast<UD*>(user_data);
79  auto* c = ptr->get_active_open_element();
80  if(c!=nullptr)
81  c->add_value(data,(size_t)len);
82 }
83 
84 
85 }//end expat_handler ------------------------------------
86 
87 
102 struct expat_svd_reader:public stream_reader_base<expat_svd_reader>
103 {
104 
105  static constexpr size_t BUFFER_SIZE=1024;
106 
107  expat_svd_reader(const std::string& file_name,bool throw_error=false):
108  parser(),
109  file(nullptr),
110  enable(false),
111  eof(true),
112  _ok(false),
113  ethrow(throw_error),
114  fname(throw_error?file_name:"")
115  {
116  if(file_read_exception::check(file_name,throw_error)){
117  file = std::fopen(file_name.data(),"r");
118  }
119  if(file){
120  parser = XML_ParserCreate( NULL );
121  XML_SetElementHandler(parser,
122  expat_handler::element_start<expat_svd_reader>,
123  expat_handler::element_end<expat_svd_reader>);
124  XML_SetCharacterDataHandler(parser,expat_handler::element_char<expat_svd_reader>);
125  XML_SetUserData(parser,this);
126  enable = true;
127  eof = false;
128  _ok = true;
129  }
130  }
131 
135  bool ok()const {return _ok;}
136 
138  stream_reader_base(std::move(d)),
139  parser(std::move(d.parser)),
140  file(d.file),
141  enable(d.enable),
142  eof(d.eof)
143  {
144  d.enable = false;
145  XML_SetUserData(parser,this);
146  }
147 
149 
150  expat_svd_reader(const expat_svd_reader&)=delete;
153 
154  void close()
155  {
156  if(enable){
157  enable = false;
158  std::fclose(file);
159  file = nullptr;
160  XML_ParserFree(parser);
161  }
162  }
163 
164  //-------------------------------------------------------------
165  // stream_reader_base interface
166  //-------------------------------------------------------------
168  void read()
169  {
170  if(enable && !eof){
171  char buffer[BUFFER_SIZE];
172  size_t len = std::fread(buffer,sizeof(char),BUFFER_SIZE,file);
173  eof = len != BUFFER_SIZE;
174  if(XML_Parse(parser,buffer,len,eof) == XML_STATUS_ERROR){
175  _ok = false;
176  eof = true;
177  if(ethrow){
178  throw xml_parse_exception::make(fname);
179  }
180  }
181  }
182  if(eof)close_children();
183  }
185  bool is_end(){ return eof;}
186 
187  private:
188  XML_Parser parser;
189  std::FILE* file;
190  bool enable;
191  bool eof;
192  bool _ok;
193  bool ethrow;
194  std::string fname;
195 };
196 
197 
198 }
199 }// end namespace nodamushi
200 
201 #endif // __NODAMUSHI_SVD_EXPAT_HPP__
static bool check(const std::string &file_name, bool throw_exception)
Definition: svd_reader.hpp:54
void read()
svd_reader_base interface function
Definition: expat.hpp:168
SVD reader with Expat(https://github.com/libexpat/libexpat)
Definition: expat.hpp:102
void XMLCALL element_char(void *user_data, const XML_Char *data, int len)
Definition: expat.hpp:74
Definition: Access.hpp:143
void add_child(P *ptr, const XML_Char *name, const XML_Char **attributes)
Definition: expat.hpp:32
expat_svd_reader(const std::string &file_name, bool throw_error=false)
Definition: expat.hpp:107
void XMLCALL element_start(void *user_data, const XML_Char *name, const XML_Char **attributes)
Definition: expat.hpp:49
svd_reader base class for stream type parser subclasses must be implements read method and is_end met...
Definition: svd_reader.hpp:356
void XMLCALL element_end(void *user_data, const XML_Char *name)
Definition: expat.hpp:60
expat_svd_reader & operator=(const expat_svd_reader &)=delete
expat_svd_reader(expat_svd_reader &&d)
Definition: expat.hpp:137
bool is_end()
svd_reader_base interface function
Definition: expat.hpp:185
svd_reader
static xml_parse_exception make(const std::string &file, size_t file_line=UNKNOWN_FILE_LINE)
Definition: svd_reader.hpp:80
static constexpr size_t BUFFER_SIZE
Definition: expat.hpp:105