/* * Copyright (C) 2019 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 #include #include namespace aidl { namespace android { namespace hardware { namespace vibrator { namespace utils { template class Is_Iterable { private: template static std::true_type test(typename U::iterator *u); template static std::false_type test(U *u); public: static const bool value = decltype(test(0))::value; }; template using Enable_If_Iterable = std::enable_if_t::value == B>; template using Enable_If_Signed = std::enable_if_t, U>; template using Enable_If_Unsigned = std::enable_if_t, U>; // override for default behavior of printing as a character inline std::ostream &operator<<(std::ostream &stream, const int8_t value) { return stream << +value; } // override for default behavior of printing as a character inline std::ostream &operator<<(std::ostream &stream, const uint8_t value) { return stream << +value; } template inline auto toUnderlying(const T value) { return static_cast>(value); } template inline Enable_If_Iterable unpack(std::istream &stream, T *value) { for (auto &entry : *value) { stream >> entry; } } template inline Enable_If_Iterable unpack(std::istream &stream, T *value) { stream >> *value; } template <> inline void unpack(std::istream &stream, std::string *value) { *value = std::string(std::istreambuf_iterator(stream), {}); stream.setstate(std::istream::eofbit); } template inline Enable_If_Signed getProperty(const std::string &key, const T def) { if (std::is_floating_point_v) { float result; std::string value = ::android::base::GetProperty(key, ""); if (!value.empty() && ::android::base::ParseFloat(value, &result)) { return result; } return def; } else { return ::android::base::GetIntProperty(key, def); } } template inline Enable_If_Unsigned getProperty(const std::string &key, const T def) { return ::android::base::GetUintProperty(key, def); } template <> inline bool getProperty(const std::string &key, const bool def) { return ::android::base::GetBoolProperty(key, def); } template static void openNoCreate(const std::string &file, T *outStream) { auto mode = std::is_base_of_v ? std::ios_base::out : std::ios_base::in; // Force 'in' mode to prevent file creation outStream->open(file, mode | std::ios_base::in); if (!*outStream) { ALOGE("Failed to open %s (%d): %s", file.c_str(), errno, strerror(errno)); } } template static void fileFromEnv(const char *env, T *outStream, std::string *outName = nullptr) { auto file = std::getenv(env); if (file == nullptr) { ALOGE("Failed get env %s", env); return; } if (outName != nullptr) { *outName = std::string(file); } openNoCreate(file, outStream); } static ATTRIBUTE_UNUSED auto pathsFromEnv(const char *env, const std::string &prefix = "") { std::map ret; auto value = std::getenv(env); if (value == nullptr) { return ret; } std::istringstream paths{value}; std::string path; while (paths >> path) { ret[path].open(prefix + path); } return ret; } static ATTRIBUTE_UNUSED std::string trim(const std::string &str, const std::string &whitespace = " \t") { const auto str_begin = str.find_first_not_of(whitespace); if (str_begin == std::string::npos) { return ""; } const auto str_end = str.find_last_not_of(whitespace); const auto str_range = str_end - str_begin + 1; return str.substr(str_begin, str_range); } } // namespace utils } // namespace vibrator } // namespace hardware } // namespace android } // namespace aidl