/* * 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 #include #include #include #include namespace aidl::android::hardware::audio::core::internal { template class XmlConverter { public: XmlConverter(const std::string& configFilePath, std::function(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& getXsdcConfig() const { return mXsdcConfig; } private: XmlConverter(const std::string& configFilePath, const bool& isReadableConfigFile, const std::function(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 (configFilePath.empty()) { errorMessage = "No audio configuration files found"; } else if (!isReadableConfigFile) { errorMessage = std::string("Could not read requested XML config file: \"") .append(configFilePath) .append("\""); } else { errorMessage = std::string("Invalid XML config file: \"") .append(configFilePath) .append("\""); } } return errorMessage; } const std::optional 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. * * ... * ... * */ template static ConversionResult> convertWrappedCollectionToAidl( const std::vector& xsdcWrapperTypeVec, std::function&(const W&)> getInnerTypeVec, std::function(const X&)> convertToAidl) { std::vector 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) { for (const X& xsdcType : getInnerTypeVec(xsdcWrapperType)) { resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType))); } } } return resultAidlTypeVec; } template static ConversionResult> convertCollectionToAidl( const std::vector& xsdcTypeVec, std::function(const X&)> convertToAidl) { std::vector resultAidlTypeVec; resultAidlTypeVec.reserve(xsdcTypeVec.size()); for (const X& xsdcType : xsdcTypeVec) { resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType))); } 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. * * ... * ... * */ template std::unordered_map generateReferenceMap(const std::vector& xsdcWrapperTypeVec) { std::unordered_map 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