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 38 // treated as bool 39 class ConfigCacheHelper { 40 public: FromConfigCache(ConfigCache & config_cache)41 static ConfigCacheHelper FromConfigCache(ConfigCache& config_cache) { 42 return ConfigCacheHelper(config_cache); 43 } ConfigCacheHelper(ConfigCache & config_cache)44 explicit ConfigCacheHelper(ConfigCache& config_cache) : config_cache_(config_cache) {} 45 virtual ~ConfigCacheHelper() = default; 46 virtual void SetBool(const std::string& section, const std::string& property, bool value); 47 virtual std::optional<bool> GetBool(const std::string& section, 48 const std::string& property) const; 49 virtual void SetUint64(const std::string& section, const std::string& property, uint64_t value); 50 virtual std::optional<uint64_t> GetUint64(const std::string& section, 51 const std::string& property) const; 52 virtual void SetUint32(const std::string& section, const std::string& property, uint32_t value); 53 virtual std::optional<uint32_t> GetUint32(const std::string& section, 54 const std::string& property) const; 55 virtual void SetInt64(const std::string& section, const std::string& property, int64_t value); 56 virtual std::optional<int64_t> GetInt64(const std::string& section, 57 const std::string& property) const; 58 virtual void SetInt(const std::string& section, const std::string& property, int value); 59 virtual std::optional<int> GetInt(const std::string& section, const std::string& property) const; 60 virtual void SetBin(const std::string& section, const std::string& property, 61 const std::vector<uint8_t>& value); 62 virtual std::optional<std::vector<uint8_t>> GetBin(const std::string& section, 63 const std::string& property) const; 64 65 template <typename T, 66 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)67 std::optional<T> Get(const std::string& section, const std::string& property) { 68 auto value = GetInt64(section, property); 69 if (!value) { 70 return std::nullopt; 71 } 72 if (!common::IsNumberInNumericLimits<T>(*value)) { 73 return std::nullopt; 74 } 75 return static_cast<T>(*value); 76 } 77 78 template <typename T, 79 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)80 std::optional<T> Get(const std::string& section, const std::string& property) { 81 auto value = GetUint64(section, property); 82 if (!value) { 83 return std::nullopt; 84 } 85 if (!common::IsNumberInNumericLimits<T>(*value)) { 86 return std::nullopt; 87 } 88 return static_cast<T>(*value); 89 } 90 91 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)92 std::optional<T> Get(const std::string& section, const std::string& property) { 93 return config_cache_.GetProperty(section, property); 94 } 95 96 template <typename T, 97 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)98 std::optional<T> Get(const std::string& section, const std::string& property) { 99 return GetBin(section, property); 100 } 101 102 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)103 std::optional<T> Get(const std::string& section, const std::string& property) { 104 return GetBool(section, property); 105 } 106 107 template <typename T, 108 typename std::enable_if<std::is_base_of_v<Serializable<T>, T>, int>::type = 0> Get(const std::string & section,const std::string & property)109 std::optional<T> Get(const std::string& section, const std::string& property) { 110 auto value = config_cache_.GetProperty(section, property); 111 if (!value) { 112 return std::nullopt; 113 } 114 return T::FromLegacyConfigString(*value); 115 } 116 117 template <typename T, typename std::enable_if<std::is_enum_v<T>, int>::type = 0> Get(const std::string & section,const std::string & property)118 std::optional<T> Get(const std::string& section, const std::string& property) { 119 auto value = config_cache_.GetProperty(section, property); 120 if (!value) { 121 return std::nullopt; 122 } 123 return bluetooth::FromLegacyConfigString<T>(*value); 124 } 125 126 template <typename T, typename std::enable_if< 127 bluetooth::common::is_specialization_of<T, std::vector>::value && 128 std::is_base_of_v<Serializable<typename T::value_type>, 129 typename T::value_type>, 130 int>::type = 0> Get(const std::string & section,const std::string & property)131 std::optional<T> Get(const std::string& section, const std::string& property) { 132 auto value = config_cache_.GetProperty(section, property); 133 if (!value) { 134 return std::nullopt; 135 } 136 auto values = common::StringSplit(*value, " "); 137 T result; 138 result.reserve(values.size()); 139 for (const auto& str : values) { 140 auto v = T::value_type::FromLegacyConfigString(str); 141 if (!v) { 142 return std::nullopt; 143 } 144 result.push_back(*v); 145 } 146 return result; 147 } 148 149 private: 150 ConfigCache& config_cache_; 151 }; 152 153 } // namespace storage 154 } // namespace bluetooth 155