2016-10-28 18:20:08 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
//#include "Values.h"
|
|
|
|
|
|
|
|
{% for namespace in config.protocol.namespace %}
|
|
|
|
namespace {{namespace}} {
|
|
|
|
{% endfor %}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
const char* const nullValueString = "null";
|
|
|
|
const char* const trueValueString = "true";
|
|
|
|
const char* const falseValueString = "false";
|
|
|
|
|
|
|
|
inline bool escapeChar(uint16_t c, StringBuilder* dst)
|
|
|
|
{
|
|
|
|
switch (c) {
|
2017-01-27 21:11:15 +00:00
|
|
|
case '\b': StringUtil::builderAppend(*dst, "\\b"); break;
|
|
|
|
case '\f': StringUtil::builderAppend(*dst, "\\f"); break;
|
|
|
|
case '\n': StringUtil::builderAppend(*dst, "\\n"); break;
|
|
|
|
case '\r': StringUtil::builderAppend(*dst, "\\r"); break;
|
|
|
|
case '\t': StringUtil::builderAppend(*dst, "\\t"); break;
|
|
|
|
case '\\': StringUtil::builderAppend(*dst, "\\\\"); break;
|
|
|
|
case '"': StringUtil::builderAppend(*dst, "\\\""); break;
|
2016-10-28 18:20:08 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char hexDigits[17] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
void appendUnsignedAsHex(uint16_t number, StringBuilder* dst)
|
|
|
|
{
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*dst, "\\u");
|
2016-10-28 18:20:08 +00:00
|
|
|
for (size_t i = 0; i < 4; ++i) {
|
|
|
|
uint16_t c = hexDigits[(number & 0xF000) >> 12];
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*dst, c);
|
2016-10-28 18:20:08 +00:00
|
|
|
number <<= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void escapeStringForJSON(const String& str, StringBuilder* dst)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < str.length(); ++i) {
|
|
|
|
uint16_t c = str[i];
|
|
|
|
if (!escapeChar(c, dst)) {
|
|
|
|
if (c < 32 || c > 126 || c == '<' || c == '>') {
|
|
|
|
// 1. Escaping <, > to prevent script execution.
|
|
|
|
// 2. Technically, we could also pass through c > 126 as UTF8, but this
|
|
|
|
// is also optional. It would also be a pain to implement here.
|
|
|
|
appendUnsignedAsHex(c, dst);
|
|
|
|
} else {
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*dst, c);
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void doubleQuoteStringForJSON(const String& str, StringBuilder* dst)
|
|
|
|
{
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*dst, '"');
|
2016-10-28 18:20:08 +00:00
|
|
|
escapeStringForJSON(str, dst);
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*dst, '"');
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
bool Value::asBoolean(bool*) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Value::asDouble(double*) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Value::asInteger(int*) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Value::asString(String*) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Value::asSerialized(String*) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Value::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
|
|
|
DCHECK(m_type == TypeNull);
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, nullValueString, 4);
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> Value::clone() const
|
|
|
|
{
|
|
|
|
return Value::null();
|
|
|
|
}
|
|
|
|
|
2016-11-23 00:45:30 +00:00
|
|
|
String Value::serialize()
|
|
|
|
{
|
|
|
|
StringBuilder result;
|
|
|
|
StringUtil::builderReserve(result, 512);
|
|
|
|
writeJSON(&result);
|
2017-01-27 21:11:15 +00:00
|
|
|
return StringUtil::builderToString(result);
|
2016-11-23 00:45:30 +00:00
|
|
|
}
|
|
|
|
|
2016-10-28 18:20:08 +00:00
|
|
|
bool FundamentalValue::asBoolean(bool* output) const
|
|
|
|
{
|
|
|
|
if (type() != TypeBoolean)
|
|
|
|
return false;
|
|
|
|
*output = m_boolValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FundamentalValue::asDouble(double* output) const
|
|
|
|
{
|
|
|
|
if (type() == TypeDouble) {
|
|
|
|
*output = m_doubleValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (type() == TypeInteger) {
|
|
|
|
*output = m_integerValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FundamentalValue::asInteger(int* output) const
|
|
|
|
{
|
|
|
|
if (type() != TypeInteger)
|
|
|
|
return false;
|
|
|
|
*output = m_integerValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FundamentalValue::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
|
|
|
DCHECK(type() == TypeBoolean || type() == TypeInteger || type() == TypeDouble);
|
|
|
|
if (type() == TypeBoolean) {
|
|
|
|
if (m_boolValue)
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, trueValueString, 4);
|
2016-10-28 18:20:08 +00:00
|
|
|
else
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, falseValueString, 5);
|
2016-10-28 18:20:08 +00:00
|
|
|
} else if (type() == TypeDouble) {
|
|
|
|
if (!std::isfinite(m_doubleValue)) {
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, nullValueString, 4);
|
2016-10-28 18:20:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, StringUtil::fromDouble(m_doubleValue));
|
2016-10-28 18:20:08 +00:00
|
|
|
} else if (type() == TypeInteger) {
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, StringUtil::fromInteger(m_integerValue));
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> FundamentalValue::clone() const
|
|
|
|
{
|
|
|
|
switch (type()) {
|
|
|
|
case TypeDouble: return FundamentalValue::create(m_doubleValue);
|
|
|
|
case TypeInteger: return FundamentalValue::create(m_integerValue);
|
|
|
|
case TypeBoolean: return FundamentalValue::create(m_boolValue);
|
|
|
|
default:
|
|
|
|
DCHECK(false);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StringValue::asString(String* output) const
|
|
|
|
{
|
|
|
|
*output = m_stringValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StringValue::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
|
|
|
DCHECK(type() == TypeString);
|
|
|
|
doubleQuoteStringForJSON(m_stringValue, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> StringValue::clone() const
|
|
|
|
{
|
|
|
|
return StringValue::create(m_stringValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SerializedValue::asSerialized(String* output) const
|
|
|
|
{
|
|
|
|
*output = m_serializedValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SerializedValue::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
|
|
|
DCHECK(type() == TypeSerialized);
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, m_serializedValue);
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> SerializedValue::clone() const
|
|
|
|
{
|
|
|
|
return SerializedValue::create(m_serializedValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
DictionaryValue::~DictionaryValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setBoolean(const String& name, bool value)
|
|
|
|
{
|
|
|
|
setValue(name, FundamentalValue::create(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setInteger(const String& name, int value)
|
|
|
|
{
|
|
|
|
setValue(name, FundamentalValue::create(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setDouble(const String& name, double value)
|
|
|
|
{
|
|
|
|
setValue(name, FundamentalValue::create(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setString(const String& name, const String& value)
|
|
|
|
{
|
|
|
|
setValue(name, StringValue::create(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setValue(const String& name, std::unique_ptr<Value> value)
|
|
|
|
{
|
|
|
|
set(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setObject(const String& name, std::unique_ptr<DictionaryValue> value)
|
|
|
|
{
|
|
|
|
set(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::setArray(const String& name, std::unique_ptr<ListValue> value)
|
|
|
|
{
|
|
|
|
set(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DictionaryValue::getBoolean(const String& name, bool* output) const
|
|
|
|
{
|
|
|
|
protocol::Value* value = get(name);
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
return value->asBoolean(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DictionaryValue::getInteger(const String& name, int* output) const
|
|
|
|
{
|
|
|
|
Value* value = get(name);
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
return value->asInteger(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DictionaryValue::getDouble(const String& name, double* output) const
|
|
|
|
{
|
|
|
|
Value* value = get(name);
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
return value->asDouble(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DictionaryValue::getString(const String& name, String* output) const
|
|
|
|
{
|
|
|
|
protocol::Value* value = get(name);
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
return value->asString(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
DictionaryValue* DictionaryValue::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
return DictionaryValue::cast(get(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
protocol::ListValue* DictionaryValue::getArray(const String& name) const
|
|
|
|
{
|
|
|
|
return ListValue::cast(get(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
protocol::Value* DictionaryValue::get(const String& name) const
|
|
|
|
{
|
|
|
|
Dictionary::const_iterator it = m_data.find(name);
|
|
|
|
if (it == m_data.end())
|
|
|
|
return nullptr;
|
|
|
|
return it->second.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
DictionaryValue::Entry DictionaryValue::at(size_t index) const
|
|
|
|
{
|
|
|
|
const String key = m_order[index];
|
|
|
|
return std::make_pair(key, m_data.find(key)->second.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DictionaryValue::booleanProperty(const String& name, bool defaultValue) const
|
|
|
|
{
|
|
|
|
bool result = defaultValue;
|
|
|
|
getBoolean(name, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DictionaryValue::integerProperty(const String& name, int defaultValue) const
|
|
|
|
{
|
|
|
|
int result = defaultValue;
|
|
|
|
getInteger(name, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
double DictionaryValue::doubleProperty(const String& name, double defaultValue) const
|
|
|
|
{
|
|
|
|
double result = defaultValue;
|
|
|
|
getDouble(name, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::remove(const String& name)
|
|
|
|
{
|
|
|
|
m_data.erase(name);
|
|
|
|
m_order.erase(std::remove(m_order.begin(), m_order.end(), name), m_order.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
void DictionaryValue::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, '{');
|
2016-10-28 18:20:08 +00:00
|
|
|
for (size_t i = 0; i < m_order.size(); ++i) {
|
|
|
|
Dictionary::const_iterator it = m_data.find(m_order[i]);
|
|
|
|
CHECK(it != m_data.end());
|
|
|
|
if (i)
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, ',');
|
2016-10-28 18:20:08 +00:00
|
|
|
doubleQuoteStringForJSON(it->first, output);
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, ':');
|
2016-10-28 18:20:08 +00:00
|
|
|
it->second->writeJSON(output);
|
|
|
|
}
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, '}');
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> DictionaryValue::clone() const
|
|
|
|
{
|
|
|
|
std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
|
|
|
|
for (size_t i = 0; i < m_order.size(); ++i) {
|
|
|
|
String key = m_order[i];
|
|
|
|
Dictionary::const_iterator value = m_data.find(key);
|
|
|
|
DCHECK(value != m_data.cend() && value->second);
|
|
|
|
result->setValue(key, value->second->clone());
|
|
|
|
}
|
|
|
|
return std::move(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
DictionaryValue::DictionaryValue()
|
|
|
|
: Value(TypeObject)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ListValue::~ListValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ListValue::writeJSON(StringBuilder* output) const
|
|
|
|
{
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, '[');
|
2016-10-28 18:20:08 +00:00
|
|
|
bool first = true;
|
|
|
|
for (const std::unique_ptr<protocol::Value>& value : m_data) {
|
|
|
|
if (!first)
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, ',');
|
2016-10-28 18:20:08 +00:00
|
|
|
value->writeJSON(output);
|
|
|
|
first = false;
|
|
|
|
}
|
2017-01-27 21:11:15 +00:00
|
|
|
StringUtil::builderAppend(*output, ']');
|
2016-10-28 18:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> ListValue::clone() const
|
|
|
|
{
|
|
|
|
std::unique_ptr<ListValue> result = ListValue::create();
|
|
|
|
for (const std::unique_ptr<protocol::Value>& value : m_data)
|
|
|
|
result->pushValue(value->clone());
|
|
|
|
return std::move(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
ListValue::ListValue()
|
|
|
|
: Value(TypeArray)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ListValue::pushValue(std::unique_ptr<protocol::Value> value)
|
|
|
|
{
|
|
|
|
DCHECK(value);
|
|
|
|
m_data.push_back(std::move(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
protocol::Value* ListValue::at(size_t index)
|
|
|
|
{
|
|
|
|
DCHECK_LT(index, m_data.size());
|
|
|
|
return m_data[index].get();
|
|
|
|
}
|
|
|
|
|
|
|
|
{% for namespace in config.protocol.namespace %}
|
|
|
|
} // namespace {{namespace}}
|
|
|
|
{% endfor %}
|