1 /* 2 * Copyright 2020 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 18 #include <cstdint> 19 #include <limits> 20 #include <optional> 21 #include <type_traits> 22 23 #include "common/numbers.h" 24 #include "common/strings.h" 25 #include "common/type_helper.h" 26 #include "hci/enum_helper.h" 27 #include "storage/config_cache.h" 28 #include "storage/mutation_entry.h" 29 #include "storage/serializable.h" 30 31 namespace bluetooth { 32 namespace storage { 33 34 // A thin wrapper around ConfigCache and implement more type supports other than std::string 35 // 36 // - all SetX methods accept value as copy and std::move() in encouraged 37 // - all GetX methods return std::optional<X> and std::nullopt if not exist. std::optional<> can be treated as bool 38 class ConfigCacheHelper { 39 public: FromConfigCache(ConfigCache & config_cache)40 static ConfigCacheHelper FromConfigCache(ConfigCache& config_cache) { 41 return ConfigCacheHelper(config_cache); 42 } ConfigCacheHelper(ConfigCache & config_cache)43 explicit ConfigCacheHelper(ConfigCache& config_cache) : config_cache_(config_cache) {} 44 virtual ~ConfigCacheHelper() = default; 45 virtual void SetBool(const std::string& section, const std::string& property, bool value); 46 virtual std::optional<bool> GetBool(const std::string& section, const std::string& property) const; 47 virtual void SetUint64(const std::string& section, const std::string& property, uint64_t value); 48 virtual std::optional<uint64_t> GetUint64(const std::string& section, const std::string& property) const; 49 virtual void SetUint32(const std::string& section, const std::string& property, uint32_t value); 50 virtual std::optional<uint32_t> GetUint32(const std::string& section, const std::string& property) const; 51 virtual void SetInt64(const std::string& section, const std::string& property, int64_t value); 52 virtual std::optional<int64_t> GetInt64(const std::string& section, const std::string& property) const; 53 virtual void SetInt(const std::string& section, const std::string& property, int value); 54 virtual std::optional<int> GetInt(const std::string& section, const std::string& property) const; 55 virtual void SetBin(const std::string& section, const std::string& property, const std::vector<uint8_t>& value); 56 virtual std::optional<std::vector<uint8_t>> GetBin(const std::string& section, const std::string& property) const; 57 58 template <typename T, typename std::enable_if<std::is_signed_v<T> && std::is_integral_v<T>, int>::type = 0> Get(const std::string & section,const std::string & property)59 std::optional<T> Get(const std::string& section, const std::string& property) { 60 auto value = GetInt64(section, property); 61 if (!value) { 62 return std::nullopt; 63 } 64 if (!common::IsNumberInNumericLimits<T>(*value)) { 65 return std::nullopt; 66 } 67 return static_cast<T>(*value); 68 } 69 70 template <typename T, typename std::enable_if<std::is_unsigned_v<T> && std::is_integral_v<T>, int>::type = 0> Get(const std::string & section,const std::string & property)71 std::optional<T> Get(const std::string& section, const std::string& property) { 72 auto value = GetUint64(section, property); 73 if (!value) { 74 return std::nullopt; 75 } 76 if (!common::IsNumberInNumericLimits<T>(*value)) { 77 return std::nullopt; 78 } 79 return static_cast<T>(*value); 80 } 81 82 template <typename T, typename std::enable_if<std::is_same_v<T, std::string>, int>::type = 0> Get(const std::string & section,const std::string & property)83 std::optional<T> Get(const std::string& section, const std::string& property) { 84 return config_cache_.GetProperty(section, property); 85 } 86 87 template <typename T, typename std::enable_if<std::is_same_v<T, std::vector<uint8_t>>, int>::type = 0> Get(const std::string & section,const std::string & property)88 std::optional<T> Get(const std::string& section, const std::string& property) { 89 return GetBin(section, property); 90 } 91 92 template <typename T, typename std::enable_if<std::is_same_v<T, bool>, int>::type = 0> Get(const std::string & section,const std::string & property)93 std::optional<T> Get(const std::string& section, const std::string& property) { 94 return GetBool(section, property); 95 } 96 97 template <typename T, typename std::enable_if<std::is_base_of_v<Serializable<T>, T>, int>::type = 0> Get(const std::string & section,const std::string & property)98 std::optional<T> Get(const std::string& section, const std::string& property) { 99 auto value = config_cache_.GetProperty(section, property); 100 if (!value) { 101 return std::nullopt; 102 } 103 return T::FromLegacyConfigString(*value); 104 } 105 106 template <typename T, typename std::enable_if<std::is_enum_v<T>, int>::type = 0> Get(const std::string & section,const std::string & property)107 std::optional<T> Get(const std::string& section, const std::string& property) { 108 auto value = config_cache_.GetProperty(section, property); 109 if (!value) { 110 return std::nullopt; 111 } 112 return bluetooth::FromLegacyConfigString<T>(*value); 113 } 114 115 template < 116 typename T, 117 typename std::enable_if< 118 bluetooth::common::is_specialization_of<T, std::vector>::value && 119 std::is_base_of_v<Serializable<typename T::value_type>, typename T::value_type>, 120 int>::type = 0> Get(const std::string & section,const std::string & property)121 std::optional<T> Get(const std::string& section, const std::string& property) { 122 auto value = config_cache_.GetProperty(section, property); 123 if (!value) { 124 return std::nullopt; 125 } 126 auto values = common::StringSplit(*value, " "); 127 T result; 128 result.reserve(values.size()); 129 for (const auto& str : values) { 130 auto v = T::value_type::FromLegacyConfigString(str); 131 if (!v) { 132 return std::nullopt; 133 } 134 result.push_back(*v); 135 } 136 return result; 137 } 138 139 private: 140 ConfigCache& config_cache_; 141 }; 142 143 } // namespace storage 144 } // namespace bluetooth 145