Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: base/values.cc

Issue 2516363005: Inline StringValue into base::Value (Closed)
Patch Set: Rebase and Nits. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
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. 76 // TODO(crbug.com/646113): Remove this once all types are implemented.
77 bool IsAssignmentSafe(Value::Type lhs, Value::Type rhs) { 77 bool IsAssignmentSafe(Value::Type lhs, Value::Type rhs) {
78 auto IsImplemented = [](Value::Type type) { 78 auto IsImplemented = [](Value::Type type) {
79 return type == Value::Type::NONE || type == Value::Type::BOOLEAN || 79 return type == Value::Type::NONE || type == Value::Type::BOOLEAN ||
80 type == Value::Type::INTEGER || type == Value::Type::DOUBLE; 80 type == Value::Type::INTEGER || type == Value::Type::DOUBLE ||
81 type == Value::Type::STRING;
81 }; 82 };
82 83
83 return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs)); 84 return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs));
84 } 85 }
85 86
86 } // namespace 87 } // namespace
87 88
88 // static 89 // static
89 std::unique_ptr<Value> Value::CreateNullValue() { 90 std::unique_ptr<Value> Value::CreateNullValue() {
90 return WrapUnique(new Value(Type::NONE)); 91 return WrapUnique(new Value(Type::NONE));
91 } 92 }
92 93
93 Value::Value(const Value& that) { 94 Value::Value(const Value& that) {
94 InternalCopyFrom(that); 95 InternalCopyConstructFrom(that);
95 } 96 }
96 97
97 Value::Value(Value&& that) { 98 Value::Value(Value&& that) {
98 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving 99 InternalMoveConstructFrom(std::move(that));
99 // and copying differ.
100 InternalCopyFrom(that);
101 } 100 }
102 101
103 Value::Value() : type_(Type::NONE) {} 102 Value::Value() : type_(Type::NONE) {}
104 103
105 Value::Value(Type type) : type_(type) { 104 Value::Value(Type type) : type_(type) {
106 // Initialize with the default value. 105 // Initialize with the default value.
107 switch (type_) { 106 switch (type_) {
108 case Type::NONE: 107 case Type::NONE:
109 return; 108 return;
110 109
111 case Type::BOOLEAN: 110 case Type::BOOLEAN:
112 bool_value_ = false; 111 bool_value_ = false;
113 return; 112 return;
114 case Type::INTEGER: 113 case Type::INTEGER:
115 int_value_ = 0; 114 int_value_ = 0;
116 return; 115 return;
117 case Type::DOUBLE: 116 case Type::DOUBLE:
118 double_value_ = 0.0; 117 double_value_ = 0.0;
119 return; 118 return;
119 case Type::STRING:
120 string_value_.Init();
121 return;
120 122
121 // TODO(crbug.com/646113): Implement these once the corresponding derived 123 // TODO(crbug.com/646113): Implement these once the corresponding derived
122 // classes are removed. 124 // classes are removed.
123 case Type::STRING:
124 case Type::BINARY: 125 case Type::BINARY:
125 case Type::LIST: 126 case Type::LIST:
126 case Type::DICTIONARY: 127 case Type::DICTIONARY:
127 return; 128 return;
128 } 129 }
129 } 130 }
130 131
131 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} 132 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
132 133
133 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} 134 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
134 135
135 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { 136 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
136 if (!std::isfinite(double_value_)) { 137 if (!std::isfinite(double_value_)) {
137 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " 138 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
138 << "values cannot be represented in JSON"; 139 << "values cannot be represented in JSON";
139 double_value_ = 0.0; 140 double_value_ = 0.0;
140 } 141 }
141 } 142 }
142 143
144 Value::Value(const char* in_string) : type_(Type::STRING) {
145 string_value_.Init(in_string);
146 DCHECK(IsStringUTF8(*string_value_));
147 }
148
149 Value::Value(const std::string& in_string) : type_(Type::STRING) {
150 string_value_.Init(in_string);
151 DCHECK(IsStringUTF8(*string_value_));
152 }
153
154 Value::Value(std::string&& in_string) : type_(Type::STRING) {
155 string_value_.Init(std::move(in_string));
156 DCHECK(IsStringUTF8(*string_value_));
157 }
158
159 Value::Value(const char16* in_string) : type_(Type::STRING) {
160 string_value_.Init(UTF16ToUTF8(in_string));
161 }
162
163 Value::Value(const string16& in_string) : type_(Type::STRING) {
164 string_value_.Init(UTF16ToUTF8(in_string));
165 }
166
167 Value::Value(StringPiece in_string) : Value(in_string.as_string()) {}
168
143 Value& Value::operator=(const Value& that) { 169 Value& Value::operator=(const Value& that) {
144 if (this != &that) { 170 if (this != &that) {
145 DCHECK(IsAssignmentSafe(type_, that.type_)); 171 DCHECK(IsAssignmentSafe(type_, that.type_));
146 InternalCopyFrom(that); 172 if (type_ == that.type_) {
173 InternalCopyAssignFrom(that);
174 } else {
175 InternalCleanup();
176 InternalCopyConstructFrom(that);
177 }
147 } 178 }
148 179
149 return *this; 180 return *this;
150 } 181 }
151 182
152 Value& Value::operator=(Value&& that) { 183 Value& Value::operator=(Value&& that) {
153 if (this != &that) { 184 if (this != &that) {
154 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving
155 // and copying differ.
156 DCHECK(IsAssignmentSafe(type_, that.type_)); 185 DCHECK(IsAssignmentSafe(type_, that.type_));
157 InternalCopyFrom(that); 186 if (type_ == that.type_) {
187 InternalMoveAssignFrom(std::move(that));
188 } else {
189 InternalCleanup();
190 InternalMoveConstructFrom(std::move(that));
191 }
158 } 192 }
159 193
160 return *this; 194 return *this;
161 } 195 }
162 196
163 Value::~Value() {} 197 Value::~Value() {
198 InternalCleanup();
199 }
164 200
165 // static 201 // static
166 const char* Value::GetTypeName(Value::Type type) { 202 const char* Value::GetTypeName(Value::Type type) {
167 DCHECK_GE(static_cast<int>(type), 0); 203 DCHECK_GE(static_cast<int>(type), 0);
168 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); 204 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames));
169 return kTypeNames[static_cast<size_t>(type)]; 205 return kTypeNames[static_cast<size_t>(type)];
170 } 206 }
171 207
172 bool Value::GetBool() const { 208 bool Value::GetBool() const {
173 CHECK(is_bool()); 209 CHECK(is_bool());
174 return bool_value_; 210 return bool_value_;
175 } 211 }
176 212
177 int Value::GetInt() const { 213 int Value::GetInt() const {
178 CHECK(is_int()); 214 CHECK(is_int());
179 return int_value_; 215 return int_value_;
180 } 216 }
181 217
182 double Value::GetDouble() const { 218 double Value::GetDouble() const {
183 if (is_double()) 219 if (is_double())
184 return double_value_; 220 return double_value_;
185 if (is_int()) 221 if (is_int())
186 return int_value_; 222 return int_value_;
187 CHECK(false); 223 CHECK(false);
188 return 0.0; 224 return 0.0;
189 } 225 }
190 226
227 const std::string& Value::GetString() const {
228 CHECK(is_string());
229 return *string_value_;
230 }
231
191 bool Value::GetAsBoolean(bool* out_value) const { 232 bool Value::GetAsBoolean(bool* out_value) const {
192 if (out_value && is_bool()) { 233 if (out_value && is_bool()) {
193 *out_value = bool_value_; 234 *out_value = bool_value_;
194 return true; 235 return true;
195 } 236 }
196 return is_bool(); 237 return is_bool();
197 } 238 }
198 239
199 bool Value::GetAsInteger(int* out_value) const { 240 bool Value::GetAsInteger(int* out_value) const {
200 if (out_value && is_int()) { 241 if (out_value && is_int()) {
201 *out_value = int_value_; 242 *out_value = int_value_;
202 return true; 243 return true;
203 } 244 }
204 return is_int(); 245 return is_int();
205 } 246 }
206 247
207 bool Value::GetAsDouble(double* out_value) const { 248 bool Value::GetAsDouble(double* out_value) const {
208 if (out_value && is_double()) { 249 if (out_value && is_double()) {
209 *out_value = double_value_; 250 *out_value = double_value_;
210 return true; 251 return true;
211 } else if (out_value && is_int()) { 252 } else if (out_value && is_int()) {
212 // Allow promotion from int to double. 253 // Allow promotion from int to double.
213 *out_value = int_value_; 254 *out_value = int_value_;
214 return true; 255 return true;
215 } 256 }
216 return is_double() || is_int(); 257 return is_double() || is_int();
217 } 258 }
218 259
219 bool Value::GetAsString(std::string* out_value) const { 260 bool Value::GetAsString(std::string* out_value) const {
220 return false; 261 if (out_value && is_string()) {
262 *out_value = *string_value_;
263 return true;
264 }
265 return is_string();
221 } 266 }
222 267
223 bool Value::GetAsString(string16* out_value) const { 268 bool Value::GetAsString(string16* out_value) const {
224 return false; 269 if (out_value && is_string()) {
270 *out_value = UTF8ToUTF16(*string_value_);
271 return true;
272 }
273 return is_string();
225 } 274 }
226 275
227 bool Value::GetAsString(const StringValue** out_value) const { 276 bool Value::GetAsString(const StringValue** out_value) const {
228 return false; 277 if (out_value && is_string()) {
278 *out_value = static_cast<const StringValue*>(this);
279 return true;
280 }
281 return is_string();
229 } 282 }
230 283
231 bool Value::GetAsString(StringPiece* out_value) const { 284 bool Value::GetAsString(StringPiece* out_value) const {
232 return false; 285 if (out_value && is_string()) {
286 *out_value = *string_value_;
287 return true;
288 }
289 return is_string();
233 } 290 }
234 291
235 bool Value::GetAsBinary(const BinaryValue** out_value) const { 292 bool Value::GetAsBinary(const BinaryValue** out_value) const {
236 return false; 293 return false;
237 } 294 }
238 295
239 bool Value::GetAsList(ListValue** out_value) { 296 bool Value::GetAsList(ListValue** out_value) {
240 return false; 297 return false;
241 } 298 }
242 299
(...skipping 17 matching lines...) Expand all
260 return CreateNullValue().release(); 317 return CreateNullValue().release();
261 318
262 // For now, make FundamentalValues for backward-compatibility. Convert to 319 // For now, make FundamentalValues for backward-compatibility. Convert to
263 // Value when that code is deleted. 320 // Value when that code is deleted.
264 case Type::BOOLEAN: 321 case Type::BOOLEAN:
265 return new FundamentalValue(bool_value_); 322 return new FundamentalValue(bool_value_);
266 case Type::INTEGER: 323 case Type::INTEGER:
267 return new FundamentalValue(int_value_); 324 return new FundamentalValue(int_value_);
268 case Type::DOUBLE: 325 case Type::DOUBLE:
269 return new FundamentalValue(double_value_); 326 return new FundamentalValue(double_value_);
327 // For now, make StringValues for backward-compatibility. Convert to
328 // Value when that code is deleted.
329 case Type::STRING:
330 return new StringValue(*string_value_);
270 331
271 default: 332 default:
272 // All other types should be handled by subclasses. 333 // All other types should be handled by subclasses.
273 NOTREACHED(); 334 NOTREACHED();
274 return nullptr; 335 return nullptr;
275 } 336 }
276 } 337 }
277 338
278 std::unique_ptr<Value> Value::CreateDeepCopy() const { 339 std::unique_ptr<Value> Value::CreateDeepCopy() const {
279 return WrapUnique(DeepCopy()); 340 return WrapUnique(DeepCopy());
280 } 341 }
281 342
282 bool Value::Equals(const Value* other) const { 343 bool Value::Equals(const Value* other) const {
283 if (other->type() != type()) 344 if (other->type() != type())
284 return false; 345 return false;
285 346
286 switch (type()) { 347 switch (type()) {
287 case Type::NONE: 348 case Type::NONE:
288 return true; 349 return true;
289 case Type::BOOLEAN: 350 case Type::BOOLEAN:
290 return bool_value_ == other->bool_value_; 351 return bool_value_ == other->bool_value_;
291 case Type::INTEGER: 352 case Type::INTEGER:
292 return int_value_ == other->int_value_; 353 return int_value_ == other->int_value_;
293 case Type::DOUBLE: 354 case Type::DOUBLE:
294 return double_value_ == other->double_value_; 355 return double_value_ == other->double_value_;
356 // TODO(crbug.com/646113): Simplify this once JSONStringValue is removed.
357 case Type::STRING: {
358 std::string lhs, rhs;
359 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
360 }
295 default: 361 default:
296 // This method should only be getting called for the above types -- all 362 // This method should only be getting called for the above types -- all
297 // subclasses need to provide their own implementation;. 363 // subclasses need to provide their own implementation;.
298 NOTREACHED(); 364 NOTREACHED();
299 return false; 365 return false;
300 } 366 }
301 } 367 }
302 368
303 // static 369 // static
304 bool Value::Equals(const Value* a, const Value* b) { 370 bool Value::Equals(const Value* a, const Value* b) {
305 if ((a == NULL) && (b == NULL)) return true; 371 if ((a == NULL) && (b == NULL)) return true;
306 if ((a == NULL) ^ (b == NULL)) return false; 372 if ((a == NULL) ^ (b == NULL)) return false;
307 return a->Equals(b); 373 return a->Equals(b);
308 } 374 }
309 375
310 void Value::InternalCopyFrom(const Value& that) { 376 void Value::InternalCopyFundamentalValue(const Value& that) {
311 type_ = that.type_;
312 switch (type_) { 377 switch (type_) {
313 case Type::NONE: 378 case Type::NONE:
314 // Nothing to do. 379 // Nothing to do.
315 return; 380 return;
316 381
317 case Type::BOOLEAN: 382 case Type::BOOLEAN:
318 bool_value_ = that.bool_value_; 383 bool_value_ = that.bool_value_;
319 return; 384 return;
320 case Type::INTEGER: 385 case Type::INTEGER:
321 int_value_ = that.int_value_; 386 int_value_ = that.int_value_;
322 return; 387 return;
323 case Type::DOUBLE: 388 case Type::DOUBLE:
324 double_value_ = that.double_value_; 389 double_value_ = that.double_value_;
325 return; 390 return;
326 391
392 default:
393 NOTREACHED();
394 }
395 }
396
397 void Value::InternalCopyConstructFrom(const Value& that) {
398 type_ = that.type_;
399
400 switch (type_) {
401 case Type::NONE:
402 case Type::BOOLEAN:
403 case Type::INTEGER:
404 case Type::DOUBLE:
405 InternalCopyFundamentalValue(that);
406 return;
407
408 case Type::STRING:
409 string_value_.Init(*that.string_value_);
410 return;
411
327 // TODO(crbug.com/646113): Implement these once the corresponding derived 412 // TODO(crbug.com/646113): Implement these once the corresponding derived
328 // classes are removed. 413 // classes are removed.
329 case Type::STRING:
330 case Type::BINARY: 414 case Type::BINARY:
331 case Type::LIST: 415 case Type::LIST:
332 case Type::DICTIONARY: 416 case Type::DICTIONARY:
333 return; 417 return;
334 } 418 }
335 } 419 }
336 420
337 ///////////////////// StringValue //////////////////// 421 void Value::InternalMoveConstructFrom(Value&& that) {
422 type_ = that.type_;
338 423
339 StringValue::StringValue(StringPiece in_value) 424 switch (type_) {
340 : Value(Type::STRING), value_(in_value.as_string()) { 425 case Type::NONE:
341 DCHECK(IsStringUTF8(in_value)); 426 case Type::BOOLEAN:
427 case Type::INTEGER:
428 case Type::DOUBLE:
429 InternalCopyFundamentalValue(that);
430 return;
431
432 case Type::STRING:
433 string_value_.InitFromMove(std::move(that.string_value_));
434 return;
435
436 // TODO(crbug.com/646113): Implement these once the corresponding derived
437 // classes are removed.
438 case Type::BINARY:
439 case Type::LIST:
440 case Type::DICTIONARY:
441 return;
442 }
342 } 443 }
343 444
344 StringValue::StringValue(const string16& in_value) 445 void Value::InternalCopyAssignFrom(const Value& that) {
345 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} 446 type_ = that.type_;
346 447
347 StringValue::~StringValue() { 448 switch (type_) {
449 case Type::NONE:
450 case Type::BOOLEAN:
451 case Type::INTEGER:
452 case Type::DOUBLE:
453 InternalCopyFundamentalValue(that);
454 return;
455
456 case Type::STRING:
457 *string_value_ = *that.string_value_;
458 return;
459
460 // TODO(crbug.com/646113): Implement these once the corresponding derived
461 // classes are removed.
462 case Type::BINARY:
463 case Type::LIST:
464 case Type::DICTIONARY:
465 return;
466 }
348 } 467 }
349 468
350 std::string* StringValue::GetString() { 469 void Value::InternalMoveAssignFrom(Value&& that) {
351 return &value_; 470 type_ = that.type_;
471
472 switch (type_) {
473 case Type::NONE:
474 case Type::BOOLEAN:
475 case Type::INTEGER:
476 case Type::DOUBLE:
477 InternalCopyFundamentalValue(that);
478 return;
479
480 case Type::STRING:
481 *string_value_ = std::move(*that.string_value_);
482 return;
483
484 // TODO(crbug.com/646113): Implement these once the corresponding derived
485 // classes are removed.
486 case Type::BINARY:
487 case Type::LIST:
488 case Type::DICTIONARY:
489 return;
490 }
352 } 491 }
353 492
354 const std::string& StringValue::GetString() const { 493 void Value::InternalCleanup() {
355 return value_; 494 switch (type_) {
356 } 495 case Type::NONE:
496 case Type::BOOLEAN:
497 case Type::INTEGER:
498 case Type::DOUBLE:
499 // Nothing to do
500 return;
357 501
358 bool StringValue::GetAsString(std::string* out_value) const { 502 case Type::STRING:
359 if (out_value) 503 string_value_.Destroy();
360 *out_value = value_; 504 return;
361 return true;
362 }
363 505
364 bool StringValue::GetAsString(string16* out_value) const { 506 // TODO(crbug.com/646113): Implement these once the corresponding derived
365 if (out_value) 507 // classes are removed.
366 *out_value = UTF8ToUTF16(value_); 508 case Type::BINARY:
367 return true; 509 case Type::LIST:
368 } 510 case Type::DICTIONARY:
369 511 return;
370 bool StringValue::GetAsString(const StringValue** out_value) const { 512 }
371 if (out_value)
372 *out_value = this;
373 return true;
374 }
375
376 bool StringValue::GetAsString(StringPiece* out_value) const {
377 if (out_value)
378 *out_value = value_;
379 return true;
380 }
381
382 StringValue* StringValue::DeepCopy() const {
383 return new StringValue(value_);
384 }
385
386 bool StringValue::Equals(const Value* other) const {
387 if (other->GetType() != GetType())
388 return false;
389 std::string lhs, rhs;
390 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
391 } 513 }
392 514
393 ///////////////////// BinaryValue //////////////////// 515 ///////////////////// BinaryValue ////////////////////
394 516
395 BinaryValue::BinaryValue() : Value(Type::BINARY), size_(0) {} 517 BinaryValue::BinaryValue() : Value(Type::BINARY), size_(0) {}
396 518
397 BinaryValue::BinaryValue(std::unique_ptr<char[]> buffer, size_t size) 519 BinaryValue::BinaryValue(std::unique_ptr<char[]> buffer, size_t size)
398 : Value(Type::BINARY), buffer_(std::move(buffer)), size_(size) {} 520 : Value(Type::BINARY), buffer_(std::move(buffer)), size_(size) {}
399 521
400 BinaryValue::~BinaryValue() { 522 BinaryValue::~BinaryValue() {
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 } 1379 }
1258 1380
1259 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1381 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1260 if (static_cast<int>(type) < 0 || 1382 if (static_cast<int>(type) < 0 ||
1261 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1383 static_cast<size_t>(type) >= arraysize(kTypeNames))
1262 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1384 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1263 return out << Value::GetTypeName(type); 1385 return out << Value::GetTypeName(type);
1264 } 1386 }
1265 1387
1266 } // namespace base 1388 } // namespace base
OLDNEW
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698