Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
1
TMessagesProj/jni/voip/webrtc/base/json/OWNERS
Normal file
1
TMessagesProj/jni/voip/webrtc/base/json/OWNERS
Normal file
|
|
@ -0,0 +1 @@
|
|||
file://base/SECURITY_OWNERS
|
||||
42
TMessagesProj/jni/voip/webrtc/base/json/json_common.h
Normal file
42
TMessagesProj/jni/voip/webrtc/base/json/json_common.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_JSON_JSON_COMMON_H_
|
||||
#define BASE_JSON_JSON_COMMON_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
// Chosen to support 99.9% of documents found in the wild late 2016.
|
||||
// http://crbug.com/673263
|
||||
const size_t kAbsoluteMaxDepth = 200;
|
||||
|
||||
// Simple class that checks for maximum recursion/stack overflow.
|
||||
class StackMarker {
|
||||
public:
|
||||
StackMarker(size_t max_depth, size_t* depth)
|
||||
: max_depth_(max_depth), depth_(depth) {
|
||||
++(*depth_);
|
||||
DCHECK_LE(*depth_, max_depth_);
|
||||
}
|
||||
~StackMarker() { --(*depth_); }
|
||||
|
||||
bool IsTooDeep() const { return *depth_ >= max_depth_; }
|
||||
|
||||
private:
|
||||
const size_t max_depth_;
|
||||
size_t* const depth_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StackMarker);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_JSON_JSON_COMMON_H_
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// A fuzzer that checks correctness of json parser/writer.
|
||||
// The fuzzer input is passed through parsing twice,
|
||||
// so that presumably valid json is parsed/written again.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/json/string_escape.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/values.h"
|
||||
|
||||
// Entry point for libFuzzer.
|
||||
// We will use the last byte of data as parsing options.
|
||||
// The rest will be used as text input to the parser.
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < 2)
|
||||
return 0;
|
||||
|
||||
// Create a copy of input buffer, as otherwise we don't catch
|
||||
// overflow that touches the last byte (which is used in options).
|
||||
std::unique_ptr<char[]> input(new char[size - 1]);
|
||||
memcpy(input.get(), data, size - 1);
|
||||
|
||||
base::StringPiece input_string(input.get(), size - 1);
|
||||
|
||||
const int options = data[size - 1];
|
||||
base::JSONReader::ValueWithError result =
|
||||
base::JSONReader::ReadAndReturnValueWithError(input_string, options);
|
||||
if (!result.value)
|
||||
return 0;
|
||||
|
||||
std::string parsed_output;
|
||||
bool b = base::JSONWriter::Write(*result.value, &parsed_output);
|
||||
LOG_ASSERT(b);
|
||||
|
||||
base::JSONReader::ValueWithError double_result =
|
||||
base::JSONReader::ReadAndReturnValueWithError(parsed_output, options);
|
||||
LOG_ASSERT(double_result.value);
|
||||
std::string double_parsed_output;
|
||||
bool b2 =
|
||||
base::JSONWriter::Write(*double_result.value, &double_parsed_output);
|
||||
LOG_ASSERT(b2);
|
||||
|
||||
LOG_ASSERT(parsed_output == double_parsed_output)
|
||||
<< "Parser/Writer mismatch."
|
||||
<< "\nInput=" << base::GetQuotedJSONString(parsed_output)
|
||||
<< "\nOutput=" << base::GetQuotedJSONString(double_parsed_output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_file_value_serializer.h"
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/json/json_string_value_serializer.h"
|
||||
#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
using base::FilePath;
|
||||
|
||||
const char JSONFileValueDeserializer::kAccessDenied[] = "Access denied.";
|
||||
const char JSONFileValueDeserializer::kCannotReadFile[] = "Can't read file.";
|
||||
const char JSONFileValueDeserializer::kFileLocked[] = "File locked.";
|
||||
const char JSONFileValueDeserializer::kNoSuchFile[] = "File doesn't exist.";
|
||||
|
||||
JSONFileValueSerializer::JSONFileValueSerializer(
|
||||
const base::FilePath& json_file_path)
|
||||
: json_file_path_(json_file_path) {
|
||||
}
|
||||
|
||||
JSONFileValueSerializer::~JSONFileValueSerializer() = default;
|
||||
|
||||
bool JSONFileValueSerializer::Serialize(const base::Value& root) {
|
||||
return SerializeInternal(root, false);
|
||||
}
|
||||
|
||||
bool JSONFileValueSerializer::SerializeAndOmitBinaryValues(
|
||||
const base::Value& root) {
|
||||
return SerializeInternal(root, true);
|
||||
}
|
||||
|
||||
bool JSONFileValueSerializer::SerializeInternal(const base::Value& root,
|
||||
bool omit_binary_values) {
|
||||
std::string json_string;
|
||||
JSONStringValueSerializer serializer(&json_string);
|
||||
serializer.set_pretty_print(true);
|
||||
bool result = omit_binary_values ?
|
||||
serializer.SerializeAndOmitBinaryValues(root) :
|
||||
serializer.Serialize(root);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
int data_size = static_cast<int>(json_string.size());
|
||||
if (base::WriteFile(json_file_path_, json_string.data(), data_size) !=
|
||||
data_size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSONFileValueDeserializer::JSONFileValueDeserializer(
|
||||
const base::FilePath& json_file_path,
|
||||
int options)
|
||||
: json_file_path_(json_file_path), options_(options), last_read_size_(0U) {}
|
||||
|
||||
JSONFileValueDeserializer::~JSONFileValueDeserializer() = default;
|
||||
|
||||
int JSONFileValueDeserializer::ReadFileToString(std::string* json_string) {
|
||||
DCHECK(json_string);
|
||||
if (!base::ReadFileToString(json_file_path_, json_string)) {
|
||||
#if defined(OS_WIN)
|
||||
int error = ::GetLastError();
|
||||
if (error == ERROR_SHARING_VIOLATION || error == ERROR_LOCK_VIOLATION) {
|
||||
return JSON_FILE_LOCKED;
|
||||
} else if (error == ERROR_ACCESS_DENIED) {
|
||||
return JSON_ACCESS_DENIED;
|
||||
}
|
||||
#endif
|
||||
return base::PathExists(json_file_path_) ? JSON_CANNOT_READ_FILE
|
||||
: JSON_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
last_read_size_ = json_string->size();
|
||||
return JSON_NO_ERROR;
|
||||
}
|
||||
|
||||
const char* JSONFileValueDeserializer::GetErrorMessageForCode(int error_code) {
|
||||
switch (error_code) {
|
||||
case JSON_NO_ERROR:
|
||||
return "";
|
||||
case JSON_ACCESS_DENIED:
|
||||
return kAccessDenied;
|
||||
case JSON_CANNOT_READ_FILE:
|
||||
return kCannotReadFile;
|
||||
case JSON_FILE_LOCKED:
|
||||
return kFileLocked;
|
||||
case JSON_NO_SUCH_FILE:
|
||||
return kNoSuchFile;
|
||||
default:
|
||||
NOTREACHED();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<base::Value> JSONFileValueDeserializer::Deserialize(
|
||||
int* error_code,
|
||||
std::string* error_str) {
|
||||
std::string json_string;
|
||||
int error = ReadFileToString(&json_string);
|
||||
if (error != JSON_NO_ERROR) {
|
||||
if (error_code)
|
||||
*error_code = error;
|
||||
if (error_str)
|
||||
*error_str = GetErrorMessageForCode(error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSONStringValueDeserializer deserializer(json_string, options_);
|
||||
return deserializer.Deserialize(error_code, error_str);
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_JSON_JSON_FILE_VALUE_SERIALIZER_H_
|
||||
#define BASE_JSON_JSON_FILE_VALUE_SERIALIZER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/values.h"
|
||||
|
||||
class BASE_EXPORT JSONFileValueSerializer : public base::ValueSerializer {
|
||||
public:
|
||||
// |json_file_path_| is the path of a file that will be destination of the
|
||||
// serialization. The serializer will attempt to create the file at the
|
||||
// specified location.
|
||||
explicit JSONFileValueSerializer(const base::FilePath& json_file_path);
|
||||
|
||||
~JSONFileValueSerializer() override;
|
||||
|
||||
// DO NOT USE except in unit tests to verify the file was written properly.
|
||||
// We should never serialize directly to a file since this will block the
|
||||
// thread. Instead, serialize to a string and write to the file you want on
|
||||
// the file thread.
|
||||
//
|
||||
// Attempt to serialize the data structure represented by Value into
|
||||
// JSON. If the return value is true, the result will have been written
|
||||
// into the file whose name was passed into the constructor.
|
||||
bool Serialize(const base::Value& root) override;
|
||||
|
||||
// Equivalent to Serialize(root) except binary values are omitted from the
|
||||
// output.
|
||||
bool SerializeAndOmitBinaryValues(const base::Value& root);
|
||||
|
||||
private:
|
||||
bool SerializeInternal(const base::Value& root, bool omit_binary_values);
|
||||
|
||||
const base::FilePath json_file_path_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueSerializer);
|
||||
};
|
||||
|
||||
class BASE_EXPORT JSONFileValueDeserializer : public base::ValueDeserializer {
|
||||
public:
|
||||
// |json_file_path_| is the path of a file that will be source of the
|
||||
// deserialization. |options| is a bitmask of JSONParserOptions.
|
||||
explicit JSONFileValueDeserializer(const base::FilePath& json_file_path,
|
||||
int options = 0);
|
||||
|
||||
~JSONFileValueDeserializer() override;
|
||||
|
||||
// Attempt to deserialize the data structure encoded in the file passed
|
||||
// in to the constructor into a structure of Value objects. If the return
|
||||
// value is NULL, and if |error_code| is non-null, |error_code| will
|
||||
// contain an integer error code (either JsonFileError or JsonParseError).
|
||||
// If |error_message| is non-null, it will be filled in with a formatted
|
||||
// error message including the location of the error if appropriate.
|
||||
// The caller takes ownership of the returned value.
|
||||
std::unique_ptr<base::Value> Deserialize(int* error_code,
|
||||
std::string* error_message) override;
|
||||
|
||||
// This enum is designed to safely overlap with JSONReader::JsonParseError.
|
||||
enum JsonFileError {
|
||||
JSON_NO_ERROR = 0,
|
||||
JSON_ACCESS_DENIED = 1000,
|
||||
JSON_CANNOT_READ_FILE,
|
||||
JSON_FILE_LOCKED,
|
||||
JSON_NO_SUCH_FILE
|
||||
};
|
||||
|
||||
// File-specific error messages that can be returned.
|
||||
static const char kAccessDenied[];
|
||||
static const char kCannotReadFile[];
|
||||
static const char kFileLocked[];
|
||||
static const char kNoSuchFile[];
|
||||
|
||||
// Convert an error code into an error message. |error_code| is assumed to
|
||||
// be a JsonFileError.
|
||||
static const char* GetErrorMessageForCode(int error_code);
|
||||
|
||||
// Returns the size (in bytes) of JSON string read from disk in the last
|
||||
// successful |Deserialize()| call.
|
||||
size_t get_last_read_size() const { return last_read_size_; }
|
||||
|
||||
private:
|
||||
// A wrapper for ReadFileToString which returns a non-zero JsonFileError if
|
||||
// there were file errors.
|
||||
int ReadFileToString(std::string* json_string);
|
||||
|
||||
const base::FilePath json_file_path_;
|
||||
const int options_;
|
||||
size_t last_read_size_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueDeserializer);
|
||||
};
|
||||
|
||||
#endif // BASE_JSON_JSON_FILE_VALUE_SERIALIZER_H_
|
||||
|
||||
746
TMessagesProj/jni/voip/webrtc/base/json/json_parser.cc
Normal file
746
TMessagesProj/jni/voip/webrtc/base/json/json_parser.cc
Normal file
|
|
@ -0,0 +1,746 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_parser.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversion_utils.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/third_party/icu/icu_utf.h"
|
||||
#include "base/values.h"
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
const int32_t kExtendedASCIIStart = 0x80;
|
||||
constexpr uint32_t kUnicodeReplacementPoint = 0xFFFD;
|
||||
|
||||
// UnprefixedHexStringToInt acts like |HexStringToInt|, but enforces that the
|
||||
// input consists purely of hex digits. I.e. no "0x" nor "OX" prefix is
|
||||
// permitted.
|
||||
bool UnprefixedHexStringToInt(StringPiece input, int* output) {
|
||||
for (size_t i = 0; i < input.size(); i++) {
|
||||
if (!IsHexDigit(input[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return HexStringToInt(input, output);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This is U+FFFD.
|
||||
const char kUnicodeReplacementString[] = "\xEF\xBF\xBD";
|
||||
|
||||
JSONParser::JSONParser(int options, size_t max_depth)
|
||||
: options_(options),
|
||||
max_depth_(max_depth),
|
||||
index_(0),
|
||||
stack_depth_(0),
|
||||
line_number_(0),
|
||||
index_last_line_(0),
|
||||
error_code_(JSONReader::JSON_NO_ERROR),
|
||||
error_line_(0),
|
||||
error_column_(0) {
|
||||
CHECK_LE(max_depth, kAbsoluteMaxDepth);
|
||||
}
|
||||
|
||||
JSONParser::~JSONParser() = default;
|
||||
|
||||
Optional<Value> JSONParser::Parse(StringPiece input) {
|
||||
input_ = input;
|
||||
index_ = 0;
|
||||
line_number_ = 1;
|
||||
index_last_line_ = 0;
|
||||
|
||||
error_code_ = JSONReader::JSON_NO_ERROR;
|
||||
error_line_ = 0;
|
||||
error_column_ = 0;
|
||||
|
||||
// ICU and ReadUnicodeCharacter() use int32_t for lengths, so ensure
|
||||
// that the index_ will not overflow when parsing.
|
||||
if (!base::IsValueInRangeForNumericType<int32_t>(input.length())) {
|
||||
ReportError(JSONReader::JSON_TOO_LARGE, 0);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
// When the input JSON string starts with a UTF-8 Byte-Order-Mark,
|
||||
// advance the start position to avoid the ParseNextToken function mis-
|
||||
// treating a Unicode BOM as an invalid character and returning NULL.
|
||||
ConsumeIfMatch("\xEF\xBB\xBF");
|
||||
|
||||
// Parse the first and any nested tokens.
|
||||
Optional<Value> root(ParseNextToken());
|
||||
if (!root)
|
||||
return nullopt;
|
||||
|
||||
// Make sure the input stream is at an end.
|
||||
if (GetNextToken() != T_END_OF_INPUT) {
|
||||
ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
JSONReader::JsonParseError JSONParser::error_code() const {
|
||||
return error_code_;
|
||||
}
|
||||
|
||||
std::string JSONParser::GetErrorMessage() const {
|
||||
return FormatErrorMessage(error_line_, error_column_,
|
||||
JSONReader::ErrorCodeToString(error_code_));
|
||||
}
|
||||
|
||||
int JSONParser::error_line() const {
|
||||
return error_line_;
|
||||
}
|
||||
|
||||
int JSONParser::error_column() const {
|
||||
return error_column_;
|
||||
}
|
||||
|
||||
// StringBuilder ///////////////////////////////////////////////////////////////
|
||||
|
||||
JSONParser::StringBuilder::StringBuilder() : StringBuilder(nullptr) {}
|
||||
|
||||
JSONParser::StringBuilder::StringBuilder(const char* pos)
|
||||
: pos_(pos), length_(0) {}
|
||||
|
||||
JSONParser::StringBuilder::~StringBuilder() = default;
|
||||
|
||||
JSONParser::StringBuilder& JSONParser::StringBuilder::operator=(
|
||||
StringBuilder&& other) = default;
|
||||
|
||||
void JSONParser::StringBuilder::Append(uint32_t point) {
|
||||
DCHECK(IsValidCodepoint(point));
|
||||
|
||||
if (point < kExtendedASCIIStart && !string_) {
|
||||
DCHECK_EQ(static_cast<char>(point), pos_[length_]);
|
||||
++length_;
|
||||
} else {
|
||||
Convert();
|
||||
if (UNLIKELY(point == kUnicodeReplacementPoint)) {
|
||||
string_->append(kUnicodeReplacementString);
|
||||
} else {
|
||||
WriteUnicodeCharacter(point, &*string_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSONParser::StringBuilder::Convert() {
|
||||
if (string_)
|
||||
return;
|
||||
string_.emplace(pos_, length_);
|
||||
}
|
||||
|
||||
std::string JSONParser::StringBuilder::DestructiveAsString() {
|
||||
if (string_)
|
||||
return std::move(*string_);
|
||||
return std::string(pos_, length_);
|
||||
}
|
||||
|
||||
// JSONParser private //////////////////////////////////////////////////////////
|
||||
|
||||
Optional<StringPiece> JSONParser::PeekChars(size_t count) {
|
||||
if (index_ + count > input_.length())
|
||||
return nullopt;
|
||||
// Using StringPiece::substr() is significantly slower (according to
|
||||
// base_perftests) than constructing a substring manually.
|
||||
return StringPiece(input_.data() + index_, count);
|
||||
}
|
||||
|
||||
Optional<char> JSONParser::PeekChar() {
|
||||
Optional<StringPiece> chars = PeekChars(1);
|
||||
if (chars)
|
||||
return (*chars)[0];
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
Optional<StringPiece> JSONParser::ConsumeChars(size_t count) {
|
||||
Optional<StringPiece> chars = PeekChars(count);
|
||||
if (chars)
|
||||
index_ += count;
|
||||
return chars;
|
||||
}
|
||||
|
||||
Optional<char> JSONParser::ConsumeChar() {
|
||||
Optional<StringPiece> chars = ConsumeChars(1);
|
||||
if (chars)
|
||||
return (*chars)[0];
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
const char* JSONParser::pos() {
|
||||
CHECK_LE(static_cast<size_t>(index_), input_.length());
|
||||
return input_.data() + index_;
|
||||
}
|
||||
|
||||
JSONParser::Token JSONParser::GetNextToken() {
|
||||
EatWhitespaceAndComments();
|
||||
|
||||
Optional<char> c = PeekChar();
|
||||
if (!c)
|
||||
return T_END_OF_INPUT;
|
||||
|
||||
switch (*c) {
|
||||
case '{':
|
||||
return T_OBJECT_BEGIN;
|
||||
case '}':
|
||||
return T_OBJECT_END;
|
||||
case '[':
|
||||
return T_ARRAY_BEGIN;
|
||||
case ']':
|
||||
return T_ARRAY_END;
|
||||
case '"':
|
||||
return T_STRING;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
return T_NUMBER;
|
||||
case 't':
|
||||
return T_BOOL_TRUE;
|
||||
case 'f':
|
||||
return T_BOOL_FALSE;
|
||||
case 'n':
|
||||
return T_NULL;
|
||||
case ',':
|
||||
return T_LIST_SEPARATOR;
|
||||
case ':':
|
||||
return T_OBJECT_PAIR_SEPARATOR;
|
||||
default:
|
||||
return T_INVALID_TOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
void JSONParser::EatWhitespaceAndComments() {
|
||||
while (Optional<char> c = PeekChar()) {
|
||||
switch (*c) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
index_last_line_ = index_;
|
||||
// Don't increment line_number_ twice for "\r\n".
|
||||
if (!(c == '\n' && index_ > 0 && input_[index_ - 1] == '\r')) {
|
||||
++line_number_;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case ' ':
|
||||
case '\t':
|
||||
ConsumeChar();
|
||||
break;
|
||||
case '/':
|
||||
if (!EatComment())
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONParser::EatComment() {
|
||||
Optional<StringPiece> comment_start = PeekChars(2);
|
||||
if (!comment_start)
|
||||
return false;
|
||||
|
||||
if (comment_start == "//") {
|
||||
ConsumeChars(2);
|
||||
// Single line comment, read to newline.
|
||||
while (Optional<char> c = PeekChar()) {
|
||||
if (c == '\n' || c == '\r')
|
||||
return true;
|
||||
ConsumeChar();
|
||||
}
|
||||
} else if (comment_start == "/*") {
|
||||
ConsumeChars(2);
|
||||
char previous_char = '\0';
|
||||
// Block comment, read until end marker.
|
||||
while (Optional<char> c = PeekChar()) {
|
||||
if (previous_char == '*' && c == '/') {
|
||||
// EatWhitespaceAndComments will inspect pos(), which will still be on
|
||||
// the last / of the comment, so advance once more (which may also be
|
||||
// end of input).
|
||||
ConsumeChar();
|
||||
return true;
|
||||
}
|
||||
previous_char = *ConsumeChar();
|
||||
}
|
||||
|
||||
// If the comment is unterminated, GetNextToken will report T_END_OF_INPUT.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ParseNextToken() {
|
||||
return ParseToken(GetNextToken());
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ParseToken(Token token) {
|
||||
switch (token) {
|
||||
case T_OBJECT_BEGIN:
|
||||
return ConsumeDictionary();
|
||||
case T_ARRAY_BEGIN:
|
||||
return ConsumeList();
|
||||
case T_STRING:
|
||||
return ConsumeString();
|
||||
case T_NUMBER:
|
||||
return ConsumeNumber();
|
||||
case T_BOOL_TRUE:
|
||||
case T_BOOL_FALSE:
|
||||
case T_NULL:
|
||||
return ConsumeLiteral();
|
||||
default:
|
||||
ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ConsumeDictionary() {
|
||||
if (ConsumeChar() != '{') {
|
||||
ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
StackMarker depth_check(max_depth_, &stack_depth_);
|
||||
if (depth_check.IsTooDeep()) {
|
||||
ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
std::vector<Value::DictStorage::value_type> dict_storage;
|
||||
|
||||
Token token = GetNextToken();
|
||||
while (token != T_OBJECT_END) {
|
||||
if (token != T_STRING) {
|
||||
ReportError(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
// First consume the key.
|
||||
StringBuilder key;
|
||||
if (!ConsumeStringRaw(&key)) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
// Read the separator.
|
||||
token = GetNextToken();
|
||||
if (token != T_OBJECT_PAIR_SEPARATOR) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
// The next token is the value. Ownership transfers to |dict|.
|
||||
ConsumeChar();
|
||||
Optional<Value> value = ParseNextToken();
|
||||
if (!value) {
|
||||
// ReportError from deeper level.
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
dict_storage.emplace_back(key.DestructiveAsString(),
|
||||
std::make_unique<Value>(std::move(*value)));
|
||||
|
||||
token = GetNextToken();
|
||||
if (token == T_LIST_SEPARATOR) {
|
||||
ConsumeChar();
|
||||
token = GetNextToken();
|
||||
if (token == T_OBJECT_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
|
||||
ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
|
||||
return nullopt;
|
||||
}
|
||||
} else if (token != T_OBJECT_END) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
ConsumeChar(); // Closing '}'.
|
||||
// Reverse |dict_storage| to keep the last of elements with the same key in
|
||||
// the input.
|
||||
std::reverse(dict_storage.begin(), dict_storage.end());
|
||||
return Value(Value::DictStorage(std::move(dict_storage)));
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ConsumeList() {
|
||||
if (ConsumeChar() != '[') {
|
||||
ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
StackMarker depth_check(max_depth_, &stack_depth_);
|
||||
if (depth_check.IsTooDeep()) {
|
||||
ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
Value::ListStorage list_storage;
|
||||
|
||||
Token token = GetNextToken();
|
||||
while (token != T_ARRAY_END) {
|
||||
Optional<Value> item = ParseToken(token);
|
||||
if (!item) {
|
||||
// ReportError from deeper level.
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
list_storage.push_back(std::move(*item));
|
||||
|
||||
token = GetNextToken();
|
||||
if (token == T_LIST_SEPARATOR) {
|
||||
ConsumeChar();
|
||||
token = GetNextToken();
|
||||
if (token == T_ARRAY_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
|
||||
ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
|
||||
return nullopt;
|
||||
}
|
||||
} else if (token != T_ARRAY_END) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
ConsumeChar(); // Closing ']'.
|
||||
|
||||
return Value(std::move(list_storage));
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ConsumeString() {
|
||||
StringBuilder string;
|
||||
if (!ConsumeStringRaw(&string))
|
||||
return nullopt;
|
||||
return Value(string.DestructiveAsString());
|
||||
}
|
||||
|
||||
bool JSONParser::ConsumeStringRaw(StringBuilder* out) {
|
||||
if (ConsumeChar() != '"') {
|
||||
ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// StringBuilder will internally build a StringPiece unless a UTF-16
|
||||
// conversion occurs, at which point it will perform a copy into a
|
||||
// std::string.
|
||||
StringBuilder string(pos());
|
||||
|
||||
while (PeekChar()) {
|
||||
uint32_t next_char = 0;
|
||||
if (!ReadUnicodeCharacter(input_.data(),
|
||||
static_cast<int32_t>(input_.length()), &index_,
|
||||
&next_char) ||
|
||||
!IsValidCodepoint(next_char)) {
|
||||
if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
|
||||
ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1);
|
||||
return false;
|
||||
}
|
||||
ConsumeChar();
|
||||
string.Append(kUnicodeReplacementPoint);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next_char == '"') {
|
||||
ConsumeChar();
|
||||
*out = std::move(string);
|
||||
return true;
|
||||
}
|
||||
if (next_char != '\\') {
|
||||
// If this character is not an escape sequence...
|
||||
ConsumeChar();
|
||||
string.Append(next_char);
|
||||
} else {
|
||||
// And if it is an escape sequence, the input string will be adjusted
|
||||
// (either by combining the two characters of an encoded escape sequence,
|
||||
// or with a UTF conversion), so using StringPiece isn't possible -- force
|
||||
// a conversion.
|
||||
string.Convert();
|
||||
|
||||
// Read past the escape '\' and ensure there's a character following.
|
||||
Optional<StringPiece> escape_sequence = ConsumeChars(2);
|
||||
if (!escape_sequence) {
|
||||
ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ((*escape_sequence)[1]) {
|
||||
// Allowed esape sequences:
|
||||
case 'x': { // UTF-8 sequence.
|
||||
// UTF-8 \x escape sequences are not allowed in the spec, but they
|
||||
// are supported here for backwards-compatiblity with the old parser.
|
||||
escape_sequence = ConsumeChars(2);
|
||||
if (!escape_sequence) {
|
||||
ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
|
||||
return false;
|
||||
}
|
||||
|
||||
int hex_digit = 0;
|
||||
if (!UnprefixedHexStringToInt(*escape_sequence, &hex_digit) ||
|
||||
!IsValidCharacter(hex_digit)) {
|
||||
ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
|
||||
return false;
|
||||
}
|
||||
|
||||
string.Append(hex_digit);
|
||||
break;
|
||||
}
|
||||
case 'u': { // UTF-16 sequence.
|
||||
// UTF units are of the form \uXXXX.
|
||||
uint32_t code_point;
|
||||
if (!DecodeUTF16(&code_point)) {
|
||||
ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
|
||||
return false;
|
||||
}
|
||||
string.Append(code_point);
|
||||
break;
|
||||
}
|
||||
case '"':
|
||||
string.Append('"');
|
||||
break;
|
||||
case '\\':
|
||||
string.Append('\\');
|
||||
break;
|
||||
case '/':
|
||||
string.Append('/');
|
||||
break;
|
||||
case 'b':
|
||||
string.Append('\b');
|
||||
break;
|
||||
case 'f':
|
||||
string.Append('\f');
|
||||
break;
|
||||
case 'n':
|
||||
string.Append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
string.Append('\r');
|
||||
break;
|
||||
case 't':
|
||||
string.Append('\t');
|
||||
break;
|
||||
case 'v': // Not listed as valid escape sequence in the RFC.
|
||||
string.Append('\v');
|
||||
break;
|
||||
// All other escape squences are illegal.
|
||||
default:
|
||||
ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Entry is at the first X in \uXXXX.
|
||||
bool JSONParser::DecodeUTF16(uint32_t* out_code_point) {
|
||||
Optional<StringPiece> escape_sequence = ConsumeChars(4);
|
||||
if (!escape_sequence)
|
||||
return false;
|
||||
|
||||
// Consume the UTF-16 code unit, which may be a high surrogate.
|
||||
int code_unit16_high = 0;
|
||||
if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_high))
|
||||
return false;
|
||||
|
||||
// If this is a high surrogate, consume the next code unit to get the
|
||||
// low surrogate.
|
||||
if (CBU16_IS_SURROGATE(code_unit16_high)) {
|
||||
// Make sure this is the high surrogate. If not, it's an encoding
|
||||
// error.
|
||||
if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high))
|
||||
return false;
|
||||
|
||||
// Make sure that the token has more characters to consume the
|
||||
// lower surrogate.
|
||||
if (!ConsumeIfMatch("\\u")) {
|
||||
if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0)
|
||||
return false;
|
||||
*out_code_point = kUnicodeReplacementPoint;
|
||||
return true;
|
||||
}
|
||||
|
||||
escape_sequence = ConsumeChars(4);
|
||||
if (!escape_sequence)
|
||||
return false;
|
||||
|
||||
int code_unit16_low = 0;
|
||||
if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_low))
|
||||
return false;
|
||||
|
||||
if (!CBU16_IS_TRAIL(code_unit16_low)) {
|
||||
if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0)
|
||||
return false;
|
||||
*out_code_point = kUnicodeReplacementPoint;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t code_point =
|
||||
CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low);
|
||||
|
||||
*out_code_point = code_point;
|
||||
} else {
|
||||
// Not a surrogate.
|
||||
DCHECK(CBU16_IS_SINGLE(code_unit16_high));
|
||||
|
||||
*out_code_point = code_unit16_high;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ConsumeNumber() {
|
||||
const char* num_start = pos();
|
||||
const int start_index = index_;
|
||||
int end_index = start_index;
|
||||
|
||||
if (PeekChar() == '-')
|
||||
ConsumeChar();
|
||||
|
||||
if (!ReadInt(false)) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
end_index = index_;
|
||||
|
||||
// The optional fraction part.
|
||||
if (PeekChar() == '.') {
|
||||
ConsumeChar();
|
||||
if (!ReadInt(true)) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
end_index = index_;
|
||||
}
|
||||
|
||||
// Optional exponent part.
|
||||
Optional<char> c = PeekChar();
|
||||
if (c == 'e' || c == 'E') {
|
||||
ConsumeChar();
|
||||
if (PeekChar() == '-' || PeekChar() == '+') {
|
||||
ConsumeChar();
|
||||
}
|
||||
if (!ReadInt(true)) {
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
end_index = index_;
|
||||
}
|
||||
|
||||
// ReadInt is greedy because numbers have no easily detectable sentinel,
|
||||
// so save off where the parser should be on exit (see Consume invariant at
|
||||
// the top of the header), then make sure the next token is one which is
|
||||
// valid.
|
||||
int exit_index = index_;
|
||||
|
||||
switch (GetNextToken()) {
|
||||
case T_OBJECT_END:
|
||||
case T_ARRAY_END:
|
||||
case T_LIST_SEPARATOR:
|
||||
case T_END_OF_INPUT:
|
||||
break;
|
||||
default:
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
index_ = exit_index;
|
||||
|
||||
StringPiece num_string(num_start, end_index - start_index);
|
||||
|
||||
int num_int;
|
||||
if (StringToInt(num_string, &num_int))
|
||||
return Value(num_int);
|
||||
|
||||
double num_double;
|
||||
if (StringToDouble(num_string.as_string(), &num_double) &&
|
||||
std::isfinite(num_double)) {
|
||||
return Value(num_double);
|
||||
}
|
||||
|
||||
ReportError(JSONReader::JSON_UNREPRESENTABLE_NUMBER, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
bool JSONParser::ReadInt(bool allow_leading_zeros) {
|
||||
size_t len = 0;
|
||||
char first = 0;
|
||||
|
||||
while (Optional<char> c = PeekChar()) {
|
||||
if (!IsAsciiDigit(c))
|
||||
break;
|
||||
|
||||
if (len == 0)
|
||||
first = *c;
|
||||
|
||||
++len;
|
||||
ConsumeChar();
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
return false;
|
||||
|
||||
if (!allow_leading_zeros && len > 1 && first == '0')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Optional<Value> JSONParser::ConsumeLiteral() {
|
||||
if (ConsumeIfMatch("true"))
|
||||
return Value(true);
|
||||
if (ConsumeIfMatch("false"))
|
||||
return Value(false);
|
||||
if (ConsumeIfMatch("null"))
|
||||
return Value(Value::Type::NONE);
|
||||
ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
bool JSONParser::ConsumeIfMatch(StringPiece match) {
|
||||
if (match == PeekChars(match.size())) {
|
||||
ConsumeChars(match.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void JSONParser::ReportError(JSONReader::JsonParseError code,
|
||||
int column_adjust) {
|
||||
error_code_ = code;
|
||||
error_line_ = line_number_;
|
||||
error_column_ = index_ - index_last_line_ + column_adjust;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string JSONParser::FormatErrorMessage(int line, int column,
|
||||
const std::string& description) {
|
||||
if (line || column) {
|
||||
return StringPrintf("Line: %i, column: %i, %s",
|
||||
line, column, description.c_str());
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
261
TMessagesProj/jni/voip/webrtc/base/json/json_parser.h
Normal file
261
TMessagesProj/jni/voip/webrtc/base/json/json_parser.h
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_JSON_JSON_PARSER_H_
|
||||
#define BASE_JSON_JSON_PARSER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/json/json_common.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/optional.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Value;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class JSONParserTest;
|
||||
|
||||
// The implementation behind the JSONReader interface. This class is not meant
|
||||
// to be used directly; it encapsulates logic that need not be exposed publicly.
|
||||
//
|
||||
// This parser guarantees O(n) time through the input string. Iteration happens
|
||||
// on the byte level, with the functions ConsumeChars() and ConsumeChar(). The
|
||||
// conversion from byte to JSON token happens without advancing the parser in
|
||||
// GetNextToken/ParseToken, that is tokenization operates on the current parser
|
||||
// position without advancing.
|
||||
//
|
||||
// Built on top of these are a family of Consume functions that iterate
|
||||
// internally. Invariant: on entry of a Consume function, the parser is wound
|
||||
// to the first byte of a valid JSON token. On exit, it is on the first byte
|
||||
// after the token that was just consumed, which would likely be the first byte
|
||||
// of the next token.
|
||||
class BASE_EXPORT JSONParser {
|
||||
public:
|
||||
JSONParser(int options, size_t max_depth = kAbsoluteMaxDepth);
|
||||
~JSONParser();
|
||||
|
||||
// Parses the input string according to the set options and returns the
|
||||
// result as a Value.
|
||||
// Wrap this in base::FooValue::From() to check the Value is of type Foo and
|
||||
// convert to a FooValue at the same time.
|
||||
Optional<Value> Parse(StringPiece input);
|
||||
|
||||
// Returns the error code.
|
||||
JSONReader::JsonParseError error_code() const;
|
||||
|
||||
// Returns the human-friendly error message.
|
||||
std::string GetErrorMessage() const;
|
||||
|
||||
// Returns the error line number if parse error happened. Otherwise always
|
||||
// returns 0.
|
||||
int error_line() const;
|
||||
|
||||
// Returns the error column number if parse error happened. Otherwise always
|
||||
// returns 0.
|
||||
int error_column() const;
|
||||
|
||||
private:
|
||||
enum Token {
|
||||
T_OBJECT_BEGIN, // {
|
||||
T_OBJECT_END, // }
|
||||
T_ARRAY_BEGIN, // [
|
||||
T_ARRAY_END, // ]
|
||||
T_STRING,
|
||||
T_NUMBER,
|
||||
T_BOOL_TRUE, // true
|
||||
T_BOOL_FALSE, // false
|
||||
T_NULL, // null
|
||||
T_LIST_SEPARATOR, // ,
|
||||
T_OBJECT_PAIR_SEPARATOR, // :
|
||||
T_END_OF_INPUT,
|
||||
T_INVALID_TOKEN,
|
||||
};
|
||||
|
||||
// A helper class used for parsing strings. One optimization performed is to
|
||||
// create base::Value with a StringPiece to avoid unnecessary std::string
|
||||
// copies. This is not possible if the input string needs to be decoded from
|
||||
// UTF-16 to UTF-8, or if an escape sequence causes characters to be skipped.
|
||||
// This class centralizes that logic.
|
||||
class StringBuilder {
|
||||
public:
|
||||
// Empty constructor. Used for creating a builder with which to assign to.
|
||||
StringBuilder();
|
||||
|
||||
// |pos| is the beginning of an input string, excluding the |"|.
|
||||
explicit StringBuilder(const char* pos);
|
||||
|
||||
~StringBuilder();
|
||||
|
||||
StringBuilder& operator=(StringBuilder&& other);
|
||||
|
||||
// Appends the Unicode code point |point| to the string, either by
|
||||
// increasing the |length_| of the string if the string has not been
|
||||
// converted, or by appending the UTF8 bytes for the code point.
|
||||
void Append(uint32_t point);
|
||||
|
||||
// Converts the builder from its default StringPiece to a full std::string,
|
||||
// performing a copy. Once a builder is converted, it cannot be made a
|
||||
// StringPiece again.
|
||||
void Convert();
|
||||
|
||||
// Returns the builder as a string, invalidating all state. This allows
|
||||
// the internal string buffer representation to be destructively moved
|
||||
// in cases where the builder will not be needed any more.
|
||||
std::string DestructiveAsString();
|
||||
|
||||
private:
|
||||
// The beginning of the input string.
|
||||
const char* pos_;
|
||||
|
||||
// Number of bytes in |pos_| that make up the string being built.
|
||||
size_t length_;
|
||||
|
||||
// The copied string representation. Will be unset until Convert() is
|
||||
// called.
|
||||
base::Optional<std::string> string_;
|
||||
};
|
||||
|
||||
// Returns the next |count| bytes of the input stream, or nullopt if fewer
|
||||
// than |count| bytes remain.
|
||||
Optional<StringPiece> PeekChars(size_t count);
|
||||
|
||||
// Calls PeekChars() with a |count| of 1.
|
||||
Optional<char> PeekChar();
|
||||
|
||||
// Returns the next |count| bytes of the input stream, or nullopt if fewer
|
||||
// than |count| bytes remain, and advances the parser position by |count|.
|
||||
Optional<StringPiece> ConsumeChars(size_t count);
|
||||
|
||||
// Calls ConsumeChars() with a |count| of 1.
|
||||
Optional<char> ConsumeChar();
|
||||
|
||||
// Returns a pointer to the current character position.
|
||||
const char* pos();
|
||||
|
||||
// Skips over whitespace and comments to find the next token in the stream.
|
||||
// This does not advance the parser for non-whitespace or comment chars.
|
||||
Token GetNextToken();
|
||||
|
||||
// Consumes whitespace characters and comments until the next non-that is
|
||||
// encountered.
|
||||
void EatWhitespaceAndComments();
|
||||
// Helper function that consumes a comment, assuming that the parser is
|
||||
// currently wound to a '/'.
|
||||
bool EatComment();
|
||||
|
||||
// Calls GetNextToken() and then ParseToken().
|
||||
Optional<Value> ParseNextToken();
|
||||
|
||||
// Takes a token that represents the start of a Value ("a structural token"
|
||||
// in RFC terms) and consumes it, returning the result as a Value.
|
||||
Optional<Value> ParseToken(Token token);
|
||||
|
||||
// Assuming that the parser is currently wound to '{', this parses a JSON
|
||||
// object into a Value.
|
||||
Optional<Value> ConsumeDictionary();
|
||||
|
||||
// Assuming that the parser is wound to '[', this parses a JSON list into a
|
||||
// Value.
|
||||
Optional<Value> ConsumeList();
|
||||
|
||||
// Calls through ConsumeStringRaw and wraps it in a value.
|
||||
Optional<Value> ConsumeString();
|
||||
|
||||
// Assuming that the parser is wound to a double quote, this parses a string,
|
||||
// decoding any escape sequences and converts UTF-16 to UTF-8. Returns true on
|
||||
// success and places result into |out|. Returns false on failure with
|
||||
// error information set.
|
||||
bool ConsumeStringRaw(StringBuilder* out);
|
||||
// Helper function for ConsumeStringRaw() that consumes the next four or 10
|
||||
// bytes (parser is wound to the first character of a HEX sequence, with the
|
||||
// potential for consuming another \uXXXX for a surrogate). Returns true on
|
||||
// success and places the code point |out_code_point|, and false on failure.
|
||||
bool DecodeUTF16(uint32_t* out_code_point);
|
||||
|
||||
// Assuming that the parser is wound to the start of a valid JSON number,
|
||||
// this parses and converts it to either an int or double value.
|
||||
Optional<Value> ConsumeNumber();
|
||||
// Helper that reads characters that are ints. Returns true if a number was
|
||||
// read and false on error.
|
||||
bool ReadInt(bool allow_leading_zeros);
|
||||
|
||||
// Consumes the literal values of |true|, |false|, and |null|, assuming the
|
||||
// parser is wound to the first character of any of those.
|
||||
Optional<Value> ConsumeLiteral();
|
||||
|
||||
// Helper function that returns true if the byte squence |match| can be
|
||||
// consumed at the current parser position. Returns false if there are fewer
|
||||
// than |match|-length bytes or if the sequence does not match, and the
|
||||
// parser state is unchanged.
|
||||
bool ConsumeIfMatch(StringPiece match);
|
||||
|
||||
// Sets the error information to |code| at the current column, based on
|
||||
// |index_| and |index_last_line_|, with an optional positive/negative
|
||||
// adjustment by |column_adjust|.
|
||||
void ReportError(JSONReader::JsonParseError code, int column_adjust);
|
||||
|
||||
// Given the line and column number of an error, formats one of the error
|
||||
// message contants from json_reader.h for human display.
|
||||
static std::string FormatErrorMessage(int line, int column,
|
||||
const std::string& description);
|
||||
|
||||
// base::JSONParserOptions that control parsing.
|
||||
const int options_;
|
||||
|
||||
// Maximum depth to parse.
|
||||
const size_t max_depth_;
|
||||
|
||||
// The input stream being parsed. Note: Not guaranteed to NUL-terminated.
|
||||
StringPiece input_;
|
||||
|
||||
// The index in the input stream to which the parser is wound.
|
||||
int index_;
|
||||
|
||||
// The number of times the parser has recursed (current stack depth).
|
||||
size_t stack_depth_;
|
||||
|
||||
// The line number that the parser is at currently.
|
||||
int line_number_;
|
||||
|
||||
// The last value of |index_| on the previous line.
|
||||
int index_last_line_;
|
||||
|
||||
// Error information.
|
||||
JSONReader::JsonParseError error_code_;
|
||||
int error_line_;
|
||||
int error_column_;
|
||||
|
||||
friend class JSONParserTest;
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, NextChar);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeDictionary);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeList);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeString);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeLiterals);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeNumbers);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ErrorMessages);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ReplaceInvalidCharacters);
|
||||
FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ReplaceInvalidUTF16EscapeSequence);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSONParser);
|
||||
};
|
||||
|
||||
// Used when decoding and an invalid utf-8 sequence is encountered.
|
||||
BASE_EXPORT extern const char kUnicodeReplacementString[];
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_JSON_JSON_PARSER_H_
|
||||
158
TMessagesProj/jni/voip/webrtc/base/json/json_reader.cc
Normal file
158
TMessagesProj/jni/voip/webrtc/base/json/json_reader.cc
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_reader.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/json/json_parser.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/optional.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Values 1000 and above are used by JSONFileValueSerializer::JsonFileError.
|
||||
static_assert(JSONReader::JSON_PARSE_ERROR_COUNT < 1000,
|
||||
"JSONReader error out of bounds");
|
||||
|
||||
const char JSONReader::kInvalidEscape[] =
|
||||
"Invalid escape sequence.";
|
||||
const char JSONReader::kSyntaxError[] =
|
||||
"Syntax error.";
|
||||
const char JSONReader::kUnexpectedToken[] =
|
||||
"Unexpected token.";
|
||||
const char JSONReader::kTrailingComma[] =
|
||||
"Trailing comma not allowed.";
|
||||
const char JSONReader::kTooMuchNesting[] =
|
||||
"Too much nesting.";
|
||||
const char JSONReader::kUnexpectedDataAfterRoot[] =
|
||||
"Unexpected data after root element.";
|
||||
const char JSONReader::kUnsupportedEncoding[] =
|
||||
"Unsupported encoding. JSON must be UTF-8.";
|
||||
const char JSONReader::kUnquotedDictionaryKey[] =
|
||||
"Dictionary keys must be quoted.";
|
||||
const char JSONReader::kInputTooLarge[] =
|
||||
"Input string is too large (>2GB).";
|
||||
const char JSONReader::kUnrepresentableNumber[] =
|
||||
"Number cannot be represented.";
|
||||
|
||||
JSONReader::ValueWithError::ValueWithError() = default;
|
||||
|
||||
JSONReader::ValueWithError::ValueWithError(ValueWithError&& other) = default;
|
||||
|
||||
JSONReader::ValueWithError::~ValueWithError() = default;
|
||||
|
||||
JSONReader::ValueWithError& JSONReader::ValueWithError::operator=(
|
||||
ValueWithError&& other) = default;
|
||||
|
||||
JSONReader::JSONReader(int options, size_t max_depth)
|
||||
: parser_(new internal::JSONParser(options, max_depth)) {}
|
||||
|
||||
JSONReader::~JSONReader() = default;
|
||||
|
||||
// static
|
||||
Optional<Value> JSONReader::Read(StringPiece json,
|
||||
int options,
|
||||
size_t max_depth) {
|
||||
internal::JSONParser parser(options, max_depth);
|
||||
return parser.Parse(json);
|
||||
}
|
||||
|
||||
std::unique_ptr<Value> JSONReader::ReadDeprecated(StringPiece json,
|
||||
int options,
|
||||
size_t max_depth) {
|
||||
Optional<Value> value = Read(json, options, max_depth);
|
||||
return value ? Value::ToUniquePtrValue(std::move(*value)) : nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
JSONReader::ValueWithError JSONReader::ReadAndReturnValueWithError(
|
||||
StringPiece json,
|
||||
int options) {
|
||||
ValueWithError ret;
|
||||
internal::JSONParser parser(options);
|
||||
ret.value = parser.Parse(json);
|
||||
if (!ret.value) {
|
||||
ret.error_message = parser.GetErrorMessage();
|
||||
ret.error_code = parser.error_code();
|
||||
ret.error_line = parser.error_line();
|
||||
ret.error_column = parser.error_column();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<Value> JSONReader::ReadAndReturnErrorDeprecated(
|
||||
StringPiece json,
|
||||
int options,
|
||||
int* error_code_out,
|
||||
std::string* error_msg_out,
|
||||
int* error_line_out,
|
||||
int* error_column_out) {
|
||||
ValueWithError ret = ReadAndReturnValueWithError(json, options);
|
||||
if (ret.value)
|
||||
return Value::ToUniquePtrValue(std::move(*ret.value));
|
||||
|
||||
if (error_code_out)
|
||||
*error_code_out = ret.error_code;
|
||||
if (error_msg_out)
|
||||
*error_msg_out = ret.error_message;
|
||||
if (error_line_out)
|
||||
*error_line_out = ret.error_line;
|
||||
if (error_column_out)
|
||||
*error_column_out = ret.error_column;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string JSONReader::ErrorCodeToString(JsonParseError error_code) {
|
||||
switch (error_code) {
|
||||
case JSON_NO_ERROR:
|
||||
return std::string();
|
||||
case JSON_INVALID_ESCAPE:
|
||||
return kInvalidEscape;
|
||||
case JSON_SYNTAX_ERROR:
|
||||
return kSyntaxError;
|
||||
case JSON_UNEXPECTED_TOKEN:
|
||||
return kUnexpectedToken;
|
||||
case JSON_TRAILING_COMMA:
|
||||
return kTrailingComma;
|
||||
case JSON_TOO_MUCH_NESTING:
|
||||
return kTooMuchNesting;
|
||||
case JSON_UNEXPECTED_DATA_AFTER_ROOT:
|
||||
return kUnexpectedDataAfterRoot;
|
||||
case JSON_UNSUPPORTED_ENCODING:
|
||||
return kUnsupportedEncoding;
|
||||
case JSON_UNQUOTED_DICTIONARY_KEY:
|
||||
return kUnquotedDictionaryKey;
|
||||
case JSON_TOO_LARGE:
|
||||
return kInputTooLarge;
|
||||
case JSON_UNREPRESENTABLE_NUMBER:
|
||||
return kUnrepresentableNumber;
|
||||
case JSON_PARSE_ERROR_COUNT:
|
||||
break;
|
||||
}
|
||||
NOTREACHED();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
Optional<Value> JSONReader::ReadToValue(StringPiece json) {
|
||||
return parser_->Parse(json);
|
||||
}
|
||||
|
||||
std::unique_ptr<Value> JSONReader::ReadToValueDeprecated(StringPiece json) {
|
||||
Optional<Value> value = parser_->Parse(json);
|
||||
return value ? std::make_unique<Value>(std::move(*value)) : nullptr;
|
||||
}
|
||||
|
||||
JSONReader::JsonParseError JSONReader::error_code() const {
|
||||
return parser_->error_code();
|
||||
}
|
||||
|
||||
std::string JSONReader::GetErrorMessage() const {
|
||||
return parser_->GetErrorMessage();
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
176
TMessagesProj/jni/voip/webrtc/base/json/json_reader.h
Normal file
176
TMessagesProj/jni/voip/webrtc/base/json/json_reader.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// A JSON parser. Converts strings of JSON into a Value object (see
|
||||
// base/values.h).
|
||||
// http://www.ietf.org/rfc/rfc4627.txt?number=4627
|
||||
//
|
||||
// Known limitations/deviations from the RFC:
|
||||
// - Only knows how to parse ints within the range of a signed 32 bit int and
|
||||
// decimal numbers within a double.
|
||||
// - Assumes input is encoded as UTF8. The spec says we should allow UTF-16
|
||||
// (BE or LE) and UTF-32 (BE or LE) as well.
|
||||
// - We limit nesting to 100 levels to prevent stack overflow (this is allowed
|
||||
// by the RFC).
|
||||
// - A Unicode FAQ ("http://unicode.org/faq/utf_bom.html") writes a data
|
||||
// stream may start with a Unicode Byte-Order-Mark (U+FEFF), i.e. the input
|
||||
// UTF-8 string for the JSONReader::JsonToValue() function may start with a
|
||||
// UTF-8 BOM (0xEF, 0xBB, 0xBF).
|
||||
// To avoid the function from mis-treating a UTF-8 BOM as an invalid
|
||||
// character, the function skips a Unicode BOM at the beginning of the
|
||||
// Unicode string (converted from the input UTF-8 string) before parsing it.
|
||||
//
|
||||
// TODO(tc): Add a parsing option to to relax object keys being wrapped in
|
||||
// double quotes
|
||||
// TODO(tc): Add an option to disable comment stripping
|
||||
|
||||
#ifndef BASE_JSON_JSON_READER_H_
|
||||
#define BASE_JSON_JSON_READER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/json/json_common.h"
|
||||
#include "base/optional.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/values.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace internal {
|
||||
class JSONParser;
|
||||
}
|
||||
|
||||
enum JSONParserOptions {
|
||||
// Parses the input strictly according to RFC 4627, except for where noted
|
||||
// above.
|
||||
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,
|
||||
};
|
||||
|
||||
class BASE_EXPORT JSONReader {
|
||||
public:
|
||||
// Error codes during parsing.
|
||||
enum JsonParseError {
|
||||
JSON_NO_ERROR = 0,
|
||||
JSON_INVALID_ESCAPE,
|
||||
JSON_SYNTAX_ERROR,
|
||||
JSON_UNEXPECTED_TOKEN,
|
||||
JSON_TRAILING_COMMA,
|
||||
JSON_TOO_MUCH_NESTING,
|
||||
JSON_UNEXPECTED_DATA_AFTER_ROOT,
|
||||
JSON_UNSUPPORTED_ENCODING,
|
||||
JSON_UNQUOTED_DICTIONARY_KEY,
|
||||
JSON_TOO_LARGE,
|
||||
JSON_UNREPRESENTABLE_NUMBER,
|
||||
JSON_PARSE_ERROR_COUNT
|
||||
};
|
||||
|
||||
struct BASE_EXPORT ValueWithError {
|
||||
ValueWithError();
|
||||
ValueWithError(ValueWithError&& other);
|
||||
ValueWithError& operator=(ValueWithError&& other);
|
||||
~ValueWithError();
|
||||
|
||||
Optional<Value> value;
|
||||
|
||||
// Contains default values if |value| exists, or the error status if |value|
|
||||
// is base::nullopt.
|
||||
JsonParseError error_code = JSON_NO_ERROR;
|
||||
std::string error_message;
|
||||
int error_line = 0;
|
||||
int error_column = 0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ValueWithError);
|
||||
};
|
||||
|
||||
// String versions of parse error codes.
|
||||
static const char kInvalidEscape[];
|
||||
static const char kSyntaxError[];
|
||||
static const char kUnexpectedToken[];
|
||||
static const char kTrailingComma[];
|
||||
static const char kTooMuchNesting[];
|
||||
static const char kUnexpectedDataAfterRoot[];
|
||||
static const char kUnsupportedEncoding[];
|
||||
static const char kUnquotedDictionaryKey[];
|
||||
static const char kInputTooLarge[];
|
||||
static const char kUnrepresentableNumber[];
|
||||
|
||||
// Constructs a reader.
|
||||
JSONReader(int options = JSON_PARSE_RFC,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
~JSONReader();
|
||||
|
||||
// Reads and parses |json|, returning a Value.
|
||||
// If |json| is not a properly formed JSON string, returns base::nullopt.
|
||||
static Optional<Value> Read(StringPiece json,
|
||||
int options = JSON_PARSE_RFC,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
// Deprecated. Use the Read() method above.
|
||||
// Reads and parses |json|, returning a Value.
|
||||
// If |json| is not a properly formed JSON string, returns nullptr.
|
||||
// Wrap this in base::FooValue::From() to check the Value is of type Foo and
|
||||
// convert to a FooValue at the same time.
|
||||
static std::unique_ptr<Value> ReadDeprecated(
|
||||
StringPiece json,
|
||||
int options = JSON_PARSE_RFC,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
// Reads and parses |json| like Read(). Returns a ValueWithError, which on
|
||||
// error, will be populated with a formatted error message, an error code, and
|
||||
// the error location if appropriate.
|
||||
static ValueWithError ReadAndReturnValueWithError(
|
||||
StringPiece json,
|
||||
int options = JSON_PARSE_RFC);
|
||||
|
||||
// Deprecated. Use the ReadAndReturnValueWithError() method above.
|
||||
// Reads and parses |json| like Read(). |error_code_out| and |error_msg_out|
|
||||
// are optional. If specified and nullptr is returned, they will be populated
|
||||
// an error code and a formatted error message (including error location if
|
||||
// appropriate). Otherwise, they will be unmodified.
|
||||
static std::unique_ptr<Value> ReadAndReturnErrorDeprecated(
|
||||
StringPiece json,
|
||||
int options, // JSONParserOptions
|
||||
int* error_code_out,
|
||||
std::string* error_msg_out,
|
||||
int* error_line_out = nullptr,
|
||||
int* error_column_out = nullptr);
|
||||
|
||||
// Converts a JSON parse error code into a human readable message.
|
||||
// Returns an empty string if error_code is JSON_NO_ERROR.
|
||||
static std::string ErrorCodeToString(JsonParseError error_code);
|
||||
|
||||
// Non-static version of Read() above.
|
||||
Optional<Value> ReadToValue(StringPiece json);
|
||||
|
||||
// Deprecated. Use the ReadToValue() method above.
|
||||
// Non-static version of Read() above.
|
||||
std::unique_ptr<Value> ReadToValueDeprecated(StringPiece json);
|
||||
|
||||
// Returns the error code if the last call to ReadToValue() failed.
|
||||
// Returns JSON_NO_ERROR otherwise.
|
||||
JsonParseError error_code() const;
|
||||
|
||||
// Converts error_code_ to a human-readable string, including line and column
|
||||
// numbers if appropriate.
|
||||
std::string GetErrorMessage() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<internal::JSONParser> parser_;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_JSON_JSON_READER_H_
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/values.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Entry point for LibFuzzer.
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < 2)
|
||||
return 0;
|
||||
|
||||
// Create a copy of input buffer, as otherwise we don't catch
|
||||
// overflow that touches the last byte (which is used in options).
|
||||
std::unique_ptr<char[]> input(new char[size - 1]);
|
||||
memcpy(input.get(), data, size - 1);
|
||||
|
||||
StringPiece input_string(input.get(), size - 1);
|
||||
|
||||
const int options = data[size - 1];
|
||||
|
||||
JSONReader::ValueWithError json_val =
|
||||
JSONReader::ReadAndReturnValueWithError(input_string, options);
|
||||
CHECK((json_val.error_code == JSONReader::JSON_NO_ERROR) ==
|
||||
json_val.value.has_value());
|
||||
|
||||
if (json_val.value) {
|
||||
// Check that the value can be serialized and deserialized back to an
|
||||
// equivalent |Value|.
|
||||
const Value& value = json_val.value.value();
|
||||
std::string serialized;
|
||||
CHECK(JSONWriter::Write(value, &serialized));
|
||||
|
||||
Optional<Value> deserialized = JSONReader::Read(StringPiece(serialized));
|
||||
CHECK(deserialized);
|
||||
CHECK(value.Equals(&deserialized.value()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_string_value_serializer.h"
|
||||
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
using base::Value;
|
||||
|
||||
JSONStringValueSerializer::JSONStringValueSerializer(std::string* json_string)
|
||||
: json_string_(json_string),
|
||||
pretty_print_(false) {
|
||||
}
|
||||
|
||||
JSONStringValueSerializer::~JSONStringValueSerializer() = default;
|
||||
|
||||
bool JSONStringValueSerializer::Serialize(const Value& root) {
|
||||
return SerializeInternal(root, false);
|
||||
}
|
||||
|
||||
bool JSONStringValueSerializer::SerializeAndOmitBinaryValues(
|
||||
const Value& root) {
|
||||
return SerializeInternal(root, true);
|
||||
}
|
||||
|
||||
bool JSONStringValueSerializer::SerializeInternal(const Value& root,
|
||||
bool omit_binary_values) {
|
||||
if (!json_string_)
|
||||
return false;
|
||||
|
||||
int options = 0;
|
||||
if (omit_binary_values)
|
||||
options |= base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES;
|
||||
if (pretty_print_)
|
||||
options |= base::JSONWriter::OPTIONS_PRETTY_PRINT;
|
||||
|
||||
return base::JSONWriter::WriteWithOptions(root, options, json_string_);
|
||||
}
|
||||
|
||||
JSONStringValueDeserializer::JSONStringValueDeserializer(
|
||||
const base::StringPiece& json_string,
|
||||
int options)
|
||||
: json_string_(json_string), options_(options) {}
|
||||
|
||||
JSONStringValueDeserializer::~JSONStringValueDeserializer() = default;
|
||||
|
||||
std::unique_ptr<Value> JSONStringValueDeserializer::Deserialize(
|
||||
int* error_code,
|
||||
std::string* error_str) {
|
||||
return base::JSONReader::ReadAndReturnErrorDeprecated(json_string_, options_,
|
||||
error_code, error_str);
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_JSON_JSON_STRING_VALUE_SERIALIZER_H_
|
||||
#define BASE_JSON_JSON_STRING_VALUE_SERIALIZER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/values.h"
|
||||
|
||||
class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
|
||||
public:
|
||||
// |json_string| is the string that will be the destination of the
|
||||
// serialization. The caller of the constructor retains ownership of the
|
||||
// string. |json_string| must not be null.
|
||||
explicit JSONStringValueSerializer(std::string* json_string);
|
||||
|
||||
~JSONStringValueSerializer() override;
|
||||
|
||||
// Attempt to serialize the data structure represented by Value into
|
||||
// JSON. If the return value is true, the result will have been written
|
||||
// into the string passed into the constructor.
|
||||
bool Serialize(const base::Value& root) override;
|
||||
|
||||
// Equivalent to Serialize(root) except binary values are omitted from the
|
||||
// output.
|
||||
bool SerializeAndOmitBinaryValues(const base::Value& root);
|
||||
|
||||
void set_pretty_print(bool new_value) { pretty_print_ = new_value; }
|
||||
bool pretty_print() { return pretty_print_; }
|
||||
|
||||
private:
|
||||
bool SerializeInternal(const base::Value& root, bool omit_binary_values);
|
||||
|
||||
// Owned by the caller of the constructor.
|
||||
std::string* json_string_;
|
||||
bool pretty_print_; // If true, serialization will span multiple lines.
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSONStringValueSerializer);
|
||||
};
|
||||
|
||||
class BASE_EXPORT JSONStringValueDeserializer : public base::ValueDeserializer {
|
||||
public:
|
||||
// This retains a reference to the contents of |json_string|, so the data
|
||||
// must outlive the JSONStringValueDeserializer. |options| is a bitmask of
|
||||
// JSONParserOptions.
|
||||
explicit JSONStringValueDeserializer(const base::StringPiece& json_string,
|
||||
int options = 0);
|
||||
|
||||
~JSONStringValueDeserializer() override;
|
||||
|
||||
// Attempt to deserialize the data structure encoded in the string passed
|
||||
// in to the constructor into a structure of Value objects. If the return
|
||||
// value is null, and if |error_code| is non-null, |error_code| will
|
||||
// contain an integer error code (a JsonParseError in this case).
|
||||
// If |error_message| is non-null, it will be filled in with a formatted
|
||||
// error message including the location of the error if appropriate.
|
||||
// The caller takes ownership of the returned value.
|
||||
std::unique_ptr<base::Value> Deserialize(int* error_code,
|
||||
std::string* error_message) override;
|
||||
|
||||
private:
|
||||
// Data is owned by the caller of the constructor.
|
||||
base::StringPiece json_string_;
|
||||
const int options_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSONStringValueDeserializer);
|
||||
};
|
||||
|
||||
#endif // BASE_JSON_JSON_STRING_VALUE_SERIALIZER_H_
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_value_converter.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
bool BasicValueConverter<int>::Convert(
|
||||
const base::Value& value, int* field) const {
|
||||
if (!value.is_int())
|
||||
return false;
|
||||
if (field)
|
||||
*field = value.GetInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicValueConverter<std::string>::Convert(
|
||||
const base::Value& value, std::string* field) const {
|
||||
if (!value.is_string())
|
||||
return false;
|
||||
if (field)
|
||||
*field = value.GetString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicValueConverter<string16>::Convert(
|
||||
const base::Value& value, string16* field) const {
|
||||
if (!value.is_string())
|
||||
return false;
|
||||
if (field)
|
||||
*field = base::UTF8ToUTF16(value.GetString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicValueConverter<double>::Convert(
|
||||
const base::Value& value, double* field) const {
|
||||
if (!value.is_double() && !value.is_int())
|
||||
return false;
|
||||
if (field)
|
||||
*field = value.GetDouble();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicValueConverter<bool>::Convert(
|
||||
const base::Value& value, bool* field) const {
|
||||
if (!value.is_bool())
|
||||
return false;
|
||||
if (field)
|
||||
*field = value.GetBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
206
TMessagesProj/jni/voip/webrtc/base/json/json_writer.cc
Normal file
206
TMessagesProj/jni/voip/webrtc/base/json/json_writer.cc
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/json_writer.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "base/json/string_escape.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
const char kPrettyPrintLineEnding[] = "\r\n";
|
||||
#else
|
||||
const char kPrettyPrintLineEnding[] = "\n";
|
||||
#endif
|
||||
|
||||
// static
|
||||
bool JSONWriter::Write(const Value& node, std::string* json, size_t max_depth) {
|
||||
return WriteWithOptions(node, 0, json, max_depth);
|
||||
}
|
||||
|
||||
// static
|
||||
bool JSONWriter::WriteWithOptions(const Value& node,
|
||||
int options,
|
||||
std::string* json,
|
||||
size_t max_depth) {
|
||||
json->clear();
|
||||
// Is there a better way to estimate the size of the output?
|
||||
json->reserve(1024);
|
||||
|
||||
JSONWriter writer(options, json, max_depth);
|
||||
bool result = writer.BuildJSONString(node, 0U);
|
||||
|
||||
if (options & OPTIONS_PRETTY_PRINT)
|
||||
json->append(kPrettyPrintLineEnding);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JSONWriter::JSONWriter(int options, std::string* json, size_t max_depth)
|
||||
: omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0),
|
||||
omit_double_type_preservation_(
|
||||
(options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION) != 0),
|
||||
pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0),
|
||||
json_string_(json),
|
||||
max_depth_(max_depth),
|
||||
stack_depth_(0) {
|
||||
DCHECK(json);
|
||||
CHECK_LE(max_depth, internal::kAbsoluteMaxDepth);
|
||||
}
|
||||
|
||||
bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
|
||||
internal::StackMarker depth_check(max_depth_, &stack_depth_);
|
||||
if (depth_check.IsTooDeep())
|
||||
return false;
|
||||
|
||||
switch (node.type()) {
|
||||
case Value::Type::NONE:
|
||||
json_string_->append("null");
|
||||
return true;
|
||||
|
||||
case Value::Type::BOOLEAN:
|
||||
// Note: We are explicitly invoking the std::string constructor in order
|
||||
// to avoid ASAN errors on Windows: https://crbug.com/900041
|
||||
json_string_->append(node.GetBool() ? std::string("true")
|
||||
: std::string("false"));
|
||||
return true;
|
||||
|
||||
case Value::Type::INTEGER:
|
||||
json_string_->append(NumberToString(node.GetInt()));
|
||||
return true;
|
||||
|
||||
case Value::Type::DOUBLE: {
|
||||
double value = node.GetDouble();
|
||||
if (omit_double_type_preservation_ &&
|
||||
value <= std::numeric_limits<int64_t>::max() &&
|
||||
value >= std::numeric_limits<int64_t>::min() &&
|
||||
std::floor(value) == value) {
|
||||
json_string_->append(NumberToString(static_cast<int64_t>(value)));
|
||||
return true;
|
||||
}
|
||||
std::string real = NumberToString(value);
|
||||
// Ensure that the number has a .0 if there's no decimal or 'e'. This
|
||||
// makes sure that when we read the JSON back, it's interpreted as a
|
||||
// real rather than an int.
|
||||
if (real.find_first_of(".eE") == std::string::npos)
|
||||
real.append(".0");
|
||||
|
||||
// The JSON spec requires that non-integer values in the range (-1,1)
|
||||
// have a zero before the decimal point - ".52" is not valid, "0.52" is.
|
||||
if (real[0] == '.') {
|
||||
real.insert(static_cast<size_t>(0), static_cast<size_t>(1), '0');
|
||||
} else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
|
||||
// "-.1" bad "-0.1" good
|
||||
real.insert(static_cast<size_t>(1), static_cast<size_t>(1), '0');
|
||||
}
|
||||
json_string_->append(real);
|
||||
return true;
|
||||
}
|
||||
|
||||
case Value::Type::STRING:
|
||||
EscapeJSONString(node.GetString(), true, json_string_);
|
||||
return true;
|
||||
|
||||
case Value::Type::LIST: {
|
||||
json_string_->push_back('[');
|
||||
if (pretty_print_)
|
||||
json_string_->push_back(' ');
|
||||
|
||||
bool first_value_has_been_output = false;
|
||||
bool result = true;
|
||||
for (const auto& value : node.GetList()) {
|
||||
if (omit_binary_values_ && value.type() == Value::Type::BINARY)
|
||||
continue;
|
||||
|
||||
if (first_value_has_been_output) {
|
||||
json_string_->push_back(',');
|
||||
if (pretty_print_)
|
||||
json_string_->push_back(' ');
|
||||
}
|
||||
|
||||
if (!BuildJSONString(value, depth))
|
||||
result = false;
|
||||
|
||||
first_value_has_been_output = true;
|
||||
}
|
||||
|
||||
if (pretty_print_)
|
||||
json_string_->push_back(' ');
|
||||
json_string_->push_back(']');
|
||||
return result;
|
||||
}
|
||||
|
||||
case Value::Type::DICTIONARY: {
|
||||
json_string_->push_back('{');
|
||||
if (pretty_print_)
|
||||
json_string_->append(kPrettyPrintLineEnding);
|
||||
|
||||
bool first_value_has_been_output = false;
|
||||
bool result = true;
|
||||
for (const auto& pair : node.DictItems()) {
|
||||
const auto& key = pair.first;
|
||||
const auto& value = pair.second;
|
||||
if (omit_binary_values_ && value.type() == Value::Type::BINARY)
|
||||
continue;
|
||||
|
||||
if (first_value_has_been_output) {
|
||||
json_string_->push_back(',');
|
||||
if (pretty_print_)
|
||||
json_string_->append(kPrettyPrintLineEnding);
|
||||
}
|
||||
|
||||
if (pretty_print_)
|
||||
IndentLine(depth + 1U);
|
||||
|
||||
EscapeJSONString(key, true, json_string_);
|
||||
json_string_->push_back(':');
|
||||
if (pretty_print_)
|
||||
json_string_->push_back(' ');
|
||||
|
||||
if (!BuildJSONString(value, depth + 1U))
|
||||
result = false;
|
||||
|
||||
first_value_has_been_output = true;
|
||||
}
|
||||
|
||||
if (pretty_print_) {
|
||||
json_string_->append(kPrettyPrintLineEnding);
|
||||
IndentLine(depth);
|
||||
}
|
||||
|
||||
json_string_->push_back('}');
|
||||
return result;
|
||||
}
|
||||
|
||||
case Value::Type::BINARY:
|
||||
// Successful only if we're allowed to omit it.
|
||||
DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value.";
|
||||
return omit_binary_values_;
|
||||
|
||||
// TODO(crbug.com/859477): Remove after root cause is found.
|
||||
case Value::Type::DEAD:
|
||||
CHECK(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||
CHECK(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
void JSONWriter::IndentLine(size_t depth) {
|
||||
json_string_->append(depth * 3U, ' ');
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
87
TMessagesProj/jni/voip/webrtc/base/json/json_writer.h
Normal file
87
TMessagesProj/jni/voip/webrtc/base/json/json_writer.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_JSON_JSON_WRITER_H_
|
||||
#define BASE_JSON_JSON_WRITER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/json/json_common.h"
|
||||
#include "base/macros.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Value;
|
||||
|
||||
class BASE_EXPORT JSONWriter {
|
||||
public:
|
||||
enum Options {
|
||||
// This option instructs the writer that if a Binary value is encountered,
|
||||
// the value (and key if within a dictionary) will be omitted from the
|
||||
// output, and success will be returned. Otherwise, if a binary value is
|
||||
// encountered, failure will be returned.
|
||||
OPTIONS_OMIT_BINARY_VALUES = 1 << 0,
|
||||
|
||||
// This option instructs the writer to write doubles that have no fractional
|
||||
// part as a normal integer (i.e., without using exponential notation
|
||||
// or appending a '.0') as long as the value is within the range of a
|
||||
// 64-bit int.
|
||||
OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION = 1 << 1,
|
||||
|
||||
// Return a slightly nicer formatted json string (pads with whitespace to
|
||||
// help with readability).
|
||||
OPTIONS_PRETTY_PRINT = 1 << 2,
|
||||
};
|
||||
|
||||
// Given a root node, generates a JSON string and puts it into |json|.
|
||||
// The output string is overwritten and not appended.
|
||||
//
|
||||
// TODO(tc): Should we generate json if it would be invalid json (e.g.,
|
||||
// |node| is not a DictionaryValue/ListValue or if there are inf/-inf float
|
||||
// values)? Return true on success and false on failure.
|
||||
static bool Write(const Value& node,
|
||||
std::string* json,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
// Same as above but with |options| which is a bunch of JSONWriter::Options
|
||||
// bitwise ORed together. Return true on success and false on failure.
|
||||
static bool WriteWithOptions(const Value& node,
|
||||
int options,
|
||||
std::string* json,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
private:
|
||||
JSONWriter(int options,
|
||||
std::string* json,
|
||||
size_t max_depth = internal::kAbsoluteMaxDepth);
|
||||
|
||||
// Called recursively to build the JSON string. When completed,
|
||||
// |json_string_| will contain the JSON.
|
||||
bool BuildJSONString(const Value& node, size_t depth);
|
||||
|
||||
// Adds space to json_string_ for the indent level.
|
||||
void IndentLine(size_t depth);
|
||||
|
||||
bool omit_binary_values_;
|
||||
bool omit_double_type_preservation_;
|
||||
bool pretty_print_;
|
||||
|
||||
// Where we write JSON data as we generate it.
|
||||
std::string* json_string_;
|
||||
|
||||
// Maximum depth to write.
|
||||
const size_t max_depth_;
|
||||
|
||||
// The number of times the writer has recursed (current stack depth).
|
||||
size_t stack_depth_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSONWriter);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_JSON_JSON_WRITER_H_
|
||||
164
TMessagesProj/jni/voip/webrtc/base/json/string_escape.cc
Normal file
164
TMessagesProj/jni/voip/webrtc/base/json/string_escape.cc
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/string_escape.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversion_utils.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/third_party/icu/icu_utf.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace {
|
||||
|
||||
// Format string for printing a \uXXXX escape sequence.
|
||||
const char kU16EscapeFormat[] = "\\u%04X";
|
||||
|
||||
// The code point to output for an invalid input code unit.
|
||||
const uint32_t kReplacementCodePoint = 0xFFFD;
|
||||
|
||||
// Used below in EscapeSpecialCodePoint().
|
||||
static_assert('<' == 0x3C, "less than sign must be 0x3c");
|
||||
|
||||
// Try to escape the |code_point| if it is a known special character. If
|
||||
// successful, returns true and appends the escape sequence to |dest|. This
|
||||
// isn't required by the spec, but it's more readable by humans.
|
||||
bool EscapeSpecialCodePoint(uint32_t code_point, std::string* dest) {
|
||||
// WARNING: if you add a new case here, you need to update the reader as well.
|
||||
// Note: \v is in the reader, but not here since the JSON spec doesn't
|
||||
// allow it.
|
||||
switch (code_point) {
|
||||
case '\b':
|
||||
dest->append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
dest->append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
dest->append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
dest->append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
dest->append("\\t");
|
||||
break;
|
||||
case '\\':
|
||||
dest->append("\\\\");
|
||||
break;
|
||||
case '"':
|
||||
dest->append("\\\"");
|
||||
break;
|
||||
// Escape < to prevent script execution; escaping > is not necessary and
|
||||
// not doing so save a few bytes.
|
||||
case '<':
|
||||
dest->append("\\u003C");
|
||||
break;
|
||||
// Escape the "Line Separator" and "Paragraph Separator" characters, since
|
||||
// they should be treated like a new line \r or \n.
|
||||
case 0x2028:
|
||||
dest->append("\\u2028");
|
||||
break;
|
||||
case 0x2029:
|
||||
dest->append("\\u2029");
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
bool EscapeJSONStringImpl(const S& str, bool put_in_quotes, std::string* dest) {
|
||||
bool did_replacement = false;
|
||||
|
||||
if (put_in_quotes)
|
||||
dest->push_back('"');
|
||||
|
||||
// Casting is necessary because ICU uses int32_t. Try and do so safely.
|
||||
CHECK_LE(str.length(),
|
||||
static_cast<size_t>(std::numeric_limits<int32_t>::max()));
|
||||
const int32_t length = static_cast<int32_t>(str.length());
|
||||
|
||||
for (int32_t i = 0; i < length; ++i) {
|
||||
uint32_t code_point;
|
||||
if (!ReadUnicodeCharacter(str.data(), length, &i, &code_point) ||
|
||||
code_point == static_cast<decltype(code_point)>(CBU_SENTINEL) ||
|
||||
!IsValidCodepoint(code_point)) {
|
||||
code_point = kReplacementCodePoint;
|
||||
did_replacement = true;
|
||||
}
|
||||
|
||||
if (EscapeSpecialCodePoint(code_point, dest))
|
||||
continue;
|
||||
|
||||
// Escape non-printing characters.
|
||||
if (code_point < 32)
|
||||
base::StringAppendF(dest, kU16EscapeFormat, code_point);
|
||||
else
|
||||
WriteUnicodeCharacter(code_point, dest);
|
||||
}
|
||||
|
||||
if (put_in_quotes)
|
||||
dest->push_back('"');
|
||||
|
||||
return !did_replacement;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool EscapeJSONString(StringPiece str, bool put_in_quotes, std::string* dest) {
|
||||
return EscapeJSONStringImpl(str, put_in_quotes, dest);
|
||||
}
|
||||
|
||||
bool EscapeJSONString(StringPiece16 str,
|
||||
bool put_in_quotes,
|
||||
std::string* dest) {
|
||||
return EscapeJSONStringImpl(str, put_in_quotes, dest);
|
||||
}
|
||||
|
||||
std::string GetQuotedJSONString(StringPiece str) {
|
||||
std::string dest;
|
||||
EscapeJSONStringImpl(str, true, &dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::string GetQuotedJSONString(StringPiece16 str) {
|
||||
std::string dest;
|
||||
EscapeJSONStringImpl(str, true, &dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::string EscapeBytesAsInvalidJSONString(StringPiece str,
|
||||
bool put_in_quotes) {
|
||||
std::string dest;
|
||||
|
||||
if (put_in_quotes)
|
||||
dest.push_back('"');
|
||||
|
||||
for (unsigned char c : str) {
|
||||
if (EscapeSpecialCodePoint(c, &dest))
|
||||
continue;
|
||||
|
||||
if (c < 32 || c > 126)
|
||||
base::StringAppendF(&dest, kU16EscapeFormat, c);
|
||||
else
|
||||
dest.push_back(c);
|
||||
}
|
||||
|
||||
if (put_in_quotes)
|
||||
dest.push_back('"');
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
61
TMessagesProj/jni/voip/webrtc/base/json/string_escape.h
Normal file
61
TMessagesProj/jni/voip/webrtc/base/json/string_escape.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This file defines utility functions for escaping strings suitable for JSON.
|
||||
|
||||
#ifndef BASE_JSON_STRING_ESCAPE_H_
|
||||
#define BASE_JSON_STRING_ESCAPE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Appends to |dest| an escaped version of |str|. Valid UTF-8 code units and
|
||||
// characters will pass through from the input to the output. Invalid code
|
||||
// units and characters will be replaced with the U+FFFD replacement character.
|
||||
// This function returns true if no replacement was necessary and false if
|
||||
// there was a lossy replacement. On return, |dest| will contain a valid UTF-8
|
||||
// JSON string.
|
||||
//
|
||||
// Non-printing control characters will be escaped as \uXXXX sequences for
|
||||
// readability.
|
||||
//
|
||||
// If |put_in_quotes| is true, then a leading and trailing double-quote mark
|
||||
// will be appended to |dest| as well.
|
||||
BASE_EXPORT bool EscapeJSONString(StringPiece str,
|
||||
bool put_in_quotes,
|
||||
std::string* dest);
|
||||
|
||||
// Performs a similar function to the UTF-8 StringPiece version above,
|
||||
// converting UTF-16 code units to UTF-8 code units and escaping non-printing
|
||||
// control characters. On return, |dest| will contain a valid UTF-8 JSON string.
|
||||
BASE_EXPORT bool EscapeJSONString(StringPiece16 str,
|
||||
bool put_in_quotes,
|
||||
std::string* dest);
|
||||
|
||||
// Helper functions that wrap the above two functions but return the value
|
||||
// instead of appending. |put_in_quotes| is always true.
|
||||
BASE_EXPORT std::string GetQuotedJSONString(StringPiece str);
|
||||
BASE_EXPORT std::string GetQuotedJSONString(StringPiece16 str);
|
||||
|
||||
// Given an arbitrary byte string |str|, this will escape all non-ASCII bytes
|
||||
// as \uXXXX escape sequences. This function is *NOT* meant to be used with
|
||||
// Unicode strings and does not validate |str| as one.
|
||||
//
|
||||
// CAVEAT CALLER: The output of this function may not be valid JSON, since
|
||||
// JSON requires escape sequences to be valid UTF-16 code units. This output
|
||||
// will be mangled if passed to to the base::JSONReader, since the reader will
|
||||
// interpret it as UTF-16 and convert it to UTF-8.
|
||||
//
|
||||
// The output of this function takes the *appearance* of JSON but is not in
|
||||
// fact valid according to RFC 4627.
|
||||
BASE_EXPORT std::string EscapeBytesAsInvalidJSONString(StringPiece str,
|
||||
bool put_in_quotes);
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_JSON_STRING_ESCAPE_H_
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/json/string_escape.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Entry point for LibFuzzer.
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < 2)
|
||||
return 0;
|
||||
|
||||
const bool put_in_quotes = data[size - 1];
|
||||
|
||||
// Create a copy of input buffer, as otherwise we don't catch
|
||||
// overflow that touches the last byte (which is used in put_in_quotes).
|
||||
size_t actual_size_char8 = size - 1;
|
||||
std::unique_ptr<char[]> input(new char[actual_size_char8]);
|
||||
memcpy(input.get(), data, actual_size_char8);
|
||||
|
||||
base::StringPiece input_string(input.get(), actual_size_char8);
|
||||
std::string escaped_string;
|
||||
base::EscapeJSONString(input_string, put_in_quotes, &escaped_string);
|
||||
|
||||
// Test for wide-strings if available size is even.
|
||||
if (actual_size_char8 & 1)
|
||||
return 0;
|
||||
|
||||
size_t actual_size_char16 = actual_size_char8 / 2;
|
||||
base::StringPiece16 input_string16(
|
||||
reinterpret_cast<base::char16*>(input.get()), actual_size_char16);
|
||||
escaped_string.clear();
|
||||
base::EscapeJSONString(input_string16, put_in_quotes, &escaped_string);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue