Chromium Code Reviews| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} | 80 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} |
| 81 | 81 |
| 82 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { | 82 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { |
| 83 if (!std::isfinite(double_value_)) { | 83 if (!std::isfinite(double_value_)) { |
| 84 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " | 84 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " |
| 85 << "values cannot be represented in JSON"; | 85 << "values cannot be represented in JSON"; |
| 86 double_value_ = 0.0; | 86 double_value_ = 0.0; |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 Value::Value(const char* in_string) : type_(Type::STRING) { | |
| 91 string_value_.Init(in_string); | |
| 92 DCHECK(IsStringUTF8(*string_value_)); | |
| 93 } | |
| 94 | |
| 95 Value::Value(StringPiece in_string) : type_(Type::STRING) { | |
| 96 string_value_.Init(in_string.as_string()); | |
| 97 DCHECK(IsStringUTF8(*string_value_)); | |
| 98 } | |
| 99 | |
| 100 Value::Value(const string16& in_string) : type_(Type::STRING) { | |
| 101 string_value_.Init(UTF16ToUTF8(in_string)); | |
| 102 } | |
| 103 | |
| 90 Value::~Value() { | 104 Value::~Value() { |
| 105 InternalCleanup(); | |
| 91 } | 106 } |
| 92 | 107 |
| 93 void Value::InternalCopyFrom(const Value& that) { | 108 void Value::InternalCopyFrom(const Value& that) { |
| 94 type_ = that.type_; | 109 type_ = that.type_; |
| 95 switch (type_) { | 110 switch (type_) { |
| 96 case Type::NONE: | 111 case Type::NONE: |
| 97 // Nothing to do | 112 // Nothing to do |
| 98 return; | 113 return; |
| 99 | 114 |
| 100 case Type::BOOLEAN: | 115 case Type::BOOLEAN: |
| 101 bool_value_ = that.bool_value_; | 116 bool_value_ = that.bool_value_; |
| 102 return; | 117 return; |
| 103 case Type::INTEGER: | 118 case Type::INTEGER: |
| 104 int_value_ = that.int_value_; | 119 int_value_ = that.int_value_; |
| 105 return; | 120 return; |
| 106 case Type::DOUBLE: | 121 case Type::DOUBLE: |
| 107 double_value_ = that.double_value_; | 122 double_value_ = that.double_value_; |
| 108 return; | 123 return; |
| 124 case Type::STRING: | |
| 125 string_value_.Init(*that.string_value_); | |
| 126 return; | |
| 109 | 127 |
| 110 // TODO(crbug.com/646113): Implement these once the corresponding derived | 128 // TODO(crbug.com/646113): Implement these once the corresponding derived |
| 111 // classes are removed. | 129 // classes are removed. |
| 112 case Type::STRING: | |
| 113 case Type::BINARY: | 130 case Type::BINARY: |
| 114 case Type::LIST: | 131 case Type::LIST: |
| 115 case Type::DICTIONARY: | 132 case Type::DICTIONARY: |
| 133 return; | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 void Value::InternalMoveFrom(Value&& that) { | |
| 138 type_ = that.type_; | |
| 139 | |
| 140 switch (type_) { | |
| 141 case Type::NONE: | |
| 142 // Nothing to do | |
| 143 return; | |
| 144 | |
| 145 case Type::BOOLEAN: | |
| 146 bool_value_ = that.bool_value_; | |
| 147 return; | |
| 148 case Type::INTEGER: | |
| 149 int_value_ = that.int_value_; | |
| 150 return; | |
| 151 case Type::DOUBLE: | |
| 152 double_value_ = that.double_value_; | |
| 153 return; | |
| 154 case Type::STRING: | |
| 155 string_value_.InitFromMove(std::move(that.string_value_)); | |
| 156 that.type_ = Type::NONE; | |
|
jdoerrie
2016/12/19 11:54:09
I decided against setting the type to NONE here, s
vabr (Chromium)
2016/12/19 13:00:56
Acknowledged.
| |
| 157 return; | |
| 158 | |
| 159 // TODO(crbug.com/646113): Implement these once the corresponding derived | |
| 160 // classes are removed. | |
| 161 case Type::BINARY: | |
| 162 case Type::LIST: | |
| 163 case Type::DICTIONARY: | |
| 164 return; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 void Value::InternalCleanup() { | |
| 169 switch (type_) { | |
| 170 case Type::NONE: | |
| 171 case Type::BOOLEAN: | |
| 172 case Type::INTEGER: | |
| 173 case Type::DOUBLE: | |
| 174 // Nothing to do | |
| 175 return; | |
| 176 | |
| 177 case Type::STRING: | |
| 178 string_value_.Destroy(); | |
| 179 return; | |
| 180 | |
| 181 // TODO(crbug.com/646113): Implement these once the corresponding derived | |
| 182 // classes are removed. | |
| 183 case Type::BINARY: | |
| 184 case Type::LIST: | |
| 185 case Type::DICTIONARY: | |
| 116 return; | 186 return; |
| 117 } | 187 } |
| 118 } | 188 } |
| 119 | 189 |
| 120 // static | 190 // static |
| 121 std::unique_ptr<Value> Value::CreateNullValue() { | 191 std::unique_ptr<Value> Value::CreateNullValue() { |
| 122 return WrapUnique(new Value(Type::NONE)); | 192 return WrapUnique(new Value(Type::NONE)); |
| 123 } | 193 } |
| 124 | 194 |
| 125 // static | 195 // static |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 141 | 211 |
| 142 double Value::GetDouble() const { | 212 double Value::GetDouble() const { |
| 143 if (is_double()) | 213 if (is_double()) |
| 144 return double_value_; | 214 return double_value_; |
| 145 if (is_int()) | 215 if (is_int()) |
| 146 return int_value_; | 216 return int_value_; |
| 147 CHECK(false); | 217 CHECK(false); |
| 148 return 0.0; | 218 return 0.0; |
| 149 } | 219 } |
| 150 | 220 |
| 221 std::string& Value::GetString() { | |
| 222 CHECK(is_string()); | |
| 223 return *string_value_; | |
| 224 } | |
| 225 | |
| 226 const std::string& Value::GetString() const { | |
| 227 CHECK(is_string()); | |
| 228 return *string_value_; | |
| 229 } | |
| 230 | |
| 151 bool Value::GetAsBinary(const BinaryValue** out_value) const { | 231 bool Value::GetAsBinary(const BinaryValue** out_value) const { |
| 152 return false; | 232 return false; |
| 153 } | 233 } |
| 154 | 234 |
| 155 bool Value::GetAsBoolean(bool* out_value) const { | 235 bool Value::GetAsBoolean(bool* out_value) const { |
| 156 if (out_value && is_bool()) { | 236 if (out_value && is_bool()) { |
| 157 *out_value = bool_value_; | 237 *out_value = bool_value_; |
| 158 return true; | 238 return true; |
| 159 } | 239 } |
| 160 return is_bool(); | 240 return is_bool(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 174 return true; | 254 return true; |
| 175 } else if (out_value && is_int()) { | 255 } else if (out_value && is_int()) { |
| 176 // Allow promotion from int to double. | 256 // Allow promotion from int to double. |
| 177 *out_value = int_value_; | 257 *out_value = int_value_; |
| 178 return true; | 258 return true; |
| 179 } | 259 } |
| 180 return is_double() || is_int(); | 260 return is_double() || is_int(); |
| 181 } | 261 } |
| 182 | 262 |
| 183 bool Value::GetAsString(std::string* out_value) const { | 263 bool Value::GetAsString(std::string* out_value) const { |
| 184 return false; | 264 if (out_value && is_string()) { |
| 265 *out_value = *string_value_; | |
| 266 return true; | |
| 267 } | |
| 268 return is_string(); | |
| 185 } | 269 } |
| 186 | 270 |
| 187 bool Value::GetAsString(string16* out_value) const { | 271 bool Value::GetAsString(string16* out_value) const { |
| 188 return false; | 272 if (out_value && is_string()) { |
| 273 *out_value = UTF8ToUTF16(*string_value_); | |
| 274 return true; | |
| 275 } | |
| 276 return is_string(); | |
| 189 } | 277 } |
| 190 | 278 |
| 191 bool Value::GetAsString(const StringValue** out_value) const { | 279 bool Value::GetAsString(const StringValue** out_value) const { |
| 192 return false; | 280 if (out_value && is_string()) { |
| 281 *out_value = static_cast<const StringValue*>(this); | |
| 282 return true; | |
| 283 } | |
| 284 return is_string(); | |
| 193 } | 285 } |
| 194 | 286 |
| 195 bool Value::GetAsList(ListValue** out_value) { | 287 bool Value::GetAsList(ListValue** out_value) { |
| 196 return false; | 288 return false; |
| 197 } | 289 } |
| 198 | 290 |
| 199 bool Value::GetAsList(const ListValue** out_value) const { | 291 bool Value::GetAsList(const ListValue** out_value) const { |
| 200 return false; | 292 return false; |
| 201 } | 293 } |
| 202 | 294 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 216 return CreateNullValue().release(); | 308 return CreateNullValue().release(); |
| 217 | 309 |
| 218 // For now, make FundamentalValues for backward-compatibility. Convert to | 310 // For now, make FundamentalValues for backward-compatibility. Convert to |
| 219 // Value when that code is deleted. | 311 // Value when that code is deleted. |
| 220 case Type::BOOLEAN: | 312 case Type::BOOLEAN: |
| 221 return new FundamentalValue(bool_value_); | 313 return new FundamentalValue(bool_value_); |
| 222 case Type::INTEGER: | 314 case Type::INTEGER: |
| 223 return new FundamentalValue(int_value_); | 315 return new FundamentalValue(int_value_); |
| 224 case Type::DOUBLE: | 316 case Type::DOUBLE: |
| 225 return new FundamentalValue(double_value_); | 317 return new FundamentalValue(double_value_); |
| 318 // For now, make StringValues for backward-compatibility. Convert to | |
| 319 // Value when that code is deleted. | |
| 320 case Type::STRING: | |
| 321 return new StringValue(*string_value_); | |
| 226 | 322 |
| 227 default: | 323 default: |
| 228 // All other types should be handled by subclasses. | 324 // All other types should be handled by subclasses. |
| 229 NOTREACHED(); | 325 NOTREACHED(); |
| 230 return nullptr; | 326 return nullptr; |
| 231 } | 327 } |
| 232 } | 328 } |
| 233 | 329 |
| 234 std::unique_ptr<Value> Value::CreateDeepCopy() const { | 330 std::unique_ptr<Value> Value::CreateDeepCopy() const { |
| 235 return WrapUnique(DeepCopy()); | 331 return WrapUnique(DeepCopy()); |
| 236 } | 332 } |
| 237 | 333 |
| 238 bool Value::Equals(const Value* other) const { | 334 bool Value::Equals(const Value* other) const { |
| 239 if (other->type() != type()) | 335 if (other->type() != type()) |
| 240 return false; | 336 return false; |
| 241 | 337 |
| 242 switch (type()) { | 338 switch (type()) { |
| 243 case Type::NONE: | 339 case Type::NONE: |
| 244 return true; | 340 return true; |
| 245 case Type::BOOLEAN: | 341 case Type::BOOLEAN: |
| 246 return bool_value_ == other->bool_value_; | 342 return bool_value_ == other->bool_value_; |
| 247 case Type::INTEGER: | 343 case Type::INTEGER: |
| 248 return int_value_ == other->int_value_; | 344 return int_value_ == other->int_value_; |
| 249 case Type::DOUBLE: | 345 case Type::DOUBLE: |
| 250 return double_value_ == other->double_value_; | 346 return double_value_ == other->double_value_; |
| 347 // TODO(crbug.com/646113): Simplify this once JSONStringValue is removed. | |
| 348 case Type::STRING: { | |
| 349 std::string lhs, rhs; | |
| 350 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; | |
| 351 } | |
| 251 default: | 352 default: |
| 252 // This method should only be getting called for the above types -- all | 353 // This method should only be getting called for the above types -- all |
| 253 // subclasses need to provide their own implementation;. | 354 // subclasses need to provide their own implementation;. |
| 254 NOTREACHED(); | 355 NOTREACHED(); |
| 255 return false; | 356 return false; |
| 256 } | 357 } |
| 257 } | 358 } |
| 258 | 359 |
| 259 // static | 360 // static |
| 260 bool Value::Equals(const Value* a, const Value* b) { | 361 bool Value::Equals(const Value* a, const Value* b) { |
| 261 if ((a == NULL) && (b == NULL)) return true; | 362 if ((a == NULL) && (b == NULL)) return true; |
| 262 if ((a == NULL) ^ (b == NULL)) return false; | 363 if ((a == NULL) ^ (b == NULL)) return false; |
| 263 return a->Equals(b); | 364 return a->Equals(b); |
| 264 } | 365 } |
| 265 | 366 |
| 266 Value::Value(Type type) : type_(type) {} | 367 Value::Value(Type type) : type_(type) {} |
| 267 | 368 |
| 268 Value::Value(const Value& that) { | 369 Value::Value(const Value& that) { |
| 269 InternalCopyFrom(that); | 370 InternalCopyFrom(that); |
| 270 } | 371 } |
| 271 | 372 |
| 272 Value::Value(Value&& that) { | 373 Value::Value(Value&& that) { |
| 273 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving | 374 InternalMoveFrom(std::move(that)); |
| 274 // and copying differ. | |
| 275 InternalCopyFrom(that); | |
| 276 } | 375 } |
| 277 | 376 |
| 278 Value& Value::operator=(const Value& that) { | 377 Value& Value::operator=(const Value& that) { |
| 279 if (this != &that) | 378 if (this != &that) { |
| 379 InternalCleanup(); | |
|
vabr (Chromium)
2016/12/16 17:00:55
Having the InternalCleanup here, and using Init in
jdoerrie
2016/12/19 11:54:09
I agree. Most likely we should act similarly with
| |
| 280 InternalCopyFrom(that); | 380 InternalCopyFrom(that); |
| 381 } | |
| 281 | 382 |
| 282 return *this; | 383 return *this; |
| 283 } | 384 } |
| 284 | 385 |
| 285 Value& Value::operator=(Value&& that) { | 386 Value& Value::operator=(Value&& that) { |
| 286 if (this != &that) { | 387 if (this != &that) { |
| 287 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving | 388 InternalCleanup(); |
| 288 // and copying differ. | 389 InternalMoveFrom(std::move(that)); |
|
vabr (Chromium)
2016/12/16 17:00:55
My comment from the const-ref operator= applies he
jdoerrie
2016/12/19 11:54:09
Acknowledged.
| |
| 289 InternalCopyFrom(that); | |
| 290 } | 390 } |
| 291 | 391 |
| 292 return *this; | 392 return *this; |
| 293 } | 393 } |
| 294 | 394 |
| 295 ///////////////////// FundamentalValue //////////////////// | 395 ///////////////////// FundamentalValue //////////////////// |
| 296 | 396 |
| 297 FundamentalValue::FundamentalValue(bool in_value) : Value(in_value) {} | 397 FundamentalValue::FundamentalValue(bool in_value) : Value(in_value) {} |
| 298 | 398 |
| 299 FundamentalValue::FundamentalValue(int in_value) : Value(in_value) {} | 399 FundamentalValue::FundamentalValue(int in_value) : Value(in_value) {} |
| 300 | 400 |
| 301 FundamentalValue::FundamentalValue(double in_value) : Value(in_value) {} | 401 FundamentalValue::FundamentalValue(double in_value) : Value(in_value) {} |
| 302 | 402 |
| 303 FundamentalValue::~FundamentalValue() {} | 403 FundamentalValue::~FundamentalValue() {} |
| 304 | 404 |
| 305 ///////////////////// StringValue //////////////////// | 405 ///////////////////// StringValue //////////////////// |
| 306 | 406 |
| 307 StringValue::StringValue(StringPiece in_value) | 407 StringValue::StringValue(StringPiece in_value) : Value(in_value) {} |
| 308 : Value(Type::STRING), value_(in_value.as_string()) { | |
| 309 DCHECK(IsStringUTF8(in_value)); | |
| 310 } | |
| 311 | 408 |
| 312 StringValue::StringValue(const string16& in_value) | 409 StringValue::StringValue(const string16& in_value) : Value(in_value) {} |
| 313 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} | |
| 314 | |
| 315 StringValue::~StringValue() { | |
| 316 } | |
| 317 | |
| 318 std::string* StringValue::GetString() { | |
| 319 return &value_; | |
| 320 } | |
| 321 | |
| 322 const std::string& StringValue::GetString() const { | |
| 323 return value_; | |
| 324 } | |
| 325 | |
| 326 bool StringValue::GetAsString(std::string* out_value) const { | |
| 327 if (out_value) | |
| 328 *out_value = value_; | |
| 329 return true; | |
| 330 } | |
| 331 | |
| 332 bool StringValue::GetAsString(string16* out_value) const { | |
| 333 if (out_value) | |
| 334 *out_value = UTF8ToUTF16(value_); | |
| 335 return true; | |
| 336 } | |
| 337 | |
| 338 bool StringValue::GetAsString(const StringValue** out_value) const { | |
| 339 if (out_value) | |
| 340 *out_value = this; | |
| 341 return true; | |
| 342 } | |
| 343 | |
| 344 StringValue* StringValue::DeepCopy() const { | |
| 345 return new StringValue(value_); | |
| 346 } | |
| 347 | |
| 348 bool StringValue::Equals(const Value* other) const { | |
| 349 if (other->GetType() != GetType()) | |
| 350 return false; | |
| 351 std::string lhs, rhs; | |
| 352 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; | |
| 353 } | |
| 354 | 410 |
| 355 ///////////////////// BinaryValue //////////////////// | 411 ///////////////////// BinaryValue //////////////////// |
| 356 | 412 |
| 357 BinaryValue::BinaryValue() : Value(Type::BINARY), size_(0) {} | 413 BinaryValue::BinaryValue() : Value(Type::BINARY), size_(0) {} |
| 358 | 414 |
| 359 BinaryValue::BinaryValue(std::unique_ptr<char[]> buffer, size_t size) | 415 BinaryValue::BinaryValue(std::unique_ptr<char[]> buffer, size_t size) |
| 360 : Value(Type::BINARY), buffer_(std::move(buffer)), size_(size) {} | 416 : Value(Type::BINARY), buffer_(std::move(buffer)), size_(size) {} |
| 361 | 417 |
| 362 BinaryValue::~BinaryValue() { | 418 BinaryValue::~BinaryValue() { |
| 363 } | 419 } |
| (...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 } | 1275 } |
| 1220 | 1276 |
| 1221 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1277 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
| 1222 if (static_cast<int>(type) < 0 || | 1278 if (static_cast<int>(type) < 0 || |
| 1223 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1279 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
| 1224 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1280 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
| 1225 return out << Value::GetTypeName(type); | 1281 return out << Value::GetTypeName(type); |
| 1226 } | 1282 } |
| 1227 | 1283 |
| 1228 } // namespace base | 1284 } // namespace base |
| OLD | NEW |