File: json_reader.h

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (136 lines) | stat: -rw-r--r-- 5,137 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A JSON parser, converting from a base::StringPiece to a base::Value.
//
// The JSON spec is:
// https://tools.ietf.org/rfc/rfc8259.txt
// which obsoletes the earlier RFCs 4627, 7158 and 7159.
//
// This RFC should be equivalent to the informal spec:
// https://www.json.org/json-en.html
//
// Implementation choices permitted by the RFC:
// - Nesting is limited (to a configurable depth, 200 by default).
// - Numbers are limited to those representable by a finite double. The
//   conversion from a JSON number (in the base::StringPiece input) to a
//   double-flavored base::Value may also be lossy.
// - The input (which must be UTF-8) may begin with a BOM (Byte Order Mark).
// - Duplicate object keys (strings) are silently allowed. Last key-value pair
//   wins. Previous pairs are discarded.
//
// Configurable (see the JSONParserOptions type) deviations from the RFC:
// - Allow trailing commas: "[1,2,]".
// - Replace invalid Unicode with U+FFFD REPLACEMENT CHARACTER.
// - Allow "// etc\n" and "/* etc */" C-style comments.
// - Allow ASCII control characters, including literal (not escaped) NUL bytes
//   and new lines, within a JSON string.
// - Allow "\\v" escapes within a JSON string, producing a vertical tab.
// - Allow "\\x23" escapes within a JSON string. Subtly, the 2-digit hex value
//   is a Unicode code point, not a UTF-8 byte. For example, "\\xFF" in the
//   JSON source decodes to a base::Value whose string contains "\xC3\xBF", the
//   UTF-8 encoding of U+00FF LATIN SMALL LETTER Y WITH DIAERESIS. Converting
//   from UTF-8 to UTF-16, e.g. via UTF8ToWide, will recover a 16-bit 0x00FF.

#ifndef BASE_JSON_JSON_READER_H_
#define BASE_JSON_JSON_READER_H_

#include <string>

#include "base/base_export.h"
#include "base/json/json_common.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace base {

enum JSONParserOptions {
  // Parses the input strictly according to RFC 8259.
  JSON_PARSE_RFC = 0,

  // Allows commas to exist after the last element in structures.
  JSON_ALLOW_TRAILING_COMMAS = 1 << 0,

  // If set the parser replaces invalid code points (i.e. lone
  // surrogates) with the Unicode replacement character (U+FFFD). If
  // not set, invalid code points trigger a hard error and parsing
  // fails.
  JSON_REPLACE_INVALID_CHARACTERS = 1 << 1,

  // Allows both C (/* */) and C++ (//) style comments.
  JSON_ALLOW_COMMENTS = 1 << 2,

  // Permits unescaped ASCII control characters (such as unescaped \r and \n)
  // in the range [0x00,0x1F].
  JSON_ALLOW_CONTROL_CHARS = 1 << 3,

  // Permits \\v vertical tab escapes.
  JSON_ALLOW_VERT_TAB = 1 << 4,

  // Permits \\xNN escapes as described above.
  JSON_ALLOW_X_ESCAPES = 1 << 5,

  // This parser historically accepted, without configuration flags,
  // non-standard JSON extensions. This flag enables that traditional parsing
  // behavior.
  //
  // This set of options is mirrored in Rust
  // base::JsonOptions::with_chromium_extensions().
  JSON_PARSE_CHROMIUM_EXTENSIONS = JSON_ALLOW_COMMENTS |
                                   JSON_ALLOW_CONTROL_CHARS |
                                   JSON_ALLOW_VERT_TAB | JSON_ALLOW_X_ESCAPES,
};

class BASE_EXPORT JSONReader {
 public:
  struct BASE_EXPORT Error {
    std::string message;
    int line = 0;
    int column = 0;

    std::string ToString() const {
      return "line " + base::NumberToString(line) + ", column " +
             base::NumberToString(column) + ": " + message;
    }
  };

  using Result = base::expected<Value, Error>;

  // This class contains only static methods.
  JSONReader() = delete;
  JSONReader(const JSONReader&) = delete;
  JSONReader& operator=(const JSONReader&) = delete;

  // Reads and parses |json|, returning a Value.
  // If |json| is not a properly formed JSON string, returns absl::nullopt.
  static absl::optional<Value> Read(
      StringPiece json,
      int options = JSON_PARSE_CHROMIUM_EXTENSIONS,
      size_t max_depth = internal::kAbsoluteMaxDepth);

  // Reads and parses |json|, returning a Value::Dict.
  // If |json| is not a properly formed JSON dict string, returns absl::nullopt.
  static absl::optional<Value::Dict> ReadDict(
      StringPiece json,
      int options = JSON_PARSE_CHROMIUM_EXTENSIONS,
      size_t max_depth = internal::kAbsoluteMaxDepth);

  // Reads and parses |json| like Read(). On success returns a Value as the
  // expected value. Otherwise, it returns an Error instance, populated with a
  // formatted error message, an error code, and the error location if
  // appropriate as the error value of the expected type.
  static Result ReadAndReturnValueWithError(
      StringPiece json,
      int options = JSON_PARSE_CHROMIUM_EXTENSIONS);

  // Determine whether the Rust parser is in use.
  static bool UsingRust();
};

}  // namespace base

#endif  // BASE_JSON_JSON_READER_H_