X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2Fjson.cpp;h=4c856598e123bc61a1a8ea8760fdf69ddbf14fdc;hb=398f83735ae9c087774af4894a794510a1e375c0;hp=cd83b5adffb68209b8edb695a93ce14986f1aa92;hpb=38fb7acd7836738bad760de579aeb7b4c5c82de2;p=folly.git diff --git a/folly/json.cpp b/folly/json.cpp index cd83b5ad..4c856598 100644 --- a/folly/json.cpp +++ b/folly/json.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,25 +256,25 @@ private: serialization_opts const& opts_; }; -////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// -struct ParseError : std::runtime_error { - explicit ParseError(int line) - : std::runtime_error(to("json parse error on line ", line)) - {} + struct ParseError : std::runtime_error { + explicit ParseError(int line) + : std::runtime_error(to("json parse error on line ", line)) + {} - explicit ParseError(int line, std::string const& context, - std::string const& expected) - : std::runtime_error(to("json parse error on line ", line, - !context.empty() ? to(" near `", context, '\'') - : "", - ": ", expected)) - {} + explicit ParseError(int line, std::string const& context, + std::string const& expected) + : std::runtime_error(to("json parse error on line ", line, + !context.empty() ? to(" near `", context, '\'') + : "", + ": ", expected)) + {} - explicit ParseError(std::string const& what) - : std::runtime_error("json parse error: " + what) - {} -}; + explicit ParseError(std::string const& msg) + : std::runtime_error("json parse error: " + msg) + {} + }; // Wraps our input buffer with some helper functions. struct Input { @@ -482,10 +482,23 @@ dynamic parseNumber(Input& in) { } auto const wasE = *in == 'e' || *in == 'E'; + + constexpr const char* maxInt = "9223372036854775807"; + constexpr const char* minInt = "9223372036854775808"; + constexpr auto maxIntLen = __builtin_strlen(maxInt); + if (*in != '.' && !wasE) { - auto val = to(integral); - in.skipWhitespace(); - return val; + if (LIKELY(!in.getOpts().double_fallback || integral.size() < maxIntLen) || + (integral.size() == maxIntLen && + (integral <= maxInt || (integral == minInt && negative)))) { + auto val = to(integral); + in.skipWhitespace(); + return val; + } else { + auto val = to(integral); + in.skipWhitespace(); + return val; + } } auto end = !wasE ? (++in, in.skipDigits().end()) : in.begin(); @@ -704,6 +717,65 @@ void escapeString(StringPiece input, out.push_back('\"'); } +fbstring stripComments(StringPiece jsonC) { + fbstring result; + enum class State { + None, + InString, + InlineComment, + LineComment + } state = State::None; + + for (size_t i = 0; i < jsonC.size(); ++i) { + auto s = jsonC.subpiece(i); + switch (state) { + case State::None: + if (s.startsWith("/*")) { + state = State::InlineComment; + ++i; + continue; + } else if (s.startsWith("//")) { + state = State::LineComment; + ++i; + continue; + } else if (s[0] == '\"') { + state = State::InString; + } + result.push_back(s[0]); + break; + case State::InString: + if (s[0] == '\\') { + if (UNLIKELY(s.size() == 1)) { + throw std::logic_error("Invalid JSONC: string is not terminated"); + } + result.push_back(s[0]); + result.push_back(s[1]); + ++i; + continue; + } else if (s[0] == '\"') { + state = State::None; + } + result.push_back(s[0]); + break; + case State::InlineComment: + if (s.startsWith("*/")) { + state = State::None; + ++i; + } + break; + case State::LineComment: + if (s[0] == '\n') { + // skip the line break. It doesn't matter. + state = State::None; + } + break; + default: + throw std::logic_error("Unknown comment state"); + } + } + return result; +} + } //////////////////////////////////////////////////////////////////////