summaryrefslogtreecommitdiffstats
path: root/src/parser/json_parser_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/json_parser_base.cpp')
-rw-r--r--src/parser/json_parser_base.cpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/parser/json_parser_base.cpp b/src/parser/json_parser_base.cpp
new file mode 100644
index 0000000..0dcdc3b
--- /dev/null
+++ b/src/parser/json_parser_base.cpp
@@ -0,0 +1,104 @@
+/* -*- 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/.
+ */
+
+#include "orcus/json_parser_base.hpp"
+#include "orcus/cell_buffer.hpp"
+#include "numeric_parser.hpp"
+
+#include <cassert>
+#include <cmath>
+
+namespace orcus { namespace json {
+
+namespace {
+
+const char* parse_numeric_json(const char* p, const char* p_end, double& value)
+{
+ using numeric_parser_type = detail::numeric_parser<detail::json_parser_trait>;
+
+ numeric_parser_type parser(p, p_end);
+ double v = parser.parse();
+ if (!std::isnan(v))
+ p = parser.get_char_position();
+
+ value = v;
+ return p;
+};
+
+} // anonymous namespace
+
+struct parser_base::impl
+{
+ cell_buffer m_buffer;
+};
+
+parser_base::parser_base(std::string_view content) :
+ orcus::parser_base(content.data(), content.size()), mp_impl(std::make_unique<impl>())
+{
+
+ set_numeric_parser(parse_numeric_json);
+}
+
+parser_base::~parser_base() {}
+
+void parser_base::skip_ws()
+{
+ skip(" \n\r\t");
+}
+
+void parser_base::parse_true()
+{
+ if (!parse_expected("true"))
+ throw parse_error("parse_true: boolean 'true' expected.", offset());
+
+ skip_ws();
+}
+
+void parser_base::parse_false()
+{
+ if (!parse_expected("false"))
+ throw parse_error("parse_false: boolean 'false' expected.", offset());
+
+ skip_ws();
+}
+
+void parser_base::parse_null()
+{
+ if (!parse_expected("null"))
+ throw parse_error("parse_null: null expected.", offset());
+
+ skip_ws();
+}
+
+double parser_base::parse_double_or_throw()
+{
+ double v = parse_double();
+ if (std::isnan(v))
+ throw parse_error("parse_double_or_throw: failed to parse double precision value.", offset());
+ return v;
+}
+
+parse_quoted_string_state parser_base::parse_string()
+{
+ assert(cur_char() == '"');
+ size_t max_length = remaining_size();
+ const char* p = mp_char;
+ parse_quoted_string_state ret = parse_double_quoted_string(p, max_length, mp_impl->m_buffer);
+ if (ret.has_control_character)
+ throw parse_error("parse_string: string contains a control character.", offset());
+
+ mp_char = p;
+
+ if (ret.str)
+ skip_ws();
+
+ return ret;
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */