forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BUG=chromium-os:16557 TEST=dbus_unittests --gtest_filter="ValuesUtilTest.*" Review URL: http://codereview.chromium.org/9702094 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127287 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
hashimoto@chromium.org
committed
Mar 16, 2012
1 parent
275c245
commit a5aae12
Showing
4 changed files
with
534 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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->Set(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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// 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. | ||
|
||
#ifndef DBUS_VALUES_UTIL_H_ | ||
#define DBUS_VALUES_UTIL_H_ | ||
#pragma once | ||
|
||
namespace base { | ||
class Value; | ||
} | ||
|
||
namespace dbus { | ||
|
||
class MessageReader; | ||
|
||
// Pops a value from |reader| as a base::Value. | ||
// Returns NULL if an error occurs. | ||
// Note: Integer values larger than int32 (including uint32) are converted to | ||
// double. Non-string diciontary keys are converted to strings. | ||
base::Value* PopDataAsValue(MessageReader* reader); | ||
|
||
} // namespace dbus | ||
|
||
#endif // DBUS_VALUES_UTIL_H_ |
Oops, something went wrong.