Commit 9598430a authored by Kamal Marhubi's avatar Kamal Marhubi

Drop <regex> in number parsing

parent c662e628
......@@ -382,7 +382,7 @@ KJ_TEST("basic json decoding") {
MallocMessageBuilder message;
auto root = message.initRoot<JsonValue>();
KJ_EXPECT_THROW_MESSAGE("Expected number", json.decodeRaw("-", root));
KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root));
}
{
......@@ -426,8 +426,8 @@ KJ_TEST("basic json decoding") {
KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root));
KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw(R"(["\n\", 3])", root));
KJ_EXPECT_THROW_MESSAGE("Invalid hex", json.decodeRaw(R"("\u12zz")", root));
KJ_EXPECT_THROW_MESSAGE("Expected number", json.decodeRaw("-", root));
KJ_EXPECT_THROW_MESSAGE("Expected number", json.decodeRaw("--", root));
KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("--", root));
}
}
......
......@@ -20,9 +20,9 @@
// THE SOFTWARE.
#include "json.h"
#include <cmath> // for HUGEVAL to check for overflow in std::strtod
#include <cstdlib> // std::strtod
#include <errno.h> // for std::strtod errors
#include <regex> // for numbers
#include <unordered_map>
#include <capnp/orphan.h>
#include <kj/debug.h>
......@@ -543,6 +543,21 @@ public:
advance(expected.size());
}
bool tryConsume(char expected) {
bool found = !inputExhausted() && nextChar() == expected;
if (found) { advance(); }
return found;
}
template <typename Predicate>
void consumeOne(Predicate&& predicate) {
char current = nextChar();
KJ_REQUIRE(predicate(current), "Unexpected input in JSON message.");
advance();
}
template <typename Predicate>
kj::ArrayPtr<const char> consumeWhile(Predicate&& predicate) {
auto originalPos = remaining_.begin();
......@@ -607,26 +622,29 @@ public:
}
kj::String consumeNumber() {
// TODO(perf): <regex> could be eliminated.
static std::regex jsonNumber(
R"(-?(0|[1-9][0-9]*)(\.[0-9]+)?((e|E)([+-])?[0-9]+)?)");
// jsonNumber matches numbers as seen in railroad diagram at http://json.org/.
auto originalPos = remaining_.begin();
tryConsume('-');
if (!tryConsume('0')) {
consumeOne([](char c) { return '1' <= c && c <= '9'; });
consumeWhile([](char c) { return '0' <= c && c <= '9'; });
}
std::cmatch match;
bool foundNumber = std::regex_search(
remaining_.begin(),
remaining_.end(),
match, jsonNumber,
std::regex_constants::match_continuous);
if (tryConsume('.')) {
consumeWhile([](char c) { return '0' <= c && c <= '9'; });
}
if (tryConsume('e') || tryConsume('E')) {
tryConsume('+') || tryConsume('-');
consumeWhile([](char c) { return '0' <= c && c <= '9'; });
}
KJ_REQUIRE(foundNumber, "Expected number in JSON input.");
KJ_REQUIRE(remaining_.begin() != originalPos, "Expected number in JSON input.");
kj::Vector<char> number;
number.addAll(match[0].first, match[0].second);
number.addAll(originalPos, remaining_.begin());
number.add('\0');
advanceTo(match.suffix().first);
return kj::String(number.releaseAsArray());
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment