react-native-mmkv 2.10.2 → 2.12.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 (56) hide show
  1. package/MMKV/Core/CodedInputData.cpp +28 -4
  2. package/MMKV/Core/CodedInputData.h +5 -1
  3. package/MMKV/Core/CodedOutputData.cpp +12 -0
  4. package/MMKV/Core/CodedOutputData.h +6 -0
  5. package/MMKV/Core/MMBuffer.cpp +7 -0
  6. package/MMKV/Core/MMBuffer.h +3 -0
  7. package/MMKV/Core/MMKV.cpp +114 -19
  8. package/MMKV/Core/MMKV.h +69 -33
  9. package/MMKV/Core/MMKVPredef.h +1 -1
  10. package/MMKV/Core/MMKV_Android.cpp +10 -8
  11. package/MMKV/Core/MMKV_IO.cpp +386 -60
  12. package/MMKV/Core/MMKV_OSX.cpp +51 -30
  13. package/MMKV/Core/MMKV_OSX.h +10 -4
  14. package/MMKV/Core/MemoryFile.cpp +31 -11
  15. package/MMKV/Core/MemoryFile.h +8 -3
  16. package/MMKV/Core/MemoryFile_Android.cpp +2 -2
  17. package/MMKV/Core/MemoryFile_OSX.cpp +2 -3
  18. package/MMKV/Core/MemoryFile_Win32.cpp +8 -5
  19. package/MMKV/Core/MiniPBCoder.cpp +11 -0
  20. package/MMKV/Core/MiniPBCoder.h +3 -0
  21. package/MMKV/Core/MiniPBCoder_OSX.cpp +8 -0
  22. package/MMKV/Core/ThreadLock.cpp +5 -0
  23. package/MMKV/Core/ThreadLock.h +4 -0
  24. package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +8 -0
  25. package/MMKV/Core/core.vcxproj +3 -3
  26. package/MMKV/README.md +3 -3
  27. package/README.md +9 -1
  28. package/android/build.gradle +21 -1
  29. package/android/src/hasNamespace/AndroidManifest.xml +3 -0
  30. package/android/src/main/cpp/MmkvHostObject.cpp +191 -204
  31. package/android/src/main/cpp/MmkvHostObject.h +2 -2
  32. package/android/src/main/cpp/cpp-adapter.cpp +62 -49
  33. package/cpp/TypedArray.cpp +69 -76
  34. package/cpp/TypedArray.h +66 -91
  35. package/img/banner-dark.png +0 -0
  36. package/img/banner-light.png +0 -0
  37. package/ios/JSIUtils.h +27 -39
  38. package/ios/JSIUtils.mm +110 -138
  39. package/ios/MmkvHostObject.h +2 -2
  40. package/ios/MmkvHostObject.mm +188 -205
  41. package/ios/MmkvModule.mm +68 -52
  42. package/lib/commonjs/createMMKV.web.js +1 -1
  43. package/lib/commonjs/createMMKV.web.js.map +1 -1
  44. package/lib/commonjs/hooks.js +16 -13
  45. package/lib/commonjs/hooks.js.map +1 -1
  46. package/lib/module/createMMKV.web.js +1 -1
  47. package/lib/module/createMMKV.web.js.map +1 -1
  48. package/lib/module/hooks.js +16 -13
  49. package/lib/module/hooks.js.map +1 -1
  50. package/lib/typescript/createMMKV.web.d.ts.map +1 -1
  51. package/lib/typescript/hooks.d.ts.map +1 -1
  52. package/package.json +13 -3
  53. package/react-native-mmkv.podspec +1 -1
  54. package/src/createMMKV.web.ts +4 -2
  55. package/src/hooks.ts +19 -16
  56. package/MMKV/LICENSE.TXT +0 -193
@@ -21,6 +21,7 @@
21
21
  #include "CodedInputData.h"
22
22
  #include "PBUtility.h"
23
23
  #include <stdexcept>
24
+ #include <cstring>
24
25
 
25
26
  #ifdef MMKV_APPLE
26
27
  # if __has_feature(objc_arc)
@@ -100,6 +101,22 @@ string CodedInputData::readString() {
100
101
  }
101
102
  }
102
103
 
104
+ void CodedInputData::readString(string &s) {
105
+ int32_t size = readRawVarint32();
106
+ if (size < 0) {
107
+ throw length_error("InvalidProtocolBuffer negativeSize");
108
+ }
109
+
110
+ auto s_size = static_cast<size_t>(size);
111
+ if (s_size <= m_size - m_position) {
112
+ s.resize(s_size);
113
+ memcpy((void *) s.data(), (char *) (m_ptr + m_position), s_size);
114
+ m_position += s_size;
115
+ } else {
116
+ throw out_of_range("InvalidProtocolBuffer truncatedMessage");
117
+ }
118
+ }
119
+
103
120
  string CodedInputData::readString(KeyValueHolder &kvHolder) {
104
121
  kvHolder.offset = static_cast<uint32_t>(m_position);
105
122
 
@@ -123,17 +140,24 @@ string CodedInputData::readString(KeyValueHolder &kvHolder) {
123
140
 
124
141
  #endif
125
142
 
126
- MMBuffer CodedInputData::readData() {
143
+ MMBuffer CodedInputData::readRealData(mmkv::MMBuffer & data) {
144
+ CodedInputData input(data.getPtr(), data.length());
145
+ return input.readData(false, true);
146
+ }
147
+
148
+ MMBuffer CodedInputData::readData(bool copy, bool exactly) {
127
149
  int32_t size = this->readRawVarint32();
128
150
  if (size < 0) {
129
151
  throw length_error("InvalidProtocolBuffer negativeSize");
130
152
  }
131
153
 
132
154
  auto s_size = static_cast<size_t>(size);
133
- if (s_size <= m_size - m_position) {
134
- MMBuffer data(((int8_t *) m_ptr) + m_position, s_size);
155
+ bool isSizeValid = exactly ? (s_size == m_size - m_position) : (s_size <= m_size - m_position);
156
+ if (isSizeValid) {
157
+ size_t pos = m_position;
135
158
  m_position += s_size;
136
- return data;
159
+ auto copyFlag = copy ? MMBufferCopy : MMBufferNoCopy;
160
+ return MMBuffer(((int8_t *) m_ptr) + pos, s_size, copyFlag);
137
161
  } else {
138
162
  throw out_of_range("InvalidProtocolBuffer truncatedMessage");
139
163
  }
@@ -64,11 +64,15 @@ public:
64
64
 
65
65
  uint32_t readUInt32();
66
66
 
67
- MMBuffer readData();
67
+ // exactly is like getValueSize(actualSize = true)
68
+ MMBuffer readData(bool copy = true, bool exactly = false);
68
69
  void readData(KeyValueHolder &kvHolder);
69
70
 
71
+ static MMBuffer readRealData(mmkv::MMBuffer & data);
72
+
70
73
  #ifndef MMKV_APPLE
71
74
  std::string readString();
75
+ void readString(std::string &s);
72
76
  std::string readString(KeyValueHolder &kvHolder);
73
77
  #else
74
78
  NSString *readString();
@@ -109,6 +109,18 @@ void CodedOutputData::seek(size_t addedSize) {
109
109
  }
110
110
  }
111
111
 
112
+ void CodedOutputData::reset() {
113
+ m_position = 0;
114
+ }
115
+
116
+ size_t CodedOutputData::getPosition() {
117
+ return m_position;
118
+ }
119
+
120
+ void CodedOutputData::setPosition(size_t position) {
121
+ m_position = position;
122
+ }
123
+
112
124
  void CodedOutputData::writeRawByte(uint8_t value) {
113
125
  if (m_position == m_size) {
114
126
  throw out_of_range("m_position: " + to_string(m_position) + " m_size: " + to_string(m_size));
@@ -43,6 +43,12 @@ public:
43
43
 
44
44
  void seek(size_t addedSize);
45
45
 
46
+ void reset();
47
+
48
+ size_t getPosition();
49
+
50
+ void setPosition(size_t position);
51
+
46
52
  void writeRawByte(uint8_t value);
47
53
 
48
54
  void writeRawLittleEndian32(int32_t value);
@@ -84,6 +84,13 @@ MMBuffer::MMBuffer(void *source, size_t length, MMBufferCopyFlag flag) : isNoCop
84
84
  }
85
85
  }
86
86
 
87
+ bool MMBuffer::operator==(const MMBuffer& other) const {
88
+ if (this->length() != other.length()) {
89
+ return false;
90
+ }
91
+ return !memcmp((uint8_t*)this->getPtr(), (uint8_t*)other.getPtr(), this->length());
92
+ }
93
+
87
94
  #ifdef MMKV_APPLE
88
95
  MMBuffer::MMBuffer(NSData *data, MMBufferCopyFlag flag)
89
96
  : type(MMBufferType_Normal), ptr((void *) data.bytes), size(data.length), isNoCopy(flag) {
@@ -91,6 +91,9 @@ public:
91
91
  // transfer ownership to others
92
92
  void detach();
93
93
 
94
+ // compare two MMBuffer
95
+ bool operator==(const MMBuffer& other) const;
96
+
94
97
  // those are expensive, just forbid it for possibly misuse
95
98
  explicit MMBuffer(const MMBuffer &other) = delete;
96
99
  MMBuffer &operator=(const MMBuffer &other) = delete;
@@ -26,6 +26,7 @@
26
26
  #include "MMKVLog.h"
27
27
  #include "MMKVMetaInfo.hpp"
28
28
  #include "MMKV_IO.h"
29
+ #include "MMKV_OSX.h"
29
30
  #include "MemoryFile.h"
30
31
  #include "MiniPBCoder.h"
31
32
  #include "PBUtility.h"
@@ -51,6 +52,7 @@
51
52
  # if __has_feature(objc_arc)
52
53
  # error This file must be compiled with MRC. Use -fno-objc-arc flag.
53
54
  # endif
55
+ # include "MMKV_OSX.h"
54
56
  #endif // MMKV_APPLE
55
57
 
56
58
  using namespace std;
@@ -77,13 +79,14 @@ bool endsWith(const MMKVPath_t &str, const MMKVPath_t &suffix);
77
79
  MMKVPath_t filename(const MMKVPath_t &path);
78
80
 
79
81
  #ifndef MMKV_ANDROID
80
- MMKV::MMKV(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath)
82
+ MMKV::MMKV(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity)
81
83
  : m_mmapID(mmapID)
82
84
  , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath))
83
85
  , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath))
84
86
  , m_dic(nullptr)
85
87
  , m_dicCrypt(nullptr)
86
- , m_file(new MemoryFile(m_path))
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))
87
90
  , m_metaFile(new MemoryFile(m_crcPath))
88
91
  , m_metaInfo(new MMKVMetaInfo())
89
92
  , m_crypter(nullptr)
@@ -116,10 +119,10 @@ MMKV::MMKV(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *ro
116
119
  m_exclusiveProcessLock->m_enable = m_isInterProcess;
117
120
 
118
121
  // sensitive zone
119
- {
122
+ /*{
120
123
  SCOPED_LOCK(m_sharedProcessLock);
121
124
  loadFromFile();
122
- }
125
+ }*/
123
126
  }
124
127
  #endif
125
128
 
@@ -193,7 +196,7 @@ void initialize() {
193
196
  #endif
194
197
  }
195
198
 
196
- ThreadOnceToken_t once_control = ThreadOnceUninitialized;
199
+ static ThreadOnceToken_t once_control = ThreadOnceUninitialized;
197
200
 
198
201
  void MMKV::initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel, mmkv::LogHandler handler) {
199
202
  g_currentLogLevel = logLevel;
@@ -201,6 +204,22 @@ void MMKV::initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel, mmkv
201
204
 
202
205
  ThreadLock::ThreadOnce(&once_control, initialize);
203
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
+
204
223
  g_rootDir = rootDir;
205
224
  mkPath(g_rootDir);
206
225
 
@@ -212,7 +231,7 @@ const MMKVPath_t &MMKV::getRootDir() {
212
231
  }
213
232
 
214
233
  #ifndef MMKV_ANDROID
215
- MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath) {
234
+ MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity) {
216
235
 
217
236
  if (mmapID.empty()) {
218
237
  return nullptr;
@@ -234,7 +253,7 @@ MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MM
234
253
  MMKVInfo("prepare to load %s (id %s) from rootPath %s", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str());
235
254
  }
236
255
 
237
- auto kv = new MMKV(mmapID, mode, cryptKey, rootPath);
256
+ auto kv = new MMKV(mmapID, mode, cryptKey, rootPath, expectedCapacity);
238
257
  kv->m_mmapKey = mmapKey;
239
258
  (*g_instanceDic)[mmapKey] = kv;
240
259
  return kv;
@@ -281,7 +300,7 @@ void MMKV::unRegisterContentChangeHandler() {
281
300
  g_contentChangeHandler = nullptr;
282
301
  }
283
302
 
284
- void MMKV::clearMemoryCache() {
303
+ void MMKV::clearMemoryCache(bool keepSpace) {
285
304
  SCOPED_LOCK(m_lock);
286
305
  if (m_needLoadFromFile) {
287
306
  return;
@@ -305,8 +324,11 @@ void MMKV::clearMemoryCache() {
305
324
  delete m_output;
306
325
  m_output = nullptr;
307
326
 
308
- m_file->clearMemoryCache();
309
- m_metaFile->clearMemoryCache();
327
+ if (!keepSpace) {
328
+ m_file->clearMemoryCache();
329
+ }
330
+ // inter-process lock rely on MetaFile's fd, never close it
331
+ // m_metaFile->clearMemoryCache();
310
332
  m_actualSize = 0;
311
333
  m_metaInfo->m_crcDigest = 0;
312
334
  }
@@ -407,6 +429,15 @@ void MMKV::recaculateCRCDigestWithIV(const void *iv) {
407
429
  }
408
430
  }
409
431
 
432
+ void MMKV::recaculateCRCDigestOnly() {
433
+ auto ptr = (const uint8_t *) m_file->getMemory();
434
+ if (ptr) {
435
+ m_crcDigest = 0;
436
+ m_crcDigest = (uint32_t) CRC32(0, ptr + Fixed32Size, (uint32_t) m_actualSize);
437
+ writeActualSize(m_actualSize, m_crcDigest, nullptr, KeepSequence);
438
+ }
439
+ }
440
+
410
441
  void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length) {
411
442
  if (ptr == nullptr) {
412
443
  return;
@@ -663,7 +694,7 @@ bool MMKV::set(const vector<string> &v, MMKVKey_t key, uint32_t expireDuration)
663
694
  auto data = MiniPBCoder::encodeDataWithObject(v);
664
695
  if (unlikely(m_enableKeyExpire) && data.length() > 0) {
665
696
  auto tmp = MMBuffer(data.length() + Fixed32Size);
666
- auto ptr = (uint8_t *)tmp.getPtr();
697
+ auto ptr = (uint8_t *) tmp.getPtr();
667
698
  memcpy(ptr, data.getPtr(), data.length());
668
699
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
669
700
  memcpy(ptr + data.length(), &time, Fixed32Size);
@@ -672,7 +703,7 @@ bool MMKV::set(const vector<string> &v, MMKVKey_t key, uint32_t expireDuration)
672
703
  return setDataForKey(std::move(data), key);
673
704
  }
674
705
 
675
- bool MMKV::getString(MMKVKey_t key, string &result) {
706
+ bool MMKV::getString(MMKVKey_t key, string &result, bool inplaceModification) {
676
707
  if (isKeyEmpty(key)) {
677
708
  return false;
678
709
  }
@@ -682,10 +713,16 @@ bool MMKV::getString(MMKVKey_t key, string &result) {
682
713
  if (data.length() > 0) {
683
714
  try {
684
715
  CodedInputData input(data.getPtr(), data.length());
685
- result = input.readString();
716
+ if (inplaceModification) {
717
+ input.readString(result);
718
+ } else {
719
+ result = input.readString();
720
+ }
686
721
  return true;
687
722
  } catch (std::exception &exception) {
688
723
  MMKVError("%s", exception.what());
724
+ } catch (...) {
725
+ MMKVError("decode fail");
689
726
  }
690
727
  }
691
728
  return false;
@@ -701,10 +738,12 @@ bool MMKV::getBytes(MMKVKey_t key, mmkv::MMBuffer &result) {
701
738
  if (data.length() > 0) {
702
739
  try {
703
740
  CodedInputData input(data.getPtr(), data.length());
704
- result = std::move(input.readData());
741
+ result = input.readData();
705
742
  return true;
706
743
  } catch (std::exception &exception) {
707
744
  MMKVError("%s", exception.what());
745
+ } catch (...) {
746
+ MMKVError("decode fail");
708
747
  }
709
748
  }
710
749
  return false;
@@ -723,6 +762,8 @@ MMBuffer MMKV::getBytes(MMKVKey_t key) {
723
762
  return input.readData();
724
763
  } catch (std::exception &exception) {
725
764
  MMKVError("%s", exception.what());
765
+ } catch (...) {
766
+ MMKVError("decode fail");
726
767
  }
727
768
  }
728
769
  return MMBuffer();
@@ -741,6 +782,8 @@ bool MMKV::getVector(MMKVKey_t key, vector<string> &result) {
741
782
  return true;
742
783
  } catch (std::exception &exception) {
743
784
  MMKVError("%s", exception.what());
785
+ } catch (...) {
786
+ MMKVError("decode fail");
744
787
  }
745
788
  }
746
789
  return false;
@@ -767,6 +810,8 @@ bool MMKV::getBool(MMKVKey_t key, bool defaultValue, bool *hasValue) {
767
810
  return input.readBool();
768
811
  } catch (std::exception &exception) {
769
812
  MMKVError("%s", exception.what());
813
+ } catch (...) {
814
+ MMKVError("decode fail");
770
815
  }
771
816
  }
772
817
  if (hasValue != nullptr) {
@@ -794,6 +839,8 @@ int32_t MMKV::getInt32(MMKVKey_t key, int32_t defaultValue, bool *hasValue) {
794
839
  return input.readInt32();
795
840
  } catch (std::exception &exception) {
796
841
  MMKVError("%s", exception.what());
842
+ } catch (...) {
843
+ MMKVError("decode fail");
797
844
  }
798
845
  }
799
846
  if (hasValue != nullptr) {
@@ -821,6 +868,8 @@ uint32_t MMKV::getUInt32(MMKVKey_t key, uint32_t defaultValue, bool *hasValue) {
821
868
  return input.readUInt32();
822
869
  } catch (std::exception &exception) {
823
870
  MMKVError("%s", exception.what());
871
+ } catch (...) {
872
+ MMKVError("decode fail");
824
873
  }
825
874
  }
826
875
  if (hasValue != nullptr) {
@@ -848,6 +897,8 @@ int64_t MMKV::getInt64(MMKVKey_t key, int64_t defaultValue, bool *hasValue) {
848
897
  return input.readInt64();
849
898
  } catch (std::exception &exception) {
850
899
  MMKVError("%s", exception.what());
900
+ } catch (...) {
901
+ MMKVError("decode fail");
851
902
  }
852
903
  }
853
904
  if (hasValue != nullptr) {
@@ -875,6 +926,8 @@ uint64_t MMKV::getUInt64(MMKVKey_t key, uint64_t defaultValue, bool *hasValue) {
875
926
  return input.readUInt64();
876
927
  } catch (std::exception &exception) {
877
928
  MMKVError("%s", exception.what());
929
+ } catch (...) {
930
+ MMKVError("decode fail");
878
931
  }
879
932
  }
880
933
  if (hasValue != nullptr) {
@@ -902,6 +955,8 @@ float MMKV::getFloat(MMKVKey_t key, float defaultValue, bool *hasValue) {
902
955
  return input.readFloat();
903
956
  } catch (std::exception &exception) {
904
957
  MMKVError("%s", exception.what());
958
+ } catch (...) {
959
+ MMKVError("decode fail");
905
960
  }
906
961
  }
907
962
  if (hasValue != nullptr) {
@@ -929,6 +984,8 @@ double MMKV::getDouble(MMKVKey_t key, double defaultValue, bool *hasValue) {
929
984
  return input.readDouble();
930
985
  } catch (std::exception &exception) {
931
986
  MMKVError("%s", exception.what());
987
+ } catch (...) {
988
+ MMKVError("decode fail");
932
989
  }
933
990
  }
934
991
  if (hasValue != nullptr) {
@@ -956,6 +1013,8 @@ size_t MMKV::getValueSize(MMKVKey_t key, bool actualSize) {
956
1013
  }
957
1014
  } catch (std::exception &exception) {
958
1015
  MMKVError("%s", exception.what());
1016
+ } catch (...) {
1017
+ MMKVError("decode fail");
959
1018
  }
960
1019
  }
961
1020
  return data.length();
@@ -990,6 +1049,8 @@ int32_t MMKV::writeValueToBuffer(MMKVKey_t key, void *ptr, int32_t size) {
990
1049
  }
991
1050
  } catch (std::exception &exception) {
992
1051
  MMKVError("%s", exception.what());
1052
+ } catch (...) {
1053
+ MMKVError("encode fail");
993
1054
  }
994
1055
  return -1;
995
1056
  }
@@ -1011,9 +1072,15 @@ bool MMKV::containsKey(MMKVKey_t key) {
1011
1072
  return raw.length() != 0;
1012
1073
  }
1013
1074
 
1014
- size_t MMKV::count() {
1075
+ size_t MMKV::count(bool filterExpire) {
1015
1076
  SCOPED_LOCK(m_lock);
1016
1077
  checkLoadData();
1078
+
1079
+ if (unlikely(filterExpire && m_enableKeyExpire)) {
1080
+ SCOPED_LOCK(m_exclusiveProcessLock);
1081
+ fullWriteback(nullptr, true);
1082
+ }
1083
+
1017
1084
  if (m_crypter) {
1018
1085
  return m_dicCrypt->size();
1019
1086
  } else {
@@ -1046,10 +1113,15 @@ void MMKV::removeValueForKey(MMKVKey_t key) {
1046
1113
 
1047
1114
  #ifndef MMKV_APPLE
1048
1115
 
1049
- vector<string> MMKV::allKeys() {
1116
+ vector<string> MMKV::allKeys(bool filterExpire) {
1050
1117
  SCOPED_LOCK(m_lock);
1051
1118
  checkLoadData();
1052
1119
 
1120
+ if (unlikely(filterExpire && m_enableKeyExpire)) {
1121
+ SCOPED_LOCK(m_exclusiveProcessLock);
1122
+ fullWriteback(nullptr, true);
1123
+ }
1124
+
1053
1125
  vector<string> keys;
1054
1126
  if (m_crypter) {
1055
1127
  for (const auto &itr : *m_dicCrypt) {
@@ -1105,6 +1177,7 @@ void MMKV::removeValuesForKeys(const vector<string> &arrKeys) {
1105
1177
  // file
1106
1178
 
1107
1179
  void MMKV::sync(SyncFlag flag) {
1180
+ MMKVInfo("MMKV::sync, SyncFlag = %d", flag);
1108
1181
  SCOPED_LOCK(m_lock);
1109
1182
  if (m_needLoadFromFile || !isFileValid()) {
1110
1183
  return;
@@ -1128,6 +1201,18 @@ bool MMKV::try_lock() {
1128
1201
  return m_exclusiveProcessLock->try_lock();
1129
1202
  }
1130
1203
 
1204
+ #ifndef MMKV_WIN32
1205
+ void MMKV::lock_thread() {
1206
+ m_lock->lock();
1207
+ }
1208
+ void MMKV::unlock_thread() {
1209
+ m_lock->unlock();
1210
+ }
1211
+ bool MMKV::try_lock_thread() {
1212
+ return m_lock->try_lock();
1213
+ }
1214
+ #endif
1215
+
1131
1216
  // backup
1132
1217
 
1133
1218
  static bool backupOneToDirectoryByFilePath(const string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
@@ -1351,7 +1436,17 @@ bool MMKV::restoreOneFromDirectory(const string &mmapKey, const MMKVPath_t &srcP
1351
1436
  auto ret = copyFileContent(srcPath, kv->m_file->getFd());
1352
1437
  if (ret) {
1353
1438
  auto srcCRCPath = srcPath + CRC_SUFFIX;
1354
- ret = copyFileContent(srcCRCPath, kv->m_metaFile->getFd());
1439
+ // ret = copyFileContent(srcCRCPath, kv->m_metaFile->getFd());
1440
+ #ifndef MMKV_ANDROID
1441
+ MemoryFile srcCRCFile(srcCRCPath);
1442
+ #else
1443
+ MemoryFile srcCRCFile(srcCRCPath, DEFAULT_MMAP_SIZE, MMFILE_TYPE_FILE);
1444
+ #endif
1445
+ if (srcCRCFile.isFileValid()) {
1446
+ memcpy(kv->m_metaFile->getMemory(), srcCRCFile.getMemory(), sizeof(MMKVMetaInfo));
1447
+ } else {
1448
+ ret = false;
1449
+ }
1355
1450
  }
1356
1451
 
1357
1452
  // reload data after restore
@@ -1496,8 +1591,8 @@ static MMKVPath_t encodeFilePath(const string &mmapID) {
1496
1591
  }
1497
1592
  }
1498
1593
  if (hasSpecialCharacter) {
1499
- static ThreadOnceToken_t once_control = ThreadOnceUninitialized;
1500
- ThreadLock::ThreadOnce(&once_control, mkSpecialCharacterFileDirectory);
1594
+ static ThreadOnceToken_t once = ThreadOnceUninitialized;
1595
+ ThreadLock::ThreadOnce(&once, mkSpecialCharacterFileDirectory);
1501
1596
  return MMKVPath_t(SPECIAL_CHARACTER_DIRECTORY_NAME) + MMKV_PATH_SLASH + string2MMKVPath_t(encodedID);
1502
1597
  } else {
1503
1598
  return string2MMKVPath_t(mmapID);