1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "tools/gn/value.h" 6 7 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_util.h" 9 #include "tools/gn/scope.h" 10 11 Value::Value() 12 : type_(NONE), 13 boolean_value_(false), 14 int_value_(0), 15 origin_(NULL) { 16 } 17 18 Value::Value(const ParseNode* origin, Type t) 19 : type_(t), 20 boolean_value_(false), 21 int_value_(0), 22 origin_(origin) { 23 } 24 25 Value::Value(const ParseNode* origin, bool bool_val) 26 : type_(BOOLEAN), 27 boolean_value_(bool_val), 28 int_value_(0), 29 origin_(origin) { 30 } 31 32 Value::Value(const ParseNode* origin, int64 int_val) 33 : type_(INTEGER), 34 boolean_value_(false), 35 int_value_(int_val), 36 origin_(origin) { 37 } 38 39 Value::Value(const ParseNode* origin, std::string str_val) 40 : type_(STRING), 41 string_value_(), 42 boolean_value_(false), 43 int_value_(0), 44 origin_(origin) { 45 string_value_.swap(str_val); 46 } 47 48 Value::Value(const ParseNode* origin, const char* str_val) 49 : type_(STRING), 50 string_value_(str_val), 51 boolean_value_(false), 52 int_value_(0), 53 origin_(origin) { 54 } 55 56 Value::Value(const ParseNode* origin, scoped_ptr<Scope> scope) 57 : type_(SCOPE), 58 string_value_(), 59 boolean_value_(false), 60 int_value_(0), 61 scope_value_(scope.Pass()), 62 origin_(origin) { 63 } 64 65 Value::Value(const Value& other) 66 : type_(other.type_), 67 string_value_(other.string_value_), 68 boolean_value_(other.boolean_value_), 69 int_value_(other.int_value_), 70 list_value_(other.list_value_), 71 origin_(other.origin_) { 72 if (type() == SCOPE && other.scope_value_.get()) 73 scope_value_ = other.scope_value_->MakeClosure(); 74 } 75 76 Value::~Value() { 77 } 78 79 Value& Value::operator=(const Value& other) { 80 type_ = other.type_; 81 string_value_ = other.string_value_; 82 boolean_value_ = other.boolean_value_; 83 int_value_ = other.int_value_; 84 list_value_ = other.list_value_; 85 if (type() == SCOPE && other.scope_value_.get()) 86 scope_value_ = other.scope_value_->MakeClosure(); 87 origin_ = other.origin_; 88 return *this; 89 } 90 91 // static 92 const char* Value::DescribeType(Type t) { 93 switch (t) { 94 case NONE: 95 return "none"; 96 case BOOLEAN: 97 return "boolean"; 98 case INTEGER: 99 return "integer"; 100 case STRING: 101 return "string"; 102 case LIST: 103 return "list"; 104 case SCOPE: 105 return "scope"; 106 default: 107 NOTREACHED(); 108 return "UNKNOWN"; 109 } 110 } 111 112 void Value::SetScopeValue(scoped_ptr<Scope> scope) { 113 DCHECK(type_ == SCOPE); 114 scope_value_ = scope.Pass(); 115 } 116 117 std::string Value::ToString(bool quote_string) const { 118 switch (type_) { 119 case NONE: 120 return "<void>"; 121 case BOOLEAN: 122 return boolean_value_ ? "true" : "false"; 123 case INTEGER: 124 return base::Int64ToString(int_value_); 125 case STRING: 126 if (quote_string) { 127 std::string escaped = string_value_; 128 // First escape all special uses of a backslash. 129 ReplaceSubstringsAfterOffset(&escaped, 0, "\\$", "\\\\$"); 130 ReplaceSubstringsAfterOffset(&escaped, 0, "\\\"", "\\\\\""); 131 132 // Now escape special chars. 133 ReplaceSubstringsAfterOffset(&escaped, 0, "$", "\\$"); 134 ReplaceSubstringsAfterOffset(&escaped, 0, "\"", "\\\""); 135 return "\"" + escaped + "\""; 136 } 137 return string_value_; 138 case LIST: { 139 std::string result = "["; 140 for (size_t i = 0; i < list_value_.size(); i++) { 141 if (i > 0) 142 result += ", "; 143 result += list_value_[i].ToString(true); 144 } 145 result.push_back(']'); 146 return result; 147 } 148 case SCOPE: { 149 Scope::KeyValueMap scope_values; 150 scope_value_->GetCurrentScopeValues(&scope_values); 151 if (scope_values.empty()) 152 return std::string("{ }"); 153 154 std::string result = "{\n"; 155 for (Scope::KeyValueMap::const_iterator i = scope_values.begin(); 156 i != scope_values.end(); ++i) { 157 result += " " + i->first.as_string() + " = " + 158 i->second.ToString(true) + "\n"; 159 } 160 result += "}"; 161 162 return result; 163 } 164 } 165 return std::string(); 166 } 167 168 bool Value::VerifyTypeIs(Type t, Err* err) const { 169 if (type_ == t) 170 return true; 171 172 *err = Err(origin(), 173 std::string("This is not a ") + DescribeType(t) + ".", 174 std::string("Instead I see a ") + DescribeType(type_) + " = " + 175 ToString(true)); 176 return false; 177 } 178 179 bool Value::operator==(const Value& other) const { 180 if (type_ != other.type_) 181 return false; 182 183 switch (type_) { 184 case Value::BOOLEAN: 185 return boolean_value() == other.boolean_value(); 186 case Value::INTEGER: 187 return int_value() == other.int_value(); 188 case Value::STRING: 189 return string_value() == other.string_value(); 190 case Value::LIST: 191 if (list_value().size() != other.list_value().size()) 192 return false; 193 for (size_t i = 0; i < list_value().size(); i++) { 194 if (list_value()[i] != other.list_value()[i]) 195 return false; 196 } 197 return true; 198 case Value::SCOPE: 199 // Scopes are always considered not equal because there's currently 200 // no use case for comparing them, and it requires a bunch of complex 201 // iteration code. 202 return false; 203 default: 204 return false; 205 } 206 } 207 208 bool Value::operator!=(const Value& other) const { 209 return !operator==(other); 210 } 211