react-native-mmkv 3.0.0-beta.6 → 3.0.0-beta.8

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 (57) hide show
  1. package/MMKV/Core/CMakeLists.txt +1 -1
  2. package/MMKV/Core/Core.xcodeproj/project.pbxproj +4 -6
  3. package/MMKV/Core/KeyValueHolder.cpp +1 -1
  4. package/MMKV/Core/KeyValueHolder.h +5 -1
  5. package/MMKV/Core/MMBuffer.h +1 -1
  6. package/MMKV/Core/MMKV.cpp +70 -73
  7. package/MMKV/Core/MMKV.h +126 -11
  8. package/MMKV/Core/MMKVPredef.h +44 -3
  9. package/MMKV/Core/MMKV_IO.cpp +47 -33
  10. package/MMKV/Core/MMKV_OSX.cpp +16 -29
  11. package/MMKV/Core/MemoryFile_Android.cpp +27 -13
  12. package/MMKV/Core/MiniPBCoder.cpp +308 -9
  13. package/MMKV/Core/MiniPBCoder.h +36 -17
  14. package/MMKV/Core/MiniPBCoder_OSX.cpp +1 -0
  15. package/MMKV/Core/PBEncodeItem.hpp +18 -0
  16. package/MMKV/Core/PBUtility.h +0 -12
  17. package/MMKV/Core/ThreadLock.cpp +1 -3
  18. package/MMKV/Core/aes/AESCrypt.cpp +26 -6
  19. package/MMKV/Core/aes/AESCrypt.h +5 -1
  20. package/MMKV/Core/core.vcxproj +4 -4
  21. package/MMKV/Core/crc32/Checksum.h +4 -1
  22. package/android/CMakeLists.txt +0 -1
  23. package/android/src/main/java/com/mrousavy/mmkv/MmkvPlatformContextModule.java +9 -0
  24. package/cpp/MmkvHostObject.cpp +35 -37
  25. package/ios/MmkvPlatformContextModule.mm +19 -1
  26. package/lib/commonjs/MMKV.js.map +1 -1
  27. package/lib/commonjs/NativeMmkvPlatformContext.js.map +1 -1
  28. package/lib/commonjs/createMMKV.js +17 -0
  29. package/lib/commonjs/createMMKV.js.map +1 -1
  30. package/lib/commonjs/hooks.js.map +1 -1
  31. package/lib/module/MMKV.js.map +1 -1
  32. package/lib/module/NativeMmkvPlatformContext.js.map +1 -1
  33. package/lib/module/createMMKV.js +17 -0
  34. package/lib/module/createMMKV.js.map +1 -1
  35. package/lib/module/hooks.js.map +1 -1
  36. package/lib/typescript/src/MMKV.d.ts +0 -1
  37. package/lib/typescript/src/MMKV.d.ts.map +1 -1
  38. package/lib/typescript/src/NativeMmkv.d.ts +3 -3
  39. package/lib/typescript/src/NativeMmkvPlatformContext.d.ts +11 -0
  40. package/lib/typescript/src/NativeMmkvPlatformContext.d.ts.map +1 -1
  41. package/lib/typescript/src/Types.d.ts +4 -0
  42. package/lib/typescript/src/Types.d.ts.map +1 -1
  43. package/lib/typescript/src/createMMKV.d.ts +1 -1
  44. package/lib/typescript/src/createMMKV.d.ts.map +1 -1
  45. package/lib/typescript/src/createMMKV.web.d.ts +1 -1
  46. package/lib/typescript/src/createMMKV.web.d.ts.map +1 -1
  47. package/lib/typescript/src/hooks.d.ts +1 -1
  48. package/lib/typescript/src/hooks.d.ts.map +1 -1
  49. package/package.json +6 -6
  50. package/src/MMKV.ts +0 -1
  51. package/src/NativeMmkv.ts +3 -3
  52. package/src/NativeMmkvPlatformContext.ts +11 -0
  53. package/src/Types.ts +4 -0
  54. package/src/createMMKV.ts +20 -2
  55. package/src/createMMKV.web.ts +1 -1
  56. package/src/hooks.ts +1 -1
  57. package/android/src/main/cpp/cpp-adapter.cpp +0 -7
@@ -155,7 +155,7 @@ IF (WIN32)
155
155
  ENDIF()
156
156
 
157
157
  set_target_properties(core PROPERTIES
158
- CXX_STANDARD 17
158
+ CXX_STANDARD 20
159
159
  CXX_EXTENSIONS OFF
160
160
  POSITION_INDEPENDENT_CODE ON
161
161
  )
@@ -452,7 +452,7 @@
452
452
  ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
453
453
  CLANG_ANALYZER_NONNULL = YES;
454
454
  CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
455
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
455
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
456
456
  CLANG_CXX_LIBRARY = "libc++";
457
457
  CLANG_ENABLE_MODULES = YES;
458
458
  CLANG_ENABLE_OBJC_ARC = YES;
@@ -517,7 +517,7 @@
517
517
  ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
518
518
  CLANG_ANALYZER_NONNULL = YES;
519
519
  CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
520
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
520
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
521
521
  CLANG_CXX_LIBRARY = "libc++";
522
522
  CLANG_ENABLE_MODULES = YES;
523
523
  CLANG_ENABLE_OBJC_ARC = YES;
@@ -572,7 +572,6 @@
572
572
  CB9563E223AB2D9500ACCD39 /* Debug */ = {
573
573
  isa = XCBuildConfiguration;
574
574
  buildSettings = {
575
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
576
575
  CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
577
576
  CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
578
577
  CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -592,13 +591,13 @@
592
591
  SKIP_INSTALL = YES;
593
592
  SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";
594
593
  TARGETED_DEVICE_FAMILY = "1,2,3";
594
+ SUPPORTS_MACCATALYST = YES;
595
595
  };
596
596
  name = Debug;
597
597
  };
598
598
  CB9563E323AB2D9500ACCD39 /* Release */ = {
599
599
  isa = XCBuildConfiguration;
600
600
  buildSettings = {
601
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
602
601
  CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
603
602
  CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
604
603
  CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -619,13 +618,13 @@
619
618
  SKIP_INSTALL = YES;
620
619
  SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";
621
620
  TARGETED_DEVICE_FAMILY = "1,2,3";
621
+ SUPPORTS_MACCATALYST = YES;
622
622
  };
623
623
  name = Release;
624
624
  };
625
625
  CBF19074243D70BA001C82ED /* Debug */ = {
626
626
  isa = XCBuildConfiguration;
627
627
  buildSettings = {
628
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
629
628
  CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
630
629
  CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
631
630
  CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -650,7 +649,6 @@
650
649
  CBF19075243D70BA001C82ED /* Release */ = {
651
650
  isa = XCBuildConfiguration;
652
651
  buildSettings = {
653
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
654
652
  CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
655
653
  CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
656
654
  CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -131,7 +131,7 @@ uint32_t KeyValueHolderCrypt::realValueSize() const {
131
131
 
132
132
  // get decrypt data with [position, -1)
133
133
  static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &inputBuffer, size_t position) {
134
- static size_t smallBuffer[16 / sizeof(size_t)];
134
+ size_t smallBuffer[16 / sizeof(size_t)];
135
135
  auto basePtr = (uint8_t *) inputBuffer.getPtr();
136
136
  auto ptr = basePtr;
137
137
  for (size_t index = sizeof(smallBuffer); index < position; index += sizeof(smallBuffer)) {
@@ -78,7 +78,11 @@ struct KeyValueHolderCrypt {
78
78
  return sizeof(KeyValueHolderCrypt) - offsetof(KeyValueHolderCrypt, paddedValue);
79
79
  }
80
80
 
81
- static bool isValueStoredAsOffset(size_t valueSize) { return valueSize >= 256; }
81
+ static constexpr size_t MediumBufferSize() {
82
+ return 256;
83
+ }
84
+
85
+ static bool isValueStoredAsOffset(size_t valueSize) { return valueSize > MediumBufferSize(); }
82
86
 
83
87
  KeyValueHolderCrypt() = default;
84
88
  KeyValueHolderCrypt(const void *valuePtr, size_t valueLength);
@@ -59,7 +59,7 @@ class MMBuffer {
59
59
  };
60
60
  struct {
61
61
  uint8_t paddedSize;
62
- // make at least 10 bytes to hold all primitive types (negative int32, int64, double etc) on 32 bit device
62
+ // make at least 10 bytes to hold all primitive types (negative int32, int64, double etc.) on 32 bit device
63
63
  // on 64 bit device it's guaranteed larger than 10 bytes
64
64
  uint8_t paddedBuffer[10];
65
65
  };
@@ -98,7 +98,7 @@ MMKV::MMKV(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *ro
98
98
  m_output = nullptr;
99
99
 
100
100
  # ifndef MMKV_DISABLE_CRYPT
101
- if (cryptKey && cryptKey->length() > 0) {
101
+ if (cryptKey && !cryptKey->empty()) {
102
102
  m_dicCrypt = new MMKVMapCrypt();
103
103
  m_crypter = new AESCrypt(cryptKey->data(), cryptKey->length());
104
104
  } else {
@@ -365,7 +365,7 @@ void MMKV::checkReSetCryptKey(const string *cryptKey) {
365
365
  SCOPED_LOCK(m_lock);
366
366
 
367
367
  if (m_crypter) {
368
- if (cryptKey && cryptKey->length() > 0) {
368
+ if (cryptKey && !cryptKey->empty()) {
369
369
  string oldKey = this->cryptKey();
370
370
  if (oldKey != *cryptKey) {
371
371
  MMKVInfo("setting new aes key");
@@ -385,7 +385,7 @@ void MMKV::checkReSetCryptKey(const string *cryptKey) {
385
385
  checkLoadData();
386
386
  }
387
387
  } else {
388
- if (cryptKey && cryptKey->length() > 0) {
388
+ if (cryptKey && !cryptKey->empty()) {
389
389
  MMKVInfo("setting new aes key");
390
390
  auto ptr = cryptKey->data();
391
391
  m_crypter = new AESCrypt(ptr, cryptKey->length());
@@ -419,7 +419,7 @@ bool MMKV::checkFileCRCValid(size_t actualSize, uint32_t crcDigest) {
419
419
  return false;
420
420
  }
421
421
 
422
- void MMKV::recaculateCRCDigestWithIV(const void *iv) {
422
+ void MMKV::recalculateCRCDigestWithIV(const void *iv) {
423
423
  auto ptr = (const uint8_t *) m_file->getMemory();
424
424
  if (ptr) {
425
425
  m_crcDigest = 0;
@@ -428,7 +428,7 @@ void MMKV::recaculateCRCDigestWithIV(const void *iv) {
428
428
  }
429
429
  }
430
430
 
431
- void MMKV::recaculateCRCDigestOnly() {
431
+ void MMKV::recalculateCRCDigestOnly() {
432
432
  auto ptr = (const uint8_t *) m_file->getMemory();
433
433
  if (ptr) {
434
434
  m_crcDigest = 0;
@@ -456,11 +456,11 @@ bool MMKV::set(bool value, MMKVKey_t key, uint32_t expireDuration) {
456
456
  if (isKeyEmpty(key)) {
457
457
  return false;
458
458
  }
459
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbBoolSize() : pbBoolSize();
459
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbBoolSize() : pbBoolSize();
460
460
  MMBuffer data(size);
461
461
  CodedOutputData output(data.getPtr(), size);
462
462
  output.writeBool(value);
463
- if (unlikely(m_enableKeyExpire)) {
463
+ if (mmkv_unlikely(m_enableKeyExpire)) {
464
464
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
465
465
  output.writeRawLittleEndian32(UInt32ToInt32(time));
466
466
  } else {
@@ -478,11 +478,11 @@ bool MMKV::set(int32_t value, MMKVKey_t key, uint32_t expireDuration) {
478
478
  if (isKeyEmpty(key)) {
479
479
  return false;
480
480
  }
481
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt32Size(value) : pbInt32Size(value);
481
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt32Size(value) : pbInt32Size(value);
482
482
  MMBuffer data(size);
483
483
  CodedOutputData output(data.getPtr(), size);
484
484
  output.writeInt32(value);
485
- if (unlikely(m_enableKeyExpire)) {
485
+ if (mmkv_unlikely(m_enableKeyExpire)) {
486
486
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
487
487
  output.writeRawLittleEndian32(UInt32ToInt32(time));
488
488
  } else {
@@ -500,11 +500,11 @@ bool MMKV::set(uint32_t value, MMKVKey_t key, uint32_t expireDuration) {
500
500
  if (isKeyEmpty(key)) {
501
501
  return false;
502
502
  }
503
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt32Size(value) : pbUInt32Size(value);
503
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt32Size(value) : pbUInt32Size(value);
504
504
  MMBuffer data(size);
505
505
  CodedOutputData output(data.getPtr(), size);
506
506
  output.writeUInt32(value);
507
- if (unlikely(m_enableKeyExpire)) {
507
+ if (mmkv_unlikely(m_enableKeyExpire)) {
508
508
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
509
509
  output.writeRawLittleEndian32(UInt32ToInt32(time));
510
510
  } else {
@@ -522,11 +522,11 @@ bool MMKV::set(int64_t value, MMKVKey_t key, uint32_t expireDuration) {
522
522
  if (isKeyEmpty(key)) {
523
523
  return false;
524
524
  }
525
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt64Size(value) : pbInt64Size(value);
525
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbInt64Size(value) : pbInt64Size(value);
526
526
  MMBuffer data(size);
527
527
  CodedOutputData output(data.getPtr(), size);
528
528
  output.writeInt64(value);
529
- if (unlikely(m_enableKeyExpire)) {
529
+ if (mmkv_unlikely(m_enableKeyExpire)) {
530
530
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
531
531
  output.writeRawLittleEndian32(UInt32ToInt32(time));
532
532
  } else {
@@ -544,11 +544,11 @@ bool MMKV::set(uint64_t value, MMKVKey_t key, uint32_t expireDuration) {
544
544
  if (isKeyEmpty(key)) {
545
545
  return false;
546
546
  }
547
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt64Size(value) : pbUInt64Size(value);
547
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbUInt64Size(value) : pbUInt64Size(value);
548
548
  MMBuffer data(size);
549
549
  CodedOutputData output(data.getPtr(), size);
550
550
  output.writeUInt64(value);
551
- if (unlikely(m_enableKeyExpire)) {
551
+ if (mmkv_unlikely(m_enableKeyExpire)) {
552
552
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
553
553
  output.writeRawLittleEndian32(UInt32ToInt32(time));
554
554
  } else {
@@ -566,11 +566,11 @@ bool MMKV::set(float value, MMKVKey_t key, uint32_t expireDuration) {
566
566
  if (isKeyEmpty(key)) {
567
567
  return false;
568
568
  }
569
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbFloatSize() : pbFloatSize();
569
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbFloatSize() : pbFloatSize();
570
570
  MMBuffer data(size);
571
571
  CodedOutputData output(data.getPtr(), size);
572
572
  output.writeFloat(value);
573
- if (unlikely(m_enableKeyExpire)) {
573
+ if (mmkv_unlikely(m_enableKeyExpire)) {
574
574
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
575
575
  output.writeRawLittleEndian32(UInt32ToInt32(time));
576
576
  } else {
@@ -588,11 +588,11 @@ bool MMKV::set(double value, MMKVKey_t key, uint32_t expireDuration) {
588
588
  if (isKeyEmpty(key)) {
589
589
  return false;
590
590
  }
591
- size_t size = unlikely(m_enableKeyExpire) ? Fixed32Size + pbDoubleSize() : pbDoubleSize();
591
+ size_t size = mmkv_unlikely(m_enableKeyExpire) ? Fixed32Size + pbDoubleSize() : pbDoubleSize();
592
592
  MMBuffer data(size);
593
593
  CodedOutputData output(data.getPtr(), size);
594
594
  output.writeDouble(value);
595
- if (unlikely(m_enableKeyExpire)) {
595
+ if (mmkv_unlikely(m_enableKeyExpire)) {
596
596
  auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
597
597
  output.writeRawLittleEndian32(UInt32ToInt32(time));
598
598
  } else {
@@ -604,6 +604,20 @@ bool MMKV::set(double value, MMKVKey_t key, uint32_t expireDuration) {
604
604
 
605
605
  #ifndef MMKV_APPLE
606
606
 
607
+ bool MMKV::setDataForKey(mmkv::MMBuffer &&data, MMKV::MMKVKey_t key, uint32_t expireDuration) {
608
+ if (mmkv_likely(!m_enableKeyExpire)) {
609
+ assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
610
+ return setDataForKey(std::move(data), key, true);
611
+ } else {
612
+ auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
613
+ CodedOutputData output(tmp.getPtr(), tmp.length());
614
+ output.writeData(data);
615
+ auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
616
+ output.writeRawLittleEndian32(UInt32ToInt32(time));
617
+ return setDataForKey(std::move(tmp), key);
618
+ }
619
+ }
620
+
607
621
  bool MMKV::set(const char *value, MMKVKey_t key) {
608
622
  return set(value, key, m_expiredInSeconds);
609
623
  }
@@ -613,21 +627,7 @@ bool MMKV::set(const char *value, MMKVKey_t key, uint32_t expireDuration) {
613
627
  removeValueForKey(key);
614
628
  return true;
615
629
  }
616
- if (likely(!m_enableKeyExpire)) {
617
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
618
- return setDataForKey(MMBuffer((void *) value, strlen(value), MMBufferNoCopy), key, true);
619
- } else {
620
- MMBuffer data((void *) value, strlen(value), MMBufferNoCopy);
621
- if (data.length() > 0) {
622
- auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
623
- CodedOutputData output(tmp.getPtr(), tmp.length());
624
- output.writeData(data);
625
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
626
- output.writeRawLittleEndian32(UInt32ToInt32(time));
627
- data = std::move(tmp);
628
- }
629
- return setDataForKey(std::move(data), key);
630
- }
630
+ return setDataForKey(MMBuffer((void *) value, strlen(value), MMBufferNoCopy), key, expireDuration);
631
631
  }
632
632
 
633
633
  bool MMKV::set(const string &value, MMKVKey_t key) {
@@ -638,21 +638,18 @@ bool MMKV::set(const string &value, MMKVKey_t key, uint32_t expireDuration) {
638
638
  if (isKeyEmpty(key)) {
639
639
  return false;
640
640
  }
641
- if (likely(!m_enableKeyExpire)) {
642
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
643
- return setDataForKey(MMBuffer((void *) value.data(), value.length(), MMBufferNoCopy), key, true);
644
- } else {
645
- MMBuffer data((void *) value.data(), value.length(), MMBufferNoCopy);
646
- if (data.length() > 0) {
647
- auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
648
- CodedOutputData output(tmp.getPtr(), tmp.length());
649
- output.writeData(data);
650
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
651
- output.writeRawLittleEndian32(UInt32ToInt32(time));
652
- data = std::move(tmp);
653
- }
654
- return setDataForKey(std::move(data), key);
641
+ return setDataForKey(MMBuffer((void *) value.data(), value.length(), MMBufferNoCopy), key, expireDuration);
642
+ }
643
+
644
+ bool MMKV::set(string_view value, MMKVKey_t key) {
645
+ return set(value, key, m_expiredInSeconds);
646
+ }
647
+
648
+ bool MMKV::set(string_view value, MMKVKey_t key, uint32_t expireDuration) {
649
+ if (isKeyEmpty(key)) {
650
+ return false;
655
651
  }
652
+ return setDataForKey(MMBuffer((void *) value.data(), value.length(), MMBufferNoCopy), key, expireDuration);
656
653
  }
657
654
 
658
655
  bool MMKV::set(const MMBuffer &value, MMKVKey_t key) {
@@ -663,23 +660,7 @@ bool MMKV::set(const MMBuffer &value, MMKVKey_t key, uint32_t expireDuration) {
663
660
  if (isKeyEmpty(key)) {
664
661
  return false;
665
662
  }
666
- // delay write the size needed for encoding value
667
- // avoid memory copying
668
- if (likely(!m_enableKeyExpire)) {
669
- assert(expireDuration == ExpireNever && "setting expire duration without calling enableAutoKeyExpire() first");
670
- return setDataForKey(MMBuffer(value.getPtr(), value.length(), MMBufferNoCopy), key, true);
671
- } else {
672
- MMBuffer data(value.getPtr(), value.length(), MMBufferNoCopy);
673
- if (data.length() > 0) {
674
- auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
675
- CodedOutputData output(tmp.getPtr(), tmp.length());
676
- output.writeData(data);
677
- auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
678
- output.writeRawLittleEndian32(UInt32ToInt32(time));
679
- data = std::move(tmp);
680
- }
681
- return setDataForKey(std::move(data), key);
682
- }
663
+ return setDataForKey(MMBuffer(value.getPtr(), value.length(), MMBufferNoCopy), key, expireDuration);
683
664
  }
684
665
 
685
666
  bool MMKV::set(const vector<string> &value, MMKVKey_t key) {
@@ -690,8 +671,12 @@ bool MMKV::set(const vector<string> &v, MMKVKey_t key, uint32_t expireDuration)
690
671
  if (isKeyEmpty(key)) {
691
672
  return false;
692
673
  }
674
+ #ifdef MMKV_HAS_CPP20
675
+ auto data = MiniPBCoder::encodeDataWithObject(std::span(v));
676
+ #else
693
677
  auto data = MiniPBCoder::encodeDataWithObject(v);
694
- if (unlikely(m_enableKeyExpire) && data.length() > 0) {
678
+ #endif
679
+ if (mmkv_unlikely(m_enableKeyExpire) && data.length() > 0) {
695
680
  auto tmp = MMBuffer(data.length() + Fixed32Size);
696
681
  auto ptr = (uint8_t *) tmp.getPtr();
697
682
  memcpy(ptr, data.getPtr(), data.length());
@@ -788,6 +773,16 @@ bool MMKV::getVector(MMKVKey_t key, vector<string> &result) {
788
773
  return false;
789
774
  }
790
775
 
776
+ void MMKV::shared_lock() {
777
+ m_lock->lock();
778
+ m_sharedProcessLock->lock();
779
+ }
780
+
781
+ void MMKV::shared_unlock() {
782
+ m_sharedProcessLock->lock();
783
+ m_lock->lock();
784
+ }
785
+
791
786
  #endif // MMKV_APPLE
792
787
 
793
788
  bool MMKV::getBool(MMKVKey_t key, bool defaultValue, bool *hasValue) {
@@ -1060,7 +1055,7 @@ bool MMKV::containsKey(MMKVKey_t key) {
1060
1055
  SCOPED_LOCK(m_lock);
1061
1056
  checkLoadData();
1062
1057
 
1063
- if (likely(!m_enableKeyExpire)) {
1058
+ if (mmkv_likely(!m_enableKeyExpire)) {
1064
1059
  if (m_crypter) {
1065
1060
  return m_dicCrypt->find(key) != m_dicCrypt->end();
1066
1061
  } else {
@@ -1075,7 +1070,7 @@ size_t MMKV::count(bool filterExpire) {
1075
1070
  SCOPED_LOCK(m_lock);
1076
1071
  checkLoadData();
1077
1072
 
1078
- if (unlikely(filterExpire && m_enableKeyExpire)) {
1073
+ if (mmkv_unlikely(filterExpire && m_enableKeyExpire)) {
1079
1074
  SCOPED_LOCK(m_exclusiveProcessLock);
1080
1075
  fullWriteback(nullptr, true);
1081
1076
  }
@@ -1116,7 +1111,7 @@ vector<string> MMKV::allKeys(bool filterExpire) {
1116
1111
  SCOPED_LOCK(m_lock);
1117
1112
  checkLoadData();
1118
1113
 
1119
- if (unlikely(filterExpire && m_enableKeyExpire)) {
1114
+ if (mmkv_unlikely(filterExpire && m_enableKeyExpire)) {
1120
1115
  SCOPED_LOCK(m_exclusiveProcessLock);
1121
1116
  fullWriteback(nullptr, true);
1122
1117
  }
@@ -1220,7 +1215,7 @@ static bool backupOneToDirectoryByFilePath(const string &mmapKey, const MMKVPath
1220
1215
  return false;
1221
1216
  }
1222
1217
 
1223
- bool ret = false;
1218
+ bool ret;
1224
1219
  {
1225
1220
  #ifdef MMKV_WIN32
1226
1221
  MMKVInfo("backup one mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
@@ -1346,7 +1341,8 @@ size_t MMKV::backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &sr
1346
1341
  auto basename = filename(srcPath);
1347
1342
  const auto &strBasename = MMKVPath_t2String(basename);
1348
1343
  auto mmapKey = isInSpecialDir ? strBasename : mmapedKVKey(strBasename, &srcDir);
1349
- auto dstPath = dstDir + MMKV_PATH_SLASH + basename;
1344
+ auto dstPath = dstDir + MMKV_PATH_SLASH;
1345
+ dstPath += basename;
1350
1346
  if (backupOneToDirectory(mmapKey, dstPath, srcPath, compareFullPath)) {
1351
1347
  count++;
1352
1348
  }
@@ -1379,7 +1375,7 @@ static bool restoreOneFromDirectoryByFilePath(const string &mmapKey, const MMKVP
1379
1375
  return false;
1380
1376
  }
1381
1377
 
1382
- bool ret = false;
1378
+ bool ret;
1383
1379
  {
1384
1380
  #ifdef MMKV_WIN32
1385
1381
  MMKVInfo("restore one mmkv[%s] from [%ls] to [%ls]", mmapKey.c_str(), srcPath.c_str(), dstPath.c_str());
@@ -1510,7 +1506,8 @@ size_t MMKV::restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t
1510
1506
  auto basename = filename(srcPath);
1511
1507
  const auto &strBasename = MMKVPath_t2String(basename);
1512
1508
  auto mmapKey = isInSpecialDir ? strBasename : mmapedKVKey(strBasename, &dstDir);
1513
- auto dstPath = dstDir + MMKV_PATH_SLASH + basename;
1509
+ auto dstPath = dstDir + MMKV_PATH_SLASH;
1510
+ dstPath += basename;
1514
1511
  if (restoreOneFromDirectory(mmapKey, srcPath, dstPath, compareFullPath)) {
1515
1512
  count++;
1516
1513
  }
package/MMKV/Core/MMKV.h CHANGED
@@ -21,9 +21,22 @@
21
21
  #ifndef MMKV_MMKV_H
22
22
  #define MMKV_MMKV_H
23
23
  #ifdef __cplusplus
24
+ #include "MMKVPredef.h"
25
+
26
+ #ifdef MMKV_APPLE
27
+
28
+ # include "MMBuffer.h"
29
+ # ifdef MMKV_HAS_CPP20
30
+ # include <span>
31
+ # endif
32
+
33
+ #else
34
+ # include "MiniPBCoder.h"
35
+ #endif
24
36
 
25
- #include "MMBuffer.h"
26
37
  #include <cstdint>
38
+ #include <type_traits>
39
+ #include <cstring>
27
40
 
28
41
  namespace mmkv {
29
42
  class CodedOutputData;
@@ -49,6 +62,32 @@ enum MMKVMode : uint32_t {
49
62
 
50
63
  #define MMKV_OUT
51
64
 
65
+ #ifdef MMKV_HAS_CPP20
66
+ template <class T>
67
+ struct mmkv_is_vector { static constexpr bool value = false; };
68
+ template <class T, class A>
69
+ struct mmkv_is_vector<std::vector<T, A>> { static constexpr bool value = true; };
70
+ template <class T, size_t S>
71
+ struct mmkv_is_vector<std::span<T, S>> { static constexpr bool value = true; };
72
+ template <class T>
73
+ inline constexpr bool mmkv_is_vector_v = mmkv_is_vector<T>::value;
74
+
75
+ template <class T>
76
+ concept MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE = std::is_integral_v<T> || std::is_floating_point_v<T>;
77
+
78
+ template <class T>
79
+ concept MMKV_SUPPORTED_POD_VALUE_TYPE = std::is_same_v<T, const char*> || std::is_same_v<T, std::string> ||
80
+ std::is_same_v<T, mmkv::MMBuffer>;
81
+
82
+ template <class T>
83
+ concept MMKV_SUPPORTED_VECTOR_VALUE_TYPE = mmkv_is_vector_v<T> &&
84
+ (MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE<typename T::value_type> || MMKV_SUPPORTED_POD_VALUE_TYPE<typename T::value_type>);
85
+
86
+ template <class T>
87
+ concept MMKV_SUPPORTED_VALUE_TYPE = MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE<T> || MMKV_SUPPORTED_POD_VALUE_TYPE<T> ||
88
+ MMKV_SUPPORTED_VECTOR_VALUE_TYPE<T>;
89
+ #endif // MMKV_HAS_CPP20
90
+
52
91
  class MMKV {
53
92
  #ifndef MMKV_ANDROID
54
93
  std::string m_mmapKey;
@@ -103,12 +142,12 @@ class MMKV {
103
142
  # define mmkv_retain_key(key) [key retain]
104
143
  # define mmkv_release_key(key) [key release]
105
144
  #else
106
- using MMKVKey_t = const std::string &;
145
+ using MMKVKey_t = std::string_view;
107
146
  static bool isKeyEmpty(MMKVKey_t key) { return key.empty(); }
108
147
  # define mmkv_key_length(key) key.length()
109
148
  # define mmkv_retain_key(key) ((void) 0)
110
149
  # define mmkv_release_key(key) ((void) 0)
111
- #endif
150
+ #endif // !MMKV_APPLE
112
151
 
113
152
  void loadFromFile();
114
153
 
@@ -124,8 +163,8 @@ class MMKV {
124
163
 
125
164
  bool checkFileCRCValid(size_t actualSize, uint32_t crcDigest);
126
165
 
127
- void recaculateCRCDigestWithIV(const void *iv);
128
- void recaculateCRCDigestOnly();
166
+ void recalculateCRCDigestWithIV(const void *iv);
167
+ void recalculateCRCDigestOnly();
129
168
 
130
169
  void updateCRCDigest(const uint8_t *ptr, size_t length);
131
170
 
@@ -151,6 +190,9 @@ class MMKV {
151
190
 
152
191
  // isDataHolder: avoid memory copying
153
192
  bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, bool isDataHolder = false);
193
+ #ifndef MMKV_APPLE
194
+ bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, uint32_t expireDuration);
195
+ #endif
154
196
 
155
197
  bool removeDataForKey(MMKVKey_t key);
156
198
 
@@ -190,6 +232,12 @@ class MMKV {
190
232
  mmkv::MMBuffer getDataWithoutMTimeForKey(MMKVKey_t key);
191
233
  size_t filterExpiredKeys();
192
234
 
235
+ #ifndef MMKV_APPLE
236
+ static constexpr uint32_t ConstFixed32Size = 4;
237
+ void shared_lock();
238
+ void shared_unlock();
239
+ #endif
240
+
193
241
  public:
194
242
  // call this before getting any MMKV instance
195
243
  static void initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel = MMKVLogInfo, mmkv::LogHandler handler = nullptr);
@@ -199,7 +247,7 @@ public:
199
247
 
200
248
  #ifndef MMKV_ANDROID
201
249
 
202
- // mmapID: any unique ID (com.tencent.xin.pay, etc)
250
+ // mmapID: any unique ID (com.tencent.xin.pay, etc.)
203
251
  // if you want a per-user mmkv, you could merge user-id within mmapID
204
252
  // cryptKey: 16 bytes at most
205
253
  static MMKV *mmkvWithID(const std::string &mmapID,
@@ -210,7 +258,7 @@ public:
210
258
 
211
259
  #else // defined(MMKV_ANDROID)
212
260
 
213
- // mmapID: any unique ID (com.tencent.xin.pay, etc)
261
+ // mmapID: any unique ID (com.tencent.xin.pay, etc.)
214
262
  // if you want a per-user mmkv, you could merge user-id within mmapID
215
263
  // cryptKey: 16 bytes at most
216
264
  static MMKV *mmkvWithID(const std::string &mmapID,
@@ -269,11 +317,21 @@ public:
269
317
  bool set(double value, MMKVKey_t key);
270
318
  bool set(double value, MMKVKey_t key, uint32_t expireDuration);
271
319
 
272
- // avoid unexpected type conversion (pointer to bool, etc)
320
+ #ifdef MMKV_HAS_CPP20
321
+ // avoid unexpected type conversion (pointer to bool, etc.)
273
322
  template <typename T>
323
+ requires(!MMKV_SUPPORTED_VALUE_TYPE<T>)
274
324
  bool set(T value, MMKVKey_t key) = delete;
325
+
326
+ // avoid unexpected type conversion (pointer to bool, etc.)
275
327
  template <typename T>
328
+ requires(!MMKV_SUPPORTED_VALUE_TYPE<T>)
276
329
  bool set(T value, MMKVKey_t key, uint32_t expireDuration) = delete;
330
+ #else
331
+ // avoid unexpected type conversion (pointer to bool, etc.)
332
+ template <typename T>
333
+ bool set(T value, MMKVKey_t key, uint32_t expireDuration) = delete;
334
+ #endif
277
335
 
278
336
  #ifdef MMKV_APPLE
279
337
  bool set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key);
@@ -287,12 +345,28 @@ public:
287
345
  bool set(const std::string &value, MMKVKey_t key);
288
346
  bool set(const std::string &value, MMKVKey_t key, uint32_t expireDuration);
289
347
 
348
+ bool set(std::string_view value, MMKVKey_t key);
349
+ bool set(std::string_view value, MMKVKey_t key, uint32_t expireDuration);
350
+
290
351
  bool set(const mmkv::MMBuffer &value, MMKVKey_t key);
291
352
  bool set(const mmkv::MMBuffer &value, MMKVKey_t key, uint32_t expireDuration);
292
353
 
293
354
  bool set(const std::vector<std::string> &vector, MMKVKey_t key);
294
355
  bool set(const std::vector<std::string> &vector, MMKVKey_t key, uint32_t expireDuration);
295
356
 
357
+ #ifdef MMKV_HAS_CPP20
358
+ template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
359
+ bool set(const T& value, MMKVKey_t key) {
360
+ return set<T>(value, key, m_expiredInSeconds);
361
+ }
362
+
363
+ template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
364
+ bool set(const T& value, MMKVKey_t key, uint32_t expireDuration);
365
+
366
+ template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
367
+ bool getVector(MMKVKey_t key, T &result);
368
+ #endif
369
+
296
370
  // inplaceModification is recommended for faster speed
297
371
  bool getString(MMKVKey_t key, std::string &result, bool inplaceModification = true);
298
372
 
@@ -346,9 +420,9 @@ public:
346
420
  bool enableCompareBeforeSet();
347
421
  bool disableCompareBeforeSet();
348
422
 
349
- bool isExpirationEnabled() { return m_enableKeyExpire; }
350
- bool isEncryptionEnabled() { return m_dicCrypt; }
351
- bool isCompareBeforeSetEnabled() { return m_enableCompareBeforeSet && !m_enableKeyExpire && !m_dicCrypt; }
423
+ bool isExpirationEnabled() const { return m_enableKeyExpire; }
424
+ bool isEncryptionEnabled() const { return m_dicCrypt; }
425
+ bool isCompareBeforeSetEnabled() const { return m_enableCompareBeforeSet && !m_enableKeyExpire && !m_dicCrypt; }
352
426
 
353
427
  #ifdef MMKV_APPLE
354
428
  // filterExpire: return all non-expired keys, keep in mind it comes with cost
@@ -460,6 +534,47 @@ public:
460
534
  MMKV &operator=(const MMKV &other) = delete;
461
535
  };
462
536
 
537
+ #if defined(MMKV_HAS_CPP20) && !defined(MMKV_APPLE)
538
+ template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
539
+ bool MMKV::set(const T& value, MMKVKey_t key, uint32_t expireDuration) {
540
+ if (isKeyEmpty(key)) {
541
+ return false;
542
+ }
543
+ mmkv::MMBuffer data;
544
+ if constexpr (std::is_same_v<T, std::vector<bool>>) {
545
+ data = mmkv::MiniPBCoder::encodeDataWithObject(value);
546
+ } else {
547
+ data = mmkv::MiniPBCoder::encodeDataWithObject(std::span(value));
548
+ }
549
+ if (mmkv_unlikely(m_enableKeyExpire) && data.length() > 0) {
550
+ auto tmp = mmkv::MMBuffer(data.length() + ConstFixed32Size);
551
+ auto ptr = (uint8_t *) tmp.getPtr();
552
+ memcpy(ptr, data.getPtr(), data.length());
553
+ auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
554
+ memcpy(ptr + data.length(), &time, ConstFixed32Size);
555
+ data = std::move(tmp);
556
+ }
557
+ return setDataForKey(std::move(data), key);
558
+ }
559
+
560
+ template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
561
+ bool MMKV::getVector(MMKVKey_t key, T &result) {
562
+ if (isKeyEmpty(key)) {
563
+ return false;
564
+ }
565
+ shared_lock();
566
+
567
+ bool ret = false;
568
+ auto data = getDataForKey(key);
569
+ if (data.length() > 0) {
570
+ ret = mmkv::MiniPBCoder::decodeVector(data, result);
571
+ }
572
+
573
+ shared_unlock();
574
+ return ret;
575
+ }
576
+ #endif // MMKV_HAS_CPP20 && !MMKV_APPLE
577
+
463
578
  MMKV_NAMESPACE_END
464
579
 
465
580
  #endif