Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / tools / gn / value.cc
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 void Value::RecursivelySetOrigin(const ParseNode* origin) {
92   set_origin(origin);
93   if (type_ == Value::LIST) {
94     for (size_t i = 0; i < list_value_.size(); i++)
95       list_value_[i].RecursivelySetOrigin(origin);
96   }
97 }
98
99 // static
100 const char* Value::DescribeType(Type t) {
101   switch (t) {
102     case NONE:
103       return "none";
104     case BOOLEAN:
105       return "boolean";
106     case INTEGER:
107       return "integer";
108     case STRING:
109       return "string";
110     case LIST:
111       return "list";
112     case SCOPE:
113       return "scope";
114     default:
115       NOTREACHED();
116       return "UNKNOWN";
117   }
118 }
119
120 void Value::SetScopeValue(scoped_ptr<Scope> scope) {
121   DCHECK(type_ == SCOPE);
122   scope_value_ = scope.Pass();
123 }
124
125 std::string Value::ToString(bool quote_string) const {
126   switch (type_) {
127     case NONE:
128       return "<void>";
129     case BOOLEAN:
130       return boolean_value_ ? "true" : "false";
131     case INTEGER:
132       return base::Int64ToString(int_value_);
133     case STRING:
134       if (quote_string) {
135         std::string escaped = string_value_;
136         // First escape all special uses of a backslash.
137         ReplaceSubstringsAfterOffset(&escaped, 0, "\\$", "\\\\$");
138         ReplaceSubstringsAfterOffset(&escaped, 0, "\\\"", "\\\\\"");
139
140         // Now escape special chars.
141         ReplaceSubstringsAfterOffset(&escaped, 0, "$", "\\$");
142         ReplaceSubstringsAfterOffset(&escaped, 0, "\"", "\\\"");
143         return "\"" + escaped + "\"";
144       }
145       return string_value_;
146     case LIST: {
147       std::string result = "[";
148       for (size_t i = 0; i < list_value_.size(); i++) {
149         if (i > 0)
150           result += ", ";
151         result += list_value_[i].ToString(true);
152       }
153       result.push_back(']');
154       return result;
155     }
156     case SCOPE: {
157       Scope::KeyValueMap scope_values;
158       scope_value_->GetCurrentScopeValues(&scope_values);
159       if (scope_values.empty())
160         return std::string("{ }");
161
162       std::string result = "{\n";
163       for (Scope::KeyValueMap::const_iterator i = scope_values.begin();
164            i != scope_values.end(); ++i) {
165         result += "  " + i->first.as_string() + " = " +
166                   i->second.ToString(true) + "\n";
167       }
168       result += "}";
169
170       return result;
171     }
172   }
173   return std::string();
174 }
175
176 bool Value::VerifyTypeIs(Type t, Err* err) const {
177   if (type_ == t)
178     return true;
179
180   *err = Err(origin(), std::string("This is not a ") + DescribeType(t) + ".");
181   return false;
182 }
183
184 bool Value::operator==(const Value& other) const {
185   if (type_ != other.type_)
186     return false;
187
188   switch (type_) {
189     case Value::BOOLEAN:
190       return boolean_value() == other.boolean_value();
191     case Value::INTEGER:
192       return int_value() == other.int_value();
193     case Value::STRING:
194       return string_value() == other.string_value();
195     case Value::LIST:
196       if (list_value().size() != other.list_value().size())
197         return false;
198       for (size_t i = 0; i < list_value().size(); i++) {
199         if (list_value()[i] != other.list_value()[i])
200           return false;
201       }
202       return true;
203     case Value::SCOPE:
204       // Scopes are always considered not equal because there's currently
205       // no use case for comparing them, and it requires a bunch of complex
206       // iteration code.
207       return false;
208     default:
209       return false;
210   }
211 }
212
213 bool Value::operator!=(const Value& other) const {
214   return !operator==(other);
215 }