blob: dd8062b8388f8fac31e580fa1bbd42e2f78532fe [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 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.
initial.commit3f4a7322008-07-27 06:49:38 +09004
5#include "base/logging.h"
6#include "base/values.h"
7
8///////////////////// Value ////////////////////
9
10Value::~Value() {
11}
12
13// static
14Value* Value::CreateNullValue() {
15 return new Value(TYPE_NULL);
16}
17
18// static
19Value* Value::CreateBooleanValue(bool in_value) {
20 return new FundamentalValue(in_value);
21}
22
23// static
24Value* Value::CreateIntegerValue(int in_value) {
25 return new FundamentalValue(in_value);
26}
27
28// static
29Value* Value::CreateRealValue(double in_value) {
30 return new FundamentalValue(in_value);
31}
32
33// static
34Value* Value::CreateStringValue(const std::wstring& in_value) {
35 return new StringValue(in_value);
36}
37
38// static
39BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
40 return BinaryValue::Create(buffer, size);
41}
42
43bool Value::GetAsBoolean(bool* in_value) const {
44 return false;
45}
46
47bool Value::GetAsInteger(int* in_value) const {
48 return false;
49}
50
51bool Value::GetAsReal(double* in_value) const {
52 return false;
53}
54
55bool Value::GetAsString(std::wstring* in_value) const {
56 return false;
57}
58
59Value* Value::DeepCopy() const {
60 // This method should only be getting called for null Values--all subclasses
61 // need to provide their own implementation;.
62 DCHECK(IsType(TYPE_NULL));
63 return CreateNullValue();
64}
65
66bool Value::Equals(const Value* other) const {
67 // This method should only be getting called for null Values--all subclasses
68 // need to provide their own implementation;.
69 DCHECK(IsType(TYPE_NULL));
70 return other->IsType(TYPE_NULL);
71}
72
73///////////////////// FundamentalValue ////////////////////
74
75FundamentalValue::~FundamentalValue() {
76}
77
78bool FundamentalValue::GetAsBoolean(bool* out_value) const {
79 if (out_value && IsType(TYPE_BOOLEAN))
80 *out_value = boolean_value_;
81 return (IsType(TYPE_BOOLEAN));
82}
83
84bool FundamentalValue::GetAsInteger(int* out_value) const {
85 if (out_value && IsType(TYPE_INTEGER))
86 *out_value = integer_value_;
87 return (IsType(TYPE_INTEGER));
88}
89
90bool FundamentalValue::GetAsReal(double* out_value) const {
91 if (out_value && IsType(TYPE_REAL))
92 *out_value = real_value_;
93 return (IsType(TYPE_REAL));
94}
95
96Value* FundamentalValue::DeepCopy() const {
97 switch (GetType()) {
98 case TYPE_BOOLEAN:
99 return CreateBooleanValue(boolean_value_);
100
101 case TYPE_INTEGER:
102 return CreateIntegerValue(integer_value_);
103
104 case TYPE_REAL:
105 return CreateRealValue(real_value_);
106
107 default:
108 NOTREACHED();
109 return NULL;
110 }
111}
112
113bool FundamentalValue::Equals(const Value* other) const {
114 if (other->GetType() != GetType())
115 return false;
116
117 switch (GetType()) {
118 case TYPE_BOOLEAN: {
119 bool lhs, rhs;
120 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
121 }
122 case TYPE_INTEGER: {
123 int lhs, rhs;
124 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
125 }
126 case TYPE_REAL: {
127 double lhs, rhs;
128 return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
129 }
130 default:
131 NOTREACHED();
132 return false;
133 }
134}
135
136///////////////////// StringValue ////////////////////
137
138StringValue::~StringValue() {
139}
140
141bool StringValue::GetAsString(std::wstring* out_value) const {
142 if (out_value)
143 *out_value = value_;
144 return true;
145}
146
147Value* StringValue::DeepCopy() const {
148 return CreateStringValue(value_);
149}
150
151bool StringValue::Equals(const Value* other) const {
152 if (other->GetType() != GetType())
153 return false;
154 std::wstring lhs, rhs;
155 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
156}
157
158///////////////////// BinaryValue ////////////////////
159
160//static
161BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
162 if (!buffer)
163 return NULL;
164
165 return new BinaryValue(buffer, size);
166}
167
168//static
169BinaryValue* BinaryValue::CreateWithCopiedBuffer(char* buffer, size_t size) {
170 if (!buffer)
171 return NULL;
172
173 char* buffer_copy = new char[size];
mmentovai@google.com4a5b6272008-08-07 00:46:59 +0900174 memcpy(buffer_copy, buffer, size);
initial.commit3f4a7322008-07-27 06:49:38 +0900175 return new BinaryValue(buffer_copy, size);
176}
177
178
179BinaryValue::BinaryValue(char* buffer, size_t size)
180 : Value(TYPE_BINARY),
181 buffer_(buffer),
182 size_(size) {
183 DCHECK(buffer_);
184}
185
186BinaryValue::~BinaryValue() {
187 DCHECK(buffer_);
188 if (buffer_)
189 delete[] buffer_;
190}
191
192Value* BinaryValue::DeepCopy() const {
193 return CreateWithCopiedBuffer(buffer_, size_);
194}
195
196bool BinaryValue::Equals(const Value* other) const {
197 if (other->GetType() != GetType())
198 return false;
199 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
200 if (other_binary->size_ != size_)
201 return false;
202 return !memcmp(buffer_, other_binary->buffer_, size_);
203}
204
205///////////////////// DictionaryValue ////////////////////
206
207DictionaryValue::~DictionaryValue() {
208 Clear();
209}
210
211void DictionaryValue::Clear() {
212 ValueMap::iterator dict_iterator = dictionary_.begin();
213 while (dict_iterator != dictionary_.end()) {
214 delete dict_iterator->second;
215 ++dict_iterator;
216 }
217
218 dictionary_.clear();
219}
220
221bool DictionaryValue::HasKey(const std::wstring& key) {
222 ValueMap::const_iterator current_entry = dictionary_.find(key);
223 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
224 return current_entry != dictionary_.end();
225}
226
227void DictionaryValue::SetInCurrentNode(const std::wstring& key,
228 Value* in_value) {
229 // If there's an existing value here, we need to delete it, because
230 // we own all our children.
231 if (HasKey(key)) {
232 DCHECK(dictionary_[key] != in_value); // This would be bogus
233 delete dictionary_[key];
234 }
235
236 dictionary_[key] = in_value;
237}
238
239bool DictionaryValue::Set(const std::wstring& path, Value* in_value) {
240 DCHECK(in_value);
241
242 std::wstring key = path;
243
244 size_t delimiter_position = path.find_first_of(L".", 0);
245 // If there isn't a dictionary delimiter in the path, we're done.
246 if (delimiter_position == std::wstring::npos) {
247 SetInCurrentNode(key, in_value);
248 return true;
249 } else {
250 key = path.substr(0, delimiter_position);
251 }
252
253 // Assume that we're indexing into a dictionary.
254 DictionaryValue* entry = NULL;
initial.commit3f4a7322008-07-27 06:49:38 +0900255 if (!HasKey(key) || (dictionary_[key]->GetType() != TYPE_DICTIONARY)) {
256 entry = new DictionaryValue;
257 SetInCurrentNode(key, entry);
258 } else {
259 entry = static_cast<DictionaryValue*>(dictionary_[key]);
260 }
261
262 std::wstring remaining_path = path.substr(delimiter_position + 1);
263 return entry->Set(remaining_path, in_value);
264}
265
266bool DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
267 return Set(path, CreateBooleanValue(in_value));
268}
269
270bool DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
271 return Set(path, CreateIntegerValue(in_value));
272}
273
274bool DictionaryValue::SetReal(const std::wstring& path, double in_value) {
275 return Set(path, CreateRealValue(in_value));
276}
277
278bool DictionaryValue::SetString(const std::wstring& path,
279 const std::wstring& in_value) {
280 return Set(path, CreateStringValue(in_value));
281}
282
283bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
284 std::wstring key = path;
285
286 size_t delimiter_position = path.find_first_of(L".", 0);
287 if (delimiter_position != std::wstring::npos) {
288 key = path.substr(0, delimiter_position);
289 }
290
291 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
292 if (entry_iterator == dictionary_.end())
293 return false;
294 Value* entry = entry_iterator->second;
295
296 if (delimiter_position == std::wstring::npos) {
297 if (out_value)
298 *out_value = entry;
299 return true;
300 }
301
302 if (entry->IsType(TYPE_DICTIONARY)) {
303 DictionaryValue* dictionary = static_cast<DictionaryValue*>(entry);
304 return dictionary->Get(path.substr(delimiter_position + 1), out_value);
305 }
306
307 return false;
308}
309
310bool DictionaryValue::GetBoolean(const std::wstring& path,
311 bool* bool_value) const {
312 Value* value;
313 if (!Get(path, &value))
314 return false;
315
316 return value->GetAsBoolean(bool_value);
317}
318
319bool DictionaryValue::GetInteger(const std::wstring& path,
320 int* out_value) const {
321 Value* value;
322 if (!Get(path, &value))
323 return false;
324
325 return value->GetAsInteger(out_value);
326}
327
328bool DictionaryValue::GetReal(const std::wstring& path,
329 double* out_value) const {
330 Value* value;
331 if (!Get(path, &value))
332 return false;
333
334 return value->GetAsReal(out_value);
335}
336
337bool DictionaryValue::GetString(const std::wstring& path,
338 std::wstring* out_value) const {
339 Value* value;
340 if (!Get(path, &value))
341 return false;
342
343 return value->GetAsString(out_value);
344}
345
346bool DictionaryValue::GetBinary(const std::wstring& path,
347 BinaryValue** out_value) const {
348 Value* value;
349 bool result = Get(path, &value);
350 if (!result || !value->IsType(TYPE_BINARY))
351 return false;
352
353 if (out_value)
354 *out_value = static_cast<BinaryValue*>(value);
355
356 return true;
357}
358
359bool DictionaryValue::GetDictionary(const std::wstring& path,
360 DictionaryValue** out_value) const {
361 Value* value;
362 bool result = Get(path, &value);
363 if (!result || !value->IsType(TYPE_DICTIONARY))
364 return false;
365
366 if (out_value)
367 *out_value = static_cast<DictionaryValue*>(value);
368
369 return true;
370}
371
372bool DictionaryValue::GetList(const std::wstring& path,
373 ListValue** out_value) const {
374 Value* value;
375 bool result = Get(path, &value);
376 if (!result || !value->IsType(TYPE_LIST))
377 return false;
378
379 if (out_value)
380 *out_value = static_cast<ListValue*>(value);
381
382 return true;
383}
384
385bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
386 std::wstring key = path;
387
388 size_t delimiter_position = path.find_first_of(L".", 0);
389 if (delimiter_position != std::wstring::npos) {
390 key = path.substr(0, delimiter_position);
391 }
392
393 ValueMap::iterator entry_iterator = dictionary_.find(key);
394 if (entry_iterator == dictionary_.end())
395 return false;
396 Value* entry = entry_iterator->second;
397
398 if (delimiter_position == std::wstring::npos) {
399 if (out_value)
400 *out_value = entry;
401 else
402 delete entry;
403
404 dictionary_.erase(entry_iterator);
405 return true;
406 }
407
408 if (entry->IsType(TYPE_DICTIONARY)) {
409 DictionaryValue* dictionary = static_cast<DictionaryValue*>(entry);
410 return dictionary->Remove(path.substr(delimiter_position + 1), out_value);
411 }
412
413 return false;
414}
415
416Value* DictionaryValue::DeepCopy() const {
417 DictionaryValue* result = new DictionaryValue;
418
419 ValueMap::const_iterator current_entry = dictionary_.begin();
420 while (current_entry != dictionary_.end()) {
421 result->Set(current_entry->first, current_entry->second->DeepCopy());
422 ++current_entry;
423 }
424
425 return result;
426}
427
428bool DictionaryValue::Equals(const Value* other) const {
429 if (other->GetType() != GetType())
430 return false;
431
432 const DictionaryValue* other_dict =
433 static_cast<const DictionaryValue*>(other);
434 key_iterator lhs_it(begin_keys());
435 key_iterator rhs_it(other_dict->begin_keys());
436 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
437 Value* lhs;
438 Value* rhs;
439 if (!Get(*lhs_it, &lhs) || !other_dict->Get(*rhs_it, &rhs) ||
440 !lhs->Equals(rhs)) {
441 return false;
442 }
443 ++lhs_it;
444 ++rhs_it;
445 }
446 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
447 return false;
448
449 return true;
450}
451
452///////////////////// ListValue ////////////////////
453
454ListValue::~ListValue() {
455 Clear();
456}
457
458void ListValue::Clear() {
459 ValueVector::iterator list_iterator = list_.begin();
460 while (list_iterator != list_.end()) {
461 delete *list_iterator;
462 ++list_iterator;
463 }
464 list_.clear();
465}
466
467bool ListValue::Set(size_t index, Value* in_value) {
468 if (!in_value)
469 return false;
470
471 if (index >= list_.size()) {
472 // Pad out any intermediate indexes with null settings
473 while (index > list_.size())
474 Append(CreateNullValue());
475 Append(in_value);
476 } else {
477 DCHECK(list_[index] != in_value);
478 delete list_[index];
479 list_[index] = in_value;
480 }
481 return true;
482}
483
484bool ListValue::Get(size_t index, Value** out_value) const {
485 if (index >= list_.size())
486 return false;
487
488 if (out_value)
489 *out_value = list_[index];
490
491 return true;
492}
493
494bool ListValue::GetDictionary(size_t index,
495 DictionaryValue** out_value) const {
496 Value* value;
497 bool result = Get(index, &value);
498 if (!result || !value->IsType(TYPE_DICTIONARY))
499 return false;
500
501 if (out_value)
502 *out_value = static_cast<DictionaryValue*>(value);
503
504 return true;
505}
506
507bool ListValue::Remove(size_t index, Value** out_value) {
508 if (index >= list_.size())
509 return false;
510
511 if (out_value)
512 *out_value = list_[index];
513 else
514 delete list_[index];
515
516 ValueVector::iterator entry = list_.begin();
517 entry += index;
518
519 list_.erase(entry);
520 return true;
521}
522
523void ListValue::Append(Value* in_value) {
524 DCHECK(in_value);
525 list_.push_back(in_value);
526}
527
528Value* ListValue::DeepCopy() const {
529 ListValue* result = new ListValue;
530
531 ValueVector::const_iterator current_entry = list_.begin();
532 while (current_entry != list_.end()) {
533 result->Append((*current_entry)->DeepCopy());
534 ++current_entry;
535 }
536
537 return result;
538}
539
540bool ListValue::Equals(const Value* other) const {
541 if (other->GetType() != GetType())
542 return false;
543
544 const ListValue* other_list =
545 static_cast<const ListValue*>(other);
546 const_iterator lhs_it, rhs_it;
547 for (lhs_it = begin(), rhs_it = other_list->begin();
548 lhs_it != end() && rhs_it != other_list->end();
549 ++lhs_it, ++rhs_it) {
550 if (!(*lhs_it)->Equals(*rhs_it))
551 return false;
552 }
553 if (lhs_it != end() || rhs_it != other_list->end())
554 return false;
555
556 return true;
557}
license.botf003cfe2008-08-24 09:55:55 +0900558