普通文本  |  332行  |  10.76 KB

//
// 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);
}