utils.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (C) 2019 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <android-base/macros.h>
  18. #include <android-base/parsedouble.h>
  19. #include <android-base/properties.h>
  20. #include <log/log.h>
  21. #include <fstream>
  22. #include <map>
  23. #include <sstream>
  24. namespace aidl {
  25. namespace android {
  26. namespace hardware {
  27. namespace vibrator {
  28. namespace utils {
  29. template <typename T>
  30. class Is_Iterable {
  31. private:
  32. template <typename U>
  33. static std::true_type test(typename U::iterator *u);
  34. template <typename U>
  35. static std::false_type test(U *u);
  36. public:
  37. static const bool value = decltype(test<T>(0))::value;
  38. };
  39. template <typename T, bool B>
  40. using Enable_If_Iterable = std::enable_if_t<Is_Iterable<T>::value == B>;
  41. template <typename T, typename U = void>
  42. using Enable_If_Signed = std::enable_if_t<std::is_signed_v<T>, U>;
  43. template <typename T, typename U = void>
  44. using Enable_If_Unsigned = std::enable_if_t<std::is_unsigned_v<T>, U>;
  45. // override for default behavior of printing as a character
  46. inline std::ostream &operator<<(std::ostream &stream, const int8_t value) {
  47. return stream << +value;
  48. }
  49. // override for default behavior of printing as a character
  50. inline std::ostream &operator<<(std::ostream &stream, const uint8_t value) {
  51. return stream << +value;
  52. }
  53. template <typename T>
  54. inline auto toUnderlying(const T value) {
  55. return static_cast<std::underlying_type_t<T>>(value);
  56. }
  57. template <typename T>
  58. inline Enable_If_Iterable<T, true> unpack(std::istream &stream, T *value) {
  59. for (auto &entry : *value) {
  60. stream >> entry;
  61. }
  62. }
  63. template <typename T>
  64. inline Enable_If_Iterable<T, false> unpack(std::istream &stream, T *value) {
  65. stream >> *value;
  66. }
  67. template <>
  68. inline void unpack<std::string>(std::istream &stream, std::string *value) {
  69. *value = std::string(std::istreambuf_iterator(stream), {});
  70. stream.setstate(std::istream::eofbit);
  71. }
  72. template <typename T>
  73. inline Enable_If_Signed<T, T> getProperty(const std::string &key, const T def) {
  74. if (std::is_floating_point_v<T>) {
  75. float result;
  76. std::string value = ::android::base::GetProperty(key, "");
  77. if (!value.empty() && ::android::base::ParseFloat(value, &result)) {
  78. return result;
  79. }
  80. return def;
  81. } else {
  82. return ::android::base::GetIntProperty(key, def);
  83. }
  84. }
  85. template <typename T>
  86. inline Enable_If_Unsigned<T, T> getProperty(const std::string &key, const T def) {
  87. return ::android::base::GetUintProperty(key, def);
  88. }
  89. template <>
  90. inline bool getProperty<bool>(const std::string &key, const bool def) {
  91. return ::android::base::GetBoolProperty(key, def);
  92. }
  93. template <typename T>
  94. static void openNoCreate(const std::string &file, T *outStream) {
  95. auto mode = std::is_base_of_v<std::ostream, T> ? std::ios_base::out : std::ios_base::in;
  96. // Force 'in' mode to prevent file creation
  97. outStream->open(file, mode | std::ios_base::in);
  98. if (!*outStream) {
  99. ALOGE("Failed to open %s (%d): %s", file.c_str(), errno, strerror(errno));
  100. }
  101. }
  102. template <typename T>
  103. static void fileFromEnv(const char *env, T *outStream, std::string *outName = nullptr) {
  104. auto file = std::getenv(env);
  105. if (file == nullptr) {
  106. ALOGE("Failed get env %s", env);
  107. return;
  108. }
  109. if (outName != nullptr) {
  110. *outName = std::string(file);
  111. }
  112. openNoCreate(file, outStream);
  113. }
  114. static ATTRIBUTE_UNUSED auto pathsFromEnv(const char *env, const std::string &prefix = "") {
  115. std::map<std::string, std::ifstream> ret;
  116. auto value = std::getenv(env);
  117. if (value == nullptr) {
  118. return ret;
  119. }
  120. std::istringstream paths{value};
  121. std::string path;
  122. while (paths >> path) {
  123. ret[path].open(prefix + path);
  124. }
  125. return ret;
  126. }
  127. static ATTRIBUTE_UNUSED std::string trim(const std::string &str,
  128. const std::string &whitespace = " \t") {
  129. const auto str_begin = str.find_first_not_of(whitespace);
  130. if (str_begin == std::string::npos) {
  131. return "";
  132. }
  133. const auto str_end = str.find_last_not_of(whitespace);
  134. const auto str_range = str_end - str_begin + 1;
  135. return str.substr(str_begin, str_range);
  136. }
  137. } // namespace utils
  138. } // namespace vibrator
  139. } // namespace hardware
  140. } // namespace android
  141. } // namespace aidl