1// Copyright (c) 2009 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.
4
5#include "base/values.h"
6
7#include "base/logging.h"
8#include "base/string_util.h"
9#include "base/utf_string_conversions.h"
10
11namespace {
12
13// Make a deep copy of |node|, but don't include empty lists or dictionaries
14// in the copy. It's possible for this function to return NULL and it
15// expects |node| to always be non-NULL.
16Value* CopyWithoutEmptyChildren(Value* node) {
17  DCHECK(node);
18  switch (node->GetType()) {
19    case Value::TYPE_LIST: {
20      ListValue* list = static_cast<ListValue*>(node);
21      ListValue* copy = new ListValue;
22      for (ListValue::const_iterator it = list->begin(); it != list->end();
23           ++it) {
24        Value* child_copy = CopyWithoutEmptyChildren(*it);
25        if (child_copy)
26          copy->Append(child_copy);
27      }
28      if (!copy->empty())
29        return copy;
30
31      delete copy;
32      return NULL;
33    }
34
35    case Value::TYPE_DICTIONARY: {
36      DictionaryValue* dict = static_cast<DictionaryValue*>(node);
37      DictionaryValue* copy = new DictionaryValue;
38      for (DictionaryValue::key_iterator it = dict->begin_keys();
39           it != dict->end_keys(); ++it) {
40        Value* child = NULL;
41        bool rv = dict->GetWithoutPathExpansion(*it, &child);
42        DCHECK(rv);
43        Value* child_copy = CopyWithoutEmptyChildren(child);
44        if (child_copy)
45          copy->SetWithoutPathExpansion(*it, child_copy);
46      }
47      if (!copy->empty())
48        return copy;
49
50      delete copy;
51      return NULL;
52    }
53
54    default:
55      // For everything else, just make a copy.
56      return node->DeepCopy();
57  }
58}
59
60}  // namespace
61
62///////////////////// Value ////////////////////
63
64Value::~Value() {
65}
66
67// static
68Value* Value::CreateNullValue() {
69  return new Value(TYPE_NULL);
70}
71
72// static
73Value* Value::CreateBooleanValue(bool in_value) {
74  return new FundamentalValue(in_value);
75}
76
77// static
78Value* Value::CreateIntegerValue(int in_value) {
79  return new FundamentalValue(in_value);
80}
81
82// static
83Value* Value::CreateRealValue(double in_value) {
84  return new FundamentalValue(in_value);
85}
86
87// static
88Value* Value::CreateStringValue(const std::string& in_value) {
89  return new StringValue(in_value);
90}
91
92// static
93Value* Value::CreateStringValue(const std::wstring& in_value) {
94  return new StringValue(in_value);
95}
96
97// static
98Value* Value::CreateStringValueFromUTF16(const string16& in_value) {
99  return new StringValue(in_value);
100}
101
102// static
103BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
104  return BinaryValue::Create(buffer, size);
105}
106
107bool Value::GetAsBoolean(bool* in_value) const {
108  return false;
109}
110
111bool Value::GetAsInteger(int* in_value) const {
112  return false;
113}
114
115bool Value::GetAsReal(double* in_value) const {
116  return false;
117}
118
119bool Value::GetAsString(std::string* in_value) const {
120  return false;
121}
122
123bool Value::GetAsString(std::wstring* in_value) const {
124  return false;
125}
126
127bool Value::GetAsUTF16(string16* out_value) const {
128  return false;
129}
130
131Value* Value::DeepCopy() const {
132  // This method should only be getting called for null Values--all subclasses
133  // need to provide their own implementation;.
134  DCHECK(IsType(TYPE_NULL));
135  return CreateNullValue();
136}
137
138bool Value::Equals(const Value* other) const {
139  // This method should only be getting called for null Values--all subclasses
140  // need to provide their own implementation;.
141  DCHECK(IsType(TYPE_NULL));
142  return other->IsType(TYPE_NULL);
143}
144
145///////////////////// FundamentalValue ////////////////////
146
147FundamentalValue::~FundamentalValue() {
148}
149
150bool FundamentalValue::GetAsBoolean(bool* out_value) const {
151  if (out_value && IsType(TYPE_BOOLEAN))
152    *out_value = boolean_value_;
153  return (IsType(TYPE_BOOLEAN));
154}
155
156bool FundamentalValue::GetAsInteger(int* out_value) const {
157  if (out_value && IsType(TYPE_INTEGER))
158    *out_value = integer_value_;
159  return (IsType(TYPE_INTEGER));
160}
161
162bool FundamentalValue::GetAsReal(double* out_value) const {
163  if (out_value && IsType(TYPE_REAL))
164    *out_value = real_value_;
165  return (IsType(TYPE_REAL));
166}
167
168Value* FundamentalValue::DeepCopy() const {
169  switch (GetType()) {
170    case TYPE_BOOLEAN:
171      return CreateBooleanValue(boolean_value_);
172
173    case TYPE_INTEGER:
174      return CreateIntegerValue(integer_value_);
175
176    case TYPE_REAL:
177      return CreateRealValue(real_value_);
178
179    default:
180      NOTREACHED();
181      return NULL;
182  }
183}
184
185bool FundamentalValue::Equals(const Value* other) const {
186  if (other->GetType() != GetType())
187    return false;
188
189  switch (GetType()) {
190    case TYPE_BOOLEAN: {
191      bool lhs, rhs;
192      return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
193    }
194    case TYPE_INTEGER: {
195      int lhs, rhs;
196      return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
197    }
198    case TYPE_REAL: {
199      double lhs, rhs;
200      return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
201    }
202    default:
203      NOTREACHED();
204      return false;
205  }
206}
207
208///////////////////// StringValue ////////////////////
209
210StringValue::StringValue(const std::string& in_value)
211    : Value(TYPE_STRING),
212      value_(in_value) {
213  DCHECK(IsStringUTF8(in_value));
214}
215
216StringValue::StringValue(const std::wstring& in_value)
217    : Value(TYPE_STRING),
218      value_(WideToUTF8(in_value)) {
219}
220
221#if !defined(WCHAR_T_IS_UTF16)
222StringValue::StringValue(const string16& in_value)
223    : Value(TYPE_STRING),
224      value_(UTF16ToUTF8(in_value)) {
225}
226#endif
227
228StringValue::~StringValue() {
229}
230
231bool StringValue::GetAsString(std::string* out_value) const {
232  if (out_value)
233    *out_value = value_;
234  return true;
235}
236
237bool StringValue::GetAsString(std::wstring* out_value) const {
238  if (out_value)
239    *out_value = UTF8ToWide(value_);
240  return true;
241}
242
243bool StringValue::GetAsUTF16(string16* out_value) const {
244  if (out_value)
245    *out_value = UTF8ToUTF16(value_);
246  return true;
247}
248
249Value* StringValue::DeepCopy() const {
250  return CreateStringValue(value_);
251}
252
253bool StringValue::Equals(const Value* other) const {
254  if (other->GetType() != GetType())
255    return false;
256  std::string lhs, rhs;
257  return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
258}
259
260///////////////////// BinaryValue ////////////////////
261
262// static
263BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
264  if (!buffer)
265    return NULL;
266
267  return new BinaryValue(buffer, size);
268}
269
270// static
271BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
272                                                 size_t size) {
273  if (!buffer)
274    return NULL;
275
276  char* buffer_copy = new char[size];
277  memcpy(buffer_copy, buffer, size);
278  return new BinaryValue(buffer_copy, size);
279}
280
281
282BinaryValue::BinaryValue(char* buffer, size_t size)
283  : Value(TYPE_BINARY),
284    buffer_(buffer),
285    size_(size) {
286  DCHECK(buffer_);
287}
288
289BinaryValue::~BinaryValue() {
290  DCHECK(buffer_);
291  if (buffer_)
292    delete[] buffer_;
293}
294
295Value* BinaryValue::DeepCopy() const {
296  return CreateWithCopiedBuffer(buffer_, size_);
297}
298
299bool BinaryValue::Equals(const Value* other) const {
300  if (other->GetType() != GetType())
301    return false;
302  const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
303  if (other_binary->size_ != size_)
304    return false;
305  return !memcmp(buffer_, other_binary->buffer_, size_);
306}
307
308///////////////////// DictionaryValue ////////////////////
309
310DictionaryValue::~DictionaryValue() {
311  Clear();
312}
313
314Value* DictionaryValue::DeepCopy() const {
315  DictionaryValue* result = new DictionaryValue;
316
317  for (ValueMap::const_iterator current_entry(dictionary_.begin());
318       current_entry != dictionary_.end(); ++current_entry) {
319    result->SetWithoutPathExpansion(current_entry->first,
320                                    current_entry->second->DeepCopy());
321  }
322
323  return result;
324}
325
326bool DictionaryValue::Equals(const Value* other) const {
327  if (other->GetType() != GetType())
328    return false;
329
330  const DictionaryValue* other_dict =
331      static_cast<const DictionaryValue*>(other);
332  key_iterator lhs_it(begin_keys());
333  key_iterator rhs_it(other_dict->begin_keys());
334  while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
335    Value* lhs;
336    Value* rhs;
337    if (!GetWithoutPathExpansion(*lhs_it, &lhs) ||
338        !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
339        !lhs->Equals(rhs)) {
340      return false;
341    }
342    ++lhs_it;
343    ++rhs_it;
344  }
345  if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
346    return false;
347
348  return true;
349}
350
351bool DictionaryValue::HasKey(const std::wstring& key) const {
352  ValueMap::const_iterator current_entry = dictionary_.find(key);
353  DCHECK((current_entry == dictionary_.end()) || current_entry->second);
354  return current_entry != dictionary_.end();
355}
356
357void DictionaryValue::Clear() {
358  ValueMap::iterator dict_iterator = dictionary_.begin();
359  while (dict_iterator != dictionary_.end()) {
360    delete dict_iterator->second;
361    ++dict_iterator;
362  }
363
364  dictionary_.clear();
365}
366
367void DictionaryValue::Set(const std::wstring& path, Value* in_value) {
368  DCHECK(in_value);
369
370  std::wstring current_path(path);
371  DictionaryValue* current_dictionary = this;
372  for (size_t delimiter_position = current_path.find('.');
373       delimiter_position != std::wstring::npos;
374       delimiter_position = current_path.find('.')) {
375    // Assume that we're indexing into a dictionary.
376    std::wstring key(current_path, 0, delimiter_position);
377    DictionaryValue* child_dictionary = NULL;
378    if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
379      child_dictionary = new DictionaryValue;
380      current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
381    }
382
383    current_dictionary = child_dictionary;
384    current_path.erase(0, delimiter_position + 1);
385  }
386
387  current_dictionary->SetWithoutPathExpansion(current_path, in_value);
388}
389
390void DictionaryValue::SetBoolean(const std::wstring& path, bool in_value) {
391  Set(path, CreateBooleanValue(in_value));
392}
393
394void DictionaryValue::SetInteger(const std::wstring& path, int in_value) {
395  Set(path, CreateIntegerValue(in_value));
396}
397
398void DictionaryValue::SetReal(const std::wstring& path, double in_value) {
399  Set(path, CreateRealValue(in_value));
400}
401
402void DictionaryValue::SetString(const std::wstring& path,
403                                const std::string& in_value) {
404  Set(path, CreateStringValue(in_value));
405}
406
407void DictionaryValue::SetString(const std::wstring& path,
408                                const std::wstring& in_value) {
409  Set(path, CreateStringValue(in_value));
410}
411
412void DictionaryValue::SetStringFromUTF16(const std::wstring& path,
413                                         const string16& in_value) {
414  Set(path, CreateStringValueFromUTF16(in_value));
415}
416
417void DictionaryValue::SetWithoutPathExpansion(const std::wstring& key,
418                                              Value* in_value) {
419  // If there's an existing value here, we need to delete it, because
420  // we own all our children.
421  if (HasKey(key)) {
422    DCHECK(dictionary_[key] != in_value);  // This would be bogus
423    delete dictionary_[key];
424  }
425
426  dictionary_[key] = in_value;
427}
428
429bool DictionaryValue::Get(const std::wstring& path, Value** out_value) const {
430  std::wstring current_path(path);
431  const DictionaryValue* current_dictionary = this;
432  for (size_t delimiter_position = current_path.find('.');
433       delimiter_position != std::wstring::npos;
434       delimiter_position = current_path.find('.')) {
435    DictionaryValue* child_dictionary = NULL;
436    if (!current_dictionary->GetDictionary(
437            current_path.substr(0, delimiter_position), &child_dictionary))
438      return false;
439
440    current_dictionary = child_dictionary;
441    current_path.erase(0, delimiter_position + 1);
442  }
443
444  return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
445}
446
447bool DictionaryValue::GetBoolean(const std::wstring& path,
448                                 bool* bool_value) const {
449  Value* value;
450  if (!Get(path, &value))
451    return false;
452
453  return value->GetAsBoolean(bool_value);
454}
455
456bool DictionaryValue::GetInteger(const std::wstring& path,
457                                 int* out_value) const {
458  Value* value;
459  if (!Get(path, &value))
460    return false;
461
462  return value->GetAsInteger(out_value);
463}
464
465bool DictionaryValue::GetReal(const std::wstring& path,
466                              double* out_value) const {
467  Value* value;
468  if (!Get(path, &value))
469    return false;
470
471  return value->GetAsReal(out_value);
472}
473
474bool DictionaryValue::GetString(const std::wstring& path,
475                                std::string* out_value) const {
476  Value* value;
477  if (!Get(path, &value))
478    return false;
479
480  return value->GetAsString(out_value);
481}
482
483bool DictionaryValue::GetString(const std::wstring& path,
484                                std::wstring* out_value) const {
485  Value* value;
486  if (!Get(path, &value))
487    return false;
488
489  return value->GetAsString(out_value);
490}
491
492bool DictionaryValue::GetStringAsUTF16(const std::wstring& path,
493                                       string16* out_value) const {
494  Value* value;
495  if (!Get(path, &value))
496    return false;
497
498  return value->GetAsUTF16(out_value);
499}
500
501bool DictionaryValue::GetBinary(const std::wstring& path,
502                                BinaryValue** out_value) const {
503  Value* value;
504  bool result = Get(path, &value);
505  if (!result || !value->IsType(TYPE_BINARY))
506    return false;
507
508  if (out_value)
509    *out_value = static_cast<BinaryValue*>(value);
510
511  return true;
512}
513
514bool DictionaryValue::GetDictionary(const std::wstring& path,
515                                    DictionaryValue** out_value) const {
516  Value* value;
517  bool result = Get(path, &value);
518  if (!result || !value->IsType(TYPE_DICTIONARY))
519    return false;
520
521  if (out_value)
522    *out_value = static_cast<DictionaryValue*>(value);
523
524  return true;
525}
526
527bool DictionaryValue::GetList(const std::wstring& path,
528                              ListValue** out_value) const {
529  Value* value;
530  bool result = Get(path, &value);
531  if (!result || !value->IsType(TYPE_LIST))
532    return false;
533
534  if (out_value)
535    *out_value = static_cast<ListValue*>(value);
536
537  return true;
538}
539
540bool DictionaryValue::GetWithoutPathExpansion(const std::wstring& key,
541                                              Value** out_value) const {
542  ValueMap::const_iterator entry_iterator = dictionary_.find(key);
543  if (entry_iterator == dictionary_.end())
544    return false;
545
546  Value* entry = entry_iterator->second;
547  if (out_value)
548    *out_value = entry;
549  return true;
550}
551
552bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::wstring& path,
553                                                     int* out_value) const {
554  Value* value;
555  if (!GetWithoutPathExpansion(path, &value))
556    return false;
557
558  return value->GetAsInteger(out_value);
559}
560
561bool DictionaryValue::GetStringWithoutPathExpansion(
562    const std::wstring& path,
563    std::string* out_value) const {
564  Value* value;
565  if (!GetWithoutPathExpansion(path, &value))
566    return false;
567
568  return value->GetAsString(out_value);
569}
570
571bool DictionaryValue::GetStringWithoutPathExpansion(
572    const std::wstring& path,
573    std::wstring* out_value) const {
574  Value* value;
575  if (!GetWithoutPathExpansion(path, &value))
576    return false;
577
578  return value->GetAsString(out_value);
579}
580
581bool DictionaryValue::GetStringAsUTF16WithoutPathExpansion(
582    const std::wstring& path,
583    string16* out_value) const {
584  Value* value;
585  if (!GetWithoutPathExpansion(path, &value))
586    return false;
587
588  return value->GetAsUTF16(out_value);
589}
590
591bool DictionaryValue::GetDictionaryWithoutPathExpansion(
592    const std::wstring& path,
593    DictionaryValue** out_value) const {
594  Value* value;
595  bool result = GetWithoutPathExpansion(path, &value);
596  if (!result || !value->IsType(TYPE_DICTIONARY))
597    return false;
598
599  if (out_value)
600    *out_value = static_cast<DictionaryValue*>(value);
601
602  return true;
603}
604
605bool DictionaryValue::GetListWithoutPathExpansion(const std::wstring& path,
606                                                  ListValue** out_value) const {
607  Value* value;
608  bool result = GetWithoutPathExpansion(path, &value);
609  if (!result || !value->IsType(TYPE_LIST))
610    return false;
611
612  if (out_value)
613    *out_value = static_cast<ListValue*>(value);
614
615  return true;
616}
617
618bool DictionaryValue::Remove(const std::wstring& path, Value** out_value) {
619  std::wstring current_path(path);
620  DictionaryValue* current_dictionary = this;
621  size_t delimiter_position = current_path.rfind('.');
622  if (delimiter_position != std::wstring::npos) {
623    if (!GetDictionary(current_path.substr(0, delimiter_position),
624                       &current_dictionary))
625      return false;
626    current_path.erase(0, delimiter_position + 1);
627  }
628
629  return current_dictionary->RemoveWithoutPathExpansion(current_path,
630                                                        out_value);
631}
632
633bool DictionaryValue::RemoveWithoutPathExpansion(const std::wstring& key,
634                                                 Value** out_value) {
635  ValueMap::iterator entry_iterator = dictionary_.find(key);
636  if (entry_iterator == dictionary_.end())
637    return false;
638
639  Value* entry = entry_iterator->second;
640  if (out_value)
641    *out_value = entry;
642  else
643    delete entry;
644  dictionary_.erase(entry_iterator);
645  return true;
646}
647
648DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
649  Value* copy = CopyWithoutEmptyChildren(this);
650  return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
651}
652
653///////////////////// ListValue ////////////////////
654
655ListValue::~ListValue() {
656  Clear();
657}
658
659void ListValue::Clear() {
660  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
661    delete *i;
662  list_.clear();
663}
664
665bool ListValue::Set(size_t index, Value* in_value) {
666  if (!in_value)
667    return false;
668
669  if (index >= list_.size()) {
670    // Pad out any intermediate indexes with null settings
671    while (index > list_.size())
672      Append(CreateNullValue());
673    Append(in_value);
674  } else {
675    DCHECK(list_[index] != in_value);
676    delete list_[index];
677    list_[index] = in_value;
678  }
679  return true;
680}
681
682bool ListValue::Get(size_t index, Value** out_value) const {
683  if (index >= list_.size())
684    return false;
685
686  if (out_value)
687    *out_value = list_[index];
688
689  return true;
690}
691
692bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
693  Value* value;
694  if (!Get(index, &value))
695    return false;
696
697  return value->GetAsBoolean(bool_value);
698}
699
700bool ListValue::GetInteger(size_t index, int* out_value) const {
701  Value* value;
702  if (!Get(index, &value))
703    return false;
704
705  return value->GetAsInteger(out_value);
706}
707
708bool ListValue::GetReal(size_t index, double* out_value) const {
709  Value* value;
710  if (!Get(index, &value))
711    return false;
712
713  return value->GetAsReal(out_value);
714}
715
716bool ListValue::GetString(size_t index, std::string* out_value) const {
717  Value* value;
718  if (!Get(index, &value))
719    return false;
720
721  return value->GetAsString(out_value);
722}
723
724bool ListValue::GetString(size_t index, std::wstring* out_value) const {
725  Value* value;
726  if (!Get(index, &value))
727    return false;
728
729  return value->GetAsString(out_value);
730}
731
732bool ListValue::GetStringAsUTF16(size_t index, string16* out_value) const {
733  Value* value;
734  if (!Get(index, &value))
735    return false;
736
737  return value->GetAsUTF16(out_value);
738}
739
740bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
741  Value* value;
742  bool result = Get(index, &value);
743  if (!result || !value->IsType(TYPE_BINARY))
744    return false;
745
746  if (out_value)
747    *out_value = static_cast<BinaryValue*>(value);
748
749  return true;
750}
751
752bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
753  Value* value;
754  bool result = Get(index, &value);
755  if (!result || !value->IsType(TYPE_DICTIONARY))
756    return false;
757
758  if (out_value)
759    *out_value = static_cast<DictionaryValue*>(value);
760
761  return true;
762}
763
764bool ListValue::GetList(size_t index, ListValue** out_value) const {
765  Value* value;
766  bool result = Get(index, &value);
767  if (!result || !value->IsType(TYPE_LIST))
768    return false;
769
770  if (out_value)
771    *out_value = static_cast<ListValue*>(value);
772
773  return true;
774}
775
776bool ListValue::Remove(size_t index, Value** out_value) {
777  if (index >= list_.size())
778    return false;
779
780  if (out_value)
781    *out_value = list_[index];
782  else
783    delete list_[index];
784
785  list_.erase(list_.begin() + index);
786  return true;
787}
788
789int ListValue::Remove(const Value& value) {
790  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
791    if ((*i)->Equals(&value)) {
792      size_t index = i - list_.begin();
793      delete *i;
794      list_.erase(i);
795      return index;
796    }
797  }
798  return -1;
799}
800
801void ListValue::Append(Value* in_value) {
802  DCHECK(in_value);
803  list_.push_back(in_value);
804}
805
806bool ListValue::Insert(size_t index, Value* in_value) {
807  DCHECK(in_value);
808  if (index > list_.size())
809    return false;
810
811  list_.insert(list_.begin() + index, in_value);
812  return true;
813}
814
815Value* ListValue::DeepCopy() const {
816  ListValue* result = new ListValue;
817
818  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
819    result->Append((*i)->DeepCopy());
820
821  return result;
822}
823
824bool ListValue::Equals(const Value* other) const {
825  if (other->GetType() != GetType())
826    return false;
827
828  const ListValue* other_list =
829      static_cast<const ListValue*>(other);
830  const_iterator lhs_it, rhs_it;
831  for (lhs_it = begin(), rhs_it = other_list->begin();
832       lhs_it != end() && rhs_it != other_list->end();
833       ++lhs_it, ++rhs_it) {
834    if (!(*lhs_it)->Equals(*rhs_it))
835      return false;
836  }
837  if (lhs_it != end() || rhs_it != other_list->end())
838    return false;
839
840  return true;
841}
842