diff --git a/Android/MMKV/gradle.properties b/Android/MMKV/gradle.properties index bfe52cbe..bb2e1df5 100644 --- a/Android/MMKV/gradle.properties +++ b/Android/MMKV/gradle.properties @@ -14,6 +14,6 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME_PREFIX=1.2.0 +VERSION_NAME_PREFIX=1.2.1 #VERSION_NAME_SUFFIX=-SNAPSHOT VERSION_NAME_SUFFIX= \ No newline at end of file diff --git a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp index 7b5e2c76..76835f17 100644 --- a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp @@ -116,6 +116,7 @@ extern "C" JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) { // get CPU status of ARMv8 extensions (CRC32, AES) #ifdef __aarch64__ auto hwcaps = getauxval(AT_HWCAP); +# ifndef MMKV_DISABLE_CRYPT if (hwcaps & HWCAP_AES) { AES_set_encrypt_key = openssl_aes_armv8_set_encrypt_key; AES_set_decrypt_key = openssl_aes_armv8_set_decrypt_key; @@ -123,11 +124,12 @@ extern "C" JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) { AES_decrypt = openssl_aes_armv8_decrypt; MMKVInfo("armv8 AES instructions is supported"); } +# endif // MMKV_DISABLE_CRYPT if (hwcaps & HWCAP_CRC32) { CRC32 = mmkv::armv8_crc32; MMKVInfo("armv8 CRC32 instructions is supported"); } -#endif +#endif // __aarch64__ return JNI_VERSION_1_6; } @@ -253,7 +255,7 @@ static void onContentChangedByOuterProcess(const std::string &mmapID) { } } -MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jint mode, jstring cryptKey, jstring relativePath) { +MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jint mode, jstring cryptKey, jstring rootPath) { MMKV *kv = nullptr; if (!mmapID) { return (jlong) kv; @@ -264,8 +266,8 @@ MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jint mode, js if (cryptKey) { string crypt = jstring2string(env, cryptKey); if (crypt.length() > 0) { - if (relativePath) { - string path = jstring2string(env, relativePath); + if (rootPath) { + string path = jstring2string(env, rootPath); kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, &crypt, &path); } else { kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, &crypt, nullptr); @@ -274,8 +276,8 @@ MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jint mode, js } } if (!done) { - if (relativePath) { - string path = jstring2string(env, relativePath); + if (rootPath) { + string path = jstring2string(env, rootPath); kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, nullptr, &path); } else { kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, nullptr, nullptr); @@ -658,6 +660,8 @@ MMKV_JNI jint pageSize(JNIEnv *env, jclass type) { return DEFAULT_MMAP_SIZE; } +#ifndef MMKV_DISABLE_CRYPT + MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) { MMKV *kv = getMMKV(env, instance); if (kv) { @@ -697,6 +701,8 @@ MMKV_JNI void checkReSetCryptKey(JNIEnv *env, jobject instance, jstring cryptKey } } +#endif // MMKV_DISABLE_CRYPT + MMKV_JNI void trim(JNIEnv *env, jobject instance) { MMKV *kv = getMMKV(env, instance); if (kv) { @@ -780,9 +786,11 @@ MMKV_JNI void checkContentChanged(JNIEnv *env, jobject instance) { static JNINativeMethod g_methods[] = { {"onExit", "()V", (void *) mmkv::onExit}, +#ifndef MMKV_DISABLE_CRYPT {"cryptKey", "()Ljava/lang/String;", (void *) mmkv::cryptKey}, {"reKey", "(Ljava/lang/String;)Z", (void *) mmkv::reKey}, {"checkReSetCryptKey", "(Ljava/lang/String;)V", (void *) mmkv::checkReSetCryptKey}, +#endif {"pageSize", "()I", (void *) mmkv::pageSize}, {"mmapID", "()Ljava/lang/String;", (void *) mmkv::mmapID}, {"lock", "()V", (void *) mmkv::lock}, diff --git a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java index 5fc2336a..949f61d6 100644 --- a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java +++ b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java @@ -176,12 +176,12 @@ public static MMKV mmkvWithID(String mmapID, int mode, String cryptKey) { } @Nullable - public static MMKV mmkvWithID(String mmapID, String relativePath) { + public static MMKV mmkvWithID(String mmapID, String rootPath) { if (rootDir == null) { throw new IllegalStateException("You should Call MMKV.initialize() first."); } - long handle = getMMKVWithID(mmapID, SINGLE_PROCESS_MODE, null, relativePath); + long handle = getMMKVWithID(mmapID, SINGLE_PROCESS_MODE, null, rootPath); if (handle == 0) { return null; } @@ -190,12 +190,12 @@ public static MMKV mmkvWithID(String mmapID, String relativePath) { // cryptKey's length <= 16 @Nullable - public static MMKV mmkvWithID(String mmapID, int mode, String cryptKey, String relativePath) { + public static MMKV mmkvWithID(String mmapID, int mode, String cryptKey, String rootPath) { if (rootDir == null) { throw new IllegalStateException("You should Call MMKV.initialize() first."); } - long handle = getMMKVWithID(mmapID, mode, cryptKey, relativePath); + long handle = getMMKVWithID(mmapID, mode, cryptKey, rootPath); if (handle == 0) { return null; } @@ -823,7 +823,7 @@ private MMKV(long handle) { private static native void jniInitialize(String rootDir, int level); - private native static long getMMKVWithID(String mmapID, int mode, String cryptKey, String relativePath); + private native static long getMMKVWithID(String mmapID, int mode, String cryptKey, String rootPath); private native static long getMMKVWithIDAndSize(String mmapID, int size, int mode, String cryptKey); diff --git a/Android/MMKV/mmkvdemo/build.gradle b/Android/MMKV/mmkvdemo/build.gradle index 30c77f1f..9df07f37 100644 --- a/Android/MMKV/mmkvdemo/build.gradle +++ b/Android/MMKV/mmkvdemo/build.gradle @@ -82,8 +82,8 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') // implementation project(':mmkv') -// implementation 'com.tencent:mmkv:1.2.0' - implementation 'com.tencent:mmkv-static:1.2.0' +// implementation 'com.tencent:mmkv:1.2.1' + implementation 'com.tencent:mmkv-static:1.2.1' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' diff --git a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java index 99780fde..01b40621 100644 --- a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java +++ b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java @@ -71,8 +71,10 @@ public void mmkvBaselineTest() { mmkvBatchReadString(); //mmkvBatchDeleteString(); - //MMKV mmkv = mmkvForTest(); + MMKV mmkv = mmkvForTest(); //mmkv.trim(); + mmkv.clearMemoryCache(); + mmkv.totalSize(); } private MMKV mmkvForTest() { diff --git a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java index f323cfda..16d90acd 100644 --- a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java +++ b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java @@ -116,6 +116,7 @@ public void onClick(View v) { //testCornerSize(); //testFastRemoveCornerSize(); //testTrimNonEmptyInterProcess(); + //testItemSizeHolderOverride(); } private void testInterProcessLogic() { @@ -133,9 +134,9 @@ private void testInterProcessLogic() { } @Nullable - private MMKV testMMKV(String mmapID, String cryptKey, boolean decodeOnly, String relativePath) { + private MMKV testMMKV(String mmapID, String cryptKey, boolean decodeOnly, String rootPath) { //MMKV kv = MMKV.defaultMMKV(); - MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, cryptKey, relativePath); + MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, cryptKey, rootPath); if (kv == null) { return null; } @@ -444,4 +445,30 @@ private void testTrimNonEmptyInterProcess() { SystemClock.sleep(1000 * 3); Log.i("MMKV", "NonEmptyKey: " + mmkv.decodeString("NonEmptyKey")); } + + private void testItemSizeHolderOverride() { + // final String mmapID = "testItemSizeHolderOverride_crypted"; + // final String encryptKey = "encrypeKey"; + final String mmapID = "testItemSizeHolderOverride_plaintext"; + final String encryptKey = null; + MMKV mmkv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, encryptKey); + /* do this in v1.1.2 + { + // mmkv.encode("b", true); + byte[] value = new byte[512]; + mmkv.encode("data", value); + Log.i("MMKV", "allKeys: " + Arrays.toString(mmkv.allKeys())); + }*/ + // do this in v1.2.0 + { + long totalSize = mmkv.totalSize(); + long bufferSize = totalSize - 512; + byte[] value = new byte[(int) bufferSize]; + // force a fullwriteback() + mmkv.encode("bigData", value); + + mmkv.clearMemoryCache(); + Log.i("MMKV", "allKeys: " + Arrays.toString(mmkv.allKeys())); + } + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7153855d..dc01ea6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # MMKV Change Log +## v1.2.1 / 2020-07-03 +This is a hotfix release. Anyone who has upgraded to v1.2.0 should upgrade to this version **immediately**. + +* Fix a potential file corruption bug when writing a file that was created in versions older than v1.2.0. This bug was introduced in v1.2.0. +* Add a preprocess directive `MMKV_DISABLE_CRYPT` to turn off MMKV encryption ability once and for all. If you integrate MMKV by source code, and if you are pretty sure encryption is not needed, you can turn that off to save some binary size. +* The parameter `relativePath` (customizing a separate folder for an MMKV instance), has been renamed to `rootPath`. Making it clear that an absolute path is expected for that parameter. + +### iOS / macOS +* `-[MMKV mmkvWithID: relativePath:]` is deprecated. Use `-[MMKV mmkvWithID: rootPath:]` instead. +* Likewise, `-[MMKV mmkvWithID: cryptKey: relativePath:]` is deprecated. Use `-[MMKV mmkvWithID: cryptKey: rootPath:]` instead. + ## v1.2.0 / 2020-06-30 This is the second **major version** of MMKV. Everything you call is the same as the last version, while almost everything underneath has been improved. diff --git a/Core/CodedInputData.cpp b/Core/CodedInputData.cpp index d2d2a196..9f8c161e 100644 --- a/Core/CodedInputData.cpp +++ b/Core/CodedInputData.cpp @@ -38,11 +38,10 @@ CodedInputData::CodedInputData(const void *oData, size_t length) } void CodedInputData::seek(size_t addedSize) { - m_position += addedSize; - - if (m_position > m_size) { + if (m_position + addedSize > m_size) { throw out_of_range("OutOfSpace"); } + m_position += addedSize; } double CodedInputData::readDouble() { diff --git a/Core/CodedInputDataCrypt.cpp b/Core/CodedInputDataCrypt.cpp index 73928484..71a83e07 100644 --- a/Core/CodedInputDataCrypt.cpp +++ b/Core/CodedInputDataCrypt.cpp @@ -30,6 +30,8 @@ # endif #endif // MMKV_APPLE +#ifndef MMKV_DISABLE_CRYPT + using namespace std; namespace mmkv { @@ -213,7 +215,7 @@ int32_t CodedInputDataCrypt::readInt32() { return this->readRawVarint32(); } -#ifndef MMKV_APPLE +# ifndef MMKV_APPLE string CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) { kvHolder.offset = static_cast(m_position); @@ -238,7 +240,7 @@ string CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) { } } -#endif +# endif void CodedInputDataCrypt::readData(KeyValueHolderCrypt &kvHolder) { int32_t size = this->readRawVarint32(); @@ -272,3 +274,5 @@ void CodedInputDataCrypt::readData(KeyValueHolderCrypt &kvHolder) { } } // namespace mmkv + +#endif // MMKV_DISABLE_CRYPT diff --git a/Core/CodedInputDataCrypt.h b/Core/CodedInputDataCrypt.h index ecd00773..fac32e62 100644 --- a/Core/CodedInputDataCrypt.h +++ b/Core/CodedInputDataCrypt.h @@ -29,6 +29,14 @@ #include "aes/AESCrypt.h" #include +#ifdef MMKV_DISABLE_CRYPT + +namespace mmkv { +class CodedInputDataCrypt; +} + +#else + namespace mmkv { class CodedInputDataCrypt { @@ -74,5 +82,6 @@ class CodedInputDataCrypt { } // namespace mmkv -#endif +#endif // MMKV_DISABLE_CRYPT +#endif // __cplusplus #endif /* CodedInputDataCrypt_h */ diff --git a/Core/CodedInputDataCrypt_OSX.cpp b/Core/CodedInputDataCrypt_OSX.cpp index f624e93e..5d19203a 100644 --- a/Core/CodedInputDataCrypt_OSX.cpp +++ b/Core/CodedInputDataCrypt_OSX.cpp @@ -20,7 +20,7 @@ #include "CodedInputDataCrypt.h" -#ifdef MMKV_APPLE +#if defined(MMKV_APPLE) && !defined(MMKV_DISABLE_CRYPT) # include "PBUtility.h" # include @@ -59,4 +59,4 @@ NSString *CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) { } // namespace mmkv -#endif // MMKV_APPLE +#endif // MMKV_APPLE && !MMKV_DISABLE_CRYPT diff --git a/Core/KeyValueHolder.cpp b/Core/KeyValueHolder.cpp index b779d8c5..9694348c 100644 --- a/Core/KeyValueHolder.cpp +++ b/Core/KeyValueHolder.cpp @@ -39,6 +39,8 @@ MMBuffer KeyValueHolder::toMMBuffer(const void *basePtr) const { return MMBuffer(realPtr, valueSize, MMBufferNoCopy); } +#ifndef MMKV_DISABLE_CRYPT + KeyValueHolderCrypt::KeyValueHolderCrypt(const void *src, size_t length) { if (length <= SmallBufferSize()) { type = KeyValueHolderType_Direct; @@ -63,9 +65,9 @@ KeyValueHolderCrypt::KeyValueHolderCrypt(MMBuffer &&data) { paddedSize = static_cast(data.length()); memcpy(paddedValue, data.getPtr(), data.length()); } else { -#ifdef MMKV_APPLE +# ifdef MMKV_APPLE assert(data.m_data == nil); -#endif +# endif type = KeyValueHolderType_Memory; memSize = static_cast(data.length()); memPtr = data.getPtr(); @@ -147,9 +149,11 @@ MMBuffer KeyValueHolderCrypt::toMMBuffer(const void *basePtr, const AESCrypt *cr } } +#endif // MMKV_DISABLE_CRYPT + } // namespace mmkv -#ifndef NDEBUG +#if !defined(MMKV_DISABLE_CRYPT) && !defined(NDEBUG) # include "CodedInputData.h" # include "CodedOutputData.h" # include "MMKVLog.h" diff --git a/Core/KeyValueHolder.h b/Core/KeyValueHolder.h index f6261a6f..355ee890 100644 --- a/Core/KeyValueHolder.h +++ b/Core/KeyValueHolder.h @@ -41,6 +41,8 @@ struct KeyValueHolder { MMBuffer toMMBuffer(const void *basePtr) const; }; +#ifndef MMKV_DISABLE_CRYPT + enum KeyValueHolderType : uint8_t { KeyValueHolderType_Direct, // store value directly KeyValueHolderType_Memory, // store value in the heap memory @@ -104,6 +106,8 @@ struct KeyValueHolderCrypt { #endif }; +#endif // MMKV_DISABLE_CRYPT + #pragma pack(pop) } // namespace mmkv diff --git a/Core/MMBuffer.h b/Core/MMBuffer.h index e61b9315..c3268f2e 100644 --- a/Core/MMBuffer.h +++ b/Core/MMBuffer.h @@ -36,7 +36,9 @@ enum MMBufferCopyFlag : bool { #pragma pack(push, 1) +#ifndef MMKV_DISABLE_CRYPT struct KeyValueHolderCrypt; +#endif class MMBuffer { enum MMBufferType : uint8_t { @@ -89,7 +91,9 @@ class MMBuffer { explicit MMBuffer(const MMBuffer &other) = delete; MMBuffer &operator=(const MMBuffer &other) = delete; +#ifndef MMKV_DISABLE_CRYPT friend KeyValueHolderCrypt; +#endif }; #pragma pack(pop) diff --git a/Core/MMKV.cpp b/Core/MMKV.cpp index 30f157e6..febcf724 100644 --- a/Core/MMKV.cpp +++ b/Core/MMKV.cpp @@ -64,10 +64,10 @@ constexpr uint32_t Fixed32Size = pbFixed32Size(); MMKV_NAMESPACE_BEGIN #ifndef MMKV_ANDROID -MMKV::MMKV(const std::string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *relativePath) +MMKV::MMKV(const std::string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath) : m_mmapID(mmapID) - , m_path(mappedKVPathWithID(m_mmapID, mode, relativePath)) - , m_crcPath(crcPathWithID(m_mmapID, mode, relativePath)) + , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath)) + , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath)) , m_dic(nullptr) , m_dicCrypt(nullptr) , m_file(new MemoryFile(m_path)) @@ -82,12 +82,16 @@ MMKV::MMKV(const std::string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_ m_actualSize = 0; m_output = nullptr; +# ifndef MMKV_DISABLE_CRYPT if (cryptKey && cryptKey->length() > 0) { m_dicCrypt = new MMKVMapCrypt(); m_crypter = new AESCrypt(cryptKey->data(), cryptKey->length()); } else { m_dic = new MMKVMap(); } +# else + m_dic = new MMKVMap(); +# endif m_needLoadFromFile = true; m_hasFullWriteback = false; @@ -110,8 +114,10 @@ MMKV::~MMKV() { clearMemoryCache(); delete m_dic; +#ifndef MMKV_DISABLE_CRYPT delete m_dicCrypt; delete m_crypter; +#endif delete m_file; delete m_metaFile; delete m_metaInfo; @@ -136,7 +142,7 @@ void initialize() { mmkv::DEFAULT_MMAP_SIZE = mmkv::getPageSize(); MMKVInfo("version %s page size:%d", MMKV_VERSION, DEFAULT_MMAP_SIZE); -#ifndef NDEBUG +#if !defined(NDEBUG) && !defined(MMKV_DISABLE_CRYPT) AESCrypt::testAESCrypt(); KeyValueHolderCrypt::testAESToMMBuffer(); #endif @@ -156,30 +162,29 @@ void MMKV::initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel) { } #ifndef MMKV_ANDROID -MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *relativePath) { +MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, string *cryptKey, MMKVPath_t *rootPath) { if (mmapID.empty()) { return nullptr; } SCOPED_LOCK(g_instanceLock); - auto mmapKey = mmapedKVKey(mmapID, relativePath); + auto mmapKey = mmapedKVKey(mmapID, rootPath); auto itr = g_instanceDic->find(mmapKey); if (itr != g_instanceDic->end()) { MMKV *kv = itr->second; return kv; } - if (relativePath) { - MMKVPath_t specialPath = (*relativePath) + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME; + if (rootPath) { + MMKVPath_t specialPath = (*rootPath) + MMKV_PATH_SLASH + SPECIAL_CHARACTER_DIRECTORY_NAME; if (!isFileExist(specialPath)) { mkPath(specialPath); } - MMKVInfo("prepare to load %s (id %s) from relativePath %s", mmapID.c_str(), mmapKey.c_str(), - relativePath->c_str()); + MMKVInfo("prepare to load %s (id %s) from rootPath %s", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str()); } - auto kv = new MMKV(mmapID, mode, cryptKey, relativePath); + auto kv = new MMKV(mmapID, mode, cryptKey, rootPath); kv->m_mmapKey = mmapKey; (*g_instanceDic)[mmapKey] = kv; return kv; @@ -205,17 +210,6 @@ const string &MMKV::mmapID() { return m_mmapID; } -string MMKV::cryptKey() { - SCOPED_LOCK(m_lock); - - if (m_crypter) { - char key[AES_KEY_LEN]; - m_crypter->getKey(key); - return string(key, strnlen(key, AES_KEY_LEN)); - } - return ""; -} - mmkv::ContentChangeHandler g_contentChangeHandler = nullptr; void MMKV::notifyContentChanged() { @@ -244,12 +238,11 @@ void MMKV::clearMemoryCache() { return; } m_needLoadFromFile = true; - - clearDictionary(m_dicCrypt); - clearDictionary(m_dic); - m_hasFullWriteback = false; + clearDictionary(m_dic); +#ifndef MMKV_DISABLE_CRYPT + clearDictionary(m_dicCrypt); if (m_crypter) { if (m_metaInfo->m_version >= MMKVVersionRandomIV) { m_crypter->resetIV(m_metaInfo->m_vector, sizeof(m_metaInfo->m_vector)); @@ -257,6 +250,7 @@ void MMKV::clearMemoryCache() { m_crypter->resetIV(); } } +#endif delete m_output; m_output = nullptr; @@ -282,6 +276,19 @@ void MMKV::close() { delete this; } +#ifndef MMKV_DISABLE_CRYPT + +string MMKV::cryptKey() { + SCOPED_LOCK(m_lock); + + if (m_crypter) { + char key[AES_KEY_LEN]; + m_crypter->getKey(key); + return string(key, strnlen(key, AES_KEY_LEN)); + } + return ""; +} + void MMKV::checkReSetCryptKey(const string *cryptKey) { SCOPED_LOCK(m_lock); @@ -318,6 +325,8 @@ void MMKV::checkReSetCryptKey(const string *cryptKey) { } } +#endif // MMKV_DISABLE_CRYPT + bool MMKV::isFileValid() { return m_file->isFileValid(); } @@ -893,22 +902,22 @@ static MMKVPath_t encodeFilePath(const string &mmapID) { } } -string mmapedKVKey(const string &mmapID, MMKVPath_t *relativePath) { - if (relativePath && g_rootDir != (*relativePath)) { - return md5(*relativePath + MMKV_PATH_SLASH + string2MMKVPath_t(mmapID)); +string mmapedKVKey(const string &mmapID, MMKVPath_t *rootPath) { + if (rootPath && g_rootDir != (*rootPath)) { + return md5(*rootPath + MMKV_PATH_SLASH + string2MMKVPath_t(mmapID)); } return mmapID; } -MMKVPath_t mappedKVPathWithID(const string &mmapID, MMKVMode mode, MMKVPath_t *relativePath) { +MMKVPath_t mappedKVPathWithID(const string &mmapID, MMKVMode mode, MMKVPath_t *rootPath) { #ifndef MMKV_ANDROID - if (relativePath) { + if (rootPath) { #else if (mode & MMKV_ASHMEM) { return ashmemMMKVPathWithID(encodeFilePath(mmapID)); - } else if (relativePath) { + } else if (rootPath) { #endif - return *relativePath + MMKV_PATH_SLASH + encodeFilePath(mmapID); + return *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapID); } return g_rootDir + MMKV_PATH_SLASH + encodeFilePath(mmapID); } @@ -919,15 +928,15 @@ constexpr auto CRC_SUFFIX = ".crc"; constexpr auto CRC_SUFFIX = L".crc"; #endif -MMKVPath_t crcPathWithID(const string &mmapID, MMKVMode mode, MMKVPath_t *relativePath) { +MMKVPath_t crcPathWithID(const string &mmapID, MMKVMode mode, MMKVPath_t *rootPath) { #ifndef MMKV_ANDROID - if (relativePath) { + if (rootPath) { #else if (mode & MMKV_ASHMEM) { return ashmemMMKVPathWithID(encodeFilePath(mmapID)) + CRC_SUFFIX; - } else if (relativePath) { + } else if (rootPath) { #endif - return *relativePath + MMKV_PATH_SLASH + encodeFilePath(mmapID) + CRC_SUFFIX; + return *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapID) + CRC_SUFFIX; } return g_rootDir + MMKV_PATH_SLASH + encodeFilePath(mmapID) + CRC_SUFFIX; } diff --git a/Core/MMKV.h b/Core/MMKV.h index 045795ab..fb505744 100644 --- a/Core/MMKV.h +++ b/Core/MMKV.h @@ -49,9 +49,9 @@ enum MMKVMode : uint32_t { class MMKV { #ifndef MMKV_ANDROID std::string m_mmapKey; - MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *relativePath); + MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath); #else // defined(MMKV_ANDROID) - MMKV(const std::string &mmapID, int size, MMKVMode mode, std::string *cryptKey, MMKVPath_t *relativePath); + MMKV(const std::string &mmapID, int size, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath); MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, std::string *cryptKey = nullptr); #endif @@ -139,7 +139,7 @@ class MMKV { void notifyContentChanged(); -#ifdef MMKV_ANDROID +#if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT) void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey); #endif @@ -163,7 +163,7 @@ class MMKV { static MMKV *mmkvWithID(const std::string &mmapID, MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr, - MMKVPath_t *relativePath = nullptr); + MMKVPath_t *rootPath = nullptr); #else // defined(MMKV_ANDROID) @@ -174,7 +174,7 @@ class MMKV { int size = mmkv::DEFAULT_MMAP_SIZE, MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr, - MMKVPath_t *relativePath = nullptr); + MMKVPath_t *rootPath = nullptr); static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, std::string *cryptKey = nullptr); @@ -191,6 +191,7 @@ class MMKV { const bool m_isInterProcess; +#ifndef MMKV_DISABLE_CRYPT std::string cryptKey(); // transform plain text into encrypted text, or vice versa with empty cryptKey @@ -200,6 +201,7 @@ class MMKV { // just reset cryptKey (will not encrypt or decrypt anything) // usually you should call this method after other process reKey() the multi-process mmkv void checkReSetCryptKey(const std::string *cryptKey); +#endif bool set(bool value, MMKVKey_t key); diff --git a/Core/MMKVPredef.h b/Core/MMKVPredef.h index 3e74fbd1..dad0a1fb 100755 --- a/Core/MMKVPredef.h +++ b/Core/MMKVPredef.h @@ -21,13 +21,19 @@ #ifndef MMKV_SRC_MMKVPREDEF_H #define MMKV_SRC_MMKVPREDEF_H +// disable encryption & decryption to reduce some code +//#define MMKV_DISABLE_CRYPT + +// using POSIX implementation +//#define FORCE_POSIX + #ifdef __cplusplus #include #include #include -constexpr auto MMKV_VERSION = "v1.2.0"; +constexpr auto MMKV_VERSION = "v1.2.1"; #ifdef __ANDROID__ # define MMKV_ANDROID @@ -142,7 +148,12 @@ extern size_t DEFAULT_MMAP_SIZE; class MMBuffer; struct KeyValueHolder; + +#ifdef MMKV_DISABLE_CRYPT +using KeyValueHolderCrypt = KeyValueHolder; +#else struct KeyValueHolderCrypt; +#endif #ifdef MMKV_APPLE struct KeyHasher { diff --git a/Core/MMKV_Android.cpp b/Core/MMKV_Android.cpp index af8734b3..b57089fb 100644 --- a/Core/MMKV_Android.cpp +++ b/Core/MMKV_Android.cpp @@ -37,14 +37,14 @@ using namespace mmkv; extern unordered_map *g_instanceDic; extern ThreadLock *g_instanceLock; -extern string mmapedKVKey(const string &mmapID, string *relativePath); -extern string mappedKVPathWithID(const string &mmapID, MMKVMode mode, string *relativePath); -extern string crcPathWithID(const string &mmapID, MMKVMode mode, string *relativePath); - -MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *relativePath) - : m_mmapID(mmapedKVKey(mmapID, relativePath)) // historically Android mistakenly use mmapKey as mmapID - , m_path(mappedKVPathWithID(m_mmapID, mode, relativePath)) - , m_crcPath(crcPathWithID(m_mmapID, mode, relativePath)) +extern string mmapedKVKey(const string &mmapID, string *rootPath); +extern string mappedKVPathWithID(const string &mmapID, MMKVMode mode, string *rootPath); +extern string crcPathWithID(const string &mmapID, MMKVMode mode, string *rootPath); + +MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *rootPath) + : m_mmapID(mmapedKVKey(mmapID, rootPath)) // historically Android mistakenly use mmapKey as mmapID + , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath)) + , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath)) , m_dic(nullptr) , m_dicCrypt(nullptr) , m_file(new MemoryFile(m_path, size, (mode & MMKV_ASHMEM) ? MMFILE_TYPE_ASHMEM : MMFILE_TYPE_FILE)) @@ -59,10 +59,13 @@ MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, stri m_actualSize = 0; m_output = nullptr; +# ifndef MMKV_DISABLE_CRYPT if (cryptKey && cryptKey->length() > 0) { m_dicCrypt = new MMKVMapCrypt(); m_crypter = new AESCrypt(cryptKey->data(), cryptKey->length()); - } else { + } else +# endif + { m_dic = new MMKVMap(); } @@ -100,10 +103,13 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe m_actualSize = 0; m_output = nullptr; +# ifndef MMKV_DISABLE_CRYPT if (cryptKey && cryptKey->length() > 0) { m_dicCrypt = new MMKVMapCrypt(); m_crypter = new AESCrypt(cryptKey->data(), cryptKey->length()); - } else { + } else +# endif + { m_dic = new MMKVMap(); } @@ -122,29 +128,28 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe } } -MMKV *MMKV::mmkvWithID(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *relativePath) { +MMKV *MMKV::mmkvWithID(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *rootPath) { if (mmapID.empty()) { return nullptr; } SCOPED_LOCK(g_instanceLock); - auto mmapKey = mmapedKVKey(mmapID, relativePath); + auto mmapKey = mmapedKVKey(mmapID, rootPath); auto itr = g_instanceDic->find(mmapKey); if (itr != g_instanceDic->end()) { MMKV *kv = itr->second; return kv; } - if (relativePath) { - if (!isFileExist(*relativePath)) { - if (!mkPath(*relativePath)) { + if (rootPath) { + if (!isFileExist(*rootPath)) { + if (!mkPath(*rootPath)) { return nullptr; } } - MMKVInfo("prepare to load %s (id %s) from relativePath %s", mmapID.c_str(), mmapKey.c_str(), - relativePath->c_str()); + MMKVInfo("prepare to load %s (id %s) from rootPath %s", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str()); } - auto kv = new MMKV(mmapID, size, mode, cryptKey, relativePath); + auto kv = new MMKV(mmapID, size, mode, cryptKey, rootPath); (*g_instanceDic)[mmapKey] = kv; return kv; } @@ -159,7 +164,9 @@ MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, string *c auto itr = g_instanceDic->find(mmapID); if (itr != g_instanceDic->end()) { MMKV *kv = itr->second; +# ifndef MMKV_DISABLE_CRYPT kv->checkReSetCryptKey(fd, metaFD, cryptKey); +# endif return kv; } auto kv = new MMKV(mmapID, fd, metaFD, cryptKey); @@ -175,6 +182,7 @@ int MMKV::ashmemMetaFD() { return (m_file->m_fileType & mmkv::MMFILE_TYPE_ASHMEM) ? m_metaFile->getFd() : -1; } +# ifndef MMKV_DISABLE_CRYPT void MMKV::checkReSetCryptKey(int fd, int metaFD, string *cryptKey) { SCOPED_LOCK(m_lock); @@ -189,5 +197,6 @@ void MMKV::checkReSetCryptKey(int fd, int metaFD, string *cryptKey) { } } } +# endif // MMKV_DISABLE_CRYPT -#endif +#endif // MMKV_ANDROID diff --git a/Core/MMKV_IO.cpp b/Core/MMKV_IO.cpp index 4302ecc9..7cf9d58d 100644 --- a/Core/MMKV_IO.cpp +++ b/Core/MMKV_IO.cpp @@ -59,12 +59,13 @@ void MMKV::loadFromFile() { if (m_metaFile->isFileValid()) { m_metaInfo->read(m_metaFile->getMemory()); } +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { if (m_metaInfo->m_version >= MMKVVersionRandomIV) { m_crypter->resetIV(m_metaInfo->m_vector, sizeof(m_metaInfo->m_vector)); } } - +#endif if (!m_file->isFileValid()) { m_file->reloadFromFile(); } @@ -89,15 +90,21 @@ void MMKV::loadFromFile() { clearDictionary(m_dic); } if (needFullWriteback) { +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { MiniPBCoder::greedyDecodeMap(*m_dicCrypt, inputBuffer, m_crypter); - } else { + } else +#endif + { MiniPBCoder::greedyDecodeMap(*m_dic, inputBuffer); } } else { +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { MiniPBCoder::decodeMap(*m_dicCrypt, inputBuffer, m_crypter); - } else { + } else +#endif + { MiniPBCoder::decodeMap(*m_dic, inputBuffer); } } @@ -148,9 +155,12 @@ void MMKV::partialLoadFromFile() { m_crcDigest = (uint32_t) CRC32(m_crcDigest, basePtr + position, addedSize); if (m_crcDigest == m_metaInfo->m_crcDigest) { MMBuffer inputBuffer(basePtr, m_actualSize, MMBufferNoCopy); +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { MiniPBCoder::greedyDecodeMap(*m_dicCrypt, inputBuffer, m_crypter, position); - } else { + } else +#endif + { MiniPBCoder::greedyDecodeMap(*m_dic, inputBuffer, position); } m_output->seek(addedSize); @@ -304,18 +314,25 @@ static pair prepareEncode(const mmkv::MMKVMap &dic) { return make_pair(MMBuffer(), totalSize); } +#ifndef MMKV_DISABLE_CRYPT static pair prepareEncode(const mmkv::MMKVMapCrypt &dic) { - // make some room for placeholder - size_t totalSize = ItemSizeHolderSize; MMKVVector vec; + size_t totalSize = 0; + // make some room for placeholder + uint32_t smallestOffet = 5 + 1; // 5 is the largest size needed to encode varint32 for (auto &itr : dic) { auto &kvHolder = itr.second; if (kvHolder.type == KeyValueHolderType_Offset) { totalSize += kvHolder.pbKeyValueSize + kvHolder.keySize + kvHolder.valueSize; + smallestOffet = min(smallestOffet, kvHolder.offset); } else { vec.emplace_back(itr.first, kvHolder.toMMBuffer(nullptr, nullptr)); } } + if (smallestOffet > 5) { + smallestOffet = ItemSizeHolderSize; + } + totalSize += smallestOffet; if (vec.empty()) { return make_pair(MMBuffer(), totalSize); } @@ -325,6 +342,7 @@ static pair prepareEncode(const mmkv::MMKVMapCrypt &dic) { totalSize += sizeOfMap; return make_pair(move(buffer), totalSize); } +#endif // since we use append mode, when -[setData: forKey:] many times, space may not be enough // try a full rewrite to make space @@ -417,6 +435,7 @@ bool MMKV::writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool m_metaInfo->m_version = MMKVVersionSequence; needsFullWrite = true; } +#ifndef MMKV_DISABLE_CRYPT if (unlikely(iv)) { memcpy(m_metaInfo->m_vector, iv, sizeof(m_metaInfo->m_vector)); if (m_metaInfo->m_version < MMKVVersionRandomIV) { @@ -424,6 +443,7 @@ bool MMKV::writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool } needsFullWrite = true; } +#endif if (unlikely(increaseSequence)) { m_metaInfo->m_sequence++; m_metaInfo->m_lastConfirmedMetaInfo.lastActualSize = static_cast(size); @@ -449,13 +469,16 @@ bool MMKV::writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool MMBuffer MMKV::getDataForKey(MMKVKey_t key) { checkLoadData(); +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { auto itr = m_dicCrypt->find(key); if (itr != m_dicCrypt->end()) { auto basePtr = (uint8_t *) (m_file->getMemory()) + Fixed32Size; return itr->second.toMMBuffer(basePtr, m_crypter); } - } else { + } else +#endif + { auto itr = m_dic->find(key); if (itr != m_dic->end()) { auto basePtr = (uint8_t *) (m_file->getMemory()) + Fixed32Size; @@ -466,12 +489,14 @@ MMBuffer MMKV::getDataForKey(MMKVKey_t key) { return nan; } +#ifndef MMKV_DISABLE_CRYPT // for Apple watch simulator -#if defined(TARGET_OS_SIMULATOR) && defined(TARGET_CPU_X86) +# if defined(TARGET_OS_SIMULATOR) && defined(TARGET_CPU_X86) static AESCryptStatus t_status; -#else +# else thread_local AESCryptStatus t_status; -#endif +# endif +#endif // MMKV_DISABLE_CRYPT bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) { if ((!isDataHolder && data.length() == 0) || isKeyEmpty(key)) { @@ -481,6 +506,7 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) { SCOPED_LOCK(m_exclusiveProcessLock); checkLoadData(); +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { if (isDataHolder) { auto sizeNeededForData = pbRawVarint32Size((uint32_t) data.length()) + data.length(); @@ -491,11 +517,11 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) { } auto itr = m_dicCrypt->find(key); if (itr != m_dicCrypt->end()) { -#ifdef MMKV_APPLE +# ifdef MMKV_APPLE auto ret = appendDataWithKey(data, key, itr->second, isDataHolder); -#else +# else auto ret = appendDataWithKey(data, key, isDataHolder); -#endif +# endif if (!ret.first) { return false; } @@ -521,7 +547,9 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) { m_dicCrypt->emplace(key, KeyValueHolderCrypt(move(data))); } } - } else { + } else +#endif // MMKV_DISABLE_CRYPT + { auto itr = m_dic->find(key); if (itr != m_dic->end()) { auto ret = appendDataWithKey(data, itr->second, isDataHolder); @@ -548,26 +576,28 @@ bool MMKV::removeDataForKey(MMKVKey_t key) { if (isKeyEmpty(key)) { return false; } - +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { auto itr = m_dicCrypt->find(key); if (itr != m_dicCrypt->end()) { m_hasFullWriteback = false; static MMBuffer nan; -#ifdef MMKV_APPLE +# ifdef MMKV_APPLE auto ret = appendDataWithKey(nan, key, itr->second); -#else +# else auto ret = appendDataWithKey(nan, key); -#endif +# endif if (ret.first) { -#ifdef MMKV_APPLE +# ifdef MMKV_APPLE [itr->first release]; -#endif +# endif m_dicCrypt->erase(itr); } return ret.first; } - } else { + } else +#endif // MMKV_DISABLE_CRYPT + { auto itr = m_dic->find(key); if (itr != m_dic->end()) { m_hasFullWriteback = false; @@ -612,12 +642,13 @@ MMKV::doAppendDataWithKey(const MMBuffer &data, const MMBuffer &keyData, bool is return make_pair(false, KeyValueHolder()); } #endif - +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { if (KeyValueHolderCrypt::isValueStoredAsOffset(valueLength)) { m_crypter->getCurStatus(t_status); } } +#endif try { if (isKeyEncoded) { m_output->writeRawData(keyData); @@ -635,9 +666,11 @@ MMKV::doAppendDataWithKey(const MMBuffer &data, const MMBuffer &keyData, bool is auto offset = static_cast(m_actualSize); auto ptr = (uint8_t *) m_file->getMemory() + Fixed32Size + m_actualSize; +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { m_crypter->encrypt(ptr, ptr, size); } +#endif m_actualSize += size; updateCRCDigest(ptr, size); @@ -716,10 +749,9 @@ bool MMKV::fullWriteback(AESCrypt *newCrypter) { // we don't need to really serialize the dictionary, just reuse what's already in the file static void memmoveDictionary(MMKVMap &dic, CodedOutputData *output, uint8_t *ptr, AESCrypt *encrypter, size_t totalSize) { - // hold the fake size of dictionay's serialization result auto originOutputPtr = output->curWritePointer(); - output->writeRawVarint32(ItemSizeHolder); - auto writePtr = output->curWritePointer(); + // make space to hold the fake size of dictionary's serialization result + auto writePtr = originOutputPtr + ItemSizeHolderSize; // reuse what's already in the file if (!dic.empty()) { // sort by offset @@ -751,48 +783,61 @@ memmoveDictionary(MMKVMap &dic, CodedOutputData *output, uint8_t *ptr, AESCrypt } // update offset if (!encrypter) { - auto offset = static_cast(output->curWritePointer() - basePtr); + auto offset = ItemSizeHolderSize; for (auto kvHolder : vec) { kvHolder->offset = offset; offset += kvHolder->computedKVSize + kvHolder->valueSize; } } } + // hold the fake size of dictionary's serialization result + output->writeRawVarint32(ItemSizeHolder); auto writtenSize = static_cast(writePtr - originOutputPtr); +#ifndef MMKV_DISABLE_CRYPT if (encrypter) { encrypter->encrypt(originOutputPtr, originOutputPtr, writtenSize); } +#endif assert(writtenSize == totalSize); output->seek(writtenSize - ItemSizeHolderSize); } +#ifndef MMKV_DISABLE_CRYPT + static void memmoveDictionary(MMKVMapCrypt &dic, CodedOutputData *output, uint8_t *ptr, AESCrypt *decrypter, AESCrypt *encrypter, pair &preparedData) { - // hold the fake size of dictionay's serialization result - output->writeRawVarint32(ItemSizeHolder); - auto writePtr = output->curWritePointer(); - if (encrypter) { - encrypter->encrypt(writePtr - ItemSizeHolderSize, writePtr - ItemSizeHolderSize, ItemSizeHolderSize); - } // reuse what's already in the file + vector vec; if (!dic.empty()) { // sort by offset - vector vec; vec.reserve(dic.size()); for (auto &itr : dic) { if (itr.second.type == KeyValueHolderType_Offset) { vec.push_back(&itr.second); } } - if (vec.empty()) { - goto WRITE_DATA; - } sort(vec.begin(), vec.end(), [](auto left, auto right) { return left->offset < right->offset; }); - + } + auto sizeHolder = ItemSizeHolder, sizeHolderSize = ItemSizeHolderSize; + if (!vec.empty()) { + auto smallestOffset = vec.front()->offset; + if (smallestOffset != ItemSizeHolderSize && smallestOffset <= 5) { + sizeHolderSize = smallestOffset; + assert(sizeHolderSize != 0); + static const uint32_t ItemSizeHolders[] = {0, 0x0f, 0xff, 0xffff, 0xffffff, 0xffffffff}; + sizeHolder = ItemSizeHolders[sizeHolderSize]; + } + } + output->writeRawVarint32(static_cast(sizeHolder)); + auto writePtr = output->curWritePointer(); + if (encrypter) { + encrypter->encrypt(writePtr - sizeHolderSize, writePtr - sizeHolderSize, sizeHolderSize); + } + if (!vec.empty()) { // merge nearby items to make memmove quicker vector> dataSections; // pair(offset, size) dataSections.push_back(vec.front()->toTuple()); @@ -814,7 +859,7 @@ static void memmoveDictionary(MMKVMapCrypt &dic, } // update offset & AESCryptStatus if (encrypter) { - auto offset = static_cast(output->curWritePointer() - basePtr); + auto offset = sizeHolderSize; for (auto kvHolder : vec) { kvHolder->offset = offset; auto size = kvHolder->pbKeyValueSize + kvHolder->keySize + kvHolder->valueSize; @@ -824,7 +869,6 @@ static void memmoveDictionary(MMKVMapCrypt &dic, } } } -WRITE_DATA: auto &data = preparedData.first; if (data.length() > 0) { auto dataSize = CodedInputData(data.getPtr(), data.length()).readUInt32(); @@ -839,11 +883,13 @@ static void memmoveDictionary(MMKVMapCrypt &dic, } } auto writtenSize = static_cast(writePtr - output->curWritePointer()); - assert(writtenSize + ItemSizeHolderSize == preparedData.second); + assert(writtenSize + sizeHolderSize == preparedData.second); output->seek(writtenSize); } -#define InvalidCryptPtr ((AESCrypt *) (void *) (1)) +# define InvalidCryptPtr ((AESCrypt *) (void *) (1)) + +#endif // MMKV_DISABLE_CRYPT bool MMKV::doFullWriteBack(pair preparedData, AESCrypt *newCrypter) { auto ptr = (uint8_t *) m_file->getMemory(); @@ -855,6 +901,7 @@ bool MMKV::doFullWriteBack(pair preparedData, AESCrypt *newCry } #endif +#ifndef MMKV_DISABLE_CRYPT uint8_t newIV[AES_KEY_LEN]; auto decrypter = m_crypter; auto encrypter = (newCrypter == InvalidCryptPtr) ? nullptr : (newCrypter ? newCrypter : m_crypter); @@ -862,19 +909,28 @@ bool MMKV::doFullWriteBack(pair preparedData, AESCrypt *newCry AESCrypt::fillRandomIV(newIV); encrypter->resetIV(newIV, sizeof(newIV)); } +#endif delete m_output; m_output = new CodedOutputData(ptr + Fixed32Size, m_file->getFileSize() - Fixed32Size); +#ifndef MMKV_DISABLE_CRYPT if (m_crypter) { memmoveDictionary(*m_dicCrypt, m_output, ptr, decrypter, encrypter, preparedData); } else { +#else + { + auto encrypter = m_crypter; +#endif memmoveDictionary(*m_dic, m_output, ptr, encrypter, totalSize); } m_actualSize = totalSize; +#ifndef MMKV_DISABLE_CRYPT if (encrypter) { recaculateCRCDigestWithIV(newIV); - } else { + } else +#endif + { recaculateCRCDigestWithIV(nullptr); } m_hasFullWriteback = true; @@ -883,6 +939,7 @@ bool MMKV::doFullWriteBack(pair preparedData, AESCrypt *newCry return true; } +#ifndef MMKV_DISABLE_CRYPT bool MMKV::reKey(const string &cryptKey) { SCOPED_LOCK(m_lock); checkLoadData(); @@ -937,6 +994,7 @@ bool MMKV::reKey(const string &cryptKey) { } return ret; } +#endif void MMKV::trim() { SCOPED_LOCK(m_lock); @@ -993,12 +1051,16 @@ void MMKV::clearAll() { } m_file->truncate(DEFAULT_MMAP_SIZE); +#ifndef MMKV_DISABLE_CRYPT uint8_t newIV[AES_KEY_LEN]; AESCrypt::fillRandomIV(newIV); if (m_crypter) { m_crypter->resetIV(newIV, sizeof(newIV)); } writeActualSize(0, 0, newIV, IncreaseSequence); +#else + writeActualSize(0, 0, nullptr, IncreaseSequence); +#endif m_metaFile->msync(MMKV_SYNC); clearMemoryCache(); diff --git a/Core/MMKV_IO.h b/Core/MMKV_IO.h index 1d4f6830..4b2d723d 100644 --- a/Core/MMKV_IO.h +++ b/Core/MMKV_IO.h @@ -26,9 +26,9 @@ MMKV_NAMESPACE_BEGIN -std::string mmapedKVKey(const std::string &mmapID, MMKVPath_t *relativePath = nullptr); -MMKVPath_t mappedKVPathWithID(const std::string &mmapID, MMKVMode mode, MMKVPath_t *relativePath); -MMKVPath_t crcPathWithID(const std::string &mmapID, MMKVMode mode, MMKVPath_t *relativePath); +std::string mmapedKVKey(const std::string &mmapID, MMKVPath_t *rootPath = nullptr); +MMKVPath_t mappedKVPathWithID(const std::string &mmapID, MMKVMode mode, MMKVPath_t *rootPath); +MMKVPath_t crcPathWithID(const std::string &mmapID, MMKVMode mode, MMKVPath_t *rootPath); MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID); MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID); diff --git a/Core/MMKV_OSX.cpp b/Core/MMKV_OSX.cpp index b90d0a63..a1db0e3c 100644 --- a/Core/MMKV_OSX.cpp +++ b/Core/MMKV_OSX.cpp @@ -52,7 +52,6 @@ using namespace mmkv; extern ThreadLock *g_instanceLock; extern MMKVPath_t g_rootDir; -constexpr uint32_t Fixed32Size = pbFixed32Size(); enum { UnKnown = 0, PowerMac = 1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch }; static void GetAppleMachineInfo(int &device, int &version); @@ -192,6 +191,10 @@ NSObject *MMKV::getObject(MMKVKey_t key, Class cls) { return nil; } +# ifndef MMKV_DISABLE_CRYPT + +constexpr uint32_t Fixed32Size = pbFixed32Size(); + pair MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, const KeyValueHolderCrypt &kvHolder, bool isDataHolder) { if (kvHolder.type != KeyValueHolderType_Offset) { @@ -210,6 +213,7 @@ MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, const KeyValueHolde return doAppendDataWithKey(data, keyData, isDataHolder, keyLength); } +# endif NSArray *MMKV::allKeys() { SCOPED_LOCK(m_lock); diff --git a/Core/MiniPBCoder.cpp b/Core/MiniPBCoder.cpp old mode 100755 new mode 100644 index 7e3d45a1..8c88523e --- a/Core/MiniPBCoder.cpp +++ b/Core/MiniPBCoder.cpp @@ -39,16 +39,22 @@ MiniPBCoder::MiniPBCoder() : m_encodeItems(new std::vector()) { MiniPBCoder::MiniPBCoder(const MMBuffer *inputBuffer, AESCrypt *crypter) : MiniPBCoder() { m_inputBuffer = inputBuffer; +#ifndef MMKV_DISABLE_CRYPT if (crypter) { m_inputDataDecrpt = new CodedInputDataCrypt(m_inputBuffer->getPtr(), m_inputBuffer->length(), *crypter); } else { m_inputData = new CodedInputData(m_inputBuffer->getPtr(), m_inputBuffer->length()); } +#else + m_inputData = new CodedInputData(m_inputBuffer->getPtr(), m_inputBuffer->length()); +#endif // MMKV_DISABLE_CRYPT } MiniPBCoder::~MiniPBCoder() { delete m_inputData; +#ifndef MMKV_DISABLE_CRYPT delete m_inputDataDecrpt; +#endif delete m_outputBuffer; delete m_outputData; delete m_encodeItems; @@ -121,6 +127,8 @@ size_t MiniPBCoder::prepareObjectForEncode(const MMBuffer &buffer) { return index; } +#ifndef MMKV_DISABLE_CRYPT + size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) { m_encodeItems->push_back(PBEncodeItem()); PBEncodeItem *encodeItem = &(m_encodeItems->back()); @@ -132,11 +140,11 @@ size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) { for (const auto &itr : vec) { const auto &key = itr.first; const auto &value = itr.second; -#ifdef MMKV_APPLE +# ifdef MMKV_APPLE if (key.length <= 0) { -#else +# else if (key.length() <= 0) { -#endif +# endif continue; } @@ -159,6 +167,8 @@ size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) { return index; } +#endif // MMKV_DISABLE_CRYPT + MMBuffer MiniPBCoder::writePreparedItems(size_t index) { PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr; if (oItem && oItem->compiledSize > 0) { @@ -277,6 +287,8 @@ void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) { } } +# ifndef MMKV_DISABLE_CRYPT + void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) { auto block = [position, this](MMKVMapCrypt &dictionary) { if (position) { @@ -318,6 +330,8 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) } } +# endif // MMKV_DISABLE_CRYPT + vector MiniPBCoder::decodeVector(const MMBuffer &oData) { MiniPBCoder oCoder(&oData); return oCoder.decodeOneVector(); @@ -335,6 +349,8 @@ void MiniPBCoder::greedyDecodeMap(MMKVMap &dic, const MMBuffer &oData, size_t po oCoder.decodeOneMap(dic, position, true); } +#ifndef MMKV_DISABLE_CRYPT + void MiniPBCoder::decodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position) { MiniPBCoder oCoder(&oData, crypter); oCoder.decodeOneMap(dic, position, false); @@ -345,4 +361,6 @@ void MiniPBCoder::greedyDecodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESC oCoder.decodeOneMap(dic, position, true); } +#endif + } // namespace mmkv diff --git a/Core/MiniPBCoder.h b/Core/MiniPBCoder.h index 157b709b..15895687 100644 --- a/Core/MiniPBCoder.h +++ b/Core/MiniPBCoder.h @@ -66,7 +66,9 @@ class MiniPBCoder { MMBuffer writePreparedItems(size_t index); void decodeOneMap(MMKVMap &dic, size_t position, bool greedy); +#ifndef MMKV_DISABLE_CRYPT void decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy); +#endif #ifndef MMKV_APPLE size_t prepareObjectForEncode(const std::string &str); @@ -99,11 +101,13 @@ class MiniPBCoder { // decode as much data as possible before any error happens static void greedyDecodeMap(MMKVMap &dic, const MMBuffer &oData, size_t position = 0); +#ifndef MMKV_DISABLE_CRYPT // return empty result if there's any error static void decodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position = 0); // decode as much data as possible before any error happens static void greedyDecodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position = 0); +#endif // MMKV_DISABLE_CRYPT #ifndef MMKV_APPLE static std::vector decodeVector(const MMBuffer &oData); diff --git a/Core/MiniPBCoder_OSX.cpp b/Core/MiniPBCoder_OSX.cpp index d4074035..20d55b00 100644 --- a/Core/MiniPBCoder_OSX.cpp +++ b/Core/MiniPBCoder_OSX.cpp @@ -121,6 +121,8 @@ void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) { } } +# ifndef MMKV_DISABLE_CRYPT + void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) { auto block = [position, this](MMKVMapCrypt &dictionary) { if (position) { @@ -167,6 +169,8 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) } } +# endif // MMKV_DISABLE_CRYPT + NSObject *MiniPBCoder::decodeObject(const MMBuffer &oData, Class cls) { if (!cls || oData.length() == 0) { return nil; diff --git a/Core/aes/AESCrypt.cpp b/Core/aes/AESCrypt.cpp index 7694887a..b71e99b1 100644 --- a/Core/aes/AESCrypt.cpp +++ b/Core/aes/AESCrypt.cpp @@ -20,10 +20,12 @@ #include "AESCrypt.h" #include "openssl/openssl_aes.h" +#include #include #include #include -#include + +#ifndef MMKV_DISABLE_CRYPT using namespace openssl; @@ -161,10 +163,10 @@ AESCrypt AESCrypt::cloneWithStatus(const AESCryptStatus &status) const { } // namespace mmkv -#ifndef NDEBUG +# ifndef NDEBUG -# include "../MMKVLog.h" -# include "../MemoryFile.h" +# include "../MMKVLog.h" +# include "../MemoryFile.h" namespace mmkv { @@ -250,4 +252,5 @@ void AESCrypt::testAESCrypt() { } // namespace mmkv -#endif +# endif // NDEBUG +#endif // MMKV_DISABLE_CRYPT diff --git a/Core/aes/AESCrypt.h b/Core/aes/AESCrypt.h index 9c11427a..e5b78dc0 100644 --- a/Core/aes/AESCrypt.h +++ b/Core/aes/AESCrypt.h @@ -25,6 +25,14 @@ #include "MMKVPredef.h" #include +#ifdef MMKV_DISABLE_CRYPT + +namespace mmkv { +class AESCrypt; +} + +#else + namespace openssl { struct AES_KEY; } @@ -94,5 +102,6 @@ class AESCrypt { } // namespace mmkv -#endif +#endif // MMKV_DISABLE_CRYPT +#endif // __cplusplus #endif /* AES_CRYPT_H_ */ diff --git a/Core/aes/openssl/openssl_aes-armv4.S b/Core/aes/openssl/openssl_aes-armv4.S index 9e57e75e..eeae3d7a 100644 --- a/Core/aes/openssl/openssl_aes-armv4.S +++ b/Core/aes/openssl/openssl_aes-armv4.S @@ -40,8 +40,9 @@ */ #include "openssl_arm_arch.h" +#include "../../MMKVPredef.h" -#if (__ARM_MAX_ARCH__ <= 7) && (__ARM_MAX_ARCH__ > 0) +#if (__ARM_MAX_ARCH__ <= 7) && (__ARM_MAX_ARCH__ > 0) && !defined(MMKV_DISABLE_CRYPT) .text #if defined(__thumb2__) && !defined(__APPLE__) diff --git a/Core/aes/openssl/openssl_aes.h b/Core/aes/openssl/openssl_aes.h index 31d71b3f..67857247 100644 --- a/Core/aes/openssl/openssl_aes.h +++ b/Core/aes/openssl/openssl_aes.h @@ -16,6 +16,8 @@ #include #include "../../MMKVPredef.h" +#ifndef MMKV_DISABLE_CRYPT + namespace openssl { /* @@ -111,5 +113,6 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); #endif // __ARM_MAX_ARCH__ > 0 -#endif -#endif +#endif // MMKV_DISABLE_CRYPT +#endif // __cplusplus +#endif // HEADER_AES_H diff --git a/Core/aes/openssl/openssl_aes_core.cpp b/Core/aes/openssl/openssl_aes_core.cpp index 577f0d03..a4fab8cc 100755 --- a/Core/aes/openssl/openssl_aes_core.cpp +++ b/Core/aes/openssl/openssl_aes_core.cpp @@ -41,6 +41,8 @@ #include "openssl_aes.h" #include "openssl_aes_locl.h" +#ifndef MMKV_DISABLE_CRYPT + #if (__ARM_MAX_ARCH__ > 7) && defined(MMKV_ANDROID) aes_set_encrypt_t AES_set_encrypt_key = openssl::AES_C_set_encrypt_key; @@ -1039,3 +1041,4 @@ void AES_C_decrypt(const uint8_t *in, uint8_t *out, const void *k) { #endif // (__ARM_MAX_ARCH__ < 0) || (__ARM_MAX_ARCH__ > 7 && defined(MMKV_ANDROID)) +#endif // MMKV_DISABLE_CRYPT diff --git a/Core/aes/openssl/openssl_aesv8-armx.S b/Core/aes/openssl/openssl_aesv8-armx.S index a2f97e99..f900c996 100644 --- a/Core/aes/openssl/openssl_aesv8-armx.S +++ b/Core/aes/openssl/openssl_aesv8-armx.S @@ -1,6 +1,8 @@ #include "openssl_arm_arch.h" +#include "../../MMKVPredef.h" + +#if (__ARM_MAX_ARCH__ > 7) && !defined(MMKV_DISABLE_CRYPT) -#if __ARM_MAX_ARCH__ > 7 .text .align 5 diff --git a/Core/aes/openssl/openssl_cfb128.cpp b/Core/aes/openssl/openssl_cfb128.cpp index 7043ea7e..5774b159 100644 --- a/Core/aes/openssl/openssl_cfb128.cpp +++ b/Core/aes/openssl/openssl_cfb128.cpp @@ -8,7 +8,10 @@ */ #include "openssl_aes.h" -#include +#include "../../MMKVPredef.h" +#include + +#ifndef MMKV_DISABLE_CRYPT namespace openssl { @@ -90,3 +93,5 @@ void AES_cfb128_decrypt(const uint8_t *in, uint8_t *out, size_t len, const AES_K } } // namespace openssl + +#endif // MMKV_DISABLE_CRYPT diff --git a/MMKV.podspec b/MMKV.podspec index 7d9e13e6..f7198976 100644 --- a/MMKV.podspec +++ b/MMKV.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKV" - s.version = "1.2.0" + s.version = "1.2.1" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.description = <<-DESC @@ -30,7 +30,7 @@ Pod::Spec.new do |s| "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF" => "NO", } - s.dependency 'MMKVCore', '~> 1.2.0' + s.dependency 'MMKVCore', '~> 1.2.1' end diff --git a/MMKVAppExtension.podspec b/MMKVAppExtension.podspec index aa504dfc..cade90d4 100644 --- a/MMKVAppExtension.podspec +++ b/MMKVAppExtension.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVAppExtension" - s.version = "1.2.0" + s.version = "1.2.1" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.module_name = "MMKVAppExtension" @@ -31,7 +31,7 @@ Pod::Spec.new do |s| "GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION", } - s.dependency 'MMKVCore', '~> 1.2.0' + s.dependency 'MMKVCore', '~> 1.2.1' end diff --git a/MMKVCore.podspec b/MMKVCore.podspec index 5a67fe97..4bd73930 100644 --- a/MMKVCore.podspec +++ b/MMKVCore.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVCore" - s.version = "1.2.0" + s.version = "1.2.1" s.summary = "MMKVCore for MMKV. MMKV is a cross-platform key-value storage framework developed by WeChat." s.description = <<-DESC diff --git a/MMKVWatchExtension.podspec b/MMKVWatchExtension.podspec index 90d1ca77..c88fbb95 100644 --- a/MMKVWatchExtension.podspec +++ b/MMKVWatchExtension.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVWatchExtension" - s.version = "1.2.0" + s.version = "1.2.1" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.module_name = "MMKVWatchExtension" @@ -31,7 +31,7 @@ Pod::Spec.new do |s| "GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION", } - s.dependency 'MMKVCore', '~> 1.2.0' + s.dependency 'MMKVCore', '~> 1.2.1' end diff --git a/README.md b/README.md index 89b7b828..36310c84 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![license](https://img.shields.io/badge/license-BSD_3-brightgreen.svg?style=flat)](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/MMKV/pulls) -[![Release Version](https://img.shields.io/badge/release-1.2.0-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) +[![Release Version](https://img.shields.io/badge/release-1.2.1-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) [![Platform](https://img.shields.io/badge/Platform-%20Android%20%7C%20iOS%2FmacOS%20%7C%20Win32%20%7C%20POSIX-brightgreen.svg)](https://github.com/Tencent/MMKV/wiki/home) 中文版本请参看[这里](./readme_cn.md) @@ -28,8 +28,8 @@ Add the following lines to `build.gradle` on your app module: ```gradle dependencies { - implementation 'com.tencent:mmkv-static:1.2.0' - // replace "1.2.0" with any available version + implementation 'com.tencent:mmkv-static:1.2.1' + // replace "1.2.1" with any available version } ``` diff --git a/iOS/MMKV/MMKV.xcodeproj/project.pbxproj b/iOS/MMKV/MMKV.xcodeproj/project.pbxproj index 24a2784e..f55ea99a 100644 --- a/iOS/MMKV/MMKV.xcodeproj/project.pbxproj +++ b/iOS/MMKV/MMKV.xcodeproj/project.pbxproj @@ -485,7 +485,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -531,7 +531,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -742,7 +742,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -782,7 +782,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -829,7 +829,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -878,7 +878,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.2.1; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index 973c23ac..cf5e2f59 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -68,12 +68,21 @@ NS_ASSUME_NONNULL_BEGIN /// @param mmapID any unique ID (com.tencent.xin.pay, etc), if you want a per-user mmkv, you could merge user-id within mmapID /// @param relativePath custom path of the file, `NSDocumentDirectory/mmkv` by default -+ (nullable instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath NS_SWIFT_NAME(init(mmapID:relativePath:)); ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath NS_SWIFT_NAME(init(mmapID:relativePath:)) __attribute__((deprecated("use +mmkvWithID:rootPath: instead"))); + +/// @param mmapID any unique ID (com.tencent.xin.pay, etc), if you want a per-user mmkv, you could merge user-id within mmapID +/// @param rootPath custom path of the file, `NSDocumentDirectory/mmkv` by default ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID rootPath:(nullable NSString *)rootPath NS_SWIFT_NAME(init(mmapID:rootPath:)); /// @param mmapID any unique ID (com.tencent.xin.pay, etc), if you want a per-user mmkv, you could merge user-id within mmapID /// @param cryptKey 16 bytes at most /// @param relativePath custom path of the file, `NSDocumentDirectory/mmkv` by default -+ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)relativePath NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)relativePath NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)) __attribute__((deprecated("use +mmkvWithID:cryptKey:rootPath: instead"))); + +/// @param mmapID any unique ID (com.tencent.xin.pay, etc), if you want a per-user mmkv, you could merge user-id within mmapID +/// @param cryptKey 16 bytes at most +/// @param rootPath custom path of the file, `NSDocumentDirectory/mmkv` by default ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey rootPath:(nullable NSString *)rootPath NS_SWIFT_NAME(init(mmapID:cryptKey:rootPath:)); // you can call this on applicationWillTerminate, it's totally fine if you don't call + (void)onAppTerminate; @@ -206,7 +215,7 @@ NS_ASSUME_NONNULL_BEGIN // for CrashProtected Only + (BOOL)isFileValid:(NSString *)mmapID NS_SWIFT_NAME(isFileValid(for:)); -+ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(isFileValid(for:relativePath:)); ++ (BOOL)isFileValid:(NSString *)mmapID rootPath:(nullable NSString *)path NS_SWIFT_NAME(isFileValid(for:rootPath:)); NS_ASSUME_NONNULL_END diff --git a/iOS/MMKV/MMKV/libMMKV.mm b/iOS/MMKV/MMKV/libMMKV.mm index 31fb65ef..0abce763 100644 --- a/iOS/MMKV/MMKV/libMMKV.mm +++ b/iOS/MMKV/MMKV/libMMKV.mm @@ -111,38 +111,46 @@ + (NSString *)initializeMMKV:(nullable NSString *)rootDir groupDir:(NSString *)g // a generic purpose instance + (instancetype)defaultMMKV { - return [MMKV mmkvWithID:(@"" DEFAULT_MMAP_ID) cryptKey:nil relativePath:nil mode:MMKVSingleProcess]; + return [MMKV mmkvWithID:(@"" DEFAULT_MMAP_ID) cryptKey:nil rootPath:nil mode:MMKVSingleProcess]; } // any unique ID (com.tencent.xin.pay, etc) + (instancetype)mmkvWithID:(NSString *)mmapID { - return [MMKV mmkvWithID:mmapID cryptKey:nil relativePath:nil mode:MMKVSingleProcess]; + return [MMKV mmkvWithID:mmapID cryptKey:nil rootPath:nil mode:MMKVSingleProcess]; } + (instancetype)mmkvWithID:(NSString *)mmapID mode:(MMKVMode)mode { - auto relativePath = (mode == MMKVSingleProcess) ? nil : g_groupPath; - return [MMKV mmkvWithID:mmapID cryptKey:nil relativePath:relativePath mode:mode]; + auto rootPath = (mode == MMKVSingleProcess) ? nil : g_groupPath; + return [MMKV mmkvWithID:mmapID cryptKey:nil rootPath:rootPath mode:mode]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - return [MMKV mmkvWithID:mmapID cryptKey:cryptKey relativePath:nil mode:MMKVSingleProcess]; + return [MMKV mmkvWithID:mmapID cryptKey:cryptKey rootPath:nil mode:MMKVSingleProcess]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey mode:(MMKVMode)mode { - auto relativePath = (mode == MMKVSingleProcess) ? nil : g_groupPath; - return [MMKV mmkvWithID:mmapID cryptKey:cryptKey relativePath:relativePath mode:mode]; + auto rootPath = (mode == MMKVSingleProcess) ? nil : g_groupPath; + return [MMKV mmkvWithID:mmapID cryptKey:cryptKey rootPath:rootPath mode:mode]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID rootPath:(nullable NSString *)rootPath { + return [MMKV mmkvWithID:mmapID cryptKey:nil rootPath:rootPath mode:MMKVSingleProcess]; } + (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { - return [MMKV mmkvWithID:mmapID cryptKey:nil relativePath:relativePath mode:MMKVSingleProcess]; + return [MMKV mmkvWithID:mmapID cryptKey:nil rootPath:relativePath mode:MMKVSingleProcess]; } -+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { - return [MMKV mmkvWithID:mmapID cryptKey:cryptKey relativePath:relativePath mode:MMKVSingleProcess]; ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey rootPath:(nullable NSString *)rootPath { + return [MMKV mmkvWithID:mmapID cryptKey:cryptKey rootPath:rootPath mode:MMKVSingleProcess]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)relativePath { + return [MMKV mmkvWithID:mmapID cryptKey:cryptKey rootPath:relativePath mode:MMKVSingleProcess]; } // relatePath and MMKVMultiProcess mode can't be set at the same time, so we hide this method from public -+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath mode:(MMKVMode)mode { ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey rootPath:(nullable NSString *)rootPath mode:(MMKVMode)mode { if (!g_hasCalledInitializeMMKV) { MMKVError("MMKV not initialized properly, must call +initializeMMKV: in main thread before calling any other MMKV methods"); } @@ -153,18 +161,18 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati SCOPED_LOCK(g_lock); if (mode == MMKVMultiProcess) { - if (!relativePath) { - relativePath = g_groupPath; + if (!rootPath) { + rootPath = g_groupPath; } - if (!relativePath) { + if (!rootPath) { MMKVError("Getting a multi-process MMKV [%@] without setting groupDir makes no sense", mmapID); MMKV_ASSERT(0); } } - NSString *kvKey = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; + NSString *kvKey = [MMKV mmapKeyWithMMapID:mmapID rootPath:rootPath]; MMKV *kv = [g_instanceDic objectForKey:kvKey]; if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:relativePath mode:mode]; + kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey rootPath:rootPath mode:mode]; if (!kv->m_mmkv) { return nil; } @@ -174,19 +182,19 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati return kv; } -- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(NSString *)relativePath mode:(MMKVMode)mode { +- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey rootPath:(NSString *)rootPath mode:(MMKVMode)mode { if (self = [super init]) { string pathTmp; - if (relativePath.length > 0) { - pathTmp = relativePath.UTF8String; + if (rootPath.length > 0) { + pathTmp = rootPath.UTF8String; } string cryptKeyTmp; if (cryptKey.length > 0) { cryptKeyTmp = string((char *) cryptKey.bytes, cryptKey.length); } - string *relativePathPtr = pathTmp.empty() ? nullptr : &pathTmp; + string *rootPathPtr = pathTmp.empty() ? nullptr : &pathTmp; string *cryptKeyPtr = cryptKeyTmp.empty() ? nullptr : &cryptKeyTmp; - m_mmkv = mmkv::MMKV::mmkvWithID(mmapID.UTF8String, (mmkv::MMKVMode) mode, cryptKeyPtr, relativePathPtr); + m_mmkv = mmkv::MMKV::mmkvWithID(mmapID.UTF8String, (mmkv::MMKVMode) mode, cryptKeyPtr, rootPathPtr); if (!m_mmkv) { return self; } @@ -256,6 +264,8 @@ - (void)trim { #pragma mark - encryption & decryption +#ifndef MMKV_DISABLE_CRYPT + - (nullable NSData *)cryptKey { auto str = m_mmkv->cryptKey(); if (str.length() > 0) { @@ -281,6 +291,21 @@ - (void)checkReSetCryptKey:(nullable NSData *)cryptKey { } } +#else + +- (nullable NSData *)cryptKey { + return nil; +} + +- (BOOL)reKey:(nullable NSData *)newKey { + return NO; +} + +- (void)checkReSetCryptKey:(nullable NSData *)cryptKey { +} + +#endif // MMKV_DISABLE_CRYPT + #pragma mark - set & get - (BOOL)setObject:(nullable NSObject *)object forKey:(NSString *)key { @@ -525,10 +550,10 @@ + (void)setMMKVBasePath:(NSString *)basePath { return [NSString stringWithCString:buf encoding:NSASCIIStringEncoding]; } -+ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { ++ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID rootPath:(nullable NSString *)rootPath { NSString *string = nil; - if ([relativePath length] > 0 && [relativePath isEqualToString:[MMKV mmkvBasePath]] == NO) { - string = md5([relativePath stringByAppendingPathComponent:mmapID]); + if ([rootPath length] > 0 && [rootPath isEqualToString:[MMKV mmkvBasePath]] == NO) { + string = md5([rootPath stringByAppendingPathComponent:mmapID]); } else { string = mmapID; } @@ -537,14 +562,14 @@ + (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSStri } + (BOOL)isFileValid:(NSString *)mmapID { - return [self isFileValid:mmapID relativePath:nil]; + return [self isFileValid:mmapID rootPath:nil]; } -+ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path { ++ (BOOL)isFileValid:(NSString *)mmapID rootPath:(nullable NSString *)path { if (mmapID.length > 0) { if (path.length > 0) { - string relativePath(path.UTF8String); - return mmkv::MMKV::isFileValid(mmapID.UTF8String, &relativePath); + string rootPath(path.UTF8String); + return mmkv::MMKV::isFileValid(mmapID.UTF8String, &rootPath); } else { return mmkv::MMKV::isFileValid(mmapID.UTF8String, nullptr); } diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.h b/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.h index 9da2d232..9d85873d 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.h +++ b/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.h @@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)testChineseCharKey; +- (void)testItemSizeHolderOverride; + @end NS_ASSUME_NONNULL_END diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.mm b/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.mm index 61709736..5a0d6f66 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController+TestCaseBad.mm @@ -128,4 +128,43 @@ - (void)testChineseCharKey { } } +- (void)testItemSizeHolderOverride { + auto mmapID = @"testItemSizeHolderOverride"; + auto cryptKey = nil; + // auto mmapID = @"testItemSizeHolderOverride_crypt"; + // auto cryptKey = [@"Key_seq_1" dataUsingEncoding:NSUTF8StringEncoding]; + + /* do these on v1.1.2 + { + auto mmkv = [MMKV mmkvWithID:mmapID cryptKey:cryptKey]; + + // turn on to check crypt MMKV + // [mmkv setBool:YES forKey:@"b"]; + + // turn on (mutex with the above setBool:forKey testcase) to check crypt MMKV + // [mmkv setInt32:0xff forKey:@"i"]; + + auto value = [NSMutableData dataWithLength:512]; + [mmkv setData:value forKey:@"data"]; + NSLog(@"%@", [mmkv allKeys]); + }*/ + + // do these on v1.2.0 + { + auto mmkv = [MMKV mmkvWithID:mmapID cryptKey:cryptKey]; + auto actualSize = [mmkv actualSize]; + auto fileSize = [mmkv totalSize]; + // force a fullwrieback() + auto valueSize = fileSize - actualSize; + auto value = [NSMutableData dataWithLength:valueSize]; + [mmkv setObject:value forKey:@"bigData"]; + + [mmkv clearMemoryCache]; + + // it might throw exception + // you won't find the key "data" + NSLog(@"%@", [mmkv allKeys]); + } +} + @end diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController.mm b/iOS/MMKVDemo/MMKVDemo/ViewController.mm index 003097d5..94912c56 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController.mm @@ -74,6 +74,7 @@ - (void)viewDidLoad { // [self testCornerSize]; // [self testFastRemoveCornerSize]; // [self testChineseCharKey]; + // [self testItemSizeHolderOverride]; DemoSwiftUsage *swiftUsageDemo = [[DemoSwiftUsage alloc] init]; [swiftUsageDemo testSwiftFunctionality]; @@ -116,7 +117,7 @@ - (void)funcionalTest:(BOOL)decodeOnly { path = [path stringByDeletingLastPathComponent]; path = [path stringByAppendingPathComponent:@"mmkv_2"]; NSData *key_1 = [@"Key_seq_1" dataUsingEncoding:NSUTF8StringEncoding]; - auto mmkv = [MMKV mmkvWithID:@"test/case_aes" cryptKey:key_1 relativePath:path]; + auto mmkv = [MMKV mmkvWithID:@"test/case_aes" cryptKey:key_1 rootPath:path]; if (!decodeOnly) { [mmkv setBool:YES forKey:@"bool"]; @@ -279,7 +280,7 @@ - (void)testReKey { } - (void)testImportFromUserDefault { - NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"testNSUserDefaults"]; + NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"testNSUserDefaults1"]; [userDefault setBool:YES forKey:@"bool"]; [userDefault setInteger:std::numeric_limits::max() forKey:@"NSInteger"]; [userDefault setFloat:3.14 forKey:@"float"]; @@ -334,8 +335,11 @@ - (void)testImportFromUserDefault { number = [NSNumber numberWithUnsignedInteger:std::numeric_limits::max()]; [userDefault setObject:number forKey:@"number_NSUInteger"]; - auto mmkv = [MMKV mmkvWithID:@"testImportNSUserDefaults"]; + auto mmkv = [MMKV mmkvWithID:@"testImportNSUserDefaults1"]; [mmkv migrateFromUserDefaults:userDefault]; + [mmkv clearMemoryCache]; + NSLog(@"%@", [mmkv allKeys]); + NSLog(@"migrate from NSUserDefault begin"); NSLog(@"bool = %d", [mmkv getBoolForKey:@"bool"]); @@ -393,15 +397,19 @@ - (IBAction)onBtnClick:(id)sender { #pragma mark - mmkv baseline test - (void)mmkvBaselineTest:(int)loops { - [self mmkvBatchWriteInt:loops]; [self mmkvBatchReadInt:loops]; - [self mmkvBatchWriteString:loops]; + [self mmkvBatchWriteInt:loops]; [self mmkvBatchReadString:loops]; + [self mmkvBatchWriteString:loops]; //[self mmkvBatchWriteObject:loops]; //[self mmkvBatchReadObject:loops]; //[self mmkvBatchDeleteString:loops]; //[[MMKV defaultMMKV] trim]; + + // auto mmkv = getMMKVForBatchTest(); + // [mmkv clearMemoryCache]; + // [mmkv actualSize]; } MMKV *getMMKVForBatchTest() { diff --git a/iOS/MMKVDemo/WatchApp Extension/ExtensionDelegate.mm b/iOS/MMKVDemo/WatchApp Extension/ExtensionDelegate.mm index d0fd07a1..6042ea30 100644 --- a/iOS/MMKVDemo/WatchApp Extension/ExtensionDelegate.mm +++ b/iOS/MMKVDemo/WatchApp Extension/ExtensionDelegate.mm @@ -34,7 +34,7 @@ - (void)funcionalTest { auto path = [MMKV mmkvBasePath]; path = [path stringByDeletingLastPathComponent]; path = [path stringByAppendingPathComponent:@"mmkv_2"]; - auto mmkv = [MMKV mmkvWithID:@"test/case1" relativePath:path]; + auto mmkv = [MMKV mmkvWithID:@"test/case1" rootPath:path]; [mmkv setBool:YES forKey:@"bool"]; NSLog(@"bool:%d", [mmkv getBoolForKey:@"bool"]); diff --git a/readme_cn.md b/readme_cn.md index f6e80686..561f3d94 100644 --- a/readme_cn.md +++ b/readme_cn.md @@ -22,8 +22,8 @@ MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列 ```gradle dependencies { - implementation 'com.tencent:mmkv-static:1.2.0' - // replace "1.2.0" with any available version + implementation 'com.tencent:mmkv-static:1.2.1' + // replace "1.2.1" with any available version } ```