OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/values.h" | 5 #include "base/values.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 | 66 |
67 case Value::Type::DICTIONARY: | 67 case Value::Type::DICTIONARY: |
68 return CopyDictionaryWithoutEmptyChildren( | 68 return CopyDictionaryWithoutEmptyChildren( |
69 static_cast<const DictionaryValue&>(node)); | 69 static_cast<const DictionaryValue&>(node)); |
70 | 70 |
71 default: | 71 default: |
72 return node.CreateDeepCopy(); | 72 return node.CreateDeepCopy(); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
| 76 // TODO(crbug.com/646113): Remove this once all types are implemented. |
| 77 bool IsAssignmentSafe(Value::Type lhs, Value::Type rhs) { |
| 78 auto IsImplemented = [](Value::Type type) { |
| 79 return type == Value::Type::NONE || type == Value::Type::BOOLEAN || |
| 80 type == Value::Type::INTEGER || type == Value::Type::DOUBLE; |
| 81 }; |
| 82 |
| 83 return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs)); |
| 84 } |
| 85 |
76 } // namespace | 86 } // namespace |
77 | 87 |
78 Value::~Value() { | |
79 } | |
80 | |
81 // static | 88 // static |
82 std::unique_ptr<Value> Value::CreateNullValue() { | 89 std::unique_ptr<Value> Value::CreateNullValue() { |
83 return WrapUnique(new Value(Type::NONE)); | 90 return WrapUnique(new Value(Type::NONE)); |
84 } | 91 } |
85 | 92 |
| 93 Value::Value(const Value& that) { |
| 94 InternalCopyFrom(that); |
| 95 } |
| 96 |
| 97 Value::Value(Value&& that) { |
| 98 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving |
| 99 // and copying differ. |
| 100 InternalCopyFrom(that); |
| 101 } |
| 102 |
| 103 Value::Value() : type_(Type::NONE) {} |
| 104 |
| 105 Value::Value(Type type) : type_(type) { |
| 106 // Initialize with the default value. |
| 107 switch (type_) { |
| 108 case Type::NONE: |
| 109 return; |
| 110 |
| 111 case Type::BOOLEAN: |
| 112 bool_value_ = false; |
| 113 return; |
| 114 case Type::INTEGER: |
| 115 int_value_ = 0; |
| 116 return; |
| 117 case Type::DOUBLE: |
| 118 double_value_ = 0.0; |
| 119 return; |
| 120 |
| 121 // TODO(crbug.com/646113): Implement these once the corresponding derived |
| 122 // classes are removed. |
| 123 case Type::STRING: |
| 124 case Type::BINARY: |
| 125 case Type::LIST: |
| 126 case Type::DICTIONARY: |
| 127 return; |
| 128 } |
| 129 } |
| 130 |
| 131 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} |
| 132 |
| 133 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} |
| 134 |
| 135 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { |
| 136 if (!std::isfinite(double_value_)) { |
| 137 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " |
| 138 << "values cannot be represented in JSON"; |
| 139 double_value_ = 0.0; |
| 140 } |
| 141 } |
| 142 |
| 143 Value& Value::operator=(const Value& that) { |
| 144 if (this != &that) { |
| 145 DCHECK(IsAssignmentSafe(type_, that.type_)); |
| 146 InternalCopyFrom(that); |
| 147 } |
| 148 |
| 149 return *this; |
| 150 } |
| 151 |
| 152 Value& Value::operator=(Value&& that) { |
| 153 if (this != &that) { |
| 154 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving |
| 155 // and copying differ. |
| 156 DCHECK(IsAssignmentSafe(type_, that.type_)); |
| 157 InternalCopyFrom(that); |
| 158 } |
| 159 |
| 160 return *this; |
| 161 } |
| 162 |
| 163 Value::~Value() {} |
| 164 |
86 // static | 165 // static |
87 const char* Value::GetTypeName(Value::Type type) { | 166 const char* Value::GetTypeName(Value::Type type) { |
88 DCHECK_GE(static_cast<int>(type), 0); | 167 DCHECK_GE(static_cast<int>(type), 0); |
89 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); | 168 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); |
90 return kTypeNames[static_cast<size_t>(type)]; | 169 return kTypeNames[static_cast<size_t>(type)]; |
91 } | 170 } |
92 | 171 |
93 bool Value::GetAsBinary(const BinaryValue** out_value) const { | 172 bool Value::GetBool() const { |
94 return false; | 173 CHECK(is_bool()); |
| 174 return bool_value_; |
| 175 } |
| 176 |
| 177 int Value::GetInt() const { |
| 178 CHECK(is_int()); |
| 179 return int_value_; |
| 180 } |
| 181 |
| 182 double Value::GetDouble() const { |
| 183 if (is_double()) |
| 184 return double_value_; |
| 185 if (is_int()) |
| 186 return int_value_; |
| 187 CHECK(false); |
| 188 return 0.0; |
95 } | 189 } |
96 | 190 |
97 bool Value::GetAsBoolean(bool* out_value) const { | 191 bool Value::GetAsBoolean(bool* out_value) const { |
98 return false; | 192 if (out_value && is_bool()) { |
| 193 *out_value = bool_value_; |
| 194 return true; |
| 195 } |
| 196 return is_bool(); |
99 } | 197 } |
100 | 198 |
101 bool Value::GetAsInteger(int* out_value) const { | 199 bool Value::GetAsInteger(int* out_value) const { |
102 return false; | 200 if (out_value && is_int()) { |
| 201 *out_value = int_value_; |
| 202 return true; |
| 203 } |
| 204 return is_int(); |
103 } | 205 } |
104 | 206 |
105 bool Value::GetAsDouble(double* out_value) const { | 207 bool Value::GetAsDouble(double* out_value) const { |
106 return false; | 208 if (out_value && is_double()) { |
| 209 *out_value = double_value_; |
| 210 return true; |
| 211 } else if (out_value && is_int()) { |
| 212 // Allow promotion from int to double. |
| 213 *out_value = int_value_; |
| 214 return true; |
| 215 } |
| 216 return is_double() || is_int(); |
107 } | 217 } |
108 | 218 |
109 bool Value::GetAsString(std::string* out_value) const { | 219 bool Value::GetAsString(std::string* out_value) const { |
110 return false; | 220 return false; |
111 } | 221 } |
112 | 222 |
113 bool Value::GetAsString(string16* out_value) const { | 223 bool Value::GetAsString(string16* out_value) const { |
114 return false; | 224 return false; |
115 } | 225 } |
116 | 226 |
117 bool Value::GetAsString(const StringValue** out_value) const { | 227 bool Value::GetAsString(const StringValue** out_value) const { |
118 return false; | 228 return false; |
119 } | 229 } |
120 | 230 |
121 bool Value::GetAsString(StringPiece* out_value) const { | 231 bool Value::GetAsString(StringPiece* out_value) const { |
122 return false; | 232 return false; |
123 } | 233 } |
124 | 234 |
| 235 bool Value::GetAsBinary(const BinaryValue** out_value) const { |
| 236 return false; |
| 237 } |
| 238 |
125 bool Value::GetAsList(ListValue** out_value) { | 239 bool Value::GetAsList(ListValue** out_value) { |
126 return false; | 240 return false; |
127 } | 241 } |
128 | 242 |
129 bool Value::GetAsList(const ListValue** out_value) const { | 243 bool Value::GetAsList(const ListValue** out_value) const { |
130 return false; | 244 return false; |
131 } | 245 } |
132 | 246 |
133 bool Value::GetAsDictionary(DictionaryValue** out_value) { | 247 bool Value::GetAsDictionary(DictionaryValue** out_value) { |
134 return false; | 248 return false; |
135 } | 249 } |
136 | 250 |
137 bool Value::GetAsDictionary(const DictionaryValue** out_value) const { | 251 bool Value::GetAsDictionary(const DictionaryValue** out_value) const { |
138 return false; | 252 return false; |
139 } | 253 } |
140 | 254 |
141 Value* Value::DeepCopy() const { | 255 Value* Value::DeepCopy() const { |
142 // This method should only be getting called for null Values--all subclasses | 256 // This method should only be getting called for null Values--all subclasses |
143 // need to provide their own implementation;. | 257 // need to provide their own implementation;. |
144 DCHECK(IsType(Type::NONE)); | 258 switch (type()) { |
145 return CreateNullValue().release(); | 259 case Type::NONE: |
| 260 return CreateNullValue().release(); |
| 261 |
| 262 // For now, make FundamentalValues for backward-compatibility. Convert to |
| 263 // Value when that code is deleted. |
| 264 case Type::BOOLEAN: |
| 265 return new FundamentalValue(bool_value_); |
| 266 case Type::INTEGER: |
| 267 return new FundamentalValue(int_value_); |
| 268 case Type::DOUBLE: |
| 269 return new FundamentalValue(double_value_); |
| 270 |
| 271 default: |
| 272 // All other types should be handled by subclasses. |
| 273 NOTREACHED(); |
| 274 return nullptr; |
| 275 } |
146 } | 276 } |
147 | 277 |
148 std::unique_ptr<Value> Value::CreateDeepCopy() const { | 278 std::unique_ptr<Value> Value::CreateDeepCopy() const { |
149 return WrapUnique(DeepCopy()); | 279 return WrapUnique(DeepCopy()); |
150 } | 280 } |
151 | 281 |
152 bool Value::Equals(const Value* other) const { | 282 bool Value::Equals(const Value* other) const { |
153 // This method should only be getting called for null Values--all subclasses | 283 if (other->type() != type()) |
154 // need to provide their own implementation;. | 284 return false; |
155 DCHECK(IsType(Type::NONE)); | 285 |
156 return other->IsType(Type::NONE); | 286 switch (type()) { |
| 287 case Type::NONE: |
| 288 return true; |
| 289 case Type::BOOLEAN: |
| 290 return bool_value_ == other->bool_value_; |
| 291 case Type::INTEGER: |
| 292 return int_value_ == other->int_value_; |
| 293 case Type::DOUBLE: |
| 294 return double_value_ == other->double_value_; |
| 295 default: |
| 296 // This method should only be getting called for the above types -- all |
| 297 // subclasses need to provide their own implementation;. |
| 298 NOTREACHED(); |
| 299 return false; |
| 300 } |
157 } | 301 } |
158 | 302 |
159 // static | 303 // static |
160 bool Value::Equals(const Value* a, const Value* b) { | 304 bool Value::Equals(const Value* a, const Value* b) { |
161 if ((a == NULL) && (b == NULL)) return true; | 305 if ((a == NULL) && (b == NULL)) return true; |
162 if ((a == NULL) ^ (b == NULL)) return false; | 306 if ((a == NULL) ^ (b == NULL)) return false; |
163 return a->Equals(b); | 307 return a->Equals(b); |
164 } | 308 } |
165 | 309 |
166 Value::Value(Type type) : type_(type) {} | 310 void Value::InternalCopyFrom(const Value& that) { |
| 311 type_ = that.type_; |
| 312 switch (type_) { |
| 313 case Type::NONE: |
| 314 // Nothing to do. |
| 315 return; |
167 | 316 |
168 Value::Value(const Value& that) : type_(that.type_) {} | 317 case Type::BOOLEAN: |
| 318 bool_value_ = that.bool_value_; |
| 319 return; |
| 320 case Type::INTEGER: |
| 321 int_value_ = that.int_value_; |
| 322 return; |
| 323 case Type::DOUBLE: |
| 324 double_value_ = that.double_value_; |
| 325 return; |
169 | 326 |
170 Value& Value::operator=(const Value& that) { | 327 // TODO(crbug.com/646113): Implement these once the corresponding derived |
171 type_ = that.type_; | 328 // classes are removed. |
172 return *this; | 329 case Type::STRING: |
173 } | 330 case Type::BINARY: |
174 | 331 case Type::LIST: |
175 ///////////////////// FundamentalValue //////////////////// | 332 case Type::DICTIONARY: |
176 | 333 return; |
177 FundamentalValue::FundamentalValue(bool in_value) | |
178 : Value(Type::BOOLEAN), boolean_value_(in_value) {} | |
179 | |
180 FundamentalValue::FundamentalValue(int in_value) | |
181 : Value(Type::INTEGER), integer_value_(in_value) {} | |
182 | |
183 FundamentalValue::FundamentalValue(double in_value) | |
184 : Value(Type::DOUBLE), double_value_(in_value) { | |
185 if (!std::isfinite(double_value_)) { | |
186 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " | |
187 << "values cannot be represented in JSON"; | |
188 double_value_ = 0.0; | |
189 } | 334 } |
190 } | 335 } |
191 | 336 |
192 FundamentalValue::~FundamentalValue() { | |
193 } | |
194 | |
195 bool FundamentalValue::GetAsBoolean(bool* out_value) const { | |
196 if (out_value && IsType(Type::BOOLEAN)) | |
197 *out_value = boolean_value_; | |
198 return (IsType(Type::BOOLEAN)); | |
199 } | |
200 | |
201 bool FundamentalValue::GetAsInteger(int* out_value) const { | |
202 if (out_value && IsType(Type::INTEGER)) | |
203 *out_value = integer_value_; | |
204 return (IsType(Type::INTEGER)); | |
205 } | |
206 | |
207 bool FundamentalValue::GetAsDouble(double* out_value) const { | |
208 if (out_value && IsType(Type::DOUBLE)) | |
209 *out_value = double_value_; | |
210 else if (out_value && IsType(Type::INTEGER)) | |
211 *out_value = integer_value_; | |
212 return (IsType(Type::DOUBLE) || IsType(Type::INTEGER)); | |
213 } | |
214 | |
215 FundamentalValue* FundamentalValue::DeepCopy() const { | |
216 switch (GetType()) { | |
217 case Type::BOOLEAN: | |
218 return new FundamentalValue(boolean_value_); | |
219 | |
220 case Type::INTEGER: | |
221 return new FundamentalValue(integer_value_); | |
222 | |
223 case Type::DOUBLE: | |
224 return new FundamentalValue(double_value_); | |
225 | |
226 default: | |
227 NOTREACHED(); | |
228 return NULL; | |
229 } | |
230 } | |
231 | |
232 bool FundamentalValue::Equals(const Value* other) const { | |
233 if (other->GetType() != GetType()) | |
234 return false; | |
235 | |
236 switch (GetType()) { | |
237 case Type::BOOLEAN: { | |
238 bool lhs, rhs; | |
239 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs; | |
240 } | |
241 case Type::INTEGER: { | |
242 int lhs, rhs; | |
243 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs; | |
244 } | |
245 case Type::DOUBLE: { | |
246 double lhs, rhs; | |
247 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs; | |
248 } | |
249 default: | |
250 NOTREACHED(); | |
251 return false; | |
252 } | |
253 } | |
254 | |
255 ///////////////////// StringValue //////////////////// | 337 ///////////////////// StringValue //////////////////// |
256 | 338 |
257 StringValue::StringValue(StringPiece in_value) | 339 StringValue::StringValue(StringPiece in_value) |
258 : Value(Type::STRING), value_(in_value.as_string()) { | 340 : Value(Type::STRING), value_(in_value.as_string()) { |
259 DCHECK(IsStringUTF8(in_value)); | 341 DCHECK(IsStringUTF8(in_value)); |
260 } | 342 } |
261 | 343 |
262 StringValue::StringValue(const string16& in_value) | 344 StringValue::StringValue(const string16& in_value) |
263 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} | 345 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} |
264 | 346 |
(...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 } | 1257 } |
1176 | 1258 |
1177 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1259 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
1178 if (static_cast<int>(type) < 0 || | 1260 if (static_cast<int>(type) < 0 || |
1179 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1261 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
1180 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1262 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
1181 return out << Value::GetTypeName(type); | 1263 return out << Value::GetTypeName(type); |
1182 } | 1264 } |
1183 | 1265 |
1184 } // namespace base | 1266 } // namespace base |
OLD | NEW |