blob: 1b53f744016fdb14be407d562d1a9f40fbdb2dc3 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_KEY_VALUE_STORE_H_
#define SHILL_KEY_VALUE_STORE_H_
#include <map>
#include <string>
#include <vector>
#include <brillo/type_list.h>
#include <brillo/type_name_undecorate.h>
#include <brillo/variant_dictionary.h>
#include "shill/data_types.h"
namespace shill {
class KeyValueStore;
using KeyValueTypes = brillo::TypeList<bool,
uint8_t,
uint16_t,
uint32_t,
int16_t,
int32_t,
int64_t,
double,
std::vector<bool>,
std::vector<uint8_t>,
std::vector<std::vector<uint8_t>>,
std::vector<uint32_t>,
std::vector<int32_t>,
std::vector<int64_t>,
std::vector<double>,
KeyValueStore,
std::string,
Stringmap,
Strings,
RpcIdentifier,
RpcIdentifiers>;
class KeyValueStore {
// A simple store for key-value pairs, which supports (a limited set of)
// heterogeneous value types, as defined in the KeyValueTypes typelist above.
//
// Compare to PropertyStore, which enables a class to (selectively)
// expose its instance members as properties accessible via
// RPC. (RPC support for ProperyStore is implemented in a
// protocol-specific adaptor. e.g. dbus_adpator.)
//
// Implemented separately from PropertyStore, to avoid complicating
// the PropertyStore interface. In particular, objects implementing the
// PropertyStore interface always provide the storage themselves. In
// contrast, users of KeyValueStore expect KeyValueStore to provide
// storage.
public:
KeyValueStore();
// Required for equality comparison when KeyValueStore is wrapped inside a
// brillo::Any object.
bool operator==(const KeyValueStore& rhs) const;
bool operator!=(const KeyValueStore& rhs) const;
const brillo::VariantDictionary& properties() const { return properties_; }
void Clear();
void CopyFrom(const KeyValueStore& b);
bool IsEmpty();
void Remove(const std::string& name);
bool ContainsVariant(const std::string& name) const;
const brillo::Any& GetVariant(const std::string& name) const;
void SetVariant(const std::string& name, const brillo::Any& value);
template <typename T, typename = brillo::EnableIfIsOneOf<T, KeyValueTypes>>
bool Contains(const std::string& name) const {
return ContainsVariant(name) &&
properties_.find(name)->second.IsTypeCompatible<T>();
}
template <typename T,
typename brillo::EnableIfIsOneOfArithmetic<T, KeyValueTypes> = 0>
T Get(const std::string& name) const {
const auto& value = GetVariant(name);
CHECK(value.IsTypeCompatible<T>())
<< "for " << brillo::GetTypeTag<T>() << " property " << name;
return value.Get<T>();
}
template <typename T,
typename brillo::EnableIfIsOneOfNonArithmetic<T, KeyValueTypes> = 0>
const T& Get(const std::string& name) const {
const auto& value = GetVariant(name);
CHECK(value.IsTypeCompatible<T>())
<< "for " << brillo::GetTypeTag<T>() << " property " << name;
return value.Get<T>();
}
template <typename T,
typename brillo::EnableIfIsOneOfArithmetic<T, KeyValueTypes> = 0>
void Set(const std::string& name, T value) {
SetVariant(name, brillo::Any(value));
}
template <typename T,
typename brillo::EnableIfIsOneOfNonArithmetic<T, KeyValueTypes> = 0>
void Set(const std::string& name, const T& value) {
SetVariant(name, brillo::Any(value));
}
// If |name| is in this store returns its value, otherwise returns
// |default_value|.
template <typename T,
typename brillo::EnableIfIsOneOfArithmetic<T, KeyValueTypes> = 0>
T Lookup(const std::string& name, T default_value) const {
const auto it(properties_.find(name));
if (it == properties_.end()) {
return default_value;
}
CHECK(it->second.IsTypeCompatible<T>())
<< "for " << brillo::GetTypeTag<T>() << " property " << name;
return it->second.Get<T>();
}
template <typename T,
typename brillo::EnableIfIsOneOfNonArithmetic<T, KeyValueTypes> = 0>
const T& Lookup(const std::string& name, const T& default_value) const {
const auto it(properties_.find(name));
if (it == properties_.end()) {
return default_value;
}
CHECK(it->second.IsTypeCompatible<T>())
<< "for " << brillo::GetTypeTag<T>() << " property " << name;
return it->second.Get<T>();
}
// Conversion function between KeyValueStore and brillo::VariantDictionary.
// Since we already use brillo::VariantDictionary for storing key value
// pairs, all conversions will be trivial except nested KeyValueStore and
// nested brillo::VariantDictionary.
static brillo::VariantDictionary ConvertToVariantDictionary(
const KeyValueStore& in_store);
static KeyValueStore ConvertFromVariantDictionary(
const brillo::VariantDictionary& in_dict);
private:
brillo::VariantDictionary properties_;
};
} // namespace shill
#endif // SHILL_KEY_VALUE_STORE_H_