blob: ec23edb70abfbbb4acb3201cff14d8be6b3d1cb2 [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#pragma once
#include <optional>
#include <string>
#include <unordered_map>
#include <system/audio_config.h>
#include <utils/Errors.h>
namespace aidl::android::hardware::audio::core::internal {
template <typename T>
class XmlConverter {
public:
XmlConverter(const std::string& configFilePath,
std::function<std::optional<T>(const char*)> readXmlConfig)
: XmlConverter(configFilePath,
::android::audio_is_readable_configuration_file(configFilePath.c_str()),
readXmlConfig) {}
const ::android::status_t& getStatus() const { return mStatus; }
const std::string& getError() const { return mErrorMessage; }
const std::optional<T>& getXsdcConfig() const { return mXsdcConfig; }
private:
XmlConverter(const std::string& configFilePath, const bool& isReadableConfigFile,
const std::function<std::optional<T>(const char*)>& readXmlConfig)
: mXsdcConfig{isReadableConfigFile ? readXmlConfig(configFilePath.c_str()) : std::nullopt},
mStatus(mXsdcConfig ? ::android::OK : ::android::NO_INIT),
mErrorMessage(generateError(configFilePath, isReadableConfigFile, mStatus)) {}
static std::string generateError(const std::string& configFilePath,
const bool& isReadableConfigFile,
const ::android::status_t& status) {
std::string errorMessage;
if (status != ::android::OK) {
if (!isReadableConfigFile) {
errorMessage = "Could not read requested config file:" + configFilePath;
} else {
errorMessage = "Invalid config file: " + configFilePath;
}
}
return errorMessage;
}
const std::optional<T> mXsdcConfig;
const ::android::status_t mStatus;
const std::string mErrorMessage;
};
/**
* Converts a vector of an xsd wrapper type to a flat vector of the
* corresponding AIDL type.
*
* Wrapper types are used in order to have well-formed xIncludes. In the
* example below, Modules is the wrapper type for Module.
* <Modules>
* <Module> ... </Module>
* <Module> ... </Module>
* </Modules>
*/
template <typename W, typename X, typename A>
static std::vector<A> convertWrappedCollectionToAidl(
const std::vector<W>& xsdcWrapperTypeVec,
std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
std::function<A(const X&)> convertToAidl) {
std::vector<A> resultAidlTypeVec;
if (!xsdcWrapperTypeVec.empty()) {
/*
* xsdcWrapperTypeVec likely only contains one element; that is, it's
* likely that all the inner types that we need to convert are inside of
* xsdcWrapperTypeVec[0].
*/
resultAidlTypeVec.reserve(getInnerTypeVec(xsdcWrapperTypeVec[0]).size());
for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
std::transform(getInnerTypeVec(xsdcWrapperType).begin(),
getInnerTypeVec(xsdcWrapperType).end(),
std::back_inserter(resultAidlTypeVec), convertToAidl);
}
}
return resultAidlTypeVec;
}
template <typename X, typename A>
static std::vector<A> convertCollectionToAidl(const std::vector<X>& xsdcTypeVec,
std::function<A(const X&)> convertToAidl) {
std::vector<A> resultAidlTypeVec;
resultAidlTypeVec.reserve(xsdcTypeVec.size());
std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
convertToAidl);
return resultAidlTypeVec;
}
/**
* Generates a map of xsd references, keyed by reference name, given a
* vector of wrapper types for the reference.
*
* Wrapper types are used in order to have well-formed xIncludes. In the
* example below, Wrapper is the wrapper type for Reference.
* <Wrapper>
* <Reference> ... </Reference>
* <Reference> ... </Reference>
* </Wrapper>
*/
template <typename W, typename R>
static std::unordered_map<std::string, R> generateReferenceMap(
const std::vector<W>& xsdcWrapperTypeVec) {
std::unordered_map<std::string, R> resultMap;
if (!xsdcWrapperTypeVec.empty()) {
/*
* xsdcWrapperTypeVec likely only contains one element; that is, it's
* likely that all the inner types that we need to convert are inside of
* xsdcWrapperTypeVec[0].
*/
resultMap.reserve(xsdcWrapperTypeVec[0].getReference().size());
for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
for (const R& xsdcReference : xsdcWrapperType.getReference()) {
resultMap.insert({xsdcReference.getName(), xsdcReference});
}
}
}
return resultMap;
}
} // namespace aidl::android::hardware::audio::core::internal