Orcus
threaded_sax_token_parser.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6  */
7 
8 #ifndef INCLUDED_ORCUS_THREADED_SAX_TOKEN_PARSER_HPP
9 #define INCLUDED_ORCUS_THREADED_SAX_TOKEN_PARSER_HPP
10 
11 #include "tokens.hpp"
12 #include "xml_namespace.hpp"
13 #include "sax_token_parser_thread.hpp"
14 #include "sax_parser_base.hpp"
15 #include "exception.hpp"
16 #include "detail/thread.hpp"
17 
18 #include <thread>
19 
20 namespace orcus {
21 
22 class xmlns_context;
23 class string_pool;
24 
25 template<typename _Handler>
27 {
28 public:
29 
30  typedef _Handler handler_type;
31 
43  const char* p, size_t n, const tokens& tks, xmlns_context& ns_cxt,
44  handler_type& hdl, size_t min_token_size);
45 
58  const char* p, size_t n, const tokens& tks, xmlns_context& ns_cxt,
59  handler_type& hdl, size_t min_token_size, size_t max_token_size);
60 
64  void parse();
65 
66  void swap_string_pool(string_pool& pool);
67 
68 private:
69  void thread_parse();
70 
71  void process_tokens(const sax::parse_tokens_t& tokens);
72 
73 private:
74  sax::parser_thread m_parser_thread;
75  handler_type& m_handler;
76 };
77 
78 template<typename _Handler>
80  const char* p, size_t n, const tokens& tks, xmlns_context& ns_cxt,
81  handler_type& hdl, size_t min_token_size) :
82  m_parser_thread(p, n, tks, ns_cxt, min_token_size), m_handler(hdl) {}
83 
84 template<typename _Handler>
86  const char* p, size_t n, const tokens& tks, xmlns_context& ns_cxt, handler_type& hdl,
87  size_t min_token_size, size_t max_token_size) :
88  m_parser_thread(p, n, tks, ns_cxt, min_token_size, max_token_size), m_handler(hdl) {}
89 
90 template<typename _Handler>
92 {
93  std::thread t(&threaded_sax_token_parser::thread_parse, this);
94  detail::thread::scoped_guard guard(std::move(t));
95 
96  sax::parse_tokens_t tokens;
97 
98  try
99  {
100  while (m_parser_thread.next_tokens(tokens))
101  process_tokens(tokens);
102 
103  process_tokens(tokens);
104  }
105  catch (const std::exception& e)
106  {
107  m_parser_thread.abort();
108  throw;
109  }
110 }
111 
112 template<typename _Handler>
114 {
115  m_parser_thread.swap_string_pool(pool);
116 }
117 
118 template<typename _Handler>
119 void threaded_sax_token_parser<_Handler>::thread_parse()
120 {
121  // Start parsing.
122  m_parser_thread.start();
123 }
124 
125 template<typename _Handler>
126 void threaded_sax_token_parser<_Handler>::process_tokens(const sax::parse_tokens_t& tks)
127 {
128  for (const sax::parse_token& t : tks)
129  {
130  switch (t.type)
131  {
132  case sax::parse_token_t::start_element:
133  {
134  const auto* elem = std::get<const xml_token_element_t*>(t.value);
135  m_handler.start_element(*elem);
136  break;
137  }
138  case sax::parse_token_t::end_element:
139  {
140  const auto* elem = std::get<const xml_token_element_t*>(t.value);
141  m_handler.end_element(*elem);
142  break;
143  }
144  case sax::parse_token_t::characters:
145  {
146  auto s = std::get<std::string_view>(t.value);
147  m_handler.characters(s, false);
148  break;
149  }
150  case sax::parse_token_t::parse_error:
151  {
152  auto v = std::get<parse_error_value_t>(t.value);
153  throw sax::malformed_xml_error(std::string{v.str}, v.offset);
154  }
155  default:
156  throw general_error("unknown token type encountered.");
157  }
158  }
159 }
160 
161 }
162 
163 #endif
164 
165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: thread.hpp:16
Definition: sax_token_parser_thread.hpp:62
Definition: string_pool.hpp:23
Definition: threaded_sax_token_parser.hpp:27
threaded_sax_token_parser(const char *p, size_t n, const tokens &tks, xmlns_context &ns_cxt, handler_type &hdl, size_t min_token_size)
Definition: threaded_sax_token_parser.hpp:79
void parse()
Definition: threaded_sax_token_parser.hpp:91
Definition: tokens.hpp:19
Definition: xml_namespace.hpp:82