roo_prefs
API Documentation for roo_prefs
Loading...
Searching...
No Matches
pref.h
Go to the documentation of this file.
1#pragma once
2
3#include <inttypes.h>
4
5#include <string>
6
8#include "roo_prefs/status.h"
10
11namespace roo_prefs {
12
13/// Persistent preference of a specific type.
14/// The preference will store its value in the preferences collection provided
15/// in the constructor, under the specified key (which needs to remain
16/// constant). The value is read lazily (on first access.) You can provide
17/// default value to be used if the collection does not contain the specified
18/// key. The value is cached in memory - subsequent reads will return the cached
19/// value. Writes always write to the persistent storage (and also, update the
20/// cache.) Read and write are performed within implicitly created
21/// transactions. If you have multiple properties that you want to read/write at
22/// the same time, you can read them under an explicit transaction:
23///
24/// roo_prefs::Collection col("foo");
25/// roo_prefs::Int16 pref1(col, "pref1");
26/// roo_prefs::String pref2(col, "pref2");
27/// int16_t a;
28/// std::string b;
29/// {
30/// Transaction t(col);
31/// a = pref1.get();
32/// b = pref2.get();
33/// }
34///
35/// For simple types, use aliases defined later in the file (Uint8, String,
36/// etc.)
37///
38/// You can persist arbitrary types (e.g. struct types). Types other than simple
39/// types and std::string are persisted as BLOBs, containing the binary
40/// representation of the object.
41///
42/// NOTE:
43/// * Preferences library is generally intended for storing small values.
44/// * If the definition (and thus the internal representation) of your complex
45/// type changes, any persisted values of that type will become unreadable or
46/// corrupted.
47/// For these reasons, it is generally not a good practice to persist large
48/// objects using this template.
49///
50template <typename T>
51class Pref {
52 public:
53 Pref(Collection& collection, const char* key, T default_value = T());
54
55 bool isSet() const;
56
57 const T& get() const;
58
59 bool set(const T& value);
60
61 bool clear();
62
63 private:
64 enum class PrefState { kUnknown, kUnset, kSet, kError };
65
66 void sync() const;
67
68 Collection& collection_;
69 const char* key_;
70 T default_value_;
71 mutable PrefState state_;
72 mutable T value_;
73};
74
86
88
89/// Implementation details follow.
90
91namespace internal {
92
93inline ClearResult StoreClear(Store& store, const char* key) {
94 return store.clear(key);
95}
96
97template <typename T>
98inline WriteResult StoreWrite(Store& store, const char* key, const T& val) {
99 return store.writeObject(key, val);
100}
101
102template <>
103inline WriteResult StoreWrite<bool>(Store& store, const char* key,
104 const bool& val) {
105 return store.writeBool(key, val);
106}
107
108template <>
109inline WriteResult StoreWrite<uint8_t>(Store& store, const char* key,
110 const uint8_t& val) {
111 return store.writeU8(key, val);
112}
113
114template <>
115inline WriteResult StoreWrite<int8_t>(Store& store, const char* key,
116 const int8_t& val) {
117 return store.writeI8(key, val);
118}
119
120template <>
121inline WriteResult StoreWrite<uint16_t>(Store& store, const char* key,
122 const uint16_t& val) {
123 return store.writeU16(key, val);
124}
125
126template <>
127inline WriteResult StoreWrite<int16_t>(Store& store, const char* key,
128 const int16_t& val) {
129 return store.writeI16(key, val);
130}
131
132template <>
133inline WriteResult StoreWrite<uint32_t>(Store& store, const char* key,
134 const uint32_t& val) {
135 return store.writeU32(key, val);
136}
137
138template <>
139inline WriteResult StoreWrite<int32_t>(Store& store, const char* key,
140 const int32_t& val) {
141 return store.writeI32(key, val);
142}
143
144template <>
145inline WriteResult StoreWrite<uint64_t>(Store& store, const char* key,
146 const uint64_t& val) {
147 return store.writeU64(key, val);
148}
149
150template <>
151inline WriteResult StoreWrite<int64_t>(Store& store, const char* key,
152 const int64_t& val) {
153 return store.writeI64(key, val);
154}
155
156template <>
157inline WriteResult StoreWrite<float>(Store& store, const char* key,
158 const float& val) {
159 return store.writeFloat(key, val);
160}
161
162template <>
163inline WriteResult StoreWrite<double>(Store& store, const char* key,
164 const double& val) {
165 return store.writeDouble(key, val);
166}
167
168template <>
169inline WriteResult StoreWrite<roo::string_view>(Store& store, const char* key,
170 const roo::string_view& val) {
171 return store.writeString(key, val);
172}
173
174template <>
175inline WriteResult StoreWrite<std::string>(Store& store, const char* key,
176 const std::string& val) {
177 return store.writeString(key, val);
178}
179
180template <typename T>
181inline ReadResult StoreRead(Store& store, const char* key, T& val) {
182 return store.readObject(key, val);
183}
184
185template <>
186inline ReadResult StoreRead<bool>(Store& store, const char* key, bool& val) {
187 return store.readBool(key, val);
188}
189
190template <>
191inline ReadResult StoreRead<uint8_t>(Store& store, const char* key,
192 uint8_t& val) {
193 return store.readU8(key, val);
194}
195
196template <>
197inline ReadResult StoreRead<int8_t>(Store& store, const char* key,
198 int8_t& val) {
199 return store.readI8(key, val);
200}
201
202template <>
203inline ReadResult StoreRead<uint16_t>(Store& store, const char* key,
204 uint16_t& val) {
205 return store.readU16(key, val);
206}
207
208template <>
209inline ReadResult StoreRead<int16_t>(Store& store, const char* key,
210 int16_t& val) {
211 return store.readI16(key, val);
212}
213
214template <>
215inline ReadResult StoreRead<uint32_t>(Store& store, const char* key,
216 uint32_t& val) {
217 return store.readU32(key, val);
218}
219
220template <>
221inline ReadResult StoreRead<int32_t>(Store& store, const char* key,
222 int32_t& val) {
223 return store.readI32(key, val);
224}
225
226template <>
227inline ReadResult StoreRead<uint64_t>(Store& store, const char* key,
228 uint64_t& val) {
229 return store.readU64(key, val);
230}
231
232template <>
233inline ReadResult StoreRead<int64_t>(Store& store, const char* key,
234 int64_t& val) {
235 return store.readI64(key, val);
236}
237
238template <>
239inline ReadResult StoreRead<float>(Store& store, const char* key, float& val) {
240 return store.readFloat(key, val);
241}
242
243template <>
244inline ReadResult StoreRead<double>(Store& store, const char* key,
245 double& val) {
246 return store.readDouble(key, val);
247}
248
249template <>
250inline ReadResult StoreRead<std::string>(Store& store, const char* key,
251 std::string& val) {
252 return store.readString(key, val);
253}
254
255} // namespace internal
256
257template <typename T>
258Pref<T>::Pref(Collection& collection, const char* key, T default_value)
259 : collection_(collection),
260 key_(key),
261 default_value_(std::move(default_value)),
262 state_(PrefState::kUnknown),
263 value_(default_value) {}
264
265template <typename T>
266bool Pref<T>::isSet() const {
267 sync();
268 return (state_ == PrefState::kSet);
269}
270
271template <typename T>
272const T& Pref<T>::get() const {
273 sync();
274 return value_;
275}
276
277template <typename T>
278bool Pref<T>::set(const T& value) {
279 sync();
280 if (state_ == PrefState::kSet && value_ == value) {
281 return true;
282 }
283 Transaction t(collection_);
284 if (!t.active()) {
285 state_ = PrefState::kError;
286 return false;
287 }
288 switch (internal::StoreWrite(t.store(), key_, value)) {
289 case WriteResult::kOk: {
290 value_ = value;
291 state_ = PrefState::kSet;
292 return true;
293 }
294 default: {
295 state_ = PrefState::kError;
296 return false;
297 }
298 }
299}
300
301template <typename T>
303 sync();
304 if (state_ == PrefState::kUnset) {
305 return true;
306 }
307 Transaction t(collection_);
308 if (!t.active()) {
309 state_ = PrefState::kError;
310 return false;
311 }
312 switch (internal::StoreClear(t.store(), key_)) {
313 case ClearResult::kOk: {
314 state_ = PrefState::kUnset;
315 value_ = default_value_;
316 return true;
317 }
318 default: {
319 state_ = PrefState::kError;
320 return false;
321 }
322 }
323}
324
325template <typename T>
326void Pref<T>::sync() const {
327 if (state_ == PrefState::kUnknown || state_ == PrefState::kError) {
328 Transaction t(collection_, true);
329 if (!t.active()) {
330 state_ = PrefState::kUnset;
331 value_ = default_value_;
332 return;
333 }
334 switch (internal::StoreRead(t.store(), key_, value_)) {
335 case ReadResult::kOk: {
336 state_ = PrefState::kSet;
337 return;
338 }
340 state_ = PrefState::kUnset;
341 value_ = default_value_;
342 return;
343 }
344 default: {
345 state_ = PrefState::kError;
346 return;
347 }
348 }
349 }
350}
351
352} // namespace roo_prefs
Collection corresponds to a preferences namespace. Use it to group related preferences.
Definition collection.h:14
Persistent preference of a specific type. The preference will store its value in the preferences coll...
Definition pref.h:51
Pref(Collection &collection, const char *key, T default_value=T())
Definition pref.h:258
bool clear()
Definition pref.h:302
bool isSet() const
Definition pref.h:266
const T & get() const
Definition pref.h:272
bool set(const T &value)
Definition pref.h:278
Low-level wrapper around the underlying preferences storage.
WriteResult writeU8(const char *key, uint8_t val)
WriteResult writeBool(const char *key, bool val)
WriteResult writeI8(const char *key, int8_t val)
ReadResult readDouble(const char *key, double &val)
WriteResult writeFloat(const char *key, float val)
ReadResult readI32(const char *key, int32_t &val)
WriteResult writeI32(const char *key, int32_t val)
ReadResult readU8(const char *key, uint8_t &val)
WriteResult writeI16(const char *key, int16_t val)
ReadResult readI8(const char *key, int8_t &val)
WriteResult writeU32(const char *key, uint32_t val)
WriteResult writeString(const char *key, roo::string_view val)
ReadResult readI16(const char *key, int16_t &val)
ReadResult readBool(const char *key, bool &val)
ReadResult readU64(const char *key, uint64_t &val)
WriteResult writeDouble(const char *key, double val)
ReadResult readU32(const char *key, uint32_t &val)
ReadResult readI64(const char *key, int64_t &val)
ClearResult clear(const char *key)
WriteResult writeObject(const char *key, const T &val)
ReadResult readFloat(const char *key, float &val)
ReadResult readObject(const char *key, T &val)
WriteResult writeU64(const char *key, uint64_t val)
ReadResult readU16(const char *key, uint16_t &val)
ReadResult readString(const char *key, std::string &val)
WriteResult writeI64(const char *key, int64_t val)
WriteResult writeU16(const char *key, uint16_t val)
Ref-counted RAII for managing access to Preference namespaces. Allows orchestrating access to the Sto...
Definition transaction.h:9
Similar to Pref<T>, but does not immediately store written data in persistent storage....
Definition collection.h:6
ReadResult
Result of reading a value from storage.
Definition status.h:8
ClearResult
Result of clearing a value from storage.
Definition status.h:14
WriteResult
Result of writing a value to storage.
Definition status.h:11