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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |