react-native-mmkv 3.3.0 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/android/CMakeLists.txt +18 -9
  2. package/android/build.gradle +6 -2
  3. package/cpp/{MMKVManagedBuffer.h → ManagedMMBuffer.h} +6 -6
  4. package/cpp/MmkvHostObject.cpp +13 -8
  5. package/cpp/MmkvHostObject.h +1 -2
  6. package/cpp/MmkvTypes.h +50 -0
  7. package/cpp/NativeMmkvModule.cpp +3 -3
  8. package/cpp/NativeMmkvModule.h +1 -8
  9. package/package.json +22 -23
  10. package/react-native-mmkv.podspec +3 -9
  11. package/react-native.config.js +9 -0
  12. package/MMKV/Core/CMakeLists.txt +0 -172
  13. package/MMKV/Core/CodedInputData.cpp +0 -252
  14. package/MMKV/Core/CodedInputData.h +0 -87
  15. package/MMKV/Core/CodedInputDataCrypt.cpp +0 -280
  16. package/MMKV/Core/CodedInputDataCrypt.h +0 -87
  17. package/MMKV/Core/CodedInputDataCrypt_OSX.cpp +0 -62
  18. package/MMKV/Core/CodedInputData_OSX.cpp +0 -92
  19. package/MMKV/Core/CodedOutputData.cpp +0 -186
  20. package/MMKV/Core/CodedOutputData.h +0 -88
  21. package/MMKV/Core/Core.xcodeproj/project.pbxproj +0 -707
  22. package/MMKV/Core/Core.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  23. package/MMKV/Core/Core.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  24. package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +0 -67
  25. package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +0 -67
  26. package/MMKV/Core/InterProcessLock.cpp +0 -186
  27. package/MMKV/Core/InterProcessLock.h +0 -119
  28. package/MMKV/Core/InterProcessLock_Android.cpp +0 -103
  29. package/MMKV/Core/InterProcessLock_Win32.cpp +0 -108
  30. package/MMKV/Core/KeyValueHolder.cpp +0 -236
  31. package/MMKV/Core/KeyValueHolder.h +0 -122
  32. package/MMKV/Core/MMBuffer.cpp +0 -210
  33. package/MMKV/Core/MMBuffer.h +0 -111
  34. package/MMKV/Core/MMKV.cpp +0 -1702
  35. package/MMKV/Core/MMKV.h +0 -595
  36. package/MMKV/Core/MMKVLog.cpp +0 -127
  37. package/MMKV/Core/MMKVLog.h +0 -86
  38. package/MMKV/Core/MMKVLog_Android.cpp +0 -134
  39. package/MMKV/Core/MMKVMetaInfo.hpp +0 -99
  40. package/MMKV/Core/MMKVPredef.h +0 -293
  41. package/MMKV/Core/MMKV_Android.cpp +0 -261
  42. package/MMKV/Core/MMKV_IO.cpp +0 -1905
  43. package/MMKV/Core/MMKV_IO.h +0 -57
  44. package/MMKV/Core/MMKV_OSX.cpp +0 -423
  45. package/MMKV/Core/MMKV_OSX.h +0 -57
  46. package/MMKV/Core/MemoryFile.cpp +0 -603
  47. package/MMKV/Core/MemoryFile.h +0 -194
  48. package/MMKV/Core/MemoryFile_Android.cpp +0 -236
  49. package/MMKV/Core/MemoryFile_Linux.cpp +0 -125
  50. package/MMKV/Core/MemoryFile_OSX.cpp +0 -142
  51. package/MMKV/Core/MemoryFile_Win32.cpp +0 -554
  52. package/MMKV/Core/MiniPBCoder.cpp +0 -672
  53. package/MMKV/Core/MiniPBCoder.h +0 -151
  54. package/MMKV/Core/MiniPBCoder_OSX.cpp +0 -237
  55. package/MMKV/Core/PBEncodeItem.hpp +0 -104
  56. package/MMKV/Core/PBUtility.cpp +0 -61
  57. package/MMKV/Core/PBUtility.h +0 -148
  58. package/MMKV/Core/ScopedLock.hpp +0 -69
  59. package/MMKV/Core/ThreadLock.cpp +0 -75
  60. package/MMKV/Core/ThreadLock.h +0 -81
  61. package/MMKV/Core/ThreadLock_Win32.cpp +0 -89
  62. package/MMKV/Core/aes/AESCrypt.cpp +0 -273
  63. package/MMKV/Core/aes/AESCrypt.h +0 -112
  64. package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +0 -1243
  65. package/MMKV/Core/aes/openssl/openssl_aes.h +0 -130
  66. package/MMKV/Core/aes/openssl/openssl_aes_core.cpp +0 -1044
  67. package/MMKV/Core/aes/openssl/openssl_aes_locl.h +0 -38
  68. package/MMKV/Core/aes/openssl/openssl_aesv8-armx.S +0 -308
  69. package/MMKV/Core/aes/openssl/openssl_arm_arch.h +0 -84
  70. package/MMKV/Core/aes/openssl/openssl_cfb128.cpp +0 -97
  71. package/MMKV/Core/aes/openssl/openssl_md32_common.h +0 -254
  72. package/MMKV/Core/aes/openssl/openssl_md5.h +0 -49
  73. package/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp +0 -166
  74. package/MMKV/Core/aes/openssl/openssl_md5_locl.h +0 -75
  75. package/MMKV/Core/aes/openssl/openssl_md5_one.cpp +0 -30
  76. package/MMKV/Core/aes/openssl/openssl_opensslconf.h +0 -271
  77. package/MMKV/Core/core.vcxproj +0 -288
  78. package/MMKV/Core/core.vcxproj.filters +0 -150
  79. package/MMKV/Core/crc32/Checksum.h +0 -75
  80. package/MMKV/Core/crc32/crc32_armv8.cpp +0 -134
  81. package/MMKV/Core/crc32/zlib/CMakeLists.txt +0 -60
  82. package/MMKV/Core/crc32/zlib/crc32.cpp +0 -55
  83. package/MMKV/Core/crc32/zlib/crc32.h +0 -48
  84. package/MMKV/Core/crc32/zlib/zconf.h +0 -380
  85. package/MMKV/Core/crc32/zlib/zutil.h +0 -25
  86. package/MMKV/LICENSE.TXT +0 -193
  87. package/MMKV/README.md +0 -354
@@ -1,1702 +0,0 @@
1
- /*
2
- * Tencent is pleased to support the open source community by making
3
- * MMKV available.
4
- *
5
- * Copyright (C) 2018 THL A29 Limited, a Tencent company.
6
- * All rights reserved.
7
- *
8
- * Licensed under the BSD 3-Clause License (the "License"); you may not use
9
- * this file except in compliance with the License. You may obtain a copy of
10
- * the License at
11
- *
12
- * https://opensource.org/licenses/BSD-3-Clause
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- */
20
-
21
- #include "CodedInputData.h"
22
- #include "CodedOutputData.h"
23
- #include "InterProcessLock.h"
24
- #include "KeyValueHolder.h"
25
- #include "MMBuffer.h"
26
- #include "MMKVLog.h"
27
- #include "MMKVMetaInfo.hpp"
28
- #include "MMKV_IO.h"
29
- #include "MMKV_OSX.h"
30
- #include "MemoryFile.h"
31
- #include "MiniPBCoder.h"
32
- #include "PBUtility.h"
33
- #include "ScopedLock.hpp"
34
- #include "ThreadLock.h"
35
- #include "aes/AESCrypt.h"
36
- #include "aes/openssl/openssl_aes.h"
37
- #include "aes/openssl/openssl_md5.h"
38
- #include "crc32/Checksum.h"
39
- #include <algorithm>
40
- #include <cstdio>
41
- #include <cstring>
42
- #include <unordered_set>
43
- #include <cassert>
44
-
45
- #if defined(__aarch64__) && defined(__linux__) && !defined (MMKV_OHOS)
46
- # include <asm/hwcap.h>
47
- # include <sys/auxv.h>
48
- #endif
49
-
50
- #ifdef MMKV_APPLE
51
- # if __has_feature(objc_arc)
52
- # error This file must be compiled with MRC. Use -fno-objc-arc flag.
53
- # endif
54
- # include "MMKV_OSX.h"
55
- #endif // MMKV_APPLE
56
-
57
- using namespace std;
58
- using namespace mmkv;
59
-
60
- unordered_map<string, MMKV *> *g_instanceDic;
61
- ThreadLock *g_instanceLock;
62
- MMKVPath_t g_rootDir;
63
- static mmkv::ErrorHandler g_errorHandler;
64
- size_t mmkv::DEFAULT_MMAP_SIZE;
65
-
66
- #ifndef MMKV_WIN32
67
- constexpr auto SPECIAL_CHARACTER_DIRECTORY_NAME = "specialCharacter";
68
- constexpr auto CRC_SUFFIX = ".crc";
69
- #else
70
- constexpr auto SPECIAL_CHARACTER_DIRECTORY_NAME = L"specialCharacter";
71
- constexpr auto CRC_SUFFIX = L".crc";
72
- #endif
73
-
74
- MMKV_NAMESPACE_BEGIN
75
-
76
- static MMKVPath_t encodeFilePath(const string &mmapID, const MMKVPath_t &rootDir);
77
- bool endsWith(const MMKVPath_t &str, const MMKVPath_t &suffix);
78
- MMKVPath_t filename(const MMKVPath_t &path);
79
-
80
- #ifndef MMKV_ANDROID
81
- MMKV::MMKV(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity)
82
- : m_mmapID(mmapID)
83
- , m_mode(mode)
84
- , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath))
85
- , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath))
86
- , m_dic(nullptr)
87
- , m_dicCrypt(nullptr)
88
- , m_expectedCapacity(std::max<size_t>(DEFAULT_MMAP_SIZE, roundUp<size_t>(expectedCapacity, DEFAULT_MMAP_SIZE)))
89
- , m_file(new MemoryFile(m_path, m_expectedCapacity, isReadOnly()))
90
- , m_metaFile(new MemoryFile(m_crcPath, 0, isReadOnly()))
91
- , m_metaInfo(new MMKVMetaInfo())
92
- , m_crypter(nullptr)
93
- , m_lock(new ThreadLock())
94
- , m_fileLock(new FileLock(m_metaFile->getFd()))
95
- , m_sharedProcessLock(new InterProcessLock(m_fileLock, SharedLockType))
96
- , m_exclusiveProcessLock(new InterProcessLock(m_fileLock, ExclusiveLockType))
97
- {
98
- m_actualSize = 0;
99
- m_output = nullptr;
100
-
101
- # ifndef MMKV_DISABLE_CRYPT
102
- if (cryptKey && !cryptKey->empty()) {
103
- m_dicCrypt = new MMKVMapCrypt();
104
- m_crypter = new AESCrypt(cryptKey->data(), cryptKey->length());
105
- } else {
106
- m_dic = new MMKVMap();
107
- }
108
- # else
109
- m_dic = new MMKVMap();
110
- # endif
111
-
112
- m_needLoadFromFile = true;
113
- m_hasFullWriteback = false;
114
-
115
- m_crcDigest = 0;
116
-
117
- m_lock->initialize();
118
- m_sharedProcessLock->m_enable = isMultiProcess();
119
- m_exclusiveProcessLock->m_enable = isMultiProcess();
120
-
121
- // sensitive zone
122
- /*{
123
- SCOPED_LOCK(m_sharedProcessLock);
124
- loadFromFile();
125
- }*/
126
- }
127
- #endif
128
-
129
- MMKV::~MMKV() {
130
- clearMemoryCache();
131
-
132
- delete m_dic;
133
- #ifndef MMKV_DISABLE_CRYPT
134
- delete m_dicCrypt;
135
- delete m_crypter;
136
- #endif
137
- delete m_file;
138
- delete m_metaFile;
139
- delete m_metaInfo;
140
- delete m_lock;
141
- delete m_fileLock;
142
- delete m_sharedProcessLock;
143
- delete m_exclusiveProcessLock;
144
- #ifdef MMKV_ANDROID
145
- delete m_fileModeLock;
146
- delete m_sharedProcessModeLock;
147
- delete m_exclusiveProcessModeLock;
148
- #endif
149
-
150
- MMKVInfo("destruct [%s]", m_mmapID.c_str());
151
- }
152
-
153
- MMKV *MMKV::defaultMMKV(MMKVMode mode, string *cryptKey) {
154
- #ifndef MMKV_ANDROID
155
- return mmkvWithID(DEFAULT_MMAP_ID, mode, cryptKey);
156
- #else
157
- return mmkvWithID(DEFAULT_MMAP_ID, DEFAULT_MMAP_SIZE, mode, cryptKey);
158
- #endif
159
- }
160
-
161
- void initialize() {
162
- g_instanceDic = new unordered_map<string, MMKV *>;
163
- g_instanceLock = new ThreadLock();
164
- g_instanceLock->initialize();
165
-
166
- mmkv::DEFAULT_MMAP_SIZE = mmkv::getPageSize();
167
- MMKVInfo("version %s, page size %d, arch %s", MMKV_VERSION, DEFAULT_MMAP_SIZE, MMKV_ABI);
168
-
169
- // get CPU status of ARMv8 extensions (CRC32, AES)
170
- #if defined(__aarch64__) && defined(__linux__) && !defined (MMKV_OHOS)
171
- auto hwcaps = getauxval(AT_HWCAP);
172
- # ifndef MMKV_DISABLE_CRYPT
173
- if (hwcaps & HWCAP_AES) {
174
- openssl::AES_set_encrypt_key = openssl_aes_armv8_set_encrypt_key;
175
- openssl::AES_set_decrypt_key = openssl_aes_armv8_set_decrypt_key;
176
- openssl::AES_encrypt = openssl_aes_armv8_encrypt;
177
- openssl::AES_decrypt = openssl_aes_armv8_decrypt;
178
- MMKVInfo("armv8 AES instructions is supported");
179
- } else {
180
- MMKVInfo("armv8 AES instructions is not supported");
181
- }
182
- # endif // MMKV_DISABLE_CRYPT
183
- # ifdef MMKV_USE_ARMV8_CRC32
184
- if (hwcaps & HWCAP_CRC32) {
185
- CRC32 = mmkv::armv8_crc32;
186
- MMKVInfo("armv8 CRC32 instructions is supported");
187
- } else {
188
- MMKVInfo("armv8 CRC32 instructions is not supported");
189
- }
190
- # endif // MMKV_USE_ARMV8_CRC32
191
- #endif // __aarch64__ && defined(__linux__) && !defined (MMKV_OHOS)
192
-
193
- #if defined(MMKV_DEBUG) && !defined(MMKV_DISABLE_CRYPT)
194
- // AESCrypt::testAESCrypt();
195
- // KeyValueHolderCrypt::testAESToMMBuffer();
196
- #endif
197
- }
198
-
199
- static ThreadOnceToken_t once_control = ThreadOnceUninitialized;
200
-
201
- void MMKV::initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel, mmkv::LogHandler handler) {
202
- g_currentLogLevel = logLevel;
203
- g_logHandler = handler;
204
-
205
- ThreadLock::ThreadOnce(&once_control, initialize);
206
-
207
- #ifdef MMKV_APPLE
208
- // crc32 instruction requires A10 chip, aka iPhone 7 or iPad 6th generation
209
- int device = 0, version = 0;
210
- GetAppleMachineInfo(device, version);
211
- # ifndef MMKV_IOS
212
- MMKVInfo("Apple Device: %d, version: %d", device, version);
213
- # else
214
- // we have verified that on iOS 13+, the mlock() protection in background is no longer needed
215
- // this may be true as well on iOS 12 or even iOS 11, sadly we can't verify that on WeChat
216
- if (@available(iOS 13, *)) {
217
- MLockPtr::isMLockPtrEnabled = false;
218
- }
219
- MMKVInfo("Apple Device: %d, version: %d, mlock enabled: %d", device, version, MLockPtr::isMLockPtrEnabled);
220
- # endif
221
- #endif
222
-
223
- if (g_rootDir.empty()) {
224
- g_rootDir = rootDir;
225
- mkPath(g_rootDir);
226
- }
227
-
228
- MMKVInfo("root dir: " MMKV_PATH_FORMAT, g_rootDir.c_str());
229
- }
230
-
231
- const MMKVPath_t &MMKV::getRootDir() {
232
- return g_rootDir;
233
- }
234
-
235
- #ifndef MMKV_ANDROID
236
- MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity) {
237
-
238
- if (mmapID.empty() || !g_instanceLock) {
239
- return nullptr;
240
- }
241
- SCOPED_LOCK(g_instanceLock);
242
-
243
- auto mmapKey = mmapedKVKey(mmapID, rootPath);
244
- auto itr = g_instanceDic->find(mmapKey);
245
- if (itr != g_instanceDic->end()) {
246
- MMKV *kv = itr->second;
247
- return kv;
248
- }
249
-
250
- if (rootPath) {
251
- MMKVPath_t specialPath = (*rootPath) + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
252
- if (!isFileExist(specialPath)) {
253
- mkPath(specialPath);
254
- }
255
- MMKVInfo("prepare to load %s (id %s) from rootPath %s", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str());
256
- }
257
-
258
- auto kv = new MMKV(mmapID, mode, cryptKey, rootPath, expectedCapacity);
259
- kv->m_mmapKey = mmapKey;
260
- (*g_instanceDic)[mmapKey] = kv;
261
- return kv;
262
- }
263
- #endif
264
-
265
- void MMKV::onExit() {
266
- if (!g_instanceLock) {
267
- return;
268
- }
269
- SCOPED_LOCK(g_instanceLock);
270
-
271
- for (auto &pair : *g_instanceDic) {
272
- MMKV *kv = pair.second;
273
- kv->sync();
274
- kv->clearMemoryCache();
275
- delete kv;
276
- pair.second = nullptr;
277
- }
278
-
279
- delete g_instanceDic;
280
- g_instanceDic = nullptr;
281
- }
282
-
283
- const string &MMKV::mmapID() const {
284
- return m_mmapID;
285
- }
286
-
287
- mmkv::ContentChangeHandler g_contentChangeHandler = nullptr;
288
-
289
- void MMKV::notifyContentChanged() {
290
- if (g_contentChangeHandler) {
291
- g_contentChangeHandler(m_mmapID);
292
- }
293
- }
294
-
295
- void MMKV::checkContentChanged() {
296
- SCOPED_LOCK(m_lock);
297
- checkLoadData();
298
- }
299
-
300
- void MMKV::registerContentChangeHandler(mmkv::ContentChangeHandler handler) {
301
- g_contentChangeHandler = handler;
302
- }
303
-
304
- void MMKV::unRegisterContentChangeHandler() {
305
- g_contentChangeHandler = nullptr;
306
- }
307
-
308
- void MMKV::clearMemoryCache(bool keepSpace) {
309
- SCOPED_LOCK(m_lock);
310
- if (m_needLoadFromFile) {
311
- return;
312
- }
313
- MMKVInfo("clearMemoryCache [%s]", m_mmapID.c_str());
314
- m_needLoadFromFile = true;
315
- m_hasFullWriteback = false;
316
-
317
- clearDictionary(m_dic);
318
- #ifndef MMKV_DISABLE_CRYPT
319
- clearDictionary(m_dicCrypt);
320
- if (m_crypter) {
321
- if (m_metaInfo->m_version >= MMKVVersionRandomIV) {
322
- m_crypter->resetIV(m_metaInfo->m_vector, sizeof(m_metaInfo->m_vector));
323
- } else {
324
- m_crypter->resetIV();
325
- }
326
- }
327
- #endif
328
-
329
- delete m_output;
330
- m_output = nullptr;
331
-
332
- if (!keepSpace) {
333
- m_file->clearMemoryCache();
334
- }
335
- // inter-process lock rely on MetaFile's fd, never close it
336
- // m_metaFile->clearMemoryCache();
337
- m_actualSize = 0;
338
- m_metaInfo->m_crcDigest = 0;
339
- }
340
-
341
- void MMKV::close() {
342
- MMKVInfo("close [%s]", m_mmapID.c_str());
343
- SCOPED_LOCK(g_instanceLock);
344
- m_lock->lock();
345
-
346
- #ifndef MMKV_ANDROID
347
- auto itr = g_instanceDic->find(m_mmapKey);
348
- #else
349
- auto itr = g_instanceDic->find(m_mmapID);
350
- #endif
351
- if (itr != g_instanceDic->end()) {
352
- g_instanceDic->erase(itr);
353
- }
354
- delete this;
355
- }
356
-
357
- #ifndef MMKV_DISABLE_CRYPT
358
-
359
- string MMKV::cryptKey() const {
360
- SCOPED_LOCK(m_lock);
361
-
362
- if (m_crypter) {
363
- char key[AES_KEY_LEN];
364
- m_crypter->getKey(key);
365
- return {key, strnlen(key, AES_KEY_LEN)};
366
- }
367
- return "";
368
- }
369
-
370
- void MMKV::checkReSetCryptKey(const string *cryptKey) {
371
- SCOPED_LOCK(m_lock);
372
-
373
- if (m_crypter) {
374
- if (cryptKey && !cryptKey->empty()) {
375
- string oldKey = this->cryptKey();
376
- if (oldKey != *cryptKey) {
377
- MMKVInfo("setting new aes key");
378
- delete m_crypter;
379
- auto ptr = cryptKey->data();
380
- m_crypter = new AESCrypt(ptr, cryptKey->length());
381
-
382
- checkLoadData();
383
- } else {
384
- // nothing to do
385
- }
386
- } else {
387
- MMKVInfo("reset aes key");
388
- delete m_crypter;
389
- m_crypter = nullptr;
390
-
391
- checkLoadData();
392
- }
393
- } else {
394
- if (cryptKey && !cryptKey->empty()) {
395
- MMKVInfo("setting new aes key");
396
- auto ptr = cryptKey->data();
397
- m_crypter = new AESCrypt(ptr, cryptKey->length());
398
-
399
- checkLoadData();
400
- } else {
401
- // nothing to do
402
- }
403
- }
404
- }
405
-
406
- #endif // MMKV_DISABLE_CRYPT
407
-
408
- bool MMKV::isFileValid() {
409
- return m_file->isFileValid();
410
- }
411
-
412
- // crc
413
-
414
- // assuming m_file is valid
415
- bool MMKV::checkFileCRCValid(size_t actualSize, uint32_t crcDigest) {
416
- auto ptr = (uint8_t *) m_file->getMemory();
417
- if (ptr) {
418
- m_crcDigest = (uint32_t) CRC32(0, (const uint8_t *) ptr + Fixed32Size, (uint32_t) actualSize);
419
-
420
- if (m_crcDigest == crcDigest) {
421
- return true;
422
- }
423
- MMKVError("check crc [%s] fail, crc32:%u, m_crcDigest:%u", m_mmapID.c_str(), crcDigest, m_crcDigest);
424
- }
425
- return false;
426
- }
427
-
428
- void MMKV::recalculateCRCDigestWithIV(const void *iv) {
429
- auto ptr = (const uint8_t *) m_file->getMemory();
430
- if (ptr) {
431
- m_crcDigest = 0;
432
- m_crcDigest = (uint32_t) CRC32(0, ptr + Fixed32Size, (uint32_t) m_actualSize);
433
- writeActualSize(m_actualSize, m_crcDigest, iv, IncreaseSequence);
434
- }
435
- }
436
-
437
- void MMKV::recalculateCRCDigestOnly() {
438
- auto ptr = (const uint8_t *) m_file->getMemory();
439
- if (ptr) {
440
- m_crcDigest = 0;
441
- m_crcDigest = (uint32_t) CRC32(0, ptr + Fixed32Size, (uint32_t) m_actualSize);
442
- writeActualSize(m_actualSize, m_crcDigest, nullptr, KeepSequence);
443
- }
444
- }
445
-
446
- void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length) {
447
- if (ptr == nullptr) {
448
- return;
449
- }
450
- m_crcDigest = (uint32_t) CRC32(m_crcDigest, ptr, (uint32_t) length);
451
-
452
- writeActualSize(m_actualSize, m_crcDigest, nullptr, KeepSequence);
453
- }
454
-
455
- // set & get
456
-
457
- bool MMKV::set(bool value, MMKVKey_t key) {
458
- return set(value, key, m_expiredInSeconds);
459
- }
460
-
461
- bool MMKV::set(bool value, MMKVKey_t key, uint32_t expireDuration) {
462
- if (isKeyEmpty(key)) {
463
- return false;
464
- }
465
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbBoolSize() : pbBoolSize();
466
- MMBuffer data(size);
467
- CodedOutputData output(data.getPtr(), size);
468
- output.writeBool(value);
469
- if (mmkv_unlikely(m_enableKeyExpire)) {
470
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
471
- output.writeRawLittleEndian32(UInt32ToInt32(time));
472
- } else {
473
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
474
- }
475
-
476
- return setDataForKey(std::move(data), key);
477
- }
478
-
479
- bool MMKV::set(int32_t value, MMKVKey_t key) {
480
- return set(value, key, m_expiredInSeconds);
481
- }
482
-
483
- bool MMKV::set(int32_t value, MMKVKey_t key, uint32_t expireDuration) {
484
- if (isKeyEmpty(key)) {
485
- return false;
486
- }
487
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt32Size(value) : pbInt32Size(value);
488
- MMBuffer data(size);
489
- CodedOutputData output(data.getPtr(), size);
490
- output.writeInt32(value);
491
- if (mmkv_unlikely(m_enableKeyExpire)) {
492
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
493
- output.writeRawLittleEndian32(UInt32ToInt32(time));
494
- } else {
495
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
496
- }
497
-
498
- return setDataForKey(std::move(data), key);
499
- }
500
-
501
- bool MMKV::set(uint32_t value, MMKVKey_t key) {
502
- return set(value, key, m_expiredInSeconds);
503
- }
504
-
505
- bool MMKV::set(uint32_t value, MMKVKey_t key, uint32_t expireDuration) {
506
- if (isKeyEmpty(key)) {
507
- return false;
508
- }
509
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt32Size(value) : pbUInt32Size(value);
510
- MMBuffer data(size);
511
- CodedOutputData output(data.getPtr(), size);
512
- output.writeUInt32(value);
513
- if (mmkv_unlikely(m_enableKeyExpire)) {
514
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
515
- output.writeRawLittleEndian32(UInt32ToInt32(time));
516
- } else {
517
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
518
- }
519
-
520
- return setDataForKey(std::move(data), key);
521
- }
522
-
523
- bool MMKV::set(int64_t value, MMKVKey_t key) {
524
- return set(value, key, m_expiredInSeconds);
525
- }
526
-
527
- bool MMKV::set(int64_t value, MMKVKey_t key, uint32_t expireDuration) {
528
- if (isKeyEmpty(key)) {
529
- return false;
530
- }
531
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt64Size(value) : pbInt64Size(value);
532
- MMBuffer data(size);
533
- CodedOutputData output(data.getPtr(), size);
534
- output.writeInt64(value);
535
- if (mmkv_unlikely(m_enableKeyExpire)) {
536
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
537
- output.writeRawLittleEndian32(UInt32ToInt32(time));
538
- } else {
539
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
540
- }
541
-
542
- return setDataForKey(std::move(data), key);
543
- }
544
-
545
- bool MMKV::set(uint64_t value, MMKVKey_t key) {
546
- return set(value, key, m_expiredInSeconds);
547
- }
548
-
549
- bool MMKV::set(uint64_t value, MMKVKey_t key, uint32_t expireDuration) {
550
- if (isKeyEmpty(key)) {
551
- return false;
552
- }
553
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt64Size(value) : pbUInt64Size(value);
554
- MMBuffer data(size);
555
- CodedOutputData output(data.getPtr(), size);
556
- output.writeUInt64(value);
557
- if (mmkv_unlikely(m_enableKeyExpire)) {
558
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
559
- output.writeRawLittleEndian32(UInt32ToInt32(time));
560
- } else {
561
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
562
- }
563
-
564
- return setDataForKey(std::move(data), key);
565
- }
566
-
567
- bool MMKV::set(float value, MMKVKey_t key) {
568
- return set(value, key, m_expiredInSeconds);
569
- }
570
-
571
- bool MMKV::set(float value, MMKVKey_t key, uint32_t expireDuration) {
572
- if (isKeyEmpty(key)) {
573
- return false;
574
- }
575
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbFloatSize() : pbFloatSize();
576
- MMBuffer data(size);
577
- CodedOutputData output(data.getPtr(), size);
578
- output.writeFloat(value);
579
- if (mmkv_unlikely(m_enableKeyExpire)) {
580
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
581
- output.writeRawLittleEndian32(UInt32ToInt32(time));
582
- } else {
583
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
584
- }
585
-
586
- return setDataForKey(std::move(data), key);
587
- }
588
-
589
- bool MMKV::set(double value, MMKVKey_t key) {
590
- return set(value, key, m_expiredInSeconds);
591
- }
592
-
593
- bool MMKV::set(double value, MMKVKey_t key, uint32_t expireDuration) {
594
- if (isKeyEmpty(key)) {
595
- return false;
596
- }
597
- size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbDoubleSize() : pbDoubleSize();
598
- MMBuffer data(size);
599
- CodedOutputData output(data.getPtr(), size);
600
- output.writeDouble(value);
601
- if (mmkv_unlikely(m_enableKeyExpire)) {
602
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
603
- output.writeRawLittleEndian32(UInt32ToInt32(time));
604
- } else {
605
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
606
- }
607
-
608
- return setDataForKey(std::move(data), key);
609
- }
610
-
611
- #ifndef MMKV_APPLE
612
-
613
- bool MMKV::setDataForKey(mmkv::MMBuffer &&data, MMKV::MMKVKey_t key, uint32_t expireDuration) {
614
- if (mmkv_likely(!m_enableKeyExpire)) {
615
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
616
- return setDataForKey(std::move(data), key, true);
617
- } else {
618
- auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
619
- CodedOutputData output(tmp.getPtr(), tmp.length());
620
- output.writeData(data);
621
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
622
- output.writeRawLittleEndian32(UInt32ToInt32(time));
623
- return setDataForKey(std::move(tmp), key);
624
- }
625
- }
626
-
627
- bool MMKV::set(const char *value, MMKVKey_t key) {
628
- return set(value, key, m_expiredInSeconds);
629
- }
630
-
631
- bool MMKV::set(const char *value, MMKVKey_t key, uint32_t expireDuration) {
632
- if (!value) {
633
- removeValueForKey(key);
634
- return true;
635
- }
636
- return setDataForKey(MMBuffer((void *) value, strlen(value), MMBufferNoCopy), key, expireDuration);
637
- }
638
-
639
- bool MMKV::set(const string &value, MMKVKey_t key) {
640
- return set(value, key, m_expiredInSeconds);
641
- }
642
-
643
- bool MMKV::set(const string &value, MMKVKey_t key, uint32_t expireDuration) {
644
- if (isKeyEmpty(key)) {
645
- return false;
646
- }
647
- return setDataForKey(MMBuffer((void *) value.data(), value.length(), MMBufferNoCopy), key, expireDuration);
648
- }
649
-
650
- bool MMKV::set(string_view value, MMKVKey_t key) {
651
- return set(value, key, m_expiredInSeconds);
652
- }
653
-
654
- bool MMKV::set(string_view value, MMKVKey_t key, uint32_t expireDuration) {
655
- if (isKeyEmpty(key)) {
656
- return false;
657
- }
658
- return setDataForKey(MMBuffer((void *) value.data(), value.length(), MMBufferNoCopy), key, expireDuration);
659
- }
660
-
661
- bool MMKV::set(const MMBuffer &value, MMKVKey_t key) {
662
- return set(value, key, m_expiredInSeconds);
663
- }
664
-
665
- bool MMKV::set(const MMBuffer &value, MMKVKey_t key, uint32_t expireDuration) {
666
- if (isKeyEmpty(key)) {
667
- return false;
668
- }
669
- return setDataForKey(MMBuffer(value.getPtr(), value.length(), MMBufferNoCopy), key, expireDuration);
670
- }
671
-
672
- bool MMKV::set(const vector<string> &value, MMKVKey_t key) {
673
- return set(value, key, m_expiredInSeconds);
674
- }
675
-
676
- bool MMKV::set(const vector<string> &v, MMKVKey_t key, uint32_t expireDuration) {
677
- if (isKeyEmpty(key)) {
678
- return false;
679
- }
680
- #ifdef MMKV_HAS_CPP20
681
- auto data = MiniPBCoder::encodeDataWithObject(std::span(v));
682
- #else
683
- auto data = MiniPBCoder::encodeDataWithObject(v);
684
- #endif
685
- if (mmkv_unlikely(m_enableKeyExpire) && data.length() > 0) {
686
- auto tmp = MMBuffer(data.length() + Fixed32Size);
687
- auto ptr = (uint8_t *) tmp.getPtr();
688
- memcpy(ptr, data.getPtr(), data.length());
689
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
690
- memcpy(ptr + data.length(), &time, Fixed32Size);
691
- data = std::move(tmp);
692
- }
693
- return setDataForKey(std::move(data), key);
694
- }
695
-
696
- bool MMKV::getString(MMKVKey_t key, string &result, bool inplaceModification) {
697
- if (isKeyEmpty(key)) {
698
- return false;
699
- }
700
- SCOPED_LOCK(m_lock);
701
- SCOPED_LOCK(m_sharedProcessLock);
702
- auto data = getDataForKey(key);
703
- if (data.length() > 0) {
704
- try {
705
- CodedInputData input(data.getPtr(), data.length());
706
- if (inplaceModification) {
707
- input.readString(result);
708
- } else {
709
- result = input.readString();
710
- }
711
- return true;
712
- } catch (std::exception &exception) {
713
- MMKVError("%s", exception.what());
714
- } catch (...) {
715
- MMKVError("decode fail");
716
- }
717
- }
718
- return false;
719
- }
720
-
721
- bool MMKV::getBytes(MMKVKey_t key, mmkv::MMBuffer &result) {
722
- if (isKeyEmpty(key)) {
723
- return false;
724
- }
725
- SCOPED_LOCK(m_lock);
726
- SCOPED_LOCK(m_sharedProcessLock);
727
- auto data = getDataForKey(key);
728
- if (data.length() > 0) {
729
- try {
730
- CodedInputData input(data.getPtr(), data.length());
731
- result = input.readData();
732
- return true;
733
- } catch (std::exception &exception) {
734
- MMKVError("%s", exception.what());
735
- } catch (...) {
736
- MMKVError("decode fail");
737
- }
738
- }
739
- return false;
740
- }
741
-
742
- MMBuffer MMKV::getBytes(MMKVKey_t key) {
743
- if (isKeyEmpty(key)) {
744
- return MMBuffer();
745
- }
746
- SCOPED_LOCK(m_lock);
747
- SCOPED_LOCK(m_sharedProcessLock);
748
- auto data = getDataForKey(key);
749
- if (data.length() > 0) {
750
- try {
751
- CodedInputData input(data.getPtr(), data.length());
752
- return input.readData();
753
- } catch (std::exception &exception) {
754
- MMKVError("%s", exception.what());
755
- } catch (...) {
756
- MMKVError("decode fail");
757
- }
758
- }
759
- return MMBuffer();
760
- }
761
-
762
- bool MMKV::getVector(MMKVKey_t key, vector<string> &result) {
763
- if (isKeyEmpty(key)) {
764
- return false;
765
- }
766
- SCOPED_LOCK(m_lock);
767
- SCOPED_LOCK(m_sharedProcessLock);
768
- auto data = getDataForKey(key);
769
- if (data.length() > 0) {
770
- try {
771
- result = MiniPBCoder::decodeVector(data);
772
- return true;
773
- } catch (std::exception &exception) {
774
- MMKVError("%s", exception.what());
775
- } catch (...) {
776
- MMKVError("decode fail");
777
- }
778
- }
779
- return false;
780
- }
781
-
782
- void MMKV::shared_lock() {
783
- m_lock->lock();
784
- m_sharedProcessLock->lock();
785
- }
786
-
787
- void MMKV::shared_unlock() {
788
- m_sharedProcessLock->lock();
789
- m_lock->lock();
790
- }
791
-
792
- #endif // MMKV_APPLE
793
-
794
- bool MMKV::getBool(MMKVKey_t key, bool defaultValue, bool *hasValue) {
795
- if (isKeyEmpty(key)) {
796
- if (hasValue != nullptr) {
797
- *hasValue = false;
798
- }
799
- return defaultValue;
800
- }
801
- SCOPED_LOCK(m_lock);
802
- SCOPED_LOCK(m_sharedProcessLock);
803
- auto data = getDataForKey(key);
804
- if (data.length() > 0) {
805
- try {
806
- CodedInputData input(data.getPtr(), data.length());
807
- if (hasValue != nullptr) {
808
- *hasValue = true;
809
- }
810
- return input.readBool();
811
- } catch (std::exception &exception) {
812
- MMKVError("%s", exception.what());
813
- } catch (...) {
814
- MMKVError("decode fail");
815
- }
816
- }
817
- if (hasValue != nullptr) {
818
- *hasValue = false;
819
- }
820
- return defaultValue;
821
- }
822
-
823
- int32_t MMKV::getInt32(MMKVKey_t key, int32_t defaultValue, bool *hasValue) {
824
- if (isKeyEmpty(key)) {
825
- if (hasValue != nullptr) {
826
- *hasValue = false;
827
- }
828
- return defaultValue;
829
- }
830
- SCOPED_LOCK(m_lock);
831
- SCOPED_LOCK(m_sharedProcessLock);
832
- auto data = getDataForKey(key);
833
- if (data.length() > 0) {
834
- try {
835
- CodedInputData input(data.getPtr(), data.length());
836
- if (hasValue != nullptr) {
837
- *hasValue = true;
838
- }
839
- return input.readInt32();
840
- } catch (std::exception &exception) {
841
- MMKVError("%s", exception.what());
842
- } catch (...) {
843
- MMKVError("decode fail");
844
- }
845
- }
846
- if (hasValue != nullptr) {
847
- *hasValue = false;
848
- }
849
- return defaultValue;
850
- }
851
-
852
- uint32_t MMKV::getUInt32(MMKVKey_t key, uint32_t defaultValue, bool *hasValue) {
853
- if (isKeyEmpty(key)) {
854
- if (hasValue != nullptr) {
855
- *hasValue = false;
856
- }
857
- return defaultValue;
858
- }
859
- SCOPED_LOCK(m_lock);
860
- SCOPED_LOCK(m_sharedProcessLock);
861
- auto data = getDataForKey(key);
862
- if (data.length() > 0) {
863
- try {
864
- CodedInputData input(data.getPtr(), data.length());
865
- if (hasValue != nullptr) {
866
- *hasValue = true;
867
- }
868
- return input.readUInt32();
869
- } catch (std::exception &exception) {
870
- MMKVError("%s", exception.what());
871
- } catch (...) {
872
- MMKVError("decode fail");
873
- }
874
- }
875
- if (hasValue != nullptr) {
876
- *hasValue = false;
877
- }
878
- return defaultValue;
879
- }
880
-
881
- int64_t MMKV::getInt64(MMKVKey_t key, int64_t defaultValue, bool *hasValue) {
882
- if (isKeyEmpty(key)) {
883
- if (hasValue != nullptr) {
884
- *hasValue = false;
885
- }
886
- return defaultValue;
887
- }
888
- SCOPED_LOCK(m_lock);
889
- SCOPED_LOCK(m_sharedProcessLock);
890
- auto data = getDataForKey(key);
891
- if (data.length() > 0) {
892
- try {
893
- CodedInputData input(data.getPtr(), data.length());
894
- if (hasValue != nullptr) {
895
- *hasValue = true;
896
- }
897
- return input.readInt64();
898
- } catch (std::exception &exception) {
899
- MMKVError("%s", exception.what());
900
- } catch (...) {
901
- MMKVError("decode fail");
902
- }
903
- }
904
- if (hasValue != nullptr) {
905
- *hasValue = false;
906
- }
907
- return defaultValue;
908
- }
909
-
910
- uint64_t MMKV::getUInt64(MMKVKey_t key, uint64_t defaultValue, bool *hasValue) {
911
- if (isKeyEmpty(key)) {
912
- if (hasValue != nullptr) {
913
- *hasValue = false;
914
- }
915
- return defaultValue;
916
- }
917
- SCOPED_LOCK(m_lock);
918
- SCOPED_LOCK(m_sharedProcessLock);
919
- auto data = getDataForKey(key);
920
- if (data.length() > 0) {
921
- try {
922
- CodedInputData input(data.getPtr(), data.length());
923
- if (hasValue != nullptr) {
924
- *hasValue = true;
925
- }
926
- return input.readUInt64();
927
- } catch (std::exception &exception) {
928
- MMKVError("%s", exception.what());
929
- } catch (...) {
930
- MMKVError("decode fail");
931
- }
932
- }
933
- if (hasValue != nullptr) {
934
- *hasValue = false;
935
- }
936
- return defaultValue;
937
- }
938
-
939
- float MMKV::getFloat(MMKVKey_t key, float defaultValue, bool *hasValue) {
940
- if (isKeyEmpty(key)) {
941
- if (hasValue != nullptr) {
942
- *hasValue = false;
943
- }
944
- return defaultValue;
945
- }
946
- SCOPED_LOCK(m_lock);
947
- SCOPED_LOCK(m_sharedProcessLock);
948
- auto data = getDataForKey(key);
949
- if (data.length() > 0) {
950
- try {
951
- CodedInputData input(data.getPtr(), data.length());
952
- if (hasValue != nullptr) {
953
- *hasValue = true;
954
- }
955
- return input.readFloat();
956
- } catch (std::exception &exception) {
957
- MMKVError("%s", exception.what());
958
- } catch (...) {
959
- MMKVError("decode fail");
960
- }
961
- }
962
- if (hasValue != nullptr) {
963
- *hasValue = false;
964
- }
965
- return defaultValue;
966
- }
967
-
968
- double MMKV::getDouble(MMKVKey_t key, double defaultValue, bool *hasValue) {
969
- if (isKeyEmpty(key)) {
970
- if (hasValue != nullptr) {
971
- *hasValue = false;
972
- }
973
- return defaultValue;
974
- }
975
- SCOPED_LOCK(m_lock);
976
- SCOPED_LOCK(m_sharedProcessLock);
977
- auto data = getDataForKey(key);
978
- if (data.length() > 0) {
979
- try {
980
- CodedInputData input(data.getPtr(), data.length());
981
- if (hasValue != nullptr) {
982
- *hasValue = true;
983
- }
984
- return input.readDouble();
985
- } catch (std::exception &exception) {
986
- MMKVError("%s", exception.what());
987
- } catch (...) {
988
- MMKVError("decode fail");
989
- }
990
- }
991
- if (hasValue != nullptr) {
992
- *hasValue = false;
993
- }
994
- return defaultValue;
995
- }
996
-
997
- size_t MMKV::getValueSize(MMKVKey_t key, bool actualSize) {
998
- if (isKeyEmpty(key)) {
999
- return 0;
1000
- }
1001
- SCOPED_LOCK(m_lock);
1002
- SCOPED_LOCK(m_sharedProcessLock);
1003
- auto data = getDataForKey(key);
1004
- if (actualSize) {
1005
- try {
1006
- CodedInputData input(data.getPtr(), data.length());
1007
- auto length = input.readInt32();
1008
- if (length >= 0) {
1009
- auto s_length = static_cast<size_t>(length);
1010
- if (pbRawVarint32Size(length) + s_length == data.length()) {
1011
- return s_length;
1012
- }
1013
- }
1014
- } catch (std::exception &exception) {
1015
- MMKVError("%s", exception.what());
1016
- } catch (...) {
1017
- MMKVError("decode fail");
1018
- }
1019
- }
1020
- return data.length();
1021
- }
1022
-
1023
- int32_t MMKV::writeValueToBuffer(MMKVKey_t key, void *ptr, int32_t size) {
1024
- if (isKeyEmpty(key) || size < 0) {
1025
- return -1;
1026
- }
1027
- auto s_size = static_cast<size_t>(size);
1028
-
1029
- SCOPED_LOCK(m_lock);
1030
- SCOPED_LOCK(m_sharedProcessLock);
1031
- auto data = getDataForKey(key);
1032
- try {
1033
- CodedInputData input(data.getPtr(), data.length());
1034
- auto length = input.readInt32();
1035
- auto offset = pbRawVarint32Size(length);
1036
- if (length >= 0) {
1037
- auto s_length = static_cast<size_t>(length);
1038
- if (offset + s_length == data.length()) {
1039
- if (s_length <= s_size) {
1040
- memcpy(ptr, (uint8_t *) data.getPtr() + offset, s_length);
1041
- return length;
1042
- }
1043
- } else {
1044
- if (data.length() <= s_size) {
1045
- memcpy(ptr, data.getPtr(), data.length());
1046
- return static_cast<int32_t>(data.length());
1047
- }
1048
- }
1049
- }
1050
- } catch (std::exception &exception) {
1051
- MMKVError("%s", exception.what());
1052
- } catch (...) {
1053
- MMKVError("encode fail");
1054
- }
1055
- return -1;
1056
- }
1057
-
1058
- // enumerate
1059
-
1060
- bool MMKV::containsKey(MMKVKey_t key) {
1061
- SCOPED_LOCK(m_lock);
1062
- checkLoadData();
1063
-
1064
- if (mmkv_likely(!m_enableKeyExpire)) {
1065
- if (m_crypter) {
1066
- return m_dicCrypt->find(key) != m_dicCrypt->end();
1067
- } else {
1068
- return m_dic->find(key) != m_dic->end();
1069
- }
1070
- }
1071
- auto raw = getDataWithoutMTimeForKey(key);
1072
- return raw.length() != 0;
1073
- }
1074
-
1075
- size_t MMKV::count(bool filterExpire) {
1076
- SCOPED_LOCK(m_lock);
1077
- checkLoadData();
1078
-
1079
- if (mmkv_unlikely(filterExpire && m_enableKeyExpire)) {
1080
- SCOPED_LOCK(m_exclusiveProcessLock);
1081
- fullWriteback(nullptr, true);
1082
- }
1083
-
1084
- if (m_crypter) {
1085
- return m_dicCrypt->size();
1086
- } else {
1087
- return m_dic->size();
1088
- }
1089
- }
1090
-
1091
- size_t MMKV::totalSize() {
1092
- SCOPED_LOCK(m_lock);
1093
- checkLoadData();
1094
- return m_file->getFileSize();
1095
- }
1096
-
1097
- size_t MMKV::actualSize() {
1098
- SCOPED_LOCK(m_lock);
1099
- checkLoadData();
1100
- return m_actualSize;
1101
- }
1102
-
1103
- bool MMKV::removeValueForKey(MMKVKey_t key) {
1104
- if (isKeyEmpty(key)) {
1105
- return false;
1106
- }
1107
- if (isReadOnly()) {
1108
- MMKVWarning("[%s] file readonly", m_mmapID.c_str());
1109
- return false;
1110
- }
1111
- SCOPED_LOCK(m_lock);
1112
- SCOPED_LOCK(m_exclusiveProcessLock);
1113
- checkLoadData();
1114
-
1115
- return removeDataForKey(key);
1116
- }
1117
-
1118
- #ifndef MMKV_APPLE
1119
-
1120
- vector<string> MMKV::allKeys(bool filterExpire) {
1121
- SCOPED_LOCK(m_lock);
1122
- checkLoadData();
1123
-
1124
- if (mmkv_unlikely(filterExpire && m_enableKeyExpire)) {
1125
- SCOPED_LOCK(m_exclusiveProcessLock);
1126
- fullWriteback(nullptr, true);
1127
- }
1128
-
1129
- vector<string> keys;
1130
- if (m_crypter) {
1131
- for (const auto &itr : *m_dicCrypt) {
1132
- keys.push_back(itr.first);
1133
- }
1134
- } else {
1135
- for (const auto &itr : *m_dic) {
1136
- keys.push_back(itr.first);
1137
- }
1138
- }
1139
- return keys;
1140
- }
1141
-
1142
- bool MMKV::removeValuesForKeys(const vector<string> &arrKeys) {
1143
- if (isReadOnly()) {
1144
- MMKVWarning("[%s] file readonly", m_mmapID.c_str());
1145
- return false;
1146
- }
1147
- if (arrKeys.empty()) {
1148
- return true;
1149
- }
1150
- if (arrKeys.size() == 1) {
1151
- return removeValueForKey(arrKeys[0]);
1152
- }
1153
-
1154
- SCOPED_LOCK(m_lock);
1155
- SCOPED_LOCK(m_exclusiveProcessLock);
1156
- checkLoadData();
1157
-
1158
- size_t deleteCount = 0;
1159
- if (m_crypter) {
1160
- for (const auto &key : arrKeys) {
1161
- auto itr = m_dicCrypt->find(key);
1162
- if (itr != m_dicCrypt->end()) {
1163
- m_dicCrypt->erase(itr);
1164
- deleteCount++;
1165
- }
1166
- }
1167
- } else {
1168
- for (const auto &key : arrKeys) {
1169
- auto itr = m_dic->find(key);
1170
- if (itr != m_dic->end()) {
1171
- m_dic->erase(itr);
1172
- deleteCount++;
1173
- }
1174
- }
1175
- }
1176
- if (deleteCount > 0) {
1177
- m_hasFullWriteback = false;
1178
-
1179
- return fullWriteback();
1180
- }
1181
- return true;
1182
- }
1183
-
1184
- #endif // MMKV_APPLE
1185
-
1186
- // file
1187
-
1188
- void MMKV::sync(SyncFlag flag) {
1189
- MMKVInfo("MMKV::sync, SyncFlag = %d", flag);
1190
- SCOPED_LOCK(m_lock);
1191
- if (m_needLoadFromFile || !isFileValid()) {
1192
- return;
1193
- }
1194
- SCOPED_LOCK(m_exclusiveProcessLock);
1195
-
1196
- m_file->msync(flag);
1197
- m_metaFile->msync(flag);
1198
- }
1199
-
1200
- void MMKV::lock() {
1201
- SCOPED_LOCK(m_lock);
1202
- m_exclusiveProcessLock->lock();
1203
- }
1204
- void MMKV::unlock() {
1205
- SCOPED_LOCK(m_lock);
1206
- m_exclusiveProcessLock->unlock();
1207
- }
1208
- bool MMKV::try_lock() {
1209
- SCOPED_LOCK(m_lock);
1210
- return m_exclusiveProcessLock->try_lock();
1211
- }
1212
-
1213
- #ifndef MMKV_WIN32
1214
- void MMKV::lock_thread() {
1215
- m_lock->lock();
1216
- }
1217
- void MMKV::unlock_thread() {
1218
- m_lock->unlock();
1219
- }
1220
- bool MMKV::try_lock_thread() {
1221
- return m_lock->try_lock();
1222
- }
1223
- #endif
1224
-
1225
- // backup
1226
-
1227
- static bool backupOneToDirectoryByFilePath(const string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
1228
- File crcFile(srcPath, OpenFlag::ReadOnly);
1229
- if (!crcFile.isFileValid()) {
1230
- return false;
1231
- }
1232
-
1233
- bool ret;
1234
- {
1235
- #ifdef MMKV_WIN32
1236
- MMKVInfo("backup one mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1237
- #else
1238
- MMKVInfo("backup one mmkv[%s] from [%s] to [%s]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1239
- #endif
1240
- FileLock fileLock(crcFile.getFd());
1241
- InterProcessLock lock(&fileLock, SharedLockType);
1242
- SCOPED_LOCK(&lock);
1243
-
1244
- ret = copyFile(srcPath, dstPath);
1245
- if (ret) {
1246
- auto srcCRCPath = srcPath + CRC_SUFFIX;
1247
- auto dstCRCPath = dstPath + CRC_SUFFIX;
1248
- ret = copyFile(srcCRCPath, dstCRCPath);
1249
- }
1250
- MMKVInfo("finish backup one mmkv[%s]", mmapKey.c_str());
1251
- }
1252
- return ret;
1253
- }
1254
-
1255
- bool MMKV::backupOneToDirectory(const string &mmapKey, const MMKVPath_t &dstPath, const MMKVPath_t &srcPath, bool compareFullPath) {
1256
- if (!g_instanceLock) {
1257
- return false;
1258
- }
1259
- // we have to lock the creation of MMKV instance, regardless of in cache or not
1260
- SCOPED_LOCK(g_instanceLock);
1261
- MMKV *kv = nullptr;
1262
- if (!compareFullPath) {
1263
- auto itr = g_instanceDic->find(mmapKey);
1264
- if (itr != g_instanceDic->end()) {
1265
- kv = itr->second;
1266
- }
1267
- } else {
1268
- // mmapKey is actually filename, we can't simply call find()
1269
- for (auto &pair : *g_instanceDic) {
1270
- if (pair.second->m_path == srcPath) {
1271
- kv = pair.second;
1272
- break;
1273
- }
1274
- }
1275
- }
1276
- // get one in cache, do it the easy way
1277
- if (kv) {
1278
- #ifdef MMKV_WIN32
1279
- MMKVInfo("backup one cached mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1280
- #else
1281
- MMKVInfo("backup one cached mmkv[%s] from [%s] to [%s]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1282
- #endif
1283
- SCOPED_LOCK(kv->m_lock);
1284
- SCOPED_LOCK(kv->m_sharedProcessLock);
1285
-
1286
- kv->sync();
1287
- auto ret = copyFile(kv->m_path, dstPath);
1288
- if (ret) {
1289
- auto dstCRCPath = dstPath + CRC_SUFFIX;
1290
- ret = copyFile(kv->m_crcPath, dstCRCPath);
1291
- }
1292
- MMKVInfo("finish backup one mmkv[%s], ret: %d", mmapKey.c_str(), ret);
1293
- return ret;
1294
- }
1295
-
1296
- // no luck with cache, do it the hard way
1297
- bool ret = backupOneToDirectoryByFilePath(mmapKey, srcPath, dstPath);
1298
- return ret;
1299
- }
1300
-
1301
- bool MMKV::backupOneToDirectory(const string &mmapID, const MMKVPath_t &dstDir, const MMKVPath_t *srcDir) {
1302
- auto rootPath = srcDir ? srcDir : &g_rootDir;
1303
- if (*rootPath == dstDir) {
1304
- return true;
1305
- }
1306
- mkPath(dstDir);
1307
- auto encodePath = encodeFilePath(mmapID, dstDir);
1308
- auto dstPath = dstDir + MMKV_PATH_SLASH + encodePath;
1309
- auto mmapKey = mmapedKVKey(mmapID, rootPath);
1310
- #ifdef MMKV_ANDROID
1311
- // historically Android mistakenly use mmapKey as mmapID
1312
- auto srcPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);
1313
- #else
1314
- auto srcPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1315
- #endif
1316
- return backupOneToDirectory(mmapKey, dstPath, srcPath, false);
1317
- }
1318
-
1319
- bool endsWith(const MMKVPath_t &str, const MMKVPath_t &suffix) {
1320
- if (str.length() >= suffix.length()) {
1321
- return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
1322
- } else {
1323
- return false;
1324
- }
1325
- }
1326
-
1327
- MMKVPath_t filename(const MMKVPath_t &path) {
1328
- auto startPos = path.rfind(MMKV_PATH_SLASH);
1329
- startPos++; // don't need to check for npos, because npos+1 == 0
1330
- auto filename = path.substr(startPos);
1331
- return filename;
1332
- }
1333
-
1334
- size_t MMKV::backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &srcDir, bool isInSpecialDir) {
1335
- unordered_set<MMKVPath_t> mmapIDSet;
1336
- unordered_set<MMKVPath_t> mmapIDCRCSet;
1337
- walkInDir(srcDir, WalkFile, [&](const MMKVPath_t &filePath, WalkType) {
1338
- if (endsWith(filePath, CRC_SUFFIX)) {
1339
- mmapIDCRCSet.insert(filePath);
1340
- } else {
1341
- mmapIDSet.insert(filePath);
1342
- }
1343
- });
1344
-
1345
- size_t count = 0;
1346
- if (!mmapIDSet.empty()) {
1347
- mkPath(dstDir);
1348
- auto compareFullPath = isInSpecialDir;
1349
- for (auto &srcPath : mmapIDSet) {
1350
- auto srcCRCPath = srcPath + CRC_SUFFIX;
1351
- if (mmapIDCRCSet.find(srcCRCPath) == mmapIDCRCSet.end()) {
1352
- #ifdef MMKV_WIN32
1353
- MMKVWarning("crc not exist [%ls]", srcCRCPath.c_str());
1354
- #else
1355
- MMKVWarning("crc not exist [%s]", srcCRCPath.c_str());
1356
- #endif
1357
- continue;
1358
- }
1359
- auto basename = filename(srcPath);
1360
- const auto &strBasename = MMKVPath_t2String(basename);
1361
- auto mmapKey = isInSpecialDir ? strBasename : mmapedKVKey(strBasename, &srcDir);
1362
- auto dstPath = dstDir + MMKV_PATH_SLASH;
1363
- dstPath += basename;
1364
- if (backupOneToDirectory(mmapKey, dstPath, srcPath, compareFullPath)) {
1365
- count++;
1366
- }
1367
- }
1368
- }
1369
- return count;
1370
- }
1371
-
1372
- size_t MMKV::backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t *srcDir) {
1373
- auto rootPath = srcDir ? srcDir : &g_rootDir;
1374
- if (*rootPath == dstDir) {
1375
- return true;
1376
- }
1377
- auto count = backupAllToDirectory(dstDir, *rootPath, false);
1378
-
1379
- auto specialSrcDir = *rootPath + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1380
- if (isFileExist(specialSrcDir)) {
1381
- auto specialDstDir = dstDir + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1382
- count += backupAllToDirectory(specialDstDir, specialSrcDir, true);
1383
- }
1384
- return count;
1385
- }
1386
-
1387
- // restore
1388
-
1389
- static bool restoreOneFromDirectoryByFilePath(const string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
1390
- auto dstCRCPath = dstPath + CRC_SUFFIX;
1391
- File dstCRCFile(std::move(dstCRCPath), OpenFlag::ReadWrite | OpenFlag::Create);
1392
- if (!dstCRCFile.isFileValid()) {
1393
- return false;
1394
- }
1395
-
1396
- bool ret;
1397
- {
1398
- #ifdef MMKV_WIN32
1399
- MMKVInfo("restore one mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1400
- #else
1401
- MMKVInfo("restore one mmkv[%s] from [%s] to [%s]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1402
- #endif
1403
- FileLock fileLock(dstCRCFile.getFd());
1404
- InterProcessLock lock(&fileLock, ExclusiveLockType);
1405
- SCOPED_LOCK(&lock);
1406
-
1407
- ret = copyFileContent(srcPath, dstPath);
1408
- if (ret) {
1409
- auto srcCRCPath = srcPath + CRC_SUFFIX;
1410
- ret = copyFileContent(srcCRCPath, dstCRCFile.getFd());
1411
- }
1412
- MMKVInfo("finish restore one mmkv[%s]", mmapKey.c_str());
1413
- }
1414
- return ret;
1415
- }
1416
-
1417
- // We can't simply replace the existing file, because other processes might have already open it.
1418
- // They won't know a difference when the file has been replaced.
1419
- // We have to let them know by overriding the existing file with new content.
1420
- bool MMKV::restoreOneFromDirectory(const string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath, bool compareFullPath) {
1421
- if (!g_instanceLock) {
1422
- return false;
1423
- }
1424
- // we have to lock the creation of MMKV instance, regardless of in cache or not
1425
- SCOPED_LOCK(g_instanceLock);
1426
- MMKV *kv = nullptr;
1427
- if (!compareFullPath) {
1428
- auto itr = g_instanceDic->find(mmapKey);
1429
- if (itr != g_instanceDic->end()) {
1430
- kv = itr->second;
1431
- }
1432
- } else {
1433
- // mmapKey is actually filename, we can't simply call find()
1434
- for (auto &pair : *g_instanceDic) {
1435
- if (pair.second->m_path == dstPath) {
1436
- kv = pair.second;
1437
- break;
1438
- }
1439
- }
1440
- }
1441
- // get one in cache, do it the easy way
1442
- if (kv) {
1443
- #ifdef MMKV_WIN32
1444
- MMKVInfo("restore one cached mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1445
- #else
1446
- MMKVInfo("restore one cached mmkv[%s] from [%s] to [%s]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
1447
- #endif
1448
- SCOPED_LOCK(kv->m_lock);
1449
- SCOPED_LOCK(kv->m_exclusiveProcessLock);
1450
-
1451
- kv->sync();
1452
- auto ret = copyFileContent(srcPath, kv->m_file->getFd());
1453
- if (ret) {
1454
- auto srcCRCPath = srcPath + CRC_SUFFIX;
1455
- // ret = copyFileContent(srcCRCPath, kv->m_metaFile->getFd());
1456
- #ifndef MMKV_ANDROID
1457
- MemoryFile srcCRCFile(srcCRCPath);
1458
- #else
1459
- MemoryFile srcCRCFile(srcCRCPath, DEFAULT_MMAP_SIZE, MMFILE_TYPE_FILE);
1460
- #endif
1461
- if (srcCRCFile.isFileValid()) {
1462
- memcpy(kv->m_metaFile->getMemory(), srcCRCFile.getMemory(), sizeof(MMKVMetaInfo));
1463
- } else {
1464
- ret = false;
1465
- }
1466
- }
1467
-
1468
- // reload data after restore
1469
- kv->clearMemoryCache();
1470
- kv->loadFromFile();
1471
- if (kv->isMultiProcess()) {
1472
- kv->notifyContentChanged();
1473
- }
1474
-
1475
- MMKVInfo("finish restore one mmkv[%s], ret: %d", mmapKey.c_str(), ret);
1476
- return ret;
1477
- }
1478
-
1479
- // no luck with cache, do it the hard way
1480
- bool ret = restoreOneFromDirectoryByFilePath(mmapKey, srcPath, dstPath);
1481
- return ret;
1482
- }
1483
-
1484
- bool MMKV::restoreOneFromDirectory(const string &mmapID, const MMKVPath_t &srcDir, const MMKVPath_t *dstDir) {
1485
- auto rootPath = dstDir ? dstDir : &g_rootDir;
1486
- if (*rootPath == srcDir) {
1487
- return true;
1488
- }
1489
- mkPath(*rootPath);
1490
- auto encodePath = encodeFilePath(mmapID, *rootPath);
1491
- auto srcPath = srcDir + MMKV_PATH_SLASH + encodePath;
1492
- auto mmapKey = mmapedKVKey(mmapID, rootPath);
1493
- #ifdef MMKV_ANDROID
1494
- // historically Android mistakenly use mmapKey as mmapID
1495
- auto dstPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);
1496
- #else
1497
- auto dstPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1498
- #endif
1499
- return restoreOneFromDirectory(mmapKey, srcPath, dstPath, false);
1500
- }
1501
-
1502
- size_t MMKV::restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t &dstDir, bool isInSpecialDir) {
1503
- unordered_set<MMKVPath_t> mmapIDSet;
1504
- unordered_set<MMKVPath_t> mmapIDCRCSet;
1505
- walkInDir(srcDir, WalkFile, [&](const MMKVPath_t &filePath, WalkType) {
1506
- if (endsWith(filePath, CRC_SUFFIX)) {
1507
- mmapIDCRCSet.insert(filePath);
1508
- } else {
1509
- mmapIDSet.insert(filePath);
1510
- }
1511
- });
1512
-
1513
- size_t count = 0;
1514
- if (!mmapIDSet.empty()) {
1515
- mkPath(dstDir);
1516
- auto compareFullPath = isInSpecialDir;
1517
- for (auto &srcPath : mmapIDSet) {
1518
- auto srcCRCPath = srcPath + CRC_SUFFIX;
1519
- if (mmapIDCRCSet.find(srcCRCPath) == mmapIDCRCSet.end()) {
1520
- #ifdef MMKV_WIN32
1521
- MMKVWarning("crc not exist [%ls]", srcCRCPath.c_str());
1522
- #else
1523
- MMKVWarning("crc not exist [%s]", srcCRCPath.c_str());
1524
- #endif
1525
- continue;
1526
- }
1527
- auto basename = filename(srcPath);
1528
- const auto &strBasename = MMKVPath_t2String(basename);
1529
- auto mmapKey = isInSpecialDir ? strBasename : mmapedKVKey(strBasename, &dstDir);
1530
- auto dstPath = dstDir + MMKV_PATH_SLASH;
1531
- dstPath += basename;
1532
- if (restoreOneFromDirectory(mmapKey, srcPath, dstPath, compareFullPath)) {
1533
- count++;
1534
- }
1535
- }
1536
- }
1537
- return count;
1538
- }
1539
-
1540
- size_t MMKV::restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t *dstDir) {
1541
- auto rootPath = dstDir ? dstDir : &g_rootDir;
1542
- if (*rootPath == srcDir) {
1543
- return true;
1544
- }
1545
- auto count = restoreAllFromDirectory(srcDir, *rootPath, true);
1546
-
1547
- auto specialSrcDir = srcDir + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1548
- if (isFileExist(specialSrcDir)) {
1549
- auto specialDstDir = *rootPath + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1550
- count += restoreAllFromDirectory(specialSrcDir, specialDstDir, false);
1551
- }
1552
- return count;
1553
- }
1554
-
1555
- // callbacks
1556
-
1557
- void MMKV::registerErrorHandler(ErrorHandler handler) {
1558
- if (!g_instanceLock) {
1559
- return;
1560
- }
1561
- SCOPED_LOCK(g_instanceLock);
1562
- g_errorHandler = handler;
1563
- }
1564
-
1565
- void MMKV::unRegisterErrorHandler() {
1566
- if (!g_instanceLock) {
1567
- return;
1568
- }
1569
- SCOPED_LOCK(g_instanceLock);
1570
- g_errorHandler = nullptr;
1571
- }
1572
-
1573
- void MMKV::registerLogHandler(LogHandler handler) {
1574
- if (!g_instanceLock) {
1575
- return;
1576
- }
1577
- SCOPED_LOCK(g_instanceLock);
1578
- g_logHandler = handler;
1579
- }
1580
-
1581
- void MMKV::unRegisterLogHandler() {
1582
- if (!g_instanceLock) {
1583
- return;
1584
- }
1585
- SCOPED_LOCK(g_instanceLock);
1586
- g_logHandler = nullptr;
1587
- }
1588
-
1589
- void MMKV::setLogLevel(MMKVLogLevel level) {
1590
- if (!g_instanceLock) {
1591
- return;
1592
- }
1593
- SCOPED_LOCK(g_instanceLock);
1594
- g_currentLogLevel = level;
1595
- }
1596
-
1597
- static void mkSpecialCharacterFileDirectory() {
1598
- MMKVPath_t path = g_rootDir + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1599
- mkPath(path);
1600
- }
1601
-
1602
- template <typename T>
1603
- static string md5(const basic_string<T> &value) {
1604
- uint8_t md[MD5_DIGEST_LENGTH] = {};
1605
- char tmp[3] = {}, buf[33] = {};
1606
- openssl::MD5((const uint8_t *) value.c_str(), value.size() * (sizeof(T) / sizeof(uint8_t)), md);
1607
- for (auto ch : md) {
1608
- snprintf(tmp, sizeof(tmp), "%2.2x", ch);
1609
- strcat(buf, tmp);
1610
- }
1611
- return {buf};
1612
- }
1613
-
1614
- static MMKVPath_t encodeFilePath(const string &mmapID) {
1615
- const char *specialCharacters = "\\/:*?\"<>|";
1616
- string encodedID;
1617
- bool hasSpecialCharacter = false;
1618
- for (auto ch : mmapID) {
1619
- if (strchr(specialCharacters, ch) != nullptr) {
1620
- encodedID = md5(mmapID);
1621
- hasSpecialCharacter = true;
1622
- break;
1623
- }
1624
- }
1625
- if (hasSpecialCharacter) {
1626
- static ThreadOnceToken_t once = ThreadOnceUninitialized;
1627
- ThreadLock::ThreadOnce(&once, mkSpecialCharacterFileDirectory);
1628
- return MMKVPath_t(SPECIAL_CHARACTER_DIRECTORY_NAME) + MMKV_PATH_SLASH + string2MMKVPath_t(encodedID);
1629
- } else {
1630
- return string2MMKVPath_t(mmapID);
1631
- }
1632
- }
1633
-
1634
- static MMKVPath_t encodeFilePath(const string &mmapID, const MMKVPath_t &rootDir) {
1635
- const char *specialCharacters = "\\/:*?\"<>|";
1636
- string encodedID;
1637
- bool hasSpecialCharacter = false;
1638
- for (auto ch : mmapID) {
1639
- if (strchr(specialCharacters, ch) != nullptr) {
1640
- encodedID = md5(mmapID);
1641
- hasSpecialCharacter = true;
1642
- break;
1643
- }
1644
- }
1645
- if (hasSpecialCharacter) {
1646
- MMKVPath_t path = rootDir + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME;
1647
- mkPath(path);
1648
-
1649
- return MMKVPath_t(SPECIAL_CHARACTER_DIRECTORY_NAME) + MMKV_PATH_SLASH + string2MMKVPath_t(encodedID);
1650
- } else {
1651
- return string2MMKVPath_t(mmapID);
1652
- }
1653
- }
1654
-
1655
- string mmapedKVKey(const string &mmapID, const MMKVPath_t *rootPath) {
1656
- if (rootPath && g_rootDir != (*rootPath)) {
1657
- return md5(*rootPath + MMKV_PATH_SLASH + string2MMKVPath_t(mmapID));
1658
- }
1659
- return mmapID;
1660
- }
1661
-
1662
- MMKVPath_t mappedKVPathWithID(const string &mmapID, MMKVMode mode, const MMKVPath_t *rootPath) {
1663
- #ifndef MMKV_ANDROID
1664
- if (rootPath) {
1665
- #else
1666
- if (mode & MMKV_ASHMEM) {
1667
- return ashmemMMKVPathWithID(encodeFilePath(mmapID));
1668
- } else if (rootPath) {
1669
- #endif
1670
- return *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapID);
1671
- }
1672
- return g_rootDir + MMKV_PATH_SLASH + encodeFilePath(mmapID);
1673
- }
1674
-
1675
- MMKVPath_t crcPathWithID(const string &mmapID, MMKVMode mode, const MMKVPath_t *rootPath) {
1676
- #ifndef MMKV_ANDROID
1677
- if (rootPath) {
1678
- #else
1679
- if (mode & MMKV_ASHMEM) {
1680
- return ashmemMMKVPathWithID(encodeFilePath(mmapID)) + CRC_SUFFIX;
1681
- } else if (rootPath) {
1682
- #endif
1683
- return *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapID) + CRC_SUFFIX;
1684
- }
1685
- return g_rootDir + MMKV_PATH_SLASH + encodeFilePath(mmapID) + CRC_SUFFIX;
1686
- }
1687
-
1688
- MMKVRecoverStrategic onMMKVCRCCheckFail(const string &mmapID) {
1689
- if (g_errorHandler) {
1690
- return g_errorHandler(mmapID, MMKVErrorType::MMKVCRCCheckFail);
1691
- }
1692
- return OnErrorDiscard;
1693
- }
1694
-
1695
- MMKVRecoverStrategic onMMKVFileLengthError(const string &mmapID) {
1696
- if (g_errorHandler) {
1697
- return g_errorHandler(mmapID, MMKVErrorType::MMKVFileLength);
1698
- }
1699
- return OnErrorDiscard;
1700
- }
1701
-
1702
- MMKV_NAMESPACE_END