summaryrefslogtreecommitdiffstats
path: root/include/orcus/threaded_json_parser.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/orcus/threaded_json_parser.hpp')
-rw-r--r--include/orcus/threaded_json_parser.hpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/include/orcus/threaded_json_parser.hpp b/include/orcus/threaded_json_parser.hpp
new file mode 100644
index 0000000..09bddfa
--- /dev/null
+++ b/include/orcus/threaded_json_parser.hpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_THREADED_JSON_PARSER_HPP
+#define INCLUDED_ORCUS_THREADED_JSON_PARSER_HPP
+
+#include "json_parser_thread.hpp"
+#include "json_parser_base.hpp"
+#include "detail/thread.hpp"
+
+#include <algorithm>
+
+namespace orcus {
+
+template<typename _Handler>
+class threaded_json_parser
+{
+public:
+
+ typedef _Handler handler_type;
+
+ /**
+ * Constructor.
+ *
+ * @param p pointer to a string stream containing JSON string.
+ * @param n size of the stream.
+ * @param hdl handler class instance.
+ * @param min_token_size minimum size of the internal token buffer.
+ */
+ threaded_json_parser(
+ const char* p, size_t n, handler_type& hdl, size_t min_token_size);
+
+ /**
+ * Constructor.
+ *
+ * @param p pointer to a string stream containing JSON string.
+ * @param n size of the stream.
+ * @param hdl handler class instance.
+ * @param min_token_size minimum size of the internal token buffer.
+ * @param max_token_size maximum size of the internal token buffer.
+ */
+ threaded_json_parser(
+ const char* p, size_t n, handler_type& hdl, size_t min_token_size,
+ size_t max_token_size);
+
+ /**
+ * Call this method to start parsing.
+ */
+ void parse();
+
+ /**
+ * Get statistics on the parsing session. Call this only after the
+ * parsing has finished.
+ *
+ * @return structure containing statistics of the parsing session.
+ */
+ json::parser_stats get_stats() const;
+
+ void swap_string_pool(string_pool& pool);
+
+private:
+ void thread_parse();
+
+ void process_tokens(json::parse_tokens_t& tokens);
+
+private:
+ json::parser_thread m_parser_thread;
+ handler_type& m_handler;
+};
+
+template<typename _Handler>
+threaded_json_parser<_Handler>::threaded_json_parser(
+ const char* p, size_t n, handler_type& hdl, size_t min_token_size) :
+ m_parser_thread(p, n, min_token_size), m_handler(hdl) {}
+
+template<typename _Handler>
+threaded_json_parser<_Handler>::threaded_json_parser(
+ const char* p, size_t n, handler_type& hdl, size_t min_token_size, size_t max_token_size) :
+ m_parser_thread(p, n, min_token_size, max_token_size), m_handler(hdl) {}
+
+template<typename _Handler>
+void threaded_json_parser<_Handler>::parse()
+{
+ std::thread t(&threaded_json_parser::thread_parse, this);
+ detail::thread::scoped_guard guard(std::move(t));
+
+ json::parse_tokens_t tokens;
+
+ while (m_parser_thread.next_tokens(tokens))
+ process_tokens(tokens);
+
+ process_tokens(tokens);
+}
+
+template<typename _Handler>
+json::parser_stats threaded_json_parser<_Handler>::get_stats() const
+{
+ return m_parser_thread.get_stats();
+}
+
+template<typename _Handler>
+void threaded_json_parser<_Handler>::swap_string_pool(string_pool& pool)
+{
+ m_parser_thread.swap_string_pool(pool);
+}
+
+template<typename _Handler>
+void threaded_json_parser<_Handler>::thread_parse()
+{
+ // Start parsing.
+ m_parser_thread.start();
+}
+
+template<typename _Handler>
+void threaded_json_parser<_Handler>::process_tokens(json::parse_tokens_t& tokens)
+{
+ std::for_each(tokens.begin(), tokens.end(),
+ [this](const json::parse_token& t)
+ {
+ switch (t.type)
+ {
+ case json::parse_token_t::begin_array:
+ m_handler.begin_array();
+ break;
+ case json::parse_token_t::begin_object:
+ m_handler.begin_object();
+ break;
+ case json::parse_token_t::begin_parse:
+ m_handler.begin_parse();
+ break;
+ case json::parse_token_t::boolean_false:
+ m_handler.boolean_false();
+ break;
+ case json::parse_token_t::boolean_true:
+ m_handler.boolean_true();
+ break;
+ case json::parse_token_t::end_array:
+ m_handler.end_array();
+ break;
+ case json::parse_token_t::end_object:
+ m_handler.end_object();
+ break;
+ case json::parse_token_t::end_parse:
+ m_handler.end_parse();
+ break;
+ case json::parse_token_t::null:
+ m_handler.null();
+ break;
+ case json::parse_token_t::number:
+ m_handler.number(std::get<double>(t.value));
+ break;
+ case json::parse_token_t::object_key:
+ {
+ auto s = std::get<std::string_view>(t.value);
+ m_handler.object_key(s.data(), s.size(), false);
+ break;
+ }
+ case json::parse_token_t::string:
+ {
+ auto s = std::get<std::string_view>(t.value);
+ m_handler.string(s.data(), s.size(), false);
+ break;
+ }
+ case json::parse_token_t::parse_error:
+ {
+ auto v = std::get<parse_error_value_t>(t.value);
+ throw parse_error(std::string{v.str}, v.offset);
+ }
+ case json::parse_token_t::unknown:
+ default:
+ throw general_error("unknown token type encountered.");
+ }
+ }
+ );
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */