mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 00:06:09 +03:00
223 lines
5.9 KiB
C++
223 lines
5.9 KiB
C++
|
// Copyright (c) 2013 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 "tools/gn/value.h"
|
||
|
|
||
|
#include <stddef.h>
|
||
|
#include <utility>
|
||
|
|
||
|
#include "base/strings/string_number_conversions.h"
|
||
|
#include "base/strings/string_util.h"
|
||
|
#include "tools/gn/scope.h"
|
||
|
|
||
|
Value::Value()
|
||
|
: type_(NONE),
|
||
|
boolean_value_(false),
|
||
|
int_value_(0),
|
||
|
origin_(nullptr) {
|
||
|
}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, Type t)
|
||
|
: type_(t),
|
||
|
boolean_value_(false),
|
||
|
int_value_(0),
|
||
|
origin_(origin) {
|
||
|
}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, bool bool_val)
|
||
|
: type_(BOOLEAN),
|
||
|
boolean_value_(bool_val),
|
||
|
int_value_(0),
|
||
|
origin_(origin) {
|
||
|
}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, int64_t int_val)
|
||
|
: type_(INTEGER),
|
||
|
boolean_value_(false),
|
||
|
int_value_(int_val),
|
||
|
origin_(origin) {
|
||
|
}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, std::string str_val)
|
||
|
: type_(STRING),
|
||
|
string_value_(std::move(str_val)),
|
||
|
boolean_value_(false),
|
||
|
int_value_(0),
|
||
|
origin_(origin) {}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, const char* str_val)
|
||
|
: type_(STRING),
|
||
|
string_value_(str_val),
|
||
|
boolean_value_(false),
|
||
|
int_value_(0),
|
||
|
origin_(origin) {
|
||
|
}
|
||
|
|
||
|
Value::Value(const ParseNode* origin, std::unique_ptr<Scope> scope)
|
||
|
: type_(SCOPE),
|
||
|
string_value_(),
|
||
|
boolean_value_(false),
|
||
|
int_value_(0),
|
||
|
scope_value_(std::move(scope)),
|
||
|
origin_(origin) {}
|
||
|
|
||
|
Value::Value(const Value& other)
|
||
|
: type_(other.type_),
|
||
|
string_value_(other.string_value_),
|
||
|
boolean_value_(other.boolean_value_),
|
||
|
int_value_(other.int_value_),
|
||
|
list_value_(other.list_value_),
|
||
|
origin_(other.origin_) {
|
||
|
if (type() == SCOPE && other.scope_value_.get())
|
||
|
scope_value_ = other.scope_value_->MakeClosure();
|
||
|
}
|
||
|
|
||
|
Value::Value(Value&& other) noexcept = default;
|
||
|
|
||
|
Value::~Value() = default;
|
||
|
|
||
|
Value& Value::operator=(const Value& other) {
|
||
|
type_ = other.type_;
|
||
|
string_value_ = other.string_value_;
|
||
|
boolean_value_ = other.boolean_value_;
|
||
|
int_value_ = other.int_value_;
|
||
|
list_value_ = other.list_value_;
|
||
|
if (type() == SCOPE && other.scope_value_.get())
|
||
|
scope_value_ = other.scope_value_->MakeClosure();
|
||
|
origin_ = other.origin_;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
const char* Value::DescribeType(Type t) {
|
||
|
switch (t) {
|
||
|
case NONE:
|
||
|
return "none";
|
||
|
case BOOLEAN:
|
||
|
return "boolean";
|
||
|
case INTEGER:
|
||
|
return "integer";
|
||
|
case STRING:
|
||
|
return "string";
|
||
|
case LIST:
|
||
|
return "list";
|
||
|
case SCOPE:
|
||
|
return "scope";
|
||
|
default:
|
||
|
NOTREACHED();
|
||
|
return "UNKNOWN";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Value::SetScopeValue(std::unique_ptr<Scope> scope) {
|
||
|
DCHECK(type_ == SCOPE);
|
||
|
scope_value_ = std::move(scope);
|
||
|
}
|
||
|
|
||
|
std::string Value::ToString(bool quote_string) const {
|
||
|
switch (type_) {
|
||
|
case NONE:
|
||
|
return "<void>";
|
||
|
case BOOLEAN:
|
||
|
return boolean_value_ ? "true" : "false";
|
||
|
case INTEGER:
|
||
|
return base::Int64ToString(int_value_);
|
||
|
case STRING:
|
||
|
if (quote_string) {
|
||
|
std::string result = "\"";
|
||
|
bool hanging_backslash = false;
|
||
|
for (char ch : string_value_) {
|
||
|
// If the last character was a literal backslash and the next
|
||
|
// character could form a valid escape sequence, we need to insert
|
||
|
// an extra backslash to prevent that.
|
||
|
if (hanging_backslash && (ch == '$' || ch == '"' || ch == '\\'))
|
||
|
result += '\\';
|
||
|
// If the next character is a dollar sign or double quote, it needs
|
||
|
// to be escaped; otherwise it can be printed as is.
|
||
|
if (ch == '$' || ch == '"')
|
||
|
result += '\\';
|
||
|
result += ch;
|
||
|
hanging_backslash = (ch == '\\');
|
||
|
}
|
||
|
// Again, we need to prevent the closing double quotes from becoming
|
||
|
// an escape sequence.
|
||
|
if (hanging_backslash)
|
||
|
result += '\\';
|
||
|
result += '"';
|
||
|
return result;
|
||
|
}
|
||
|
return string_value_;
|
||
|
case LIST: {
|
||
|
std::string result = "[";
|
||
|
for (size_t i = 0; i < list_value_.size(); i++) {
|
||
|
if (i > 0)
|
||
|
result += ", ";
|
||
|
result += list_value_[i].ToString(true);
|
||
|
}
|
||
|
result.push_back(']');
|
||
|
return result;
|
||
|
}
|
||
|
case SCOPE: {
|
||
|
Scope::KeyValueMap scope_values;
|
||
|
scope_value_->GetCurrentScopeValues(&scope_values);
|
||
|
if (scope_values.empty())
|
||
|
return std::string("{ }");
|
||
|
|
||
|
std::string result = "{\n";
|
||
|
for (const auto& pair : scope_values) {
|
||
|
result += " " + pair.first.as_string() + " = " +
|
||
|
pair.second.ToString(true) + "\n";
|
||
|
}
|
||
|
result += "}";
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
return std::string();
|
||
|
}
|
||
|
|
||
|
bool Value::VerifyTypeIs(Type t, Err* err) const {
|
||
|
if (type_ == t)
|
||
|
return true;
|
||
|
|
||
|
*err = Err(origin(),
|
||
|
std::string("This is not a ") + DescribeType(t) + ".",
|
||
|
std::string("Instead I see a ") + DescribeType(type_) + " = " +
|
||
|
ToString(true));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool Value::operator==(const Value& other) const {
|
||
|
if (type_ != other.type_)
|
||
|
return false;
|
||
|
|
||
|
switch (type_) {
|
||
|
case Value::BOOLEAN:
|
||
|
return boolean_value() == other.boolean_value();
|
||
|
case Value::INTEGER:
|
||
|
return int_value() == other.int_value();
|
||
|
case Value::STRING:
|
||
|
return string_value() == other.string_value();
|
||
|
case Value::LIST:
|
||
|
if (list_value().size() != other.list_value().size())
|
||
|
return false;
|
||
|
for (size_t i = 0; i < list_value().size(); i++) {
|
||
|
if (list_value()[i] != other.list_value()[i])
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
case Value::SCOPE:
|
||
|
// Scopes are always considered not equal because there's currently
|
||
|
// no use case for comparing them, and it requires a bunch of complex
|
||
|
// iteration code.
|
||
|
return false;
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Value::operator!=(const Value& other) const {
|
||
|
return !operator==(other);
|
||
|
}
|