Fix some clang compiler warnings/errors
[folly.git] / folly / json.cpp
1 /*
2  * Copyright 2012 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "folly/json.h"
18 #include <cassert>
19 #include <boost/next_prior.hpp>
20 #include <boost/algorithm/string.hpp>
21
22 #include "folly/Range.h"
23 #include "folly/Unicode.h"
24 #include "folly/Conv.h"
25
26 namespace folly {
27
28 //////////////////////////////////////////////////////////////////////
29
30 namespace json {
31 namespace {
32
33 char32_t decodeUtf8(const unsigned char*& p, const unsigned char* const e) {
34   /* The following encodings are valid, except for the 5 and 6 byte
35    * combinations:
36    * 0xxxxxxx
37    * 110xxxxx 10xxxxxx
38    * 1110xxxx 10xxxxxx 10xxxxxx
39    * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
40    * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
41    * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
42    */
43
44   if (p >= e) {
45     throw std::runtime_error("folly::decodeUtf8 empty/invalid string");
46   }
47
48   unsigned char fst = *p;
49   if (!(fst & 0x80)) {
50     // trivial case
51     return *p++;
52   }
53
54   static const uint32_t bitMask[] = {
55     (1 << 7) - 1,
56     (1 << 11) - 1,
57     (1 << 16) - 1,
58     (1 << 21) - 1
59   };
60
61   // upper control bits are masked out later
62   uint32_t d = fst;
63
64   if ((fst & 0xC0) != 0xC0) {
65     throw std::runtime_error(
66       to<std::string>("folly::decodeUtf8 i=0 d=", d));
67   }
68
69   fst <<= 1;
70
71   for (unsigned int i = 1; i != 3 && p + i < e; ++i) {
72     unsigned char tmp = p[i];
73
74     if ((tmp & 0xC0) != 0x80) {
75       throw std::runtime_error(
76         to<std::string>("folly::decodeUtf8 i=", i, " tmp=", (uint32_t)tmp));
77     }
78
79     d = (d << 6) | (tmp & 0x3F);
80     fst <<= 1;
81
82     if (!(fst & 0x80)) {
83       d &= bitMask[i];
84
85       // overlong, could have been encoded with i bytes
86       if ((d & ~bitMask[i - 1]) == 0) {
87         throw std::runtime_error(
88           to<std::string>("folly::decodeUtf8 i=", i, " d=", d));
89       }
90
91       // check for surrogates only needed for 3 bytes
92       if (i == 2) {
93         if ((d >= 0xD800 && d <= 0xDFFF) || d > 0x10FFFF) {
94           throw std::runtime_error(
95             to<std::string>("folly::decodeUtf8 i=", i, " d=", d));
96         }
97       }
98
99       p += i + 1;
100       return d;
101     }
102   }
103
104   throw std::runtime_error("folly::decodeUtf8 encoding length maxed out");
105 }
106
107 // Escape a string so that it is legal to print it in JSON text.
108 void escapeString(StringPiece input,
109                   fbstring& out,
110                   const serialization_opts& opts) {
111   auto hexDigit = [] (int c) -> char {
112     return c < 10 ? c + '0' : c - 10 + 'a';
113   };
114
115   out.reserve(out.size() + input.size() + 2);
116   out.push_back('\"');
117
118   auto* p = reinterpret_cast<const unsigned char*>(input.begin());
119   auto* q = reinterpret_cast<const unsigned char*>(input.begin());
120   auto* e = reinterpret_cast<const unsigned char*>(input.end());
121
122   while (p < e) {
123     // Since non-ascii encoding inherently does utf8 validation
124     // we explicitly validate utf8 only if non-ascii encoding is disabled.
125     if (opts.validate_utf8 && !opts.encode_non_ascii) {
126       // to achieve better spatial and temporal coherence
127       // we do utf8 validation progressively along with the
128       // string-escaping instead of two separate passes
129
130       // as the encoding progresses, q will stay at or ahead of p
131       CHECK(q >= p);
132
133       // as p catches up with q, move q forward
134       if (q == p) {
135         // calling utf8_decode has the side effect of
136         // checking that utf8 encodings are valid
137         decodeUtf8(q, e);
138       }
139     }
140
141     if (opts.encode_non_ascii && (*p & 0x80)) {
142       // note that this if condition captures utf8 chars
143       // with value > 127, so size > 1 byte
144       char32_t v = decodeUtf8(p, e);
145       out.append("\\u");
146       out.push_back(hexDigit(v >> 12));
147       out.push_back(hexDigit((v >> 8) & 0x0f));
148       out.push_back(hexDigit((v >> 4) & 0x0f));
149       out.push_back(hexDigit(v & 0x0f));
150     } else if (*p == '\\' || *p == '\"') {
151       out.push_back('\\');
152       out.push_back(*p++);
153     } else if (*p <= 0x1f) {
154       switch (*p) {
155       case '\b': out.append("\\b"); p++; break;
156       case '\f': out.append("\\f"); p++; break;
157       case '\n': out.append("\\n"); p++; break;
158       case '\r': out.append("\\r"); p++; break;
159       case '\t': out.append("\\t"); p++; break;
160       default:
161         // note that this if condition captures non readable chars
162         // with value < 32, so size = 1 byte (e.g control chars).
163         out.append("\\u00");
164         out.push_back(hexDigit((*p & 0xf0) >> 4));
165         out.push_back(hexDigit(*p & 0xf));
166         p++;
167       }
168     } else {
169       out.push_back(*p++);
170     }
171   }
172
173   out.push_back('\"');
174 }
175
176 struct Printer {
177   explicit Printer(fbstring& out,
178                    unsigned* indentLevel,
179                    serialization_opts const* opts)
180     : out_(out)
181     , indentLevel_(indentLevel)
182     , opts_(*opts)
183   {}
184
185   void operator()(dynamic const& v) const {
186     switch (v.type()) {
187     case dynamic::DOUBLE:
188       toAppend(v.asDouble(), &out_);
189       break;
190     case dynamic::INT64: {
191       auto intval = v.asInt();
192       if (opts_.javascript_safe) {
193         // Use folly::to to check that this integer can be represented
194         // as a double without loss of precision.
195         intval = int64_t(to<double>(intval));
196       }
197       toAppend(intval, &out_);
198       break;
199     }
200     case dynamic::BOOL:
201       out_ += v.asBool() ? "true" : "false";
202       break;
203     case dynamic::NULLT:
204       out_ += "null";
205       break;
206     case dynamic::STRING:
207       escapeString(v.asString(), out_, opts_);
208       break;
209     case dynamic::OBJECT:
210       printObject(v);
211       break;
212     case dynamic::ARRAY:
213       printArray(v);
214       break;
215     default:
216       CHECK(0) << "Bad type " << v.type();
217     }
218   }
219
220 private:
221   void printKV(const std::pair<dynamic, dynamic>& p) const {
222     if (!opts_.allow_non_string_keys && !p.first.isString()) {
223       throw std::runtime_error("folly::toJson: JSON object key was not a "
224         "string");
225     }
226     (*this)(p.first);
227     mapColon();
228     (*this)(p.second);
229   }
230
231   void printObject(dynamic const& o) const {
232     if (o.empty()) {
233       out_ += "{}";
234       return;
235     }
236
237     out_ += '{';
238     indent();
239     newline();
240     auto it = o.items().begin();
241     printKV(*it);
242     for (++it; it != o.items().end(); ++it) {
243       out_ += ',';
244       newline();
245       printKV(*it);
246     }
247     outdent();
248     newline();
249     out_ += '}';
250   }
251
252   void printArray(dynamic const& a) const {
253     if (a.empty()) {
254       out_ += "[]";
255       return;
256     }
257
258     out_ += '[';
259     indent();
260     newline();
261     (*this)(a[0]);
262     for (auto& val : makeRange(boost::next(a.begin()), a.end())) {
263       out_ += ',';
264       newline();
265       (*this)(val);
266     }
267     outdent();
268     newline();
269     out_ += ']';
270   }
271
272 private:
273   void outdent() const {
274     if (indentLevel_) {
275       --*indentLevel_;
276     }
277   }
278
279   void indent() const {
280     if (indentLevel_) {
281       ++*indentLevel_;
282     }
283   }
284
285   void newline() const {
286     if (indentLevel_) {
287       out_ += to<fbstring>('\n', fbstring(*indentLevel_ * 2, ' '));
288     }
289   }
290
291   void mapColon() const {
292     out_ += indentLevel_ ? " : " : ":";
293   }
294
295 private:
296   fbstring& out_;
297   unsigned* const indentLevel_;
298   serialization_opts const& opts_;
299 };
300
301 //////////////////////////////////////////////////////////////////////
302
303 struct ParseError : std::runtime_error {
304   explicit ParseError(int line)
305     : std::runtime_error(to<std::string>("json parse error on line ", line))
306   {}
307
308   explicit ParseError(int line, std::string const& context,
309       std::string const& expected)
310     : std::runtime_error(to<std::string>("json parse error on line ", line,
311         !context.empty() ? to<std::string>(" near `", context, '\'')
312                         : "",
313         ": ", expected))
314   {}
315
316   explicit ParseError(std::string const& what)
317     : std::runtime_error("json parse error: " + what)
318   {}
319 };
320
321 // Wraps our input buffer with some helper functions.
322 struct Input {
323   explicit Input(StringPiece range)
324     : range_(range)
325     , lineNum_(0)
326   {
327     storeCurrent();
328   }
329
330   Input(Input const&) = delete;
331   Input& operator=(Input const&) = delete;
332
333   char const* begin() const { return range_.begin(); }
334
335   // Parse ahead for as long as the supplied predicate is satisfied,
336   // returning a range of what was skipped.
337   template<class Predicate>
338   StringPiece skipWhile(const Predicate& p) {
339     std::size_t skipped = 0;
340     for (; skipped < range_.size(); ++skipped) {
341       if (!p(range_[skipped])) {
342         break;
343       }
344       if (range_[skipped] == '\n') {
345         ++lineNum_;
346       }
347     }
348     auto ret = range_.subpiece(0, skipped);
349     range_.advance(skipped);
350     storeCurrent();
351     return ret;
352   }
353
354   StringPiece skipDigits() {
355     return skipWhile([] (char c) { return c >= '0' && c <= '9'; });
356   }
357
358   void skipWhitespace() {
359     // Spaces other than ' ' characters are less common but should be
360     // checked.  This configuration where we loop on the ' '
361     // separately from oddspaces was empirically fastest.
362     auto oddspace = [] (char c) {
363       return c == '\n' || c == '\t' || c == '\r';
364     };
365
366   loop:
367     for (; !range_.empty() && range_.front() == ' '; range_.pop_front()) {
368     }
369     if (!range_.empty() && oddspace(range_.front())) {
370       range_.pop_front();
371       goto loop;
372     }
373     storeCurrent();
374   }
375
376   void expect(char c) {
377     if (**this != c) {
378       throw ParseError(lineNum_, context(),
379         to<std::string>("expected '", c, '\''));
380     }
381     ++*this;
382   }
383
384   std::size_t size() const {
385     return range_.size();
386   }
387
388   int operator*() const {
389     return current_;
390   }
391
392   void operator++() {
393     range_.pop_front();
394     storeCurrent();
395   }
396
397   template<class T>
398   T extract() {
399     try {
400       return to<T>(&range_);
401     } catch (std::exception const& e) {
402       error(e.what());
403     }
404   }
405
406   bool consume(StringPiece str) {
407     if (boost::starts_with(range_, str)) {
408       range_.advance(str.size());
409       storeCurrent();
410       return true;
411     }
412     return false;
413   }
414
415   std::string context() const {
416     return range_.subpiece(0, 16 /* arbitrary */).toString();
417   }
418
419   dynamic error(char const* what) const {
420     throw ParseError(lineNum_, context(), what);
421   }
422
423 private:
424   void storeCurrent() {
425     current_ = range_.empty() ? EOF : range_.front();
426   }
427
428 private:
429   StringPiece range_;
430   unsigned lineNum_;
431   int current_;
432 };
433
434 dynamic parseValue(Input& in);
435 fbstring parseString(Input& in);
436
437 dynamic parseObject(Input& in) {
438   assert(*in == '{');
439   ++in;
440
441   dynamic ret = dynamic::object;
442
443   in.skipWhitespace();
444   if (*in == '}') {
445     ++in;
446     return ret;
447   }
448
449   for (;;) {
450     if (*in != '\"') {
451       in.error("expected string for object key name");
452     }
453     auto key = parseString(in);
454     in.skipWhitespace();
455     in.expect(':');
456     in.skipWhitespace();
457     ret.insert(std::move(key), parseValue(in));
458     in.skipWhitespace();
459     if (*in != ',') {
460       break;
461     }
462     ++in;
463     in.skipWhitespace();
464   }
465   in.expect('}');
466
467   return ret;
468 }
469
470 dynamic parseArray(Input& in) {
471   assert(*in == '[');
472   ++in;
473
474   dynamic ret = {};
475
476   in.skipWhitespace();
477   if (*in == ']') {
478     ++in;
479     return ret;
480   }
481
482   for (;;) {
483     ret.push_back(parseValue(in));
484     in.skipWhitespace();
485     if (*in != ',') {
486       break;
487     }
488     ++in;
489     in.skipWhitespace();
490   }
491   in.expect(']');
492
493   return ret;
494 }
495
496 dynamic parseNumber(Input& in) {
497   bool const negative = (*in == '-');
498   if (negative) {
499     ++in;
500     if (in.consume("Infinity")) {
501       return -std::numeric_limits<double>::infinity();
502     }
503   }
504
505   auto integral = in.skipDigits();
506   if (integral.empty()) {
507     in.error("expected digits after `-'");
508   }
509   auto const wasE = *in == 'e' || *in == 'E';
510   if (*in != '.' && !wasE) {
511     auto val = to<int64_t>(integral);
512     if (negative) {
513       val = -val;
514     }
515     in.skipWhitespace();
516     return val;
517   }
518
519   auto end = !wasE ? (++in, in.skipDigits().end()) : in.begin();
520   if (*in == 'e' || *in == 'E') {
521     ++in;
522     if (*in == '+' || *in == '-') {
523       ++in;
524     }
525     auto expPart = in.skipDigits();
526     end = expPart.end();
527   }
528   auto fullNum = makeRange(integral.begin(), end);
529
530   auto val = to<double>(fullNum);
531   if (negative) {
532     val *= -1;
533   }
534   return val;
535 }
536
537 fbstring decodeUnicodeEscape(Input& in) {
538   auto hexVal = [&] (char c) -> unsigned {
539     return c >= '0' && c <= '9' ? c - '0' :
540            c >= 'a' && c <= 'f' ? c - 'a' + 10 :
541            c >= 'A' && c <= 'F' ? c - 'A' + 10 :
542            (in.error("invalid hex digit"), 0);
543   };
544
545   auto readHex = [&]() -> uint16_t {
546     if (in.size() < 4) {
547       in.error("expected 4 hex digits");
548     }
549
550     uint16_t ret = hexVal(*in) * 4096;
551     ++in;
552     ret += hexVal(*in) * 256;
553     ++in;
554     ret += hexVal(*in) * 16;
555     ++in;
556     ret += hexVal(*in);
557     ++in;
558     return ret;
559   };
560
561   /*
562    * If the value encoded is in the surrogate pair range, we need to
563    * make sure there is another escape that we can use also.
564    */
565   uint32_t codePoint = readHex();
566   if (codePoint >= 0xd800 && codePoint <= 0xdbff) {
567     if (!in.consume("\\u")) {
568       in.error("expected another unicode escape for second half of "
569         "surrogate pair");
570     }
571     uint16_t second = readHex();
572     if (second >= 0xdc00 && second <= 0xdfff) {
573       codePoint = 0x10000 + ((codePoint & 0x3ff) << 10) +
574                   (second & 0x3ff);
575     } else {
576       in.error("second character in surrogate pair is invalid");
577     }
578   } else if (codePoint >= 0xdc00 && codePoint <= 0xdfff) {
579     in.error("invalid unicode code point (in range [0xdc00,0xdfff])");
580   }
581
582   return codePointToUtf8(codePoint);
583 }
584
585 fbstring parseString(Input& in) {
586   assert(*in == '\"');
587   ++in;
588
589   fbstring ret;
590   for (;;) {
591     auto range = in.skipWhile(
592       [] (char c) { return c != '\"' && c != '\\'; }
593     );
594     ret.append(range.begin(), range.end());
595
596     if (*in == '\"') {
597       ++in;
598       break;
599     }
600     if (*in == '\\') {
601       ++in;
602       switch (*in) {
603       case '\"':    ret.push_back('\"'); ++in; break;
604       case '\\':    ret.push_back('\\'); ++in; break;
605       case '/':     ret.push_back('/');  ++in; break;
606       case 'b':     ret.push_back('\b'); ++in; break;
607       case 'f':     ret.push_back('\f'); ++in; break;
608       case 'n':     ret.push_back('\n'); ++in; break;
609       case 'r':     ret.push_back('\r'); ++in; break;
610       case 't':     ret.push_back('\t'); ++in; break;
611       case 'u':     ++in; ret += decodeUnicodeEscape(in); break;
612       default:      in.error(to<fbstring>("unknown escape ", *in,
613                                           " in string").c_str());
614       }
615       continue;
616     }
617     if (*in == EOF) {
618       in.error("unterminated string");
619     }
620     if (!*in) {
621       /*
622        * Apparently we're actually supposed to ban all control
623        * characters from strings.  This seems unnecessarily
624        * restrictive, so we're only banning zero bytes.  (Since the
625        * string is presumed to be UTF-8 encoded it's fine to just
626        * check this way.)
627        */
628       in.error("null byte in string");
629     }
630
631     ret.push_back(*in);
632     ++in;
633   }
634
635   return ret;
636 }
637
638 dynamic parseValue(Input& in) {
639   in.skipWhitespace();
640   return *in == '[' ? parseArray(in) :
641          *in == '{' ? parseObject(in) :
642          *in == '\"' ? parseString(in) :
643          (*in == '-' || (*in >= '0' && *in <= '9')) ? parseNumber(in) :
644          in.consume("true") ? true :
645          in.consume("false") ? false :
646          in.consume("null") ? nullptr :
647          in.consume("Infinity") ? std::numeric_limits<double>::infinity() :
648          in.consume("NaN") ? std::numeric_limits<double>::quiet_NaN() :
649          in.error("expected json value");
650 }
651
652 }
653
654 //////////////////////////////////////////////////////////////////////
655
656 fbstring serialize(dynamic const& dyn, serialization_opts const& opts) {
657   fbstring ret;
658   unsigned indentLevel = 0;
659   Printer p(ret, opts.pretty_formatting ? &indentLevel : nullptr, &opts);
660   p(dyn);
661   return ret;
662 }
663
664 }
665
666 //////////////////////////////////////////////////////////////////////
667
668 dynamic parseJson(StringPiece range) {
669   json::Input in(range);
670
671   auto ret = parseValue(in);
672   in.skipWhitespace();
673   if (*in != '\0' && in.size()) {
674     in.error("parsing didn't consume all input");
675   }
676   return ret;
677 }
678
679 fbstring toJson(dynamic const& dyn) {
680   return json::serialize(dyn, json::serialization_opts());
681 }
682
683 fbstring toPrettyJson(dynamic const& dyn) {
684   json::serialization_opts opts;
685   opts.pretty_formatting = true;
686   return json::serialize(dyn, opts);
687 }
688
689 //////////////////////////////////////////////////////////////////////
690 // dynamic::print_as_pseudo_json() is implemented here for header
691 // ordering reasons (most of the dynamic implementation is in
692 // dynamic-inl.h, which we don't want to include json.h).
693
694 void dynamic::print_as_pseudo_json(std::ostream& out) const {
695   json::serialization_opts opts;
696   opts.allow_non_string_keys = true;
697   out << json::serialize(*this, opts);
698 }
699
700 //////////////////////////////////////////////////////////////////////
701
702 }