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