values.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Use of this source code is governed by a BSD-style license that can be
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// found in the LICENSE file.
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "base/values.h"
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "base/logging.h"
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "base/string_util.h"
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "base/utf_string_conversions.h"
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace {
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Make a deep copy of |node|, but don't include empty lists or dictionaries
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// in the copy. It's possible for this function to return NULL and it
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// expects |node| to always be non-NULL.
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* CopyWithoutEmptyChildren(Value* node) {
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  DCHECK(node);
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  switch (node->GetType()) {
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    case Value::TYPE_LIST: {
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      ListValue* list = static_cast<ListValue*>(node);
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      ListValue* copy = new ListValue;
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      for (ListValue::const_iterator it = list->begin(); it != list->end();
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang           ++it) {
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Value* child_copy = CopyWithoutEmptyChildren(*it);
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (child_copy)
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang          copy->Append(child_copy);
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      }
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      if (!copy->empty())
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return copy;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      delete copy;
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      return NULL;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    case Value::TYPE_DICTIONARY: {
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      DictionaryValue* dict = static_cast<DictionaryValue*>(node);
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      DictionaryValue* copy = new DictionaryValue;
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      for (DictionaryValue::key_iterator it = dict->begin_keys();
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang           it != dict->end_keys(); ++it) {
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Value* child = NULL;
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        bool rv = dict->GetWithoutPathExpansion(*it, &child);
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        DCHECK(rv);
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Value* child_copy = CopyWithoutEmptyChildren(child);
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (child_copy)
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang          copy->SetWithoutPathExpansion(*it, child_copy);
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      }
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      if (!copy->empty())
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return copy;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      delete copy;
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      return NULL;
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    default:
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      // For everything else, just make a copy.
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang      return node->DeepCopy();
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  }
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}  // namespace
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang///////////////////// Value ////////////////////
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue::~Value() {
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateNullValue() {
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new Value(TYPE_NULL);
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateBooleanValue(bool in_value) {
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new FundamentalValue(in_value);
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateIntegerValue(int in_value) {
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new FundamentalValue(in_value);
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateRealValue(double in_value) {
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new FundamentalValue(in_value);
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateStringValue(const std::string& in_value) {
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new StringValue(in_value);
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangValue* Value::CreateStringValue(const string16& in_value) {
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return new StringValue(in_value);
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// static
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangBinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) {
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang  return BinaryValue::Create(buffer, size);
100}
101
102bool Value::GetAsBoolean(bool* out_value) const {
103  return false;
104}
105
106bool Value::GetAsInteger(int* out_value) const {
107  return false;
108}
109
110bool Value::GetAsReal(double* out_value) const {
111  return false;
112}
113
114bool Value::GetAsString(std::string* out_value) const {
115  return false;
116}
117
118bool Value::GetAsString(string16* out_value) const {
119  return false;
120}
121
122bool Value::GetAsList(ListValue** out_value) {
123  return false;
124}
125
126Value* Value::DeepCopy() const {
127  // This method should only be getting called for null Values--all subclasses
128  // need to provide their own implementation;.
129  DCHECK(IsType(TYPE_NULL));
130  return CreateNullValue();
131}
132
133bool Value::Equals(const Value* other) const {
134  // This method should only be getting called for null Values--all subclasses
135  // need to provide their own implementation;.
136  DCHECK(IsType(TYPE_NULL));
137  return other->IsType(TYPE_NULL);
138}
139
140// static
141bool Value::Equals(const Value* a, const Value* b) {
142  if ((a == NULL) && (b == NULL)) return true;
143  if ((a == NULL) ^  (b == NULL)) return false;
144  return a->Equals(b);
145}
146
147Value::Value(ValueType type) : type_(type) {
148}
149
150///////////////////// FundamentalValue ////////////////////
151
152FundamentalValue::FundamentalValue(bool in_value)
153    : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
154}
155
156FundamentalValue::FundamentalValue(int in_value)
157    : Value(TYPE_INTEGER), integer_value_(in_value) {
158}
159
160FundamentalValue::FundamentalValue(double in_value)
161    : Value(TYPE_REAL), real_value_(in_value) {
162}
163
164FundamentalValue::~FundamentalValue() {
165}
166
167bool FundamentalValue::GetAsBoolean(bool* out_value) const {
168  if (out_value && IsType(TYPE_BOOLEAN))
169    *out_value = boolean_value_;
170  return (IsType(TYPE_BOOLEAN));
171}
172
173bool FundamentalValue::GetAsInteger(int* out_value) const {
174  if (out_value && IsType(TYPE_INTEGER))
175    *out_value = integer_value_;
176  return (IsType(TYPE_INTEGER));
177}
178
179bool FundamentalValue::GetAsReal(double* out_value) const {
180  if (out_value && IsType(TYPE_REAL))
181    *out_value = real_value_;
182  return (IsType(TYPE_REAL));
183}
184
185Value* FundamentalValue::DeepCopy() const {
186  switch (GetType()) {
187    case TYPE_BOOLEAN:
188      return CreateBooleanValue(boolean_value_);
189
190    case TYPE_INTEGER:
191      return CreateIntegerValue(integer_value_);
192
193    case TYPE_REAL:
194      return CreateRealValue(real_value_);
195
196    default:
197      NOTREACHED();
198      return NULL;
199  }
200}
201
202bool FundamentalValue::Equals(const Value* other) const {
203  if (other->GetType() != GetType())
204    return false;
205
206  switch (GetType()) {
207    case TYPE_BOOLEAN: {
208      bool lhs, rhs;
209      return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
210    }
211    case TYPE_INTEGER: {
212      int lhs, rhs;
213      return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
214    }
215    case TYPE_REAL: {
216      double lhs, rhs;
217      return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
218    }
219    default:
220      NOTREACHED();
221      return false;
222  }
223}
224
225///////////////////// StringValue ////////////////////
226
227StringValue::StringValue(const std::string& in_value)
228    : Value(TYPE_STRING),
229      value_(in_value) {
230  DCHECK(IsStringUTF8(in_value));
231}
232
233StringValue::StringValue(const string16& in_value)
234    : Value(TYPE_STRING),
235      value_(UTF16ToUTF8(in_value)) {
236}
237
238StringValue::~StringValue() {
239}
240
241bool StringValue::GetAsString(std::string* out_value) const {
242  if (out_value)
243    *out_value = value_;
244  return true;
245}
246
247bool StringValue::GetAsString(string16* out_value) const {
248  if (out_value)
249    *out_value = UTF8ToUTF16(value_);
250  return true;
251}
252
253Value* StringValue::DeepCopy() const {
254  return CreateStringValue(value_);
255}
256
257bool StringValue::Equals(const Value* other) const {
258  if (other->GetType() != GetType())
259    return false;
260  std::string lhs, rhs;
261  return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
262}
263
264///////////////////// BinaryValue ////////////////////
265
266BinaryValue::~BinaryValue() {
267  DCHECK(buffer_);
268  if (buffer_)
269    delete[] buffer_;
270}
271
272// static
273BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
274  if (!buffer)
275    return NULL;
276
277  return new BinaryValue(buffer, size);
278}
279
280// static
281BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
282                                                 size_t size) {
283  if (!buffer)
284    return NULL;
285
286  char* buffer_copy = new char[size];
287  memcpy(buffer_copy, buffer, size);
288  return new BinaryValue(buffer_copy, size);
289}
290
291Value* BinaryValue::DeepCopy() const {
292  return CreateWithCopiedBuffer(buffer_, size_);
293}
294
295bool BinaryValue::Equals(const Value* other) const {
296  if (other->GetType() != GetType())
297    return false;
298  const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
299  if (other_binary->size_ != size_)
300    return false;
301  return !memcmp(buffer_, other_binary->buffer_, size_);
302}
303
304BinaryValue::BinaryValue(char* buffer, size_t size)
305  : Value(TYPE_BINARY),
306    buffer_(buffer),
307    size_(size) {
308  DCHECK(buffer_);
309}
310
311///////////////////// DictionaryValue ////////////////////
312
313DictionaryValue::DictionaryValue()
314    : Value(TYPE_DICTIONARY) {
315}
316
317DictionaryValue::~DictionaryValue() {
318  Clear();
319}
320
321bool DictionaryValue::HasKey(const std::string& key) const {
322  DCHECK(IsStringUTF8(key));
323  ValueMap::const_iterator current_entry = dictionary_.find(key);
324  DCHECK((current_entry == dictionary_.end()) || current_entry->second);
325  return current_entry != dictionary_.end();
326}
327
328void DictionaryValue::Clear() {
329  ValueMap::iterator dict_iterator = dictionary_.begin();
330  while (dict_iterator != dictionary_.end()) {
331    delete dict_iterator->second;
332    ++dict_iterator;
333  }
334
335  dictionary_.clear();
336}
337
338void DictionaryValue::Set(const std::string& path, Value* in_value) {
339  DCHECK(IsStringUTF8(path));
340  DCHECK(in_value);
341
342  std::string current_path(path);
343  DictionaryValue* current_dictionary = this;
344  for (size_t delimiter_position = current_path.find('.');
345       delimiter_position != std::string::npos;
346       delimiter_position = current_path.find('.')) {
347    // Assume that we're indexing into a dictionary.
348    std::string key(current_path, 0, delimiter_position);
349    DictionaryValue* child_dictionary = NULL;
350    if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
351      child_dictionary = new DictionaryValue;
352      current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
353    }
354
355    current_dictionary = child_dictionary;
356    current_path.erase(0, delimiter_position + 1);
357  }
358
359  current_dictionary->SetWithoutPathExpansion(current_path, in_value);
360}
361
362void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
363  Set(path, CreateBooleanValue(in_value));
364}
365
366void DictionaryValue::SetInteger(const std::string& path, int in_value) {
367  Set(path, CreateIntegerValue(in_value));
368}
369
370void DictionaryValue::SetReal(const std::string& path, double in_value) {
371  Set(path, CreateRealValue(in_value));
372}
373
374void DictionaryValue::SetString(const std::string& path,
375                                const std::string& in_value) {
376  Set(path, CreateStringValue(in_value));
377}
378
379void DictionaryValue::SetString(const std::string& path,
380                                const string16& in_value) {
381  Set(path, CreateStringValue(in_value));
382}
383
384void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
385                                              Value* in_value) {
386  // If there's an existing value here, we need to delete it, because
387  // we own all our children.
388  if (HasKey(key)) {
389    DCHECK(dictionary_[key] != in_value);  // This would be bogus
390    delete dictionary_[key];
391  }
392
393  dictionary_[key] = in_value;
394}
395
396bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
397  DCHECK(IsStringUTF8(path));
398  std::string current_path(path);
399  const DictionaryValue* current_dictionary = this;
400  for (size_t delimiter_position = current_path.find('.');
401       delimiter_position != std::string::npos;
402       delimiter_position = current_path.find('.')) {
403    DictionaryValue* child_dictionary = NULL;
404    if (!current_dictionary->GetDictionary(
405            current_path.substr(0, delimiter_position), &child_dictionary))
406      return false;
407
408    current_dictionary = child_dictionary;
409    current_path.erase(0, delimiter_position + 1);
410  }
411
412  return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
413}
414
415bool DictionaryValue::GetBoolean(const std::string& path,
416                                 bool* bool_value) const {
417  Value* value;
418  if (!Get(path, &value))
419    return false;
420
421  return value->GetAsBoolean(bool_value);
422}
423
424bool DictionaryValue::GetInteger(const std::string& path,
425                                 int* out_value) const {
426  Value* value;
427  if (!Get(path, &value))
428    return false;
429
430  return value->GetAsInteger(out_value);
431}
432
433bool DictionaryValue::GetReal(const std::string& path,
434                              double* out_value) const {
435  Value* value;
436  if (!Get(path, &value))
437    return false;
438
439  return value->GetAsReal(out_value);
440}
441
442bool DictionaryValue::GetString(const std::string& path,
443                                std::string* out_value) const {
444  Value* value;
445  if (!Get(path, &value))
446    return false;
447
448  return value->GetAsString(out_value);
449}
450
451bool DictionaryValue::GetString(const std::string& path,
452                                string16* out_value) const {
453  Value* value;
454  if (!Get(path, &value))
455    return false;
456
457  return value->GetAsString(out_value);
458}
459
460bool DictionaryValue::GetStringASCII(const std::string& path,
461                                     std::string* out_value) const {
462  std::string out;
463  if (!GetString(path, &out))
464    return false;
465
466  if (!IsStringASCII(out)) {
467    NOTREACHED();
468    return false;
469  }
470
471  out_value->assign(out);
472  return true;
473}
474
475bool DictionaryValue::GetBinary(const std::string& path,
476                                BinaryValue** out_value) const {
477  Value* value;
478  bool result = Get(path, &value);
479  if (!result || !value->IsType(TYPE_BINARY))
480    return false;
481
482  if (out_value)
483    *out_value = static_cast<BinaryValue*>(value);
484
485  return true;
486}
487
488bool DictionaryValue::GetDictionary(const std::string& path,
489                                    DictionaryValue** out_value) const {
490  Value* value;
491  bool result = Get(path, &value);
492  if (!result || !value->IsType(TYPE_DICTIONARY))
493    return false;
494
495  if (out_value)
496    *out_value = static_cast<DictionaryValue*>(value);
497
498  return true;
499}
500
501bool DictionaryValue::GetList(const std::string& path,
502                              ListValue** out_value) const {
503  Value* value;
504  bool result = Get(path, &value);
505  if (!result || !value->IsType(TYPE_LIST))
506    return false;
507
508  if (out_value)
509    *out_value = static_cast<ListValue*>(value);
510
511  return true;
512}
513
514bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
515                                              Value** out_value) const {
516  DCHECK(IsStringUTF8(key));
517  ValueMap::const_iterator entry_iterator = dictionary_.find(key);
518  if (entry_iterator == dictionary_.end())
519    return false;
520
521  Value* entry = entry_iterator->second;
522  if (out_value)
523    *out_value = entry;
524  return true;
525}
526
527bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
528                                                     int* out_value) const {
529  Value* value;
530  if (!GetWithoutPathExpansion(key, &value))
531    return false;
532
533  return value->GetAsInteger(out_value);
534}
535
536bool DictionaryValue::GetRealWithoutPathExpansion(const std::string& key,
537                                                  double* out_value) const {
538  Value* value;
539  if (!GetWithoutPathExpansion(key, &value))
540    return false;
541
542  return value->GetAsReal(out_value);
543}
544
545bool DictionaryValue::GetStringWithoutPathExpansion(
546    const std::string& key,
547    std::string* out_value) const {
548  Value* value;
549  if (!GetWithoutPathExpansion(key, &value))
550    return false;
551
552  return value->GetAsString(out_value);
553}
554
555bool DictionaryValue::GetStringWithoutPathExpansion(
556    const std::string& key,
557    string16* out_value) const {
558  Value* value;
559  if (!GetWithoutPathExpansion(key, &value))
560    return false;
561
562  return value->GetAsString(out_value);
563}
564
565bool DictionaryValue::GetDictionaryWithoutPathExpansion(
566    const std::string& key,
567    DictionaryValue** out_value) const {
568  Value* value;
569  bool result = GetWithoutPathExpansion(key, &value);
570  if (!result || !value->IsType(TYPE_DICTIONARY))
571    return false;
572
573  if (out_value)
574    *out_value = static_cast<DictionaryValue*>(value);
575
576  return true;
577}
578
579bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
580                                                  ListValue** out_value) const {
581  Value* value;
582  bool result = GetWithoutPathExpansion(key, &value);
583  if (!result || !value->IsType(TYPE_LIST))
584    return false;
585
586  if (out_value)
587    *out_value = static_cast<ListValue*>(value);
588
589  return true;
590}
591
592bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
593  DCHECK(IsStringUTF8(path));
594  std::string current_path(path);
595  DictionaryValue* current_dictionary = this;
596  size_t delimiter_position = current_path.rfind('.');
597  if (delimiter_position != std::string::npos) {
598    if (!GetDictionary(current_path.substr(0, delimiter_position),
599                       &current_dictionary))
600      return false;
601    current_path.erase(0, delimiter_position + 1);
602  }
603
604  return current_dictionary->RemoveWithoutPathExpansion(current_path,
605                                                        out_value);
606}
607
608bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
609                                                 Value** out_value) {
610  DCHECK(IsStringUTF8(key));
611  ValueMap::iterator entry_iterator = dictionary_.find(key);
612  if (entry_iterator == dictionary_.end())
613    return false;
614
615  Value* entry = entry_iterator->second;
616  if (out_value)
617    *out_value = entry;
618  else
619    delete entry;
620  dictionary_.erase(entry_iterator);
621  return true;
622}
623
624DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
625  Value* copy = CopyWithoutEmptyChildren(this);
626  return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
627}
628
629void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
630  for (DictionaryValue::key_iterator key(dictionary->begin_keys());
631       key != dictionary->end_keys(); ++key) {
632    Value* merge_value;
633    if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
634      // Check whether we have to merge dictionaries.
635      if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
636        DictionaryValue* sub_dict;
637        if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
638          sub_dict->MergeDictionary(
639              static_cast<const DictionaryValue*>(merge_value));
640          continue;
641        }
642      }
643      // All other cases: Make a copy and hook it up.
644      SetWithoutPathExpansion(*key, merge_value->DeepCopy());
645    }
646  }
647}
648
649Value* DictionaryValue::DeepCopy() const {
650  DictionaryValue* result = new DictionaryValue;
651
652  for (ValueMap::const_iterator current_entry(dictionary_.begin());
653       current_entry != dictionary_.end(); ++current_entry) {
654    result->SetWithoutPathExpansion(current_entry->first,
655                                    current_entry->second->DeepCopy());
656  }
657
658  return result;
659}
660
661bool DictionaryValue::Equals(const Value* other) const {
662  if (other->GetType() != GetType())
663    return false;
664
665  const DictionaryValue* other_dict =
666      static_cast<const DictionaryValue*>(other);
667  key_iterator lhs_it(begin_keys());
668  key_iterator rhs_it(other_dict->begin_keys());
669  while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
670    Value* lhs;
671    Value* rhs;
672    if (*lhs_it != *rhs_it ||
673        !GetWithoutPathExpansion(*lhs_it, &lhs) ||
674        !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
675        !lhs->Equals(rhs)) {
676      return false;
677    }
678    ++lhs_it;
679    ++rhs_it;
680  }
681  if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
682    return false;
683
684  return true;
685}
686
687///////////////////// ListValue ////////////////////
688
689ListValue::ListValue() : Value(TYPE_LIST) {
690}
691
692ListValue::~ListValue() {
693  Clear();
694}
695
696void ListValue::Clear() {
697  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
698    delete *i;
699  list_.clear();
700}
701
702bool ListValue::Set(size_t index, Value* in_value) {
703  if (!in_value)
704    return false;
705
706  if (index >= list_.size()) {
707    // Pad out any intermediate indexes with null settings
708    while (index > list_.size())
709      Append(CreateNullValue());
710    Append(in_value);
711  } else {
712    DCHECK(list_[index] != in_value);
713    delete list_[index];
714    list_[index] = in_value;
715  }
716  return true;
717}
718
719bool ListValue::Get(size_t index, Value** out_value) const {
720  if (index >= list_.size())
721    return false;
722
723  if (out_value)
724    *out_value = list_[index];
725
726  return true;
727}
728
729bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
730  Value* value;
731  if (!Get(index, &value))
732    return false;
733
734  return value->GetAsBoolean(bool_value);
735}
736
737bool ListValue::GetInteger(size_t index, int* out_value) const {
738  Value* value;
739  if (!Get(index, &value))
740    return false;
741
742  return value->GetAsInteger(out_value);
743}
744
745bool ListValue::GetReal(size_t index, double* out_value) const {
746  Value* value;
747  if (!Get(index, &value))
748    return false;
749
750  return value->GetAsReal(out_value);
751}
752
753bool ListValue::GetString(size_t index, std::string* out_value) const {
754  Value* value;
755  if (!Get(index, &value))
756    return false;
757
758  return value->GetAsString(out_value);
759}
760
761bool ListValue::GetString(size_t index, string16* out_value) const {
762  Value* value;
763  if (!Get(index, &value))
764    return false;
765
766  return value->GetAsString(out_value);
767}
768
769bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
770  Value* value;
771  bool result = Get(index, &value);
772  if (!result || !value->IsType(TYPE_BINARY))
773    return false;
774
775  if (out_value)
776    *out_value = static_cast<BinaryValue*>(value);
777
778  return true;
779}
780
781bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
782  Value* value;
783  bool result = Get(index, &value);
784  if (!result || !value->IsType(TYPE_DICTIONARY))
785    return false;
786
787  if (out_value)
788    *out_value = static_cast<DictionaryValue*>(value);
789
790  return true;
791}
792
793bool ListValue::GetList(size_t index, ListValue** out_value) const {
794  Value* value;
795  bool result = Get(index, &value);
796  if (!result || !value->IsType(TYPE_LIST))
797    return false;
798
799  if (out_value)
800    *out_value = static_cast<ListValue*>(value);
801
802  return true;
803}
804
805bool ListValue::Remove(size_t index, Value** out_value) {
806  if (index >= list_.size())
807    return false;
808
809  if (out_value)
810    *out_value = list_[index];
811  else
812    delete list_[index];
813
814  list_.erase(list_.begin() + index);
815  return true;
816}
817
818int ListValue::Remove(const Value& value) {
819  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
820    if ((*i)->Equals(&value)) {
821      size_t index = i - list_.begin();
822      delete *i;
823      list_.erase(i);
824
825      // TODO(anyone): Returning a signed int type here is just wrong.
826      // Change this interface to return a size_t.
827      DCHECK(index <= INT_MAX);
828      int return_index = static_cast<int>(index);
829      return return_index;
830    }
831  }
832  return -1;
833}
834
835void ListValue::Append(Value* in_value) {
836  DCHECK(in_value);
837  list_.push_back(in_value);
838}
839
840bool ListValue::AppendIfNotPresent(Value* in_value) {
841  DCHECK(in_value);
842  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
843    if ((*i)->Equals(in_value))
844      return false;
845  }
846  list_.push_back(in_value);
847  return true;
848}
849
850bool ListValue::Insert(size_t index, Value* in_value) {
851  DCHECK(in_value);
852  if (index > list_.size())
853    return false;
854
855  list_.insert(list_.begin() + index, in_value);
856  return true;
857}
858
859bool ListValue::GetAsList(ListValue** out_value) {
860  if (out_value)
861    *out_value = this;
862  return true;
863}
864
865Value* ListValue::DeepCopy() const {
866  ListValue* result = new ListValue;
867
868  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
869    result->Append((*i)->DeepCopy());
870
871  return result;
872}
873
874bool ListValue::Equals(const Value* other) const {
875  if (other->GetType() != GetType())
876    return false;
877
878  const ListValue* other_list =
879      static_cast<const ListValue*>(other);
880  const_iterator lhs_it, rhs_it;
881  for (lhs_it = begin(), rhs_it = other_list->begin();
882       lhs_it != end() && rhs_it != other_list->end();
883       ++lhs_it, ++rhs_it) {
884    if (!(*lhs_it)->Equals(*rhs_it))
885      return false;
886  }
887  if (lhs_it != end() || rhs_it != other_list->end())
888    return false;
889
890  return true;
891}
892
893ValueSerializer::~ValueSerializer() {
894}
895