* limitations under the License.
*/
-#include "folly/json.h"
+#include <folly/json.h>
#include <cassert>
#include <boost/next_prior.hpp>
#include <boost/algorithm/string.hpp>
-#include "folly/Range.h"
-#include "folly/Unicode.h"
-#include "folly/Conv.h"
+#include <folly/Conv.h>
+#include <folly/Range.h>
+#include <folly/String.h>
+#include <folly/Unicode.h>
namespace folly {
switch (v.type()) {
case dynamic::DOUBLE:
if (!opts_.allow_nan_inf &&
- (isnan(v.asDouble()) || isinf(v.asDouble()))) {
+ (std::isnan(v.asDouble()) || std::isinf(v.asDouble()))) {
throw std::runtime_error("folly::toJson: JSON object value was a "
"NaN or INF");
}
- toAppend(v.asDouble(), &out_);
+ toAppend(v.asDouble(), &out_, opts_.double_mode, opts_.double_num_digits);
break;
case dynamic::INT64: {
auto intval = v.asInt();
indent();
newline();
(*this)(a[0]);
- for (auto& val : makeRange(boost::next(a.begin()), a.end())) {
+ for (auto& val : range(boost::next(a.begin()), a.end())) {
out_ += ',';
newline();
(*this)(val);
serialization_opts const& opts_;
};
-//////////////////////////////////////////////////////////////////////
-
-struct ParseError : std::runtime_error {
- explicit ParseError(int line)
- : std::runtime_error(to<std::string>("json parse error on line ", line))
- {}
-
- explicit ParseError(int line, std::string const& context,
- std::string const& expected)
- : std::runtime_error(to<std::string>("json parse error on line ", line,
- !context.empty() ? to<std::string>(" near `", context, '\'')
- : "",
- ": ", expected))
- {}
-
- explicit ParseError(std::string const& what)
- : std::runtime_error("json parse error: " + what)
- {}
-};
-
// Wraps our input buffer with some helper functions.
struct Input {
explicit Input(StringPiece range, json::serialization_opts const* opts)
}
void skipWhitespace() {
- // Spaces other than ' ' characters are less common but should be
- // checked. This configuration where we loop on the ' '
- // separately from oddspaces was empirically fastest.
- auto oddspace = [] (char c) {
- return c == '\n' || c == '\t' || c == '\r';
- };
-
- loop:
- for (; !range_.empty() && range_.front() == ' '; range_.pop_front()) {
- }
- if (!range_.empty() && oddspace(range_.front())) {
- range_.pop_front();
- goto loop;
- }
+ range_ = folly::skipWhitespace(range_);
storeCurrent();
}
auto expPart = in.skipDigits();
end = expPart.end();
}
- auto fullNum = makeRange(integral.begin(), end);
+ auto fullNum = range(integral.begin(), end);
auto val = to<double>(fullNum);
return val;
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.startsWith("\"")) {
+ state = State::InString;
+ }
+ result.push_back(s[0]);
+ break;
+ case State::InString:
+ if (s.startsWith("\\\"")) {
+ result.push_back(s[0]);
+ result.push_back(s[1]);
+ ++i;
+ continue;
+ } else if (s.startsWith("\"")) {
+ 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.startsWith("\n")) {
+ // skip the line break. It doesn't matter.
+ state = State::None;
+ }
+ break;
+ default:
+ throw std::logic_error("Unknown comment state");
+ }
+ }
+ return result;
+}
+
}
//////////////////////////////////////////////////////////////////////