//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "proxy_util.h"
namespace {
template<typename VectorType> void GetXmlRpcArrayFromVector(
const VectorType& vector_in,
XmlRpc::XmlRpcValue* xml_rpc_value_out) {
if (vector_in.empty()) {
xml_rpc_value_out->setToNil();
return;
}
int i = 0;
for (const auto& value : vector_in) {
(*xml_rpc_value_out)[++i] = value;
}
}
void GetXmlRpcStructFromStringMap(
const std::map<std::string, std::string>& string_map_in,
XmlRpc::XmlRpcValue* xml_rpc_value_out) {
if (string_map_in.empty()) {
xml_rpc_value_out->setToNil();
return;
}
for (const auto& value : string_map_in) {
(*xml_rpc_value_out)[value.first] = value.second;
}
}
void GetXmlRpcStructFromBrilloVariantDictionary(
const brillo::VariantDictionary& var_dict_in,
XmlRpc::XmlRpcValue* xml_rpc_value_out) {
if (var_dict_in.empty()) {
xml_rpc_value_out->setToNil();
return;
}
for (const auto& value : var_dict_in) {
XmlRpc::XmlRpcValue tmp_value;
GetXmlRpcValueFromBrilloAnyValue(value.second, &tmp_value);
(*xml_rpc_value_out)[value.first] = tmp_value;
}
}
template<typename ElementType> void GetVectorFromXmlRpcArray(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
std::vector<ElementType>* vector_out) {
int array_size = xml_rpc_value_in->size();
for (int i = 0; i < array_size; ++i) {
vector_out->push_back(static_cast<ElementType>((*xml_rpc_value_in)[i]));
}
}
void GetBrilloAnyVectorFromXmlRpcArray(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
brillo::Any* any_value_out) {
int array_size = xml_rpc_value_in->size();
if (!array_size) {
any_value_out->Clear();
return;
}
XmlRpc::XmlRpcValue::Type elem_type = (*xml_rpc_value_in)[0].getType();
for (int i = 0; i < array_size; ++i) {
CHECK((*xml_rpc_value_in)[i].getType() == elem_type);
}
switch (elem_type) {
case XmlRpc::XmlRpcValue::TypeBoolean: {
std::vector<bool> bool_vec;
GetVectorFromXmlRpcArray(xml_rpc_value_in, &bool_vec);
*any_value_out = bool_vec;
return;
}
case XmlRpc::XmlRpcValue::TypeInt: {
std::vector<int> int_vec;
GetVectorFromXmlRpcArray(xml_rpc_value_in, &int_vec);
*any_value_out = int_vec;
return;
}
case XmlRpc::XmlRpcValue::TypeDouble: {
std::vector<double> double_vec;
GetVectorFromXmlRpcArray(xml_rpc_value_in, &double_vec);
*any_value_out = double_vec;
return;
}
case XmlRpc::XmlRpcValue::TypeString: {
std::vector<std::string> string_vec;
GetVectorFromXmlRpcArray(xml_rpc_value_in, &string_vec);
*any_value_out = string_vec;
return;
}
default:
LOG(FATAL) << __func__ << ". Unhandled type: "
<< (*xml_rpc_value_in)[0].getType();
}
}
template<typename ValueType> XmlRpc::XmlRpcValue::Type GetXmlRpcType();
template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<bool>() {
return XmlRpc::XmlRpcValue::TypeBoolean;
}
template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<int>() {
return XmlRpc::XmlRpcValue::TypeInt;
}
template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<double>() {
return XmlRpc::XmlRpcValue::TypeDouble;
}
template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<std::string>() {
return XmlRpc::XmlRpcValue::TypeString;
}
template<typename ValueType> bool IsMemberValuePresent(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name) {
if (xml_rpc_value_in->hasMember(member_name) &&
((*xml_rpc_value_in)[member_name].getType() ==
GetXmlRpcType<ValueType>())) {
return true;
}
return false;
}
template<typename ValueType> bool GetValueFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
ValueType default_value,
ValueType* value_out) {
if (!IsMemberValuePresent<ValueType>(xml_rpc_value_in, member_name)) {
*value_out = default_value;
return false;
}
*value_out = ValueType((*xml_rpc_value_in)[member_name]);
return true;
}
template<typename ElementType> bool IsMemberVectorPresent(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name) {
if (xml_rpc_value_in->hasMember(member_name) &&
((*xml_rpc_value_in)[member_name].getType() ==
XmlRpc::XmlRpcValue::TypeArray) &&
((*xml_rpc_value_in)[member_name][0].getType() ==
GetXmlRpcType<ElementType>())) {
return true;
}
return false;
}
template<typename ElementType> bool GetVectorFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
std::vector<ElementType> default_value,
std::vector<ElementType>* value_out) {
if (!IsMemberVectorPresent<ElementType>(xml_rpc_value_in, member_name)) {
*value_out = default_value;
return false;
}
XmlRpc::XmlRpcValue& xml_rpc_member_array = (*xml_rpc_value_in)[member_name];
int array_size = xml_rpc_member_array.size();
for (int array_pos = 0; array_pos < array_size; ++array_pos) {
value_out->push_back(ElementType(xml_rpc_member_array[array_pos]));
}
return true;
}
} // namespace
void GetXmlRpcValueFromBrilloAnyValue(
const brillo::Any& any_value_in,
XmlRpc::XmlRpcValue* xml_rpc_value_out) {
if (any_value_in.IsTypeCompatible<bool>()) {
*xml_rpc_value_out = any_value_in.Get<bool>();
return;
}
if (any_value_in.IsTypeCompatible<uint8_t>()) {
*xml_rpc_value_out = any_value_in.Get<uint8_t>();
return;
}
if (any_value_in.IsTypeCompatible<uint16_t>()) {
*xml_rpc_value_out = any_value_in.Get<uint16_t>();
return;
}
if (any_value_in.IsTypeCompatible<int>()) {
*xml_rpc_value_out = any_value_in.Get<int>();
return;
}
if (any_value_in.IsTypeCompatible<double>()) {
*xml_rpc_value_out = any_value_in.Get<double>();
return;
}
if (any_value_in.IsTypeCompatible<std::string>()) {
*xml_rpc_value_out = any_value_in.Get<std::string>();
return;
}
if (any_value_in.IsTypeCompatible<dbus::ObjectPath>()) {
*xml_rpc_value_out = any_value_in.Get<dbus::ObjectPath>().value();
return;
}
if (any_value_in.IsTypeCompatible<std::vector<bool>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<bool>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<uint8_t>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<uint8_t>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<uint16_t>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<uint16_t>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<int>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<int>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<double>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<double>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<std::string>>()) {
GetXmlRpcArrayFromVector(
any_value_in.Get<std::vector<std::string>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::vector<dbus::ObjectPath>>()) {
std::vector<std::string> string_vec;
for (const auto& object : any_value_in.Get<std::vector<dbus::ObjectPath>>()) {
string_vec.push_back(object.value());
}
GetXmlRpcArrayFromVector(string_vec, xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<std::map<std::string, std::string>>()) {
GetXmlRpcStructFromStringMap(
any_value_in.Get<std::map<std::string, std::string>>(), xml_rpc_value_out);
return;
}
if (any_value_in.IsTypeCompatible<brillo::VariantDictionary>()) {
GetXmlRpcStructFromBrilloVariantDictionary(
any_value_in.Get<brillo::VariantDictionary>(), xml_rpc_value_out);
return;
}
LOG(FATAL) << __func__ << ". Unhandled type: "
<< any_value_in.GetUndecoratedTypeName();
}
void GetBrilloAnyValueFromXmlRpcValue(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
brillo::Any* any_value_out) {
switch (xml_rpc_value_in->getType()) {
case XmlRpc::XmlRpcValue::TypeBoolean:
*any_value_out = static_cast<bool>(*xml_rpc_value_in);
return;
case XmlRpc::XmlRpcValue::TypeInt:
*any_value_out = static_cast<int>(*xml_rpc_value_in);
return;
case XmlRpc::XmlRpcValue::TypeDouble:
*any_value_out = static_cast<double>(*xml_rpc_value_in);
return;
case XmlRpc::XmlRpcValue::TypeString:
*any_value_out = static_cast<std::string>(*xml_rpc_value_in);
return;
case XmlRpc::XmlRpcValue::TypeArray:
GetBrilloAnyVectorFromXmlRpcArray(xml_rpc_value_in, any_value_out);
return;
default:
LOG(FATAL) << __func__ << ". Unhandled type: "
<< xml_rpc_value_in->getType();
}
}
bool GetBoolValueFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
bool default_value,
bool* value_out) {
return GetValueFromXmlRpcValueStructMember(
xml_rpc_value_in, member_name, default_value, value_out);
}
bool GetIntValueFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
int default_value,
int* value_out) {
return GetValueFromXmlRpcValueStructMember(
xml_rpc_value_in, member_name, default_value, value_out);
}
bool GetDoubleValueFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
double default_value,
double* value_out){
return GetValueFromXmlRpcValueStructMember(
xml_rpc_value_in, member_name, default_value, value_out);
}
bool GetStringValueFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
const std::string& default_value,
std::string* value_out) {
return GetValueFromXmlRpcValueStructMember(
xml_rpc_value_in, member_name, default_value, value_out);
}
bool GetStringVectorFromXmlRpcValueStructMember(
XmlRpc::XmlRpcValue* xml_rpc_value_in,
const std::string& member_name,
const std::vector<std::string>& default_value,
std::vector<std::string>* value_out) {
return GetVectorFromXmlRpcValueStructMember(
xml_rpc_value_in, member_name, default_value, value_out);
}