20
20
21
21
#include < stdio.h>
22
22
23
- #include < map>
24
23
#include < cstdlib>
25
24
#include < cstring>
26
25
#include < string>
27
26
28
- #include " mgos.h "
27
+ #include " mgos.hpp "
29
28
30
29
class KVStore {
31
30
public:
32
31
explicit KVStore (const char * fileName);
32
+ ~KVStore ();
33
33
HAPError
34
34
Get (HAPPlatformKeyValueStoreDomain domain,
35
35
HAPPlatformKeyValueStoreKey key,
@@ -41,8 +41,9 @@ class KVStore {
41
41
Set (HAPPlatformKeyValueStoreDomain domain,
42
42
HAPPlatformKeyValueStoreKey key,
43
43
const void * bytes,
44
- size_t numBytes);
45
- HAPError Remove (HAPPlatformKeyValueStoreDomain domain, HAPPlatformKeyValueStoreKey key);
44
+ size_t numBytes,
45
+ bool save = true );
46
+ HAPError Remove (HAPPlatformKeyValueStoreDomain domain, HAPPlatformKeyValueStoreKey key, bool save = true );
46
47
HAPError Enumerate (
47
48
HAPPlatformKeyValueStoreRef keyValueStore,
48
49
HAPPlatformKeyValueStoreDomain domain,
@@ -51,20 +52,62 @@ class KVStore {
51
52
HAPError PurgeDomain (HAPPlatformKeyValueStoreDomain domain);
52
53
53
54
private:
55
+ struct Item {
56
+ Item* next;
57
+ HAPPlatformKeyValueStoreDomain dom;
58
+ HAPPlatformKeyValueStoreKey key;
59
+ uint16_t len;
60
+ uint8_t data[];
61
+
62
+ static Item*
63
+ New (HAPPlatformKeyValueStoreDomain domain,
64
+ HAPPlatformKeyValueStoreKey key,
65
+ const void * data,
66
+ uint8_t len) {
67
+ Item* itm = reinterpret_cast <Item*>(new uint8_t [sizeof (Item) + len]);
68
+ itm->next = nullptr ;
69
+ itm->dom = domain;
70
+ itm->key = key;
71
+ itm->len = len;
72
+ std::memcpy (itm->data , data, len);
73
+ return itm;
74
+ }
75
+
76
+ static void Delete (Item* itm) {
77
+ delete[] reinterpret_cast <uint8_t *>(itm);
78
+ }
79
+ };
80
+
54
81
static uint16_t KVSKey (HAPPlatformKeyValueStoreDomain domain, HAPPlatformKeyValueStoreKey key);
55
82
void Load ();
83
+ void Clear ();
56
84
HAPError Save () const ;
57
85
58
86
const std::string fileName_;
59
- std::map< uint16_t , std::string> kvs_ ;
87
+ Item* items_ = nullptr ;
60
88
};
61
89
62
90
KVStore::KVStore (const char * fileName)
63
91
: fileName_(fileName) {
64
92
Load ();
65
93
}
66
94
95
+ KVStore::~KVStore () {
96
+ Clear ();
97
+ }
98
+
99
+ void KVStore::Clear () {
100
+ Item *itm = items_, *next;
101
+ while (itm != nullptr ) {
102
+ next = itm->next ;
103
+ Item::Delete (itm);
104
+ itm = next;
105
+ }
106
+ items_ = nullptr ;
107
+ }
108
+
67
109
void KVStore::Load () {
110
+ Clear ();
68
111
void * h = NULL ;
69
112
size_t size = 0 ;
70
113
char * data = cs_read_file (fileName_.c_str (), &size);
@@ -77,12 +120,8 @@ void KVStore::Load() {
77
120
rename (tmpFileName.c_str (), fileName_.c_str ());
78
121
}
79
122
}
80
- if (data == NULL ) {
81
- LOG (LL_WARN, (" No KVStore data" ));
82
- goto out;
83
- }
84
-
85
- kvs_.clear ();
123
+ mgos::ScopedCPtr data_owner (data);
124
+ int num_keys = 0 ;
86
125
struct json_token key, val;
87
126
while ((h = json_next_key (data, size, h, " " , &key, &val)) != NULL ) {
88
127
char * v = NULL ;
@@ -94,15 +133,14 @@ void KVStore::Load() {
94
133
val.ptr --;
95
134
val.len += 2 ;
96
135
if (json_scanf (val.ptr - 1 , val.len + 2 , " %V" , &v, &vs) == 1 ) {
97
- kvs_[k] = std::string (v, vs);
136
+ HAPPlatformKeyValueStoreDomain dd = (HAPPlatformKeyValueStoreDomain)(k >> 8 );
137
+ HAPPlatformKeyValueStoreKey kk = (HAPPlatformKeyValueStoreKey) k;
138
+ Set (dd, kk, v, vs, false /* save */ );
139
+ num_keys++;
98
140
free (v);
99
141
}
100
142
}
101
-
102
- LOG (LL_DEBUG, (" Loaded %d keys from %s" , (int ) kvs_.size (), fileName_.c_str ()));
103
-
104
- out:
105
- free (data);
143
+ LOG (LL_DEBUG, (" Loaded %d keys from %s ss %d" , num_keys, fileName_.c_str (), (int ) sizeof (Item)));
106
144
}
107
145
108
146
HAPError KVStore::Save () const {
@@ -116,13 +154,14 @@ HAPError KVStore::Save() const {
116
154
struct json_out out;
117
155
out = JSON_OUT_FILE (fp);
118
156
int num;
119
- num = 0 ;
157
+ const Item* itm ;
120
158
json_printf (&out, " {" );
121
- for (auto it = kvs_. begin (); it != kvs_. end (); it++ , num++) {
159
+ for (itm = items_, num = 0 ; itm != nullptr ; itm = itm-> next , num++) {
122
160
if (num != 0 ) {
123
161
json_printf (&out, " ," );
124
162
}
125
- if (json_printf (&out, " \n \" %d\" : %V" , it->first , it->second .data (), (int ) it->second .size ()) < 0 ) {
163
+ uint16_t fkey = ((((uint16_t ) itm->dom ) << 8 ) | ((uint16_t ) itm->key ));
164
+ if (json_printf (&out, " \n \" %u\" : %V" , fkey, &itm->data [0 ], itm->len ) < 0 ) {
126
165
goto out;
127
166
}
128
167
}
@@ -138,8 +177,9 @@ HAPError KVStore::Save() const {
138
177
err = kHAPError_None ;
139
178
140
179
out:
141
- if (fp != NULL )
180
+ if (fp != NULL ) {
142
181
fclose (fp);
182
+ }
143
183
return err;
144
184
}
145
185
@@ -155,14 +195,15 @@ HAPError KVStore::Get(
155
195
size_t maxBytes,
156
196
size_t * _Nullable numBytes,
157
197
bool * found) const {
158
- auto it = kvs_. find ( KVSKey (domain, key)) ;
159
- if (it == kvs_. end () ) {
160
- *found = false ;
161
- *numBytes = 0 ;
162
- } else {
163
- *numBytes = std::min (it-> second . size () , maxBytes);
164
- std::memcpy (bytes, it-> second . data () , *numBytes);
198
+ *found = false ;
199
+ for ( const Item* itm = items_; itm != nullptr ; itm = itm-> next ) {
200
+ if (itm-> dom != domain || itm-> key != key) {
201
+ continue ;
202
+ }
203
+ *numBytes = std::min (( size_t ) itm-> len , maxBytes);
204
+ std::memcpy (bytes, &itm-> data [ 0 ] , *numBytes);
165
205
*found = true ;
206
+ break ;
166
207
}
167
208
return kHAPError_None ;
168
209
}
@@ -171,14 +212,47 @@ HAPError KVStore::Set(
171
212
HAPPlatformKeyValueStoreDomain domain,
172
213
HAPPlatformKeyValueStoreKey key,
173
214
const void * bytes,
174
- size_t numBytes) {
175
- kvs_[KVSKey (domain, key)] = std::string (static_cast <const char *>(bytes), numBytes);
176
- return Save ();
215
+ size_t numBytes,
216
+ bool save) {
217
+ Item *prev = nullptr , *itm = items_, *next = nullptr ;
218
+ while (itm != nullptr ) {
219
+ if (itm->dom == domain && itm->key == key) {
220
+ break ;
221
+ }
222
+ prev = itm;
223
+ itm = itm->next ;
224
+ }
225
+ if (itm != nullptr ) {
226
+ next = itm->next ;
227
+ }
228
+ if (itm != nullptr ) {
229
+ Item::Delete (itm);
230
+ }
231
+ bool changed;
232
+ if (bytes != nullptr ) {
233
+ itm = Item::New (domain, key, bytes, numBytes);
234
+ if (itm == nullptr ) {
235
+ return kHAPError_OutOfResources ;
236
+ }
237
+ changed = true ;
238
+ } else {
239
+ changed = (itm != nullptr );
240
+ itm = next;
241
+ next = nullptr ;
242
+ }
243
+ if (prev != nullptr ) {
244
+ prev->next = itm;
245
+ } else {
246
+ items_ = itm;
247
+ }
248
+ if (next != nullptr ) {
249
+ itm->next = next;
250
+ }
251
+ return (changed && save ? Save () : kHAPError_None );
177
252
}
178
253
179
- HAPError KVStore::Remove (HAPPlatformKeyValueStoreDomain domain, HAPPlatformKeyValueStoreKey key) {
180
- size_t numErased = kvs_.erase (KVSKey (domain, key));
181
- return (numErased == 0 ? kHAPError_None : Save ());
254
+ HAPError KVStore::Remove (HAPPlatformKeyValueStoreDomain domain, HAPPlatformKeyValueStoreKey key, bool save) {
255
+ return Set (domain, key, nullptr , 0 , save);
182
256
}
183
257
184
258
HAPError KVStore::Enumerate (
@@ -187,13 +261,12 @@ HAPError KVStore::Enumerate(
187
261
HAPPlatformKeyValueStoreEnumerateCallback callback,
188
262
void * _Nullable context) const {
189
263
HAPError err = kHAPError_None ;
190
- const auto from_it = kvs_.lower_bound (KVSKey (domain, 0x00 ));
191
- const auto to_it = kvs_.lower_bound (KVSKey (domain, 0xff ));
192
- for (auto it = from_it; it != to_it; it++) {
193
- HAPPlatformKeyValueStoreDomain kd = static_cast <HAPPlatformKeyValueStoreDomain>(it->first >> 8 );
194
- HAPPlatformKeyValueStoreKey kk = static_cast <HAPPlatformKeyValueStoreKey>(it->first );
264
+ for (const Item* itm = items_; itm != nullptr ; itm = itm->next ) {
265
+ if (itm->dom != domain) {
266
+ continue ;
267
+ }
195
268
bool shouldContinue = true ;
196
- err = callback (context, keyValueStore, kd, kk , &shouldContinue);
269
+ err = callback (context, keyValueStore, itm-> dom , itm-> key , &shouldContinue);
197
270
if (err != kHAPError_None || !shouldContinue) {
198
271
break ;
199
272
}
@@ -202,15 +275,22 @@ HAPError KVStore::Enumerate(
202
275
}
203
276
204
277
HAPError KVStore::PurgeDomain (HAPPlatformKeyValueStoreDomain domain) {
205
- const auto from_it = kvs_.lower_bound (KVSKey (domain, 0x00 ));
206
- const auto to_it = kvs_.lower_bound (KVSKey (domain, 0xff ));
207
- size_t numErased = 0 ;
208
- for (auto it = from_it; it != to_it;) {
209
- auto it2 = it++;
210
- kvs_.erase (it2);
211
- numErased++;
278
+ bool changed = false ;
279
+ while (true ) {
280
+ Item* itm = items_;
281
+ while (itm != nullptr ) {
282
+ if (itm->dom == domain) {
283
+ break ;
284
+ }
285
+ itm = itm->next ;
286
+ }
287
+ if (itm == nullptr ) {
288
+ break ;
289
+ }
290
+ Remove (itm->dom , itm->key , false /* save */ );
291
+ changed = true ;
212
292
}
213
- return (numErased == 0 ? kHAPError_None : Save ());
293
+ return (changed ? Save () : kHAPError_None );
214
294
}
215
295
216
296
extern " C" {
@@ -265,7 +345,7 @@ void HAPPlatformKeyValueStoreCreate(
265
345
void HAPPlatformKeyValueStoreRelease (HAPPlatformKeyValueStoreRef keyValueStore) {
266
346
auto * kvs = static_cast <KVStore*>(keyValueStore->ctx );
267
347
keyValueStore->ctx = nullptr ;
268
- delete ( kvs) ;
348
+ delete kvs;
269
349
}
270
350
271
351
} // extern "C"
0 commit comments