OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "dbus/values_util.h" | |
6 | |
7 #include "base/json/json_writer.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/values.h" | |
11 #include "dbus/message.h" | |
12 | |
13 namespace dbus { | |
14 | |
15 namespace { | |
16 | |
17 // Returns if |value| is exactly representable by double or not. | |
18 template<typename T> | |
19 bool IsExactlyRepresentableByDouble(T value) { | |
20 return value == static_cast<T>(static_cast<double>(value)); | |
21 } | |
22 | |
23 // Pops values from |reader| and appends them to |list_value|. | |
24 bool PopListElements(MessageReader* reader, ListValue* list_value) { | |
25 while (reader->HasMoreData()) { | |
26 Value* element_value = PopDataAsValue(reader); | |
27 if (!element_value) | |
28 return false; | |
29 list_value->Append(element_value); | |
30 } | |
31 return true; | |
32 } | |
33 | |
34 // Pops dict-entries from |reader| and sets them to |dictionary_value| | |
35 bool PopDictionaryEntries(MessageReader* reader, | |
36 DictionaryValue* dictionary_value) { | |
37 while (reader->HasMoreData()) { | |
38 DCHECK(reader->GetDataType() == Message::DICT_ENTRY); | |
satorux1
2012/03/16 16:23:59
DCHECK_EQ
hashimoto
2012/03/16 16:55:26
Done.
| |
39 MessageReader entry_reader(NULL); | |
40 if (!reader->PopDictEntry(&entry_reader)) | |
41 return false; | |
42 // Get key as a string. | |
43 std::string key_string; | |
44 if (entry_reader.GetDataType() == Message::STRING) { | |
45 // If the type of keys is STRING, pop it directly. | |
46 if (!entry_reader.PopString(&key_string)) | |
47 return false; | |
48 } else { | |
49 // If the type of keys is not STRING, convert it to string. | |
satorux1
2012/03/16 16:23:59
Why? I thought DictionaryValue can have non-string
hashimoto
2012/03/16 16:55:26
DictionaryValue's class comment says its keys are
stevenjb
2012/03/16 17:51:59
No, this is correct, DictionaryValue keys are alwa
hashimoto
2012/03/16 18:19:44
Done.
satorux1
2012/03/16 18:28:11
Oh I see. Then it's likely JSON's spec. Please doc
hashimoto
2012/03/16 19:21:44
Done.
| |
50 scoped_ptr<Value> key(PopDataAsValue(&entry_reader)); | |
51 if (!key.get()) | |
52 return false; | |
53 const bool kPrettyPrint = false; | |
54 base::JSONWriter::Write(key.get(), kPrettyPrint, &key_string); | |
55 } | |
56 // Get the value and set the key-value pair. | |
57 Value* value = PopDataAsValue(&entry_reader); | |
58 if (!value) | |
59 return false; | |
60 dictionary_value->Set(key_string, value); | |
61 } | |
62 return true; | |
63 } | |
64 | |
65 } // namespace | |
66 | |
67 Value* PopDataAsValue(MessageReader* reader) { | |
68 Value* result = NULL; | |
69 switch (reader->GetDataType()) { | |
70 case Message::INVALID_DATA: | |
71 // Do nothing. | |
72 break; | |
73 case Message::BYTE: { | |
74 uint8 value = 0; | |
75 if (reader->PopByte(&value)) | |
76 result = Value::CreateIntegerValue(value); | |
77 break; | |
78 } | |
79 case Message::BOOL: { | |
80 bool value = false; | |
81 if (reader->PopBool(&value)) | |
82 result = Value::CreateBooleanValue(value); | |
83 break; | |
84 } | |
85 case Message::INT16: { | |
86 int16 value = 0; | |
87 if (reader->PopInt16(&value)) | |
88 result = Value::CreateIntegerValue(value); | |
89 break; | |
90 } | |
91 case Message::UINT16: { | |
92 uint16 value = 0; | |
93 if (reader->PopUint16(&value)) | |
94 result = Value::CreateIntegerValue(value); | |
95 break; | |
96 } | |
97 case Message::INT32: { | |
98 int32 value = 0; | |
99 if (reader->PopInt32(&value)) | |
100 result = Value::CreateIntegerValue(value); | |
101 break; | |
102 } | |
103 case Message::UINT32: { | |
104 uint32 value = 0; | |
105 if (reader->PopUint32(&value)) | |
106 result = Value::CreateDoubleValue(value); | |
107 break; | |
108 } | |
109 case Message::INT64: { | |
110 int64 value = 0; | |
111 if (reader->PopInt64(&value)) { | |
112 DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value)) << | |
113 "|value| is not exactly representable by double"; | |
114 result = Value::CreateDoubleValue(value); | |
115 } | |
116 break; | |
117 } | |
118 case Message::UINT64: { | |
119 uint64 value = 0; | |
120 if (reader->PopUint64(&value)) { | |
121 DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value)) << | |
122 "|value| is not exactly representable by double"; | |
123 result = Value::CreateDoubleValue(value); | |
124 } | |
125 break; | |
126 } | |
127 case Message::DOUBLE: { | |
128 double value = 0; | |
129 if (reader->PopDouble(&value)) | |
130 result = Value::CreateDoubleValue(value); | |
131 break; | |
132 } | |
133 case Message::STRING: { | |
134 std::string value; | |
135 if (reader->PopString(&value)) | |
136 result = Value::CreateStringValue(value); | |
137 break; | |
138 } | |
139 case Message::OBJECT_PATH: { | |
140 ObjectPath value; | |
141 if (reader->PopObjectPath(&value)) | |
142 result = Value::CreateStringValue(value.value()); | |
143 break; | |
144 } | |
145 case Message::ARRAY: { | |
146 MessageReader sub_reader(NULL); | |
147 if (reader->PopArray(&sub_reader)) { | |
148 // If the type of the array's element is DICT_ENTRY, create a | |
149 // DictionaryValue, otherwise create a ListValue. | |
150 if (sub_reader.GetDataType() == Message::DICT_ENTRY) { | |
151 scoped_ptr<DictionaryValue> dictionary_value(new DictionaryValue); | |
152 if (PopDictionaryEntries(&sub_reader, dictionary_value.get())) | |
153 result = dictionary_value.release(); | |
154 } else { | |
155 scoped_ptr<ListValue> list_value(new ListValue); | |
156 if (PopListElements(&sub_reader, list_value.get())) | |
157 result = list_value.release(); | |
158 } | |
159 } | |
160 break; | |
161 } | |
162 case Message::STRUCT: { | |
163 MessageReader sub_reader(NULL); | |
164 if (reader->PopStruct(&sub_reader)) { | |
165 scoped_ptr<ListValue> list_value(new ListValue); | |
166 if (PopListElements(&sub_reader, list_value.get())) | |
167 result = list_value.release(); | |
168 } | |
169 break; | |
170 } | |
171 case Message::DICT_ENTRY: | |
172 // DICT_ENTRY must be popped as an element of an array. | |
173 NOTREACHED(); | |
174 break; | |
175 case Message::VARIANT: { | |
176 MessageReader sub_reader(NULL); | |
177 if (reader->PopVariant(&sub_reader)) | |
178 result = PopDataAsValue(&sub_reader); | |
179 break; | |
180 } | |
181 } | |
182 return result; | |
183 } | |
184 | |
185 } // namespace dbus | |
OLD | NEW |