Full Code of Tencent/MMKV for AI

master f7f0f47fa940 cached
614 files
16.0 MB
732.2k tokens
1947 symbols
1 requests
Download .txt
Showing preview only (2,914K chars total). Download the full file or copy to clipboard to get everything.
Repository: Tencent/MMKV
Branch: master
Commit: f7f0f47fa940
Files: 614
Total size: 16.0 MB

Directory structure:
gitextract_t9qzaftc/

├── .clang-format
├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       └── bug_report.md
├── .gitignore
├── .gitmodules
├── Android/
│   └── MMKV/
│       ├── .gitignore
│       ├── build.gradle
│       ├── checkstyle.xml
│       ├── debug.keystore
│       ├── gradle/
│       │   ├── android-publish-private.gradle
│       │   ├── android-publish.gradle
│       │   ├── build_library.gradle
│       │   ├── check.gradle
│       │   └── wrapper/
│       │       ├── gradle-wrapper.jar
│       │       └── gradle-wrapper.properties
│       ├── gradle.properties
│       ├── gradlew
│       ├── gradlew.bat
│       ├── mmkv/
│       │   ├── .gitignore
│       │   ├── CMakeLists.txt
│       │   ├── build.gradle
│       │   ├── gradle.properties
│       │   ├── proguard-rules.pro
│       │   └── src/
│       │       ├── androidTest/
│       │       │   ├── AndroidManifest.xml
│       │       │   └── java/
│       │       │       └── com/
│       │       │           └── tencent/
│       │       │               └── mmkv/
│       │       │                   ├── MMKVTest.java
│       │       │                   └── MMKVTestService.java
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           ├── aidl/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkv/
│       │           │               └── ParcelableMMKV.aidl
│       │           ├── cpp/
│       │           │   ├── flutter-bridge.cpp
│       │           │   └── native-bridge.cpp
│       │           └── java/
│       │               └── com/
│       │                   └── tencent/
│       │                       └── mmkv/
│       │                           ├── MMKV.java
│       │                           ├── MMKVConfig.java
│       │                           ├── MMKVContentChangeNotification.java
│       │                           ├── MMKVContentProvider.java
│       │                           ├── MMKVHandler.java
│       │                           ├── MMKVLogLevel.java
│       │                           ├── MMKVProcessUtil.java
│       │                           ├── MMKVRecoverStrategic.java
│       │                           ├── NameSpace.java
│       │                           ├── NativeBuffer.java
│       │                           ├── ParcelableMMKV.java
│       │                           └── UnsupportedArchitectureException.java
│       ├── mmkvannotation/
│       │   ├── .gitignore
│       │   ├── build.gradle
│       │   └── src/
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           └── java/
│       │               └── dalvik/
│       │                   └── annotation/
│       │                       └── optimization/
│       │                           └── FastNative.java
│       ├── mmkvdemo/
│       │   ├── .gitignore
│       │   ├── build.gradle
│       │   ├── proguard-rules.pro
│       │   └── src/
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           ├── aidl/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkvdemo/
│       │           │               └── IAshmemMMKV.aidl
│       │           ├── cpp/
│       │           │   ├── CMakeLists.txt
│       │           │   └── mmkvdemo.cpp
│       │           ├── java/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkvdemo/
│       │           │               ├── Baseline.java
│       │           │               ├── BenchMarkBaseService.java
│       │           │               ├── FakeInfo.java
│       │           │               ├── Info.java
│       │           │               ├── MainActivity.java
│       │           │               ├── MultiProcessSharedPreferences.java
│       │           │               ├── MyApplication.java
│       │           │               ├── MyService.java
│       │           │               ├── MyService_1.java
│       │           │               ├── SQLiteKV.java
│       │           │               └── TestParcelable.java
│       │           ├── kotlin/
│       │           │   └── KotlinUsecase.kt
│       │           └── res/
│       │               ├── drawable/
│       │               │   └── ic_launcher_background.xml
│       │               ├── drawable-v24/
│       │               │   └── ic_launcher_foreground.xml
│       │               ├── layout/
│       │               │   └── activity_main.xml
│       │               ├── mipmap-anydpi-v26/
│       │               │   ├── ic_launcher.xml
│       │               │   └── ic_launcher_round.xml
│       │               └── values/
│       │                   ├── colors.xml
│       │                   ├── strings.xml
│       │                   └── styles.xml
│       ├── pmd-ruleset.xml
│       ├── proguard-rules/
│       │   ├── proguard-rules-android-lib.pro
│       │   └── proguard-rules-test.pro
│       └── settings.gradle
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Core/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── CodedInputData.cpp
│   ├── CodedInputData.h
│   ├── CodedInputDataCrypt.cpp
│   ├── CodedInputDataCrypt.h
│   ├── CodedInputDataCrypt_OSX.cpp
│   ├── CodedInputData_OSX.cpp
│   ├── CodedOutputData.cpp
│   ├── CodedOutputData.h
│   ├── Core.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           ├── Core.xcscheme
│   │           └── MMKVWatchCore.xcscheme
│   ├── InterProcessLock.cpp
│   ├── InterProcessLock.h
│   ├── InterProcessLock_Android.cpp
│   ├── InterProcessLock_Win32.cpp
│   ├── KeyValueHolder.cpp
│   ├── KeyValueHolder.h
│   ├── MMBuffer.cpp
│   ├── MMBuffer.h
│   ├── MMKV.cpp
│   ├── MMKV.h
│   ├── MMKVHandler.h
│   ├── MMKVLog.cpp
│   ├── MMKVLog.h
│   ├── MMKVLog_Android.cpp
│   ├── MMKVMetaInfo.hpp
│   ├── MMKVPredef.h
│   ├── MMKV_Android.cpp
│   ├── MMKV_IO.cpp
│   ├── MMKV_IO.h
│   ├── MMKV_OSX.cpp
│   ├── MMKV_OSX.h
│   ├── MemoryFile.cpp
│   ├── MemoryFile.h
│   ├── MemoryFile_Android.cpp
│   ├── MemoryFile_Linux.cpp
│   ├── MemoryFile_OSX.cpp
│   ├── MemoryFile_Win32.cpp
│   ├── MiniPBCoder.cpp
│   ├── MiniPBCoder.h
│   ├── MiniPBCoder_OSX.cpp
│   ├── PBEncodeItem.hpp
│   ├── PBUtility.cpp
│   ├── PBUtility.h
│   ├── ScopedLock.hpp
│   ├── ThreadLock.cpp
│   ├── ThreadLock.h
│   ├── ThreadLock_Win32.cpp
│   ├── aes/
│   │   ├── AESCrypt.cpp
│   │   ├── AESCrypt.h
│   │   └── openssl/
│   │       ├── openssl_aes.h
│   │       ├── openssl_aes_core.cpp
│   │       ├── openssl_aes_locl.h
│   │       ├── openssl_aesv8-armx.S
│   │       ├── openssl_arm_arch.h
│   │       ├── openssl_cfb128.cpp
│   │       ├── openssl_md32_common.h
│   │       ├── openssl_md5.h
│   │       ├── openssl_md5_dgst.cpp
│   │       ├── openssl_md5_locl.h
│   │       ├── openssl_md5_one.cpp
│   │       └── openssl_opensslconf.h
│   ├── core.vcxproj
│   ├── core.vcxproj.filters
│   ├── crc32/
│   │   ├── CMakeLists.txt
│   │   ├── Checksum.h
│   │   ├── crc32_armv8.cpp
│   │   └── zlib/
│   │       ├── crc32.cpp
│   │       ├── crc32.h
│   │       ├── zconf.h
│   │       └── zutil.h
│   └── fakeinclude/
│       └── MMKVCore/
│           ├── MMBuffer.h
│           ├── MMKV.h
│           ├── MMKVHandler.h
│           ├── MMKVLog.h
│           ├── MMKVPredef.h
│           ├── MemoryFile.h
│           ├── MiniPBCoder.h
│           ├── ScopedLock.hpp
│           └── ThreadLock.h
├── Dockerfile
├── LICENSE.TXT
├── MMKV.podspec
├── MMKV.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcshareddata/
│       └── IDEWorkspaceChecks.plist
├── MMKVAppExtension.podspec
├── MMKVCore.podspec
├── MMKVWatchExtension.podspec
├── Makefile
├── OpenHarmony/
│   ├── .gitignore
│   ├── AppScope/
│   │   ├── app.json5
│   │   └── resources/
│   │       └── base/
│   │           └── element/
│   │               └── string.json
│   ├── MMKV/
│   │   ├── .gitignore
│   │   ├── BuildProfile.ets
│   │   ├── CHANGELOG.md
│   │   ├── Index.ets
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── build-profile.json5
│   │   ├── consumer-rules.txt
│   │   ├── example/
│   │   │   ├── Index.ets
│   │   │   └── Util.ets
│   │   ├── hvigorfile.ts
│   │   ├── obfuscation-rules.txt
│   │   ├── oh-package.json5
│   │   └── src/
│   │       └── main/
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── flutter-bridge.cpp
│   │           │   ├── native_bridge.cpp
│   │           │   └── types/
│   │           │       └── libmmkv/
│   │           │           ├── index.d.ts
│   │           │           └── oh-package.json5
│   │           ├── ets/
│   │           │   └── utils/
│   │           │       ├── MMKV.ets
│   │           │       ├── MMKVConfig.ets
│   │           │       ├── MMKVHandler.ets
│   │           │       ├── MMKVLogLevel.ets
│   │           │       ├── NativeBuffer.ets
│   │           │       └── Util.ts
│   │           └── module.json5
│   ├── build-profile.json5
│   ├── dependencies/
│   │   ├── hvigor-4.3.0.tgz
│   │   └── hvigor-ohos-plugin-4.3.0.tgz
│   ├── entry/
│   │   ├── .gitignore
│   │   ├── build-profile.json5
│   │   ├── hvigorfile.ts
│   │   ├── obfuscation-rules.txt
│   │   ├── oh-package.json5
│   │   └── src/
│   │       ├── main/
│   │       │   ├── cpp/
│   │       │   │   ├── CMakeLists.txt
│   │       │   │   ├── napi_init.cpp
│   │       │   │   └── types/
│   │       │   │       └── libentry/
│   │       │   │           ├── index.d.ts
│   │       │   │           └── oh-package.json5
│   │       │   ├── ets/
│   │       │   │   ├── Util/
│   │       │   │   │   ├── Baseline.ets
│   │       │   │   │   ├── MyMMKVHandler.ets
│   │       │   │   │   └── Util.ets
│   │       │   │   ├── entryability/
│   │       │   │   │   └── EntryAbility.ets
│   │       │   │   ├── pages/
│   │       │   │   │   └── Index.ets
│   │       │   │   └── process/
│   │       │   │       └── DemoProcess.ets
│   │       │   ├── module.json5
│   │       │   └── resources/
│   │       │       ├── base/
│   │       │       │   ├── element/
│   │       │       │   │   ├── color.json
│   │       │       │   │   └── string.json
│   │       │       │   ├── media/
│   │       │       │   │   └── layered_image.json
│   │       │       │   └── profile/
│   │       │       │       └── main_pages.json
│   │       │       ├── en_US/
│   │       │       │   └── element/
│   │       │       │       └── string.json
│   │       │       └── zh_CN/
│   │       │           └── element/
│   │       │               └── string.json
│   │       ├── mock/
│   │       │   └── mock-config.json5
│   │       ├── ohosTest/
│   │       │   ├── ets/
│   │       │   │   ├── test/
│   │       │   │   │   ├── Ability.test.ets
│   │       │   │   │   └── List.test.ets
│   │       │   │   ├── testability/
│   │       │   │   │   ├── TestAbility.ets
│   │       │   │   │   └── pages/
│   │       │   │   │       └── Index.ets
│   │       │   │   └── testrunner/
│   │       │   │       └── OpenHarmonyTestRunner.ets
│   │       │   ├── module.json5
│   │       │   └── resources/
│   │       │       └── base/
│   │       │           ├── element/
│   │       │           │   ├── color.json
│   │       │           │   └── string.json
│   │       │           └── profile/
│   │       │               └── test_pages.json
│   │       └── test/
│   │           ├── List.test.ets
│   │           └── LocalUnit.test.ets
│   ├── hvigor/
│   │   └── hvigor-config.json5
│   ├── hvigorfile.ts
│   └── oh-package.json5
├── POSIX/
│   ├── CMakeLists.txt
│   ├── demo/
│   │   ├── CMakeLists.txt
│   │   ├── TestInterProcessLock.cpp
│   │   ├── UnitTest.cpp
│   │   ├── demo.cpp
│   │   └── process.cpp
│   ├── golang/
│   │   ├── .gitignore
│   │   ├── CMakeLists.txt
│   │   ├── callback.go
│   │   ├── go.mod
│   │   ├── golang-bridge.cpp
│   │   ├── golang-bridge.h
│   │   ├── mmkv.go
│   │   ├── mmkv_test.go
│   │   └── test/
│   │       ├── go.mod
│   │       └── main.go
│   └── src/
│       ├── CMakeLists.txt
│       └── libmmkv.cpp
├── Package.swift
├── Python/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── demo.py
│   ├── libmmkv_python.cpp
│   ├── setup.py
│   └── unit_test.py
├── README.md
├── README_CN.md
├── SECURITY.md
├── Script/
│   ├── dumpJavaSignature.py
│   └── formatCode.py
├── Win32/
│   ├── .clang-format
│   ├── Win32.sln
│   ├── Win32Demo/
│   │   ├── Win32Demo.cpp
│   │   ├── Win32Demo.vcxproj
│   │   ├── Win32Demo.vcxproj.filters
│   │   ├── pch.cpp
│   │   └── pch.h
│   └── Win32DemoProcess/
│       ├── Win32DemoProcess.cpp
│       ├── Win32DemoProcess.vcxproj
│       ├── Win32DemoProcess.vcxproj.filters
│       ├── pch.cpp
│       └── pch.h
├── flutter/
│   ├── .gitignore
│   ├── .metadata
│   ├── .vscode/
│   │   ├── launch.json
│   │   └── settings.json
│   ├── mmkv/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── example/
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── android/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── app/
│   │   │   │   │   ├── build.gradle
│   │   │   │   │   └── src/
│   │   │   │   │       ├── main/
│   │   │   │   │       │   ├── AndroidManifest.xml
│   │   │   │   │       │   ├── java/
│   │   │   │   │       │   │   └── com/
│   │   │   │   │       │   │       └── tencent/
│   │   │   │   │       │   │           └── mmkv_example/
│   │   │   │   │       │   │               └── MainActivity.java
│   │   │   │   │       │   └── res/
│   │   │   │   │       │       ├── drawable/
│   │   │   │   │       │       │   └── launch_background.xml
│   │   │   │   │       │       └── values/
│   │   │   │   │       │           └── styles.xml
│   │   │   │   │       └── profile/
│   │   │   │   │           └── AndroidManifest.xml
│   │   │   │   ├── build.gradle
│   │   │   │   ├── gradle/
│   │   │   │   │   └── wrapper/
│   │   │   │   │       └── gradle-wrapper.properties
│   │   │   │   ├── gradle.properties
│   │   │   │   ├── settings.gradle
│   │   │   │   └── settings_aar.gradle
│   │   │   ├── ios/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Flutter/
│   │   │   │   │   ├── AppFrameworkInfo.plist
│   │   │   │   │   ├── Debug.xcconfig
│   │   │   │   │   ├── Release.xcconfig
│   │   │   │   │   └── ephemeral/
│   │   │   │   │       ├── flutter_lldb_helper.py
│   │   │   │   │       └── flutter_lldbinit
│   │   │   │   ├── Podfile
│   │   │   │   ├── Runner/
│   │   │   │   │   ├── AppDelegate.h
│   │   │   │   │   ├── AppDelegate.m
│   │   │   │   │   ├── Assets.xcassets/
│   │   │   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   │   │   └── Contents.json
│   │   │   │   │   │   └── LaunchImage.imageset/
│   │   │   │   │   │       ├── Contents.json
│   │   │   │   │   │       └── README.md
│   │   │   │   │   ├── Base.lproj/
│   │   │   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   │   │   └── Main.storyboard
│   │   │   │   │   ├── Info.plist
│   │   │   │   │   ├── Runner.entitlements
│   │   │   │   │   └── main.m
│   │   │   │   ├── Runner.xcodeproj/
│   │   │   │   │   ├── project.pbxproj
│   │   │   │   │   ├── project.xcworkspace/
│   │   │   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   │   │   └── xcshareddata/
│   │   │   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       └── xcschemes/
│   │   │   │   │           └── Runner.xcscheme
│   │   │   │   └── Runner.xcworkspace/
│   │   │   │       ├── contents.xcworkspacedata
│   │   │   │       └── xcshareddata/
│   │   │   │           ├── IDEWorkspaceChecks.plist
│   │   │   │           └── WorkspaceSettings.xcsettings
│   │   │   ├── lib/
│   │   │   │   └── main.dart
│   │   │   ├── linux/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── CMakeLists.txt
│   │   │   │   ├── flutter/
│   │   │   │   │   ├── CMakeLists.txt
│   │   │   │   │   ├── generated_plugin_registrant.cc
│   │   │   │   │   ├── generated_plugin_registrant.h
│   │   │   │   │   └── generated_plugins.cmake
│   │   │   │   └── runner/
│   │   │   │       ├── CMakeLists.txt
│   │   │   │       ├── main.cc
│   │   │   │       ├── my_application.cc
│   │   │   │       └── my_application.h
│   │   │   ├── macos/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Flutter/
│   │   │   │   │   ├── Flutter-Debug.xcconfig
│   │   │   │   │   ├── Flutter-Release.xcconfig
│   │   │   │   │   └── GeneratedPluginRegistrant.swift
│   │   │   │   ├── Podfile
│   │   │   │   ├── Runner/
│   │   │   │   │   ├── AppDelegate.swift
│   │   │   │   │   ├── Assets.xcassets/
│   │   │   │   │   │   └── AppIcon.appiconset/
│   │   │   │   │   │       └── Contents.json
│   │   │   │   │   ├── Base.lproj/
│   │   │   │   │   │   └── MainMenu.xib
│   │   │   │   │   ├── Configs/
│   │   │   │   │   │   ├── AppInfo.xcconfig
│   │   │   │   │   │   ├── Debug.xcconfig
│   │   │   │   │   │   ├── Release.xcconfig
│   │   │   │   │   │   └── Warnings.xcconfig
│   │   │   │   │   ├── DebugProfile.entitlements
│   │   │   │   │   ├── Info.plist
│   │   │   │   │   ├── MainFlutterWindow.swift
│   │   │   │   │   └── Release.entitlements
│   │   │   │   ├── Runner.xcodeproj/
│   │   │   │   │   ├── project.pbxproj
│   │   │   │   │   ├── project.xcworkspace/
│   │   │   │   │   │   └── xcshareddata/
│   │   │   │   │   │       └── IDEWorkspaceChecks.plist
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       └── xcschemes/
│   │   │   │   │           └── Runner.xcscheme
│   │   │   │   ├── Runner.xcworkspace/
│   │   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   │   └── RunnerTests/
│   │   │   │       └── RunnerTests.swift
│   │   │   ├── ohos/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── AppScope/
│   │   │   │   │   ├── app.json5
│   │   │   │   │   └── resources/
│   │   │   │   │       └── base/
│   │   │   │   │           └── element/
│   │   │   │   │               └── string.json
│   │   │   │   ├── build-profile.json5
│   │   │   │   ├── entry/
│   │   │   │   │   ├── .gitignore
│   │   │   │   │   ├── build-profile.json5
│   │   │   │   │   ├── hvigorfile.ts
│   │   │   │   │   ├── oh-package.json5
│   │   │   │   │   └── src/
│   │   │   │   │       ├── main/
│   │   │   │   │       │   ├── ets/
│   │   │   │   │       │   │   ├── entryability/
│   │   │   │   │       │   │   │   └── EntryAbility.ets
│   │   │   │   │       │   │   ├── pages/
│   │   │   │   │       │   │   │   └── Index.ets
│   │   │   │   │       │   │   └── plugins/
│   │   │   │   │       │   │       └── GeneratedPluginRegistrant.ets
│   │   │   │   │       │   ├── module.json5
│   │   │   │   │       │   └── resources/
│   │   │   │   │       │       ├── base/
│   │   │   │   │       │       │   ├── element/
│   │   │   │   │       │       │   │   ├── color.json
│   │   │   │   │       │       │   │   └── string.json
│   │   │   │   │       │       │   └── profile/
│   │   │   │   │       │       │       └── main_pages.json
│   │   │   │   │       │       ├── en_US/
│   │   │   │   │       │       │   └── element/
│   │   │   │   │       │       │       └── string.json
│   │   │   │   │       │       └── zh_CN/
│   │   │   │   │       │           └── element/
│   │   │   │   │       │               └── string.json
│   │   │   │   │       └── ohosTest/
│   │   │   │   │           ├── ets/
│   │   │   │   │           │   ├── test/
│   │   │   │   │           │   │   ├── Ability.test.ets
│   │   │   │   │           │   │   └── List.test.ets
│   │   │   │   │           │   ├── testability/
│   │   │   │   │           │   │   ├── TestAbility.ets
│   │   │   │   │           │   │   └── pages/
│   │   │   │   │           │   │       └── Index.ets
│   │   │   │   │           │   └── testrunner/
│   │   │   │   │           │       └── OpenHarmonyTestRunner.ts
│   │   │   │   │           ├── module.json5
│   │   │   │   │           └── resources/
│   │   │   │   │               └── base/
│   │   │   │   │                   ├── element/
│   │   │   │   │                   │   ├── color.json
│   │   │   │   │                   │   └── string.json
│   │   │   │   │                   └── profile/
│   │   │   │   │                       └── test_pages.json
│   │   │   │   ├── hvigor/
│   │   │   │   │   └── hvigor-config.json5
│   │   │   │   ├── hvigorfile.ts
│   │   │   │   └── oh-package.json5
│   │   │   ├── pubspec.yaml
│   │   │   └── windows/
│   │   │       ├── .gitignore
│   │   │       ├── CMakeLists.txt
│   │   │       ├── flutter/
│   │   │       │   ├── CMakeLists.txt
│   │   │       │   ├── generated_plugin_registrant.cc
│   │   │       │   ├── generated_plugin_registrant.h
│   │   │       │   └── generated_plugins.cmake
│   │   │       └── runner/
│   │   │           ├── CMakeLists.txt
│   │   │           ├── Runner.rc
│   │   │           ├── flutter_window.cpp
│   │   │           ├── flutter_window.h
│   │   │           ├── main.cpp
│   │   │           ├── resource.h
│   │   │           ├── runner.exe.manifest
│   │   │           ├── utils.cpp
│   │   │           ├── utils.h
│   │   │           ├── win32_window.cpp
│   │   │           └── win32_window.h
│   │   ├── lib/
│   │   │   └── mmkv.dart
│   │   ├── mmkv.iml
│   │   ├── pubspec.yaml
│   │   ├── test/
│   │   │   └── mmkv_test.dart
│   │   └── tool/
│   │       ├── fix_mmkv_plugin_name.rb
│   │       └── mmkvpodhelper.rb
│   ├── mmkv.iml
│   ├── mmkv_android/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── android/
│   │   │   ├── .gitignore
│   │   │   ├── build.gradle
│   │   │   ├── gradle/
│   │   │   │   └── wrapper/
│   │   │   │       ├── gradle-wrapper.jar
│   │   │   │       └── gradle-wrapper.properties
│   │   │   ├── gradle.properties
│   │   │   ├── gradlew
│   │   │   ├── gradlew.bat
│   │   │   ├── settings.gradle
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           └── java/
│   │   │               └── com/
│   │   │                   └── tencent/
│   │   │                       └── mmkv/
│   │   │                           └── MMKVPlugin.java
│   │   ├── lib/
│   │   │   └── mmkv_android.dart
│   │   └── pubspec.yaml
│   ├── mmkv_ios/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── darwin/
│   │   │   ├── .gitignore
│   │   │   ├── Classes/
│   │   │   │   ├── MMKVPlugin.h
│   │   │   │   ├── MMKVPlugin.mm
│   │   │   │   ├── flutter-bridge.h
│   │   │   │   └── flutter-bridge.mm
│   │   │   └── mmkv_ios.podspec
│   │   ├── lib/
│   │   │   └── mmkv_ios.dart
│   │   └── pubspec.yaml
│   ├── mmkv_linux/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── lib/
│   │   │   └── mmkv_linux.dart
│   │   ├── linux/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── flutter-bridge.cpp
│   │   │   ├── include/
│   │   │   │   └── mmkv_linux/
│   │   │   │       └── mmkv_linux_plugin.h
│   │   │   └── mmkv_linux_plugin.cc
│   │   └── pubspec.yaml
│   ├── mmkv_ohos/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── lib/
│   │   │   └── mmkv_ohos.dart
│   │   ├── ohos/
│   │   │   ├── .gitignore
│   │   │   ├── build-profile.json5
│   │   │   ├── hvigorfile.ts
│   │   │   ├── index.ets
│   │   │   ├── oh-package.json5
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── ets/
│   │   │           │   └── components/
│   │   │           │       └── plugin/
│   │   │           │           └── MMKVPlugin.ets
│   │   │           └── module.json5
│   │   └── pubspec.yaml
│   ├── mmkv_platform_interface/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── mmkv_platform_ffi.dart
│   │   │   └── mmkv_platform_interface.dart
│   │   └── pubspec.yaml
│   └── mmkv_win32/
│       ├── .gitignore
│       ├── .metadata
│       ├── CHANGELOG.md
│       ├── LICENSE
│       ├── README.md
│       ├── analysis_options.yaml
│       ├── lib/
│       │   └── mmkv_win32.dart
│       └── pubspec.yaml
└── iOS/
    ├── MMKV/
    │   ├── MMKV/
    │   │   ├── AutoCleanInfo.hpp
    │   │   ├── MMKV.h
    │   │   ├── MMKVAppExtension/
    │   │   │   ├── include/
    │   │   │   │   └── MMKVAppExtension/
    │   │   │   │       └── MMKV.h
    │   │   │   └── libMMKV.mm
    │   │   ├── MMKVHandler.h
    │   │   ├── Resources/
    │   │   │   ├── Info.plist
    │   │   │   └── PrivacyInfo.xcprivacy
    │   │   ├── fakeinclude/
    │   │   │   └── MMKV/
    │   │   │       └── MMKV.h
    │   │   └── libMMKV.mm
    │   └── MMKV.xcodeproj/
    │       ├── project.pbxproj
    │       ├── project.xcworkspace/
    │       │   ├── contents.xcworkspacedata
    │       │   └── xcshareddata/
    │       │       └── IDEWorkspaceChecks.plist
    │       └── xcshareddata/
    │           └── xcschemes/
    │               ├── MMKV For App Extension.xcscheme
    │               ├── MMKV Static.xcscheme
    │               ├── MMKV.xcscheme
    │               └── MMKVWatchExtension.xcscheme
    └── MMKVDemo/
        ├── Config.xcconfig
        ├── MMKVCatalystDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── Assets.xcassets/
        │   │   ├── AccentColor.colorset/
        │   │   │   └── Contents.json
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   ├── LaunchScreen.storyboard
        │   │   └── Main.storyboard
        │   ├── Info.plist
        │   ├── MMKVCatalystDemo.entitlements
        │   ├── SceneDelegate.h
        │   ├── SceneDelegate.m
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── DemoSwiftUsage.swift
        │   ├── MMKVDemo-Bridging-Header.h
        │   ├── Resources/
        │   │   ├── Assets.xcassets/
        │   │   │   └── AppIcon.appiconset/
        │   │   │       └── Contents.json
        │   │   ├── Base.lproj/
        │   │   │   ├── LaunchScreen.storyboard
        │   │   │   └── Main.storyboard
        │   │   ├── Info.plist
        │   │   ├── MMKVDemo.entitlements
        │   │   ├── testReadOnly
        │   │   └── testReadOnly.crc
        │   ├── TestMMKVCpp.cpp
        │   ├── TestMMKVCpp.hpp
        │   ├── ViewController+TestCaseBad.h
        │   ├── ViewController+TestCaseBad.mm
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVDemo.xcodeproj/
        │   ├── project.pbxproj
        │   ├── project.xcworkspace/
        │   │   ├── contents.xcworkspacedata
        │   │   └── xcshareddata/
        │   │       ├── IDEWorkspaceChecks.plist
        │   │       └── WorkspaceSettings.xcsettings
        │   └── xcshareddata/
        │       └── xcschemes/
        │           ├── MMKVDemo.xcscheme
        │           ├── MMKVMacDemo.xcscheme
        │           ├── MMKVTodayExtensionDemo.xcscheme
        │           ├── WatchApp (Notification).xcscheme
        │           ├── WatchApp.xcscheme
        │           └── kvdemo.xcscheme
        ├── MMKVDemoTests/
        │   ├── Info.plist
        │   ├── MMKVDemoTests.mm
        │   └── MMKVPerformanceTest.mm
        ├── MMKVMacDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   └── Main.storyboard
        │   ├── Info.plist
        │   ├── MMKVMacDemo.entitlements
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVTodayExtensionDemo/
        │   ├── Base.lproj/
        │   │   └── MainInterface.storyboard
        │   ├── Info.plist
        │   ├── MMKVTodayExtensionDemo.entitlements
        │   ├── TodayViewController.h
        │   └── TodayViewController.m
        ├── MMKVVisionDemo/
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.solidimagestack/
        │   │   │   ├── Back.solidimagestacklayer/
        │   │   │   │   ├── Content.imageset/
        │   │   │   │   │   └── Contents.json
        │   │   │   │   └── Contents.json
        │   │   │   ├── Contents.json
        │   │   │   ├── Front.solidimagestacklayer/
        │   │   │   │   ├── Content.imageset/
        │   │   │   │   │   └── Contents.json
        │   │   │   │   └── Contents.json
        │   │   │   └── Middle.solidimagestacklayer/
        │   │   │       ├── Content.imageset/
        │   │   │       │   └── Contents.json
        │   │   │       └── Contents.json
        │   │   └── Contents.json
        │   ├── ContentView.swift
        │   ├── Info.plist
        │   ├── MMKVVisionDemoApp.swift
        │   └── Preview Content/
        │       └── Preview Assets.xcassets/
        │           └── Contents.json
        ├── WatchApp/
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   └── Interface.storyboard
        │   └── Info.plist
        ├── WatchApp Extension/
        │   ├── Assets.xcassets/
        │   │   ├── Complication.complicationset/
        │   │   │   ├── Circular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Contents.json
        │   │   │   ├── Extra Large.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Bezel.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Circular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Corner.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Extra Large.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Large Rectangular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Modular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   └── Utilitarian.imageset/
        │   │   │       └── Contents.json
        │   │   └── Contents.json
        │   ├── ExtensionDelegate.h
        │   ├── ExtensionDelegate.mm
        │   ├── Info.plist
        │   ├── InterfaceController.h
        │   ├── InterfaceController.m
        │   ├── NotificationController.h
        │   ├── NotificationController.m
        │   └── PushNotificationPayload.apns
        └── kvdemo/
            ├── AppDelegate.h
            ├── AppDelegate.m
            ├── Assets.xcassets/
            │   ├── AccentColor.colorset/
            │   │   └── Contents.json
            │   ├── AppIcon.appiconset/
            │   │   └── Contents.json
            │   └── Contents.json
            ├── Base.lproj/
            │   ├── LaunchScreen.storyboard
            │   └── Main.storyboard
            ├── Info.plist
            ├── SceneDelegate.h
            ├── SceneDelegate.m
            ├── ViewController.h
            ├── ViewController.m
            ├── kvdemo.entitlements
            └── main.m

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
AlwaysBreakTemplateDeclarations: true
AllowShortFunctionsOnASingleLine: InlineOnly
#AllowShortLambdasOnASingleLine: Inline
BreakAfterJavaFieldAnnotations: true
#BreakBeforeBraces: Linux
SpaceAfterCStyleCast: true
IndentCaseLabels: true
AccessModifierOffset: -4
BreakBeforeBraces: Custom
BraceWrapping:
    AfterNamespace: false
    AfterClass: false
    AfterFunction: false

BreakConstructorInitializersBeforeComma: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
BinPackParameters: false
ReflowComments: false
ObjCBlockIndentWidth: 4
---
Language: Cpp
ColumnLimit: 120
IndentPPDirectives: AfterHash
---
Language: ObjC
ColumnLimit: 0
#UseTab: ForIndentation
---
Language: Java
ColumnLimit: 120
AllowShortFunctionsOnASingleLine: None
BreakBeforeBinaryOperators: NonAssignment


================================================
FILE: .dockerignore
================================================
# 排除特定文件
output/


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [lingol]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
---

## Note:
An crash issue will be **ignored & closed** in a week **without logs**.

### The language of MMKV

> e.g. Objective-C, Swift, Java, or Kotlin



### The version of MMKV

> e.g. v1.2.2  
> Note: For versions older than the latest version, please upgrade before posting any issue.  
> We don't have much time for old version tech support.



### The platform of MMKV

> e.g. iOS or Android



### The installation of MMKV

> e.g. Cocoapods, Maven, or Git clone



### What's the issue?

> Post the outputs or screenshots for errors.
> 
> Explain what you want by example or code **in English**.
> If you have a crash/OOM/ANR on Android, please provide **symbolize stack traces**. https://developer.android.com/ndk/guides/ndk-stack.html

### What's the log of MMKV when that happened?
> Your **detail logs**. As much as possible.
> For how to forward MMKV's log, you can checkout the wiki on each platform.
> An crash issue will be **ignored & closed** in a week **without logs**.


================================================
FILE: .gitignore
================================================
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata

## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint

#python
venv

## OS X
.DS_Store

## Xcode
DerivedData

## Visual Studio
.vs
[Dd]ebug/
[Rr]elease/
*.user
*.VC.opendb
*.VC.db
ipch/

#cmake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Linux/Makefile
cmake-build-debug/
cmake-build-release/
build/
build_*/
dist/
*.egg-info/
.cmake

#CLion
.idea

#Android Studio
.cxx

pubspec.lock
Podfile.lock

#docker
output/

#swiftpm
.swiftpm


================================================
FILE: .gitmodules
================================================
[submodule "Python/pybind11"]
	path = Python/pybind11
	url = https://github.com/pybind/pybind11.git


================================================
FILE: Android/MMKV/.gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
.DS_Store
/build
/captures
.externalNativeBuild
.idea/caches/build_file_checksums.ser
.idea/


================================================
FILE: Android/MMKV/build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '2.2.20'

    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:8.13.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

ext {
    minSdkVersion = 23
    compileSdk = 35
    targetSdkVersion = compileSdk
    supportLibVersion = "25.4.0"
    javaVersion = JavaVersion.VERSION_11

    defaultsToPrivateOnly = true

    GROUP = 'com.tencent'
    VERSION_NAME = "${VERSION_NAME_PREFIX}${VERSION_NAME_SUFFIX}"

    POM_PACKAGING = "pom"
    POM_DESCRIPTION = "MMKV for Android"

    POM_URL = "https://github.com/Tencent/MMKV"
    POM_SCM_URL = "https://github.com/Tencent/MMKV"
    POM_SCM_CONNECTION="scm:git:github.com/Tencent/MMKV.git"
    POM_SCM_DEV_CONNECTION="scm:git:ssh://git@github.com/Tencent/MMKV.git"

    POM_ISSUE_URL = 'https://github.com/Tencent/MMKV/issues'

    POM_LICENCE_NAME = "BSD License"
    POM_LICENCE_URL = "https://opensource.org/licenses/BSD-3-Clause"

    POM_DEVELOPER_ID = "Tencent Wechat"
    POM_DEVELOPER_NAME = "Tencent Wechat, Inc."
}


================================================
FILE: Android/MMKV/checkstyle.xml
================================================
<?xml version="1.0"?>
<!--
  Copyright (C) 2016 THL A29 Limited, a Tencent company.
  Copyright (C) 2014 Square, Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  -->
<!DOCTYPE module PUBLIC
    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">

<module name="Checker">
  <!--module name="NewlineAtEndOfFile"/-->
  <module name="FileLength"/>
  <module name="FileTabCharacter"/>
  <module name="SuppressWarningsFilter"/>

  <!-- Trailing spaces -->
  <module name="RegexpSingleline">
    <property name="format" value="\s+$"/>
    <property name="message" value="Line has trailing spaces."/>
  </module>

  <!-- Space after 'for' and 'if' -->
  <module name="RegexpSingleline">
    <property name="format" value="^\s*(for|if)[^ ]\("/>
    <property name="message" value="Space needed before opening parenthesis."/>
  </module>

  <!-- For each spacing -->
  <module name="RegexpSingleline">
    <property name="format" value="^\s*for \(.*?([^ ]:|:[^ ])"/>
    <property name="message" value="Space needed around ':' character."/>
  </module>

  <module name="TreeWalker">
    <!-- Checks for Javadoc comments.                     -->
    <!-- See http://checkstyle.sf.net/config_javadoc.html -->
    <!--module name="JavadocMethod"/-->
    <!--module name="JavadocType"/-->
    <!--module name="JavadocVariable"/-->
    <!--module name="JavadocStyle"/-->


    <!-- Checks for Naming Conventions.                  -->
    <!-- See http://checkstyle.sf.net/config_naming.html -->
    <!--<module name="ConstantName"/>-->
    <module name="LocalFinalVariableName"/>
    <module name="LocalVariableName"/>
    <module name="MemberName"/>
    <module name="MethodName">
      <property name="format" value="^[a-z][a-zA-Z0-9_]*$"/>
    </module>
    <module name="PackageName"/>
    <module name="ParameterName"/>
    <module name="StaticVariableName"/>
    <module name="TypeName">
      <property name="format" value="^[A-Z][a-zA-Z0-9_]*$"/>
    </module>


    <!-- Checks for imports                              -->
    <!-- See http://checkstyle.sf.net/config_import.html -->
    <module name="AvoidStarImport"/>
    <module name="IllegalImport"/>
    <module name="RedundantImport"/>
    <module name="UnusedImports"/>


    <!-- Checks for Size Violations.                    -->
    <!-- See http://checkstyle.sf.net/config_sizes.html -->
    <!--module name="LineLength"-->
      <!--property name="max" value="100"/-->
    <!--/module-->
    <!--module name="MethodLength"/-->
    <!--<module name="ParameterNumber"/>-->

    <!-- Checks for whitespace                               -->
    <!-- See http://checkstyle.sf.net/config_whitespace.html -->
    <module name="GenericWhitespace"/>
    <module name="EmptyForIteratorPad"/>
    <module name="MethodParamPad"/>


    <module name="NoWhitespaceAfter"/>
    <module name="NoWhitespaceBefore"/>
    <module name="OperatorWrap"/>
    <module name="ParenPad"/>
    <module name="TypecastParenPad"/>
    <module name="WhitespaceAfter"/>
    <module name="WhitespaceAround"/>


    <!-- Modifier Checks                                    -->
    <!-- See http://checkstyle.sf.net/config_modifiers.html -->
    <!--module name="ModifierOrder"/-->
    <module name="RedundantModifier"/>


    <!-- Checks for blocks. You know, those {}'s         -->
    <!-- See http://checkstyle.sf.net/config_blocks.html -->
    <!--module name="AvoidNestedBlocks"/-->
    <!--module name="EmptyBlock"/-->
    <module name="LeftCurly"/>
    <!--allow single line-->
    <module name="NeedBraces">
      <property name="allowSingleLineStatement" value="true"/>
    </module>

    <module name="RightCurly"/>


    <!-- Checks for common coding problems               -->
    <!-- See http://checkstyle.sf.net/config_coding.html -->
    <!--module name="AvoidInlineConditionals"/-->
    <module name="CovariantEquals"/>
    <module name="EmptyStatement"/>
    <!--module name="EqualsAvoidNull"/-->
    <!--<module name="EqualsHashCode"/>-->
    <!--module name="HiddenField"/-->
    <module name="IllegalInstantiation"/>
    <!--<module name="InnerAssignment"/>-->
    <!--module name="MagicNumber"/-->
    <!--<module name="MissingSwitchDefault"/>-->
    <!--<module name="RedundantThrows"/>-->
    <module name="SimplifyBooleanExpression"/>
    <module name="SimplifyBooleanReturn"/>

    <!-- Checks for class design                         -->
    <!-- See http://checkstyle.sf.net/config_design.html -->
    <!--module name="DesignForExtension"/-->
    <!--module name="FinalClass"/-->
    <!--<module name="HideUtilityClassConstructor"/>-->
    <!--module name="InterfaceIsType"/-->
    <!--module name="VisibilityModifier"/-->


    <!-- Miscellaneous other checks.                   -->
    <!-- See http://checkstyle.sf.net/config_misc.html -->
    <module name="ArrayTypeStyle"/>
    <!--module name="FinalParameters"/-->
    <!--<module name="TodoComment"/>-->
    <module name="UpperEll"/>
    <module name="SuppressWarningsHolder"/>
  </module>
</module>

================================================
FILE: Android/MMKV/gradle/android-publish-private.gradle
================================================
// OSS_ANDROID_TEMPLATE_FILE_HEADER
/**
 * New android-publish gradle script (for private use only, without bintray support)
 *
 * 1. Multiple flavors support.
 * 2. Provide PRIVATE_RELEASE_REPOSITORY_URL and PRIVATE_SNAPSHOT_REPOSITORY_URL with gradle.properties or local.properties.
 * 3. Provide PRIVATE_REPOSITORY_USERNAME and PRIVATE_REPOSITORY_PASSWORD if needed.
 */
apply plugin: 'digital.wup.android-maven-publish'
apply plugin: 'signing'

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return hasProperty('PRIVATE_RELEASE_REPOSITORY_URL') ? PRIVATE_RELEASE_REPOSITORY_URL : readPropertyFromLocalProperties('PRIVATE_RELEASE_REPOSITORY_URL')
}

def getSnapshotRepositoryUrl() {
    return hasProperty('PRIVATE_SNAPSHOT_REPOSITORY_URL') ? PRIVATE_SNAPSHOT_REPOSITORY_URL : readPropertyFromLocalProperties('PRIVATE_SNAPSHOT_REPOSITORY_URL')
}

def readPropertyFromLocalProperties(String key) {
    Properties properties = new Properties()
    try {
        properties.load(project.rootProject.file('local.properties').newDataInputStream())
    } catch (Exception e) {
        println("load local properties failed msg:${e.message}")
    }
    return properties.getProperty(key)
}

def getRepositoryUsername() {
    return hasProperty('PRIVATE_REPOSITORY_USERNAME') ? PRIVATE_REPOSITORY_USERNAME : readPropertyFromLocalProperties('PRIVATE_REPOSITORY_USERNAME')
}

def getRepositoryPassword() {
    return hasProperty('PRIVATE_REPOSITORY_PASSWORD') ? PRIVATE_REPOSITORY_PASSWORD : readPropertyFromLocalProperties('PRIVATE_REPOSITORY_PASSWORD')
}

def pomConfig = {
    scm {
        url POM_SCM_URL
    }

    licenses {
        license {
            name POM_LICENCE_NAME
            url POM_LICENCE_URL
            distribution POM_LICENCE_DIST
        }
    }

    developers {
        developer {
            id POM_DEVELOPER_ID
            name POM_DEVELOPER_NAME
        }
    }
}

android.libraryVariants.all { variant ->
    // Skipped debug variants
    if (variant.buildType.name == "debug") {
        return
    }

    def hasFlavors = !variant.flavorName.isEmpty()

    def artifactIdSuffix = hasFlavors ? variant.flavorName.replace('_', '-').capitalize() : ''
    variant.productFlavors.each { flavor ->
        def flavorArtifactIdSuffix = flavor.ext.has('artifactIdSuffix') ? flavor.ext.artifactIdSuffix : flavor.name
        if (!flavorArtifactIdSuffix.isEmpty()) {
            artifactIdSuffix = artifactIdSuffix.replace(flavor.name.capitalize(), "-${flavorArtifactIdSuffix}")
        } else {
            artifactIdSuffix = artifactIdSuffix.replace(flavor.name.capitalize(), "")
        }
    }
    if (!artifactIdSuffix.isEmpty() && !artifactIdSuffix.startsWith('-')) {
        artifactIdSuffix = '-' + artifactIdSuffix
    }

    def curArtifactId = "${POM_ARTIFACT_ID}${artifactIdSuffix}"

    /**
     * Includes
     */
    def sourceDirs = variant.sourceSets.collect {
        it.javaDirectories // TODO: kotlin sources
    }
    def javadoc = task("${variant.name}Javadoc", type: Javadoc) {
        source = variant.javaCompile.source // TODO: deprecated
        options.encoding = 'utf-8'
        destinationDir = file("${buildDir}/docs/javadoc${hasFlavors ? artifactIdSuffix : ""}")
        ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdk}/android.jar"
        classpath += files(ext.androidJar)
        classpath += files(configurations.compile)
        exclude '**/BuildConfig.java'
        exclude '**/R.java'
        failOnError false
    }
    def javadocJar = task("${variant.name}JavadocJar", type: Jar, dependsOn: javadoc) {
        classifier = 'javadoc'
        from javadoc.destinationDir
    }
    def sourcesJar = task("${variant.name}SourcesJar", type: Jar) {
        classifier = 'sources'
        from sourceDirs
    }
    def jniSymbolsJar = task("${variant.name}SymbolJar", type: Jar, dependsOn: 'build') {
        classifier = "so-symbols"
        boolean hasNativeBuildTask = false
        tasks.each { task ->
            if (task.getName().startsWith("externalNativeBuild")) {
                hasNativeBuildTask = true
            }
        }

        if (!hasNativeBuildTask) {
            return
        }

        if (hasFlavors) {
            variant.productFlavors.each { flavor ->
                from file("build/intermediates/cmake/${flavor.name}/release/obj/")
            }
        } else {
            from file("build/intermediates/cmake/release/obj/")
        }

    }

    // require gradle 4.x +
    if (GradleVersion.current() < GradleVersion.version('4.0')) {
        throw new GradleException('android-publish.gradle need Gradle 4.0 or newer')
    }

    def publicationName = "component${variant.name.capitalize()}"

    // Declare publications
    publishing.publications {
        "$publicationName"(MavenPublication) {
            artifactId curArtifactId
            groupId groupId
            version version

            from components.findByName("android${variant.name.capitalize()}")

            artifact javadocJar
            artifact jniSymbolsJar
        }
    }
}

/**
 * Setup custom maven repo
 */
publishing.repositories {
    maven {
        url "${isReleaseBuild() ? getReleaseRepositoryUrl() : getSnapshotRepositoryUrl()}"
        credentials {
            username "${getRepositoryUsername()}"
            password "${getRepositoryPassword()}"
        }
    }
}

if (JavaVersion.current().isJava8Compatible()) {
    allprojects {
        tasks.withType(Javadoc) {
            options.addStringOption('Xdoclint:none', '-quiet')
        }
    }
}

task buildAndPublishToLocalMaven(type: Copy, dependsOn: ['build', 'publishToMavenLocal']) {
    group = 'publishing'

    // save artifacts files to artifacts folder
    from configurations.archives.allArtifacts.files
    into "${rootProject.buildDir}/outputs/artifacts/"
    rename { String fileName ->
        fileName.replace("release.aar", "${version}.aar")
    }

    doLast {
        println "* published to maven local: ${project.group}:${project.name}:${project.version}"
    }
}

task buildAndPublishRepo(type: Copy, dependsOn: ['build', 'publish']) {
    group = "publishing"

    // save artifacts files to artifacts folder
    from configurations.archives.allArtifacts.files
    into "${rootProject.buildDir}/outputs/artifacts/"
    rename { String fileName ->
        fileName.replace("release.aar", "${version}.aar")
    }

    doLast {
        println "* published to repo: ${project.group}:${project.name}:${project.version}"
    }
}

apply from: rootProject.file('gradle/check.gradle')

================================================
FILE: Android/MMKV/gradle/android-publish.gradle
================================================
import java.util.regex.Matcher
import java.util.regex.Pattern

// OSS_ANDROID_TEMPLATE_FILE_HEADER
/**
 * New android-publish gradle script
 *
 * 1. Multiple flavors support.
 * 2. Provide RELEASE_REPOSITORY_URL and SNAPSHOT_REPOSITORY_URL with gradle.properties or local.properties.
 * 3. Provide REPOSITORY_USERNAME and REPOSITORY_PASSWORD if needed.
 */
apply plugin: 'maven-publish'
apply plugin: 'signing'

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL : readPropertyFromLocalProperties('RELEASE_REPOSITORY_URL')
}

def getSnapshotRepositoryUrl() {
    return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL : readPropertyFromLocalProperties('SNAPSHOT_REPOSITORY_URL')
}

def readPropertyFromLocalProperties(String key) {
    Properties properties = new Properties()
    try {
        properties.load(project.rootProject.file('local.properties').newDataInputStream())
    } catch (Exception e) {
        println("load local properties failed msg:${e.message}")
    }
    return properties.getProperty(key)
}

def getRepositoryUsername() {
    return hasProperty('REPOSITORY_USERNAME') ? REPOSITORY_USERNAME : readPropertyFromLocalProperties('REPOSITORY_USERNAME')
}

def getRepositoryPassword() {
    return hasProperty('REPOSITORY_PASSWORD') ? REPOSITORY_PASSWORD : readPropertyFromLocalProperties('REPOSITORY_PASSWORD')
}

def curArtifactId

android.libraryVariants.all { variant ->
    // Skipped debug variants
    if (variant.buildType.name == "debug") {
        return
    }
    // Skipped non publishing variants
//    println('android.defaultPublishConfig=' + android.defaultPublishConfig)
//    println('variant.flavorName=' + variant.flavorName)
//    if (!android.defaultPublishConfig.startsWith(variant.flavorName)) {
//        return
//    }

    def hasFlavors = !variant.flavorName.isEmpty()

    def artifactIdSuffix = hasFlavors ? variant.flavorName.replace('_', '-').capitalize() : ''
    variant.productFlavors.each { flavor ->
        def flavorArtifactIdSuffix = flavor.ext.has('artifactIdSuffix') ? flavor.ext.artifactIdSuffix : flavor.name
        if (!flavorArtifactIdSuffix.isEmpty()) {
            artifactIdSuffix = artifactIdSuffix.replace(flavor.name.capitalize(), "-${flavorArtifactIdSuffix}")
        } else {
            artifactIdSuffix = artifactIdSuffix.replace(flavor.name.capitalize(), "")
        }
    }
    if (!artifactIdSuffix.isEmpty() && !artifactIdSuffix.startsWith('-')) {
        artifactIdSuffix = '-' + artifactIdSuffix
    }

    curArtifactId = "${POM_ARTIFACT_ID}${artifactIdSuffix}"

    def jniJar = task("${variant.name}JniJar", type: Jar, dependsOn: 'build') {
    }
    def javadoc = task("${variant.name}Javadoc", type: Javadoc) {
        source = variant.javaCompileProvider.get().source
        options.encoding = 'utf-8'
        destinationDir = file("${buildDir}/docs/javadoc${hasFlavors ? artifactIdSuffix : ""}")
        ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdk}/android.jar"
        classpath += files(ext.androidJar)
        classpath += files(variant.javaCompileProvider.get().classpath)
        classpath += files(configurations.javadocDeps)
        exclude '**/BuildConfig.java'
        exclude '**/R.java'
        failOnError = false
    }
    def javadocJar = task("${variant.name}JavadocJar", type: Jar, dependsOn: javadoc) {
        archiveClassifier = 'javadoc'
        from javadoc.destinationDir
    }
    def jniSymbolsJar = task("${variant.name}SymbolJar", type: Jar, dependsOn: 'build') {
        archiveClassifier = "so-symbols"
        boolean hasNativeBuildTask = false
        tasks.each { task ->
            if (task.getName().startsWith("externalNativeBuild")) {
                hasNativeBuildTask = true
            }
        }

        if (!hasNativeBuildTask) {
            return
        }

        if (hasFlavors) {
            variant.productFlavors.each { flavor ->
                from file("build/intermediates/cmake/${flavor.name}Release/obj/")
            }
        } else {
            from file("build/intermediates/cmake/release/obj/")
        }
    }
    // Custom task to package headers into a ZIP file
    def headerZip = task("${variant.name}Header", type: Zip, dependsOn: 'build') {
        archiveClassifier = "header"
        from('../../../Core/include') {
            exclude '*/MemoryFile.h'
            exclude '*/MMKVLog.h'
        }
        archiveFileName = 'headers.zip'
        destinationDirectory = file("$buildDir/outputs/headers")
    }

    def publicationName = "component${variant.name.capitalize()}"

    // Declare publications
    publishing.publications {
        "$publicationName"(MavenPublication) {
            groupId groupId
            artifactId curArtifactId
            version version

            from components.findByName("android${variant.name.capitalize()}")

            if (hasFlavors) {
                variant.productFlavors.each { flavor ->
                    artifact("build/outputs/aar/${project.getName()}-${flavor.name}-release.aar")
                }
            } else {
                artifact("build/outputs/aar/${project.getName()}-release.aar")
            }
            artifact javadocJar
            artifact jniSymbolsJar
            artifact headerZip

            pom {
                name = 'MMKV'
                description = POM_DESCRIPTION
                url = POM_URL
                licenses {
                    license {
                        name = POM_LICENCE_NAME
                        url = POM_LICENCE_URL
                    }
                }

                developers {
                    developer {
                        id = POM_DEVELOPER_ID
                        name = POM_DEVELOPER_NAME
                    }
                }

                scm {
                    url = POM_SCM_URL
                    connection = POM_SCM_CONNECTION
                    developerConnection = POM_SCM_DEV_CONNECTION
                }

                // write the dependency of the library into pom
                withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')
                    project.configurations.all { configuration ->
                        def name = configuration.name
                        if (name != "implementation" && name != "compile" && name != "api") {
                            return
                        }
                        configuration.dependencies.each {
                            if (it.name == "unspecified") {
                                return
                            }
                            def dependencyNode = dependenciesNode.appendNode('dependency')
                            dependencyNode.appendNode('groupId', it.group)
                            dependencyNode.appendNode('artifactId', it.name)
                            dependencyNode.appendNode('version', it.version)
                            if (name == "api" || name == "compile") {
                                dependencyNode.appendNode("scope", "compile")
                            } else {
                                dependencyNode.appendNode("scope", "runtime")
                            }
                        }
                    }
                }
            }
        }
    }
}

signing {
    sign publishing.publications
}

publishing.repositories {
    maven {
        url "${isReleaseBuild() ? getReleaseRepositoryUrl() : getSnapshotRepositoryUrl()}"
        credentials {
            username "${getRepositoryUsername()}"
            password "${getRepositoryPassword()}"
        }
    }
}

if (JavaVersion.current().isJava8Compatible()) {
    allprojects {
        tasks.withType(Javadoc) {
            options.addStringOption('Xdoclint:none', '-quiet')
        }
    }
}

task buildAndPublishToLocalMaven(type: Copy, dependsOn: ['build', 'publishToMavenLocal']) {
    group = 'publishing'

    // save artifacts files to artifacts folder
    from "$buildDir/outputs/aar"
    include '*.aar'
    into "${rootProject.buildDir}/outputs/artifacts"

    rename { String fileName ->
        fileName.replace("release.aar", "${version}.aar")
    }

    doLast {
        println "* published to maven local: ${project.group}:${project.name}:${project.version}"
    }
}

task buildAndPublishRepo(type: Copy, dependsOn: ['build', 'publish']) {
    group = "publishing"

    // save artifacts files to artifacts folder
    from configurations.archives.allArtifacts.files
    into "${rootProject.buildDir}/outputs/artifacts/"
    rename { String fileName ->
        fileName.replace("release.aar", "${version}.aar")
    }

    doLast {
        println "* published to repo: ${project.group}:${project.name}:${project.version}"
    }
}

//tasks.register('closeCentralRepository', Exec) {
//    // This task will only run if the 'centralUsername' property exists
////    onlyIf { project.hasProperty('centralUsername') && project.hasProperty('centralToken') }
//
//    // Define your namespace here
//    def namespace = "com.tencent" // <-- IMPORTANT: Replace with your actual namespace
//
//    group = "publishing"
//    description = "Closes the repository on the Central Publisher Portal."
//
//    commandLine "curl", "-X", "POST",
//            "-u", "${getRepositoryUsername()}:${getRepositoryPassword()}",
//            "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/${namespace}"
//}
//
//// Find your specific publish task and make it trigger the new task
//// Replace 'publish' with the actual name of your main publishing task if it's different.
//tasks.named('publish') {
//    finalizedBy 'closeCentralRepository'
//}

apply from: rootProject.file('gradle/check.gradle')

================================================
FILE: Android/MMKV/gradle/build_library.gradle
================================================
// OSS_ANDROID_TEMPLATE_FILE_HEADER
/**
 * Optional android libraries gradle file
 *
 * Simply apply from: rootProject.file('gradle/build_library.gradle') if needed
 *
 */
apply plugin: 'com.android.library'

android {
    compileSdk rootProject.ext.compileSdk

    defaultConfig {
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
    }

    signingConfigs {
        configDebug {
            keyAlias 'key0'
            keyPassword 'mmkv.wxg'
            storeFile rootProject.file('debug.keystore')
            storePassword 'mmkv.wxg'
        }

        configRelease {
            keyAlias 'key0'
            keyPassword 'mmkv.wxg'
            storeFile rootProject.file('debug.keystore')
            storePassword 'mmkv.wxg'
        }
    }

    buildTypes {
        debug {
            debuggable true
            signingConfig signingConfigs.configDebug
            minifyEnabled false
        }
        release {
            signingConfig signingConfigs.configRelease
            minifyEnabled true
            proguardFile getDefaultProguardFile('proguard-android.txt')
            proguardFile project.file('proguard-rules-android-lib.pro') // NOTE: default rules for android library if this file exists
        }
    }
}

// Publication
version = rootProject.ext.VERSION_NAME
group = rootProject.ext.GROUP

//def check_private_only = project.hasProperty('PRIVATE_ONLY') ? PRIVATE_ONLY.toBoolean() : rootProject.ext.defaultsToPrivateOnly // Dangerous, turn on for default
//
//if (check_private_only) {
//    // Publish to private only repositories
//    apply from: rootProject.file('gradle/android-publish-private.gradle')
//
//} else {
//    // Publish to public repositories
//    apply from: rootProject.file('gradle/android-publish.gradle')
//}


================================================
FILE: Android/MMKV/gradle/check.gradle
================================================
// OSS_ANDROID_TEMPLATE_FILE_HEADER

apply plugin: 'checkstyle'


checkstyle {
    configFile rootProject.file('checkstyle.xml')
    toolVersion '6.19'
    ignoreFailures false
    showViolations true
}

task('checkstyle', type: Checkstyle) {
    source 'src/main/java'
    include '**/*.java'
    classpath = files()
}

check.dependsOn('checkstyle')


//apply plugin: 'pmd'
//
//pmd {
//    toolVersion '5.4.0'
//}
//
//task pmd(type: Pmd) {
//    targetJdk = TargetJdk.VERSION_1_7
//
//    description 'Run pmd'
//    group 'verification'
//
//    // If ruleSets is not empty, it seems to contain some
//    // defaults which override rules in the ruleset file...
//    ruleSets = []
//    ruleSetFiles = rootProject.files('pmd-ruleset.xml')
//    source = fileTree('src/main/java')
//    ignoreFailures = false
//
//    reports {
//        xml.enabled = false
//        html.enabled = true
//    }
//}
//
//check.dependsOn('pmd')

//apply plugin: 'findbugs'
//
//def classTree = 'build/intermediates/classes/debug'
//
//if (project.plugins.hasPlugin('java')) {
//    classTree = 'build/classes'
//}
//task findbugs(type: FindBugs) {
//
//    description 'Run findbugs'
//    group 'verification'
//
//    classes = fileTree(classTree)
//    source = fileTree('src/main/java/')
//    classpath = files()
//
//    effort = 'default'
//
//    excludeFilter = rootProject.file("findbugs-exclude.xml")
//
//    reports {
//        xml.enabled = false
//        html.enabled = true
//    }
//    ignoreFailures = true
//}

//check.dependsOn('findbugs')

================================================
FILE: Android/MMKV/gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Oct 16 21:16:39 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip


================================================
FILE: Android/MMKV/gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

VERSION_NAME_PREFIX=2.4.0
#VERSION_NAME_SUFFIX=-SNAPSHOT
VERSION_NAME_SUFFIX=

RELEASE_REPOSITORY_URL=https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2
SNAPSHOT_REPOSITORY_URL=https://ossrh-staging-api.central.sonatype.com/content/repositories/snapshots
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false


================================================
FILE: Android/MMKV/gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"


================================================
FILE: Android/MMKV/gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: Android/MMKV/mmkv/.gitignore
================================================
/build


================================================
FILE: Android/MMKV/mmkv/CMakeLists.txt
================================================
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

project(mmkv)

# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.0)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_subdirectory(../../../Core Core)

add_library( mmkv

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-bridge.cpp
             src/main/cpp/flutter-bridge.cpp
        )

set_target_properties(mmkv PROPERTIES
        CXX_STANDARD 20
        CXX_EXTENSIONS OFF
        POSITION_INDEPENDENT_CODE ON
        )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( mmkv

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib}
                       core
#                       aes
)


================================================
FILE: Android/MMKV/mmkv/build.gradle
================================================
plugins {
    id 'com.android.library'
    id 'maven-publish'
    id 'signing'
//    id 'org.jetbrains.dokka' version '1.4.32' // For Kotlin projects
}
apply from: rootProject.file('gradle/build_library.gradle')

android {
    namespace "com.tencent.mmkv"
    compileSdk rootProject.ext.compileSdk
    publishing {
        multipleVariants("DefaultCppRelease") {
            includeBuildTypeValues('release')
            includeFlavorDimensionAndValues('stl_mode', 'DefaultCpp')
            withJavadocJar()
        }
        multipleVariants("StaticCppRelease") {
            includeBuildTypeValues('release')
            includeFlavorDimensionAndValues('stl_mode', 'StaticCpp')
            withJavadocJar()
        }
        multipleVariants("SharedCppRelease") {
            includeBuildTypeValues('release')
            includeFlavorDimensionAndValues('stl_mode', 'SharedCpp')
            withJavadocJar()
        }
    }

    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                abiFilters 'arm64-v8a', 'x86_64'
            }
        }
        ndkVersion "28.1.13356709"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
    }
    buildTypes {
        release {
            minifyEnabled false
            externalNativeBuild {
                cmake {
                    cppFlags "-fvisibility=hidden", "-funwind-tables", "-fasynchronous-unwind-tables", "-O2"
                }
            }
            consumerProguardFiles 'proguard-rules.pro'
//            debuggable true
//            jniDebuggable true
        }
        debug {
            jniDebuggable true
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
            version "3.18.0+"
        }
    }
    packagingOptions {
        jniLibs {
            useLegacyPackaging true
        }
    }
    flavorDimensions = ["stl_mode"]
    productFlavors {
        DefaultCpp {
            dimension "stl_mode"
            ext.artifactIdSuffix = ''
            externalNativeBuild {
                cmake {
                    arguments = ["-DANDROID_STL=c++_static"]
                    cppFlags "-DMMKV_STL_SHARED=0"
                }
            }
        }
        StaticCpp {
            dimension "stl_mode"
            ext.artifactIdSuffix = 'static'
            externalNativeBuild {
                cmake {
                    arguments = ["-DANDROID_STL=c++_static"]
                    cppFlags "-DMMKV_STL_SHARED=0"
                }
            }
            // not working
//            packagingOptions {
//                exclude "prefab/modules/**"
//            }
        }
        SharedCpp {
            dimension "stl_mode"
            ext.artifactIdSuffix = 'shared'
            externalNativeBuild {
                cmake {
                    arguments = ["-DANDROID_STL=c++_shared"]
                    cppFlags "-DMMKV_STL_SHARED=1"
                }
            }
        }
    }
    buildFeatures {
        prefab true
        prefabPublishing true
        aidl true
    }
    prefab {
        mmkv {
            headers "../../../Core/include"
        }
    }
}

afterEvaluate {
    android.libraryVariants.configureEach { variant ->
        if (variant.buildType.name == "release") {
            def abiFilters = ['arm64-v8a', 'x86_64']

            def strippedLibsDir = "$buildDir/intermediates/stripped_native_libs/${variant.name}/strip${variant.name}DebugSymbols/out/lib"
            // Create per-variant copy task
            tasks.register("syncStrippedLibsToPrefab${variant.name.capitalize()}", Copy) {
                from(strippedLibsDir) {
                    include "**/libmmkv.so"
                }
                into "$buildDir/intermediates/prefab_package/${variant.name.capitalize()}/prefab/modules/mmkv/libs"
                eachFile {
//                    println('hhh before:' + path)
                    for (abi in abiFilters) {
                        if (path.contains("${abi}/")) {
                            path = path.replace("${abi}/", "android.${abi}/")
                            break
                        }
                    }
//                    println('hhh after:' + path)
                }

                // Hook into build process
                dependsOn("strip${variant.name.capitalize()}DebugSymbols")
            }

            // Hook into build process
            tasks.named("externalNativeBuild${variant.name.capitalize()}") {
                finalizedBy("syncStrippedLibsToPrefab${variant.name.capitalize()}")
            }
            tasks.named("bundle${variant.name.capitalize()}Aar") {
                dependsOn("syncStrippedLibsToPrefab${variant.name.capitalize()}")
            }
            tasks.named("bundle${variant.name.capitalize()}LocalLintAar") {
                dependsOn("syncStrippedLibsToPrefab${variant.name.capitalize()}")
            }

            // Generate combined artifact suffix from all flavor dimensions
            def flavorSuffixes = variant.productFlavors.collect { it.ext.artifactIdSuffix }
            def artifactIdSuffix = flavorSuffixes.join("-")
            def fullArtifactId = "${POM_ARTIFACT_ID}${artifactIdSuffix ? "-$artifactIdSuffix" : ""}"

            // 1. Find the task that merges native libs (unstripped).
            //    Name pattern is typically: mergeReleaseNativeLibs or mergeFlavorReleaseNativeLibs
            def mergeTaskName = "merge${variant.name.capitalize()}NativeLibs"
            def mergeTask = tasks.findByName(mergeTaskName)

            if (!mergeTask) {
                println "Warning: Could not find Native Merge task: $mergeTaskName"
                return // Skip creating the symbols jar if we can't find the source
            }

            // Create debug symbols task
            def symbolsTask = tasks.register("bundleSymbols${variant.name.capitalize()}", Jar) {
                // 2. FIX: Don't use a hardcoded path string.
                //    Use the output files of the merge task directly.
                from(mergeTask.outputs.files)

                // 3. Ensure we only grab the .so files (the merge task might output a tree structure like /lib/arm64/...)
                include '**/*.so'

                archiveClassifier.set("so-symbols")
                destinationDirectory.set(file("$buildDir/intermediates/so-symbols/${variant.name}"))
                dependsOn mergeTask
            }

            // Create publication per variant
            publishing.publications.create(variant.name, MavenPublication) {
                from components.findByName(variant.name)

                groupId = group
                artifactId = fullArtifactId
                version = version

                // Add debug symbols
                artifact symbolsTask

                // Configure POM
                pom {
                    name = 'MMKV'
                    description = POM_DESCRIPTION
                    url = POM_URL
                    licenses {
                        license {
                            name = POM_LICENCE_NAME
                            url = POM_LICENCE_URL
                        }
                    }

                    developers {
                        developer {
                            id = POM_DEVELOPER_ID
                            name = POM_DEVELOPER_NAME
                        }
                    }

                    scm {
                        url = POM_SCM_URL
                        connection = POM_SCM_CONNECTION
                        developerConnection = POM_SCM_DEV_CONNECTION
                    }
                }
            }
        }
    }

    // Configure repositories and signing
    publishing.repositories {
        maven {
            name = "MavenCentral"
            url = RELEASE_REPOSITORY_URL
            credentials {
                username = REPOSITORY_USERNAME
                password = REPOSITORY_PASSWORD
            }
        }
    }

    signing {
        // Ensure signing only targets publications that were successfully created
        sign publishing.publications.matching {
            it.name in android.libraryVariants.collect { v -> v.name }
        }
    }
}

configurations {
    javadocDeps
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.annotation:annotation:1.9.1'
    javadocDeps 'androidx.annotation:annotation:1.9.1'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test:runner:1.7.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'

    compileOnly project(':mmkvannotation')
}


================================================
FILE: Android/MMKV/mmkv/gradle.properties
================================================
POM_ARTIFACT_ID=mmkv
PRIVATE_ONLY=false


================================================
FILE: Android/MMKV/mmkv/proguard-rules.pro
================================================
# Keep all native methods, their classes and any classes in their descriptors
-keepclasseswithmembers,includedescriptorclasses class com.tencent.mmkv.** {
    native <methods>;
    long nativeHandle;
    private static *** onMMKVCRCCheckFail(***);
    private static *** onMMKVFileLengthError(***);
    private static *** mmkvLogImp(...);
    private static *** onContentChangedByOuterProcess(***);
    private static *** onMMKVContentLoadSuccessfully(***);
}


================================================
FILE: Android/MMKV/mmkv/src/androidTest/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <service
            android:name=".MMKVTestService"
            android:enabled="true"
            android:exported="false"
            android:process=":mmkvtest_svr">
        </service>
    </application>
</manifest>


================================================
FILE: Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTest.java
================================================
/*
 * Tencent is pleased to support the open source community by making
 * MMKV available.
 *
 * Copyright (C) 2018 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *       https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tencent.mmkv;

import static org.junit.Assert.*;

import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import androidx.test.InstrumentationRegistry;
import java.util.HashSet;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class MMKVTest {

    static MMKV mmkv;
    static final String KeyNotExist = "Key_Not_Exist";
    static final float Delta = 0.000001f;

    @BeforeClass
    public static void setUp() throws Exception {
        Context appContext = InstrumentationRegistry.getTargetContext();
        MMKV.initialize(appContext);

        mmkv = MMKV.mmkvWithID("unitTest", MMKV.SINGLE_PROCESS_MODE, "UnitTestCryptKey");
    }

    @AfterClass
    public static void tearDown() throws Exception {
        mmkv.clearAll();
    }

    @Test
    public void testBool() {
        boolean ret = mmkv.encode("bool", true);
        assertEquals(ret, true);

        boolean value = mmkv.decodeBool("bool");
        assertEquals(value, true);

        value = mmkv.decodeBool(KeyNotExist);
        assertEquals(value, false);

        value = mmkv.decodeBool(KeyNotExist, true);
        assertEquals(value, true);
    }

    @Test
    public void testInt() {
        boolean ret = mmkv.encode("int", Integer.MAX_VALUE);
        assertEquals(ret, true);

        int value = mmkv.decodeInt("int");
        assertEquals(value, Integer.MAX_VALUE);

        value = mmkv.decodeInt(KeyNotExist);
        assertEquals(value, 0);

        value = mmkv.decodeInt(KeyNotExist, -1);
        assertEquals(value, -1);
    }

    @Test
    public void testLong() {
        boolean ret = mmkv.encode("long", Long.MAX_VALUE);
        assertEquals(ret, true);

        long value = mmkv.decodeLong("long");
        assertEquals(value, Long.MAX_VALUE);

        value = mmkv.decodeLong(KeyNotExist);
        assertEquals(value, 0);

        value = mmkv.decodeLong(KeyNotExist, -1);
        assertEquals(value, -1);
    }

    @Test
    public void testFloat() {
        boolean ret = mmkv.encode("float", Float.MAX_VALUE);
        assertEquals(ret, true);

        float value = mmkv.decodeFloat("float");
        assertEquals(value, Float.MAX_VALUE, Delta);

        value = mmkv.decodeFloat(KeyNotExist);
        assertEquals(value, 0, Delta);

        value = mmkv.decodeFloat(KeyNotExist, -1);
        assertEquals(value, -1, Delta);
    }

    @Test
    public void testDouble() {
        boolean ret = mmkv.encode("double", Double.MAX_VALUE);
        assertEquals(ret, true);

        double value = mmkv.decodeDouble("double");
        assertEquals(value, Double.MAX_VALUE, Delta);

        value = mmkv.decodeDouble(KeyNotExist);
        assertEquals(value, 0, Delta);

        value = mmkv.decodeDouble(KeyNotExist, -1);
        assertEquals(value, -1, Delta);
    }

    @Test
    public void testString() {
        String str = "Hello 2018 world cup 世界杯";
        boolean ret = mmkv.encode("string", str);
        assertEquals(ret, true);

        String value = mmkv.decodeString("string");
        assertEquals(value, str);

        value = mmkv.decodeString(KeyNotExist);
        assertEquals(value, null);

        value = mmkv.decodeString(KeyNotExist, "Empty");
        assertEquals(value, "Empty");
    }

    @Test
    public void testStringSet() {
        HashSet<String> set = new HashSet<String>();
        set.add("W");
        set.add("e");
        set.add("C");
        set.add("h");
        set.add("a");
        set.add("t");
        boolean ret = mmkv.encode("string_set", set);
        assertEquals(ret, true);

        HashSet<String> value = (HashSet<String>) mmkv.decodeStringSet("string_set");
        assertEquals(value, set);

        value = (HashSet<String>) mmkv.decodeStringSet(KeyNotExist);
        assertEquals(value, null);

        set = new HashSet<String>();
        set.add("W");
        value = (HashSet<String>) mmkv.decodeStringSet(KeyNotExist, set);
        assertEquals(value, set);
    }

    @Test
    public void testBytes() {
        byte[] bytes = {'m', 'm', 'k', 'v'};
        boolean ret = mmkv.encode("bytes", bytes);
        assertEquals(ret, true);

        byte[] value = mmkv.decodeBytes("bytes");
        assertArrayEquals(value, bytes);
    }

    @Test
    public void testRemove() {
        boolean ret = mmkv.encode("bool_1", true);
        ret &= mmkv.encode("int_1", Integer.MIN_VALUE);
        ret &= mmkv.encode("long_1", Long.MIN_VALUE);
        ret &= mmkv.encode("float_1", Float.MIN_VALUE);
        ret &= mmkv.encode("double_1", Double.MIN_VALUE);
        ret &= mmkv.encode("string_1", "hello");

        HashSet<String> set = new HashSet<String>();
        set.add("W");
        set.add("e");
        set.add("C");
        set.add("h");
        set.add("a");
        set.add("t");
        ret &= mmkv.encode("string_set_1", set);

        byte[] bytes = {'m', 'm', 'k', 'v'};
        ret &= mmkv.encode("bytes_1", bytes);
        assertEquals(ret, true);

        {
            long count = mmkv.count();

            mmkv.removeValueForKey("bool_1");
            mmkv.removeValuesForKeys(new String[] {"int_1", "long_1"});

            long newCount = mmkv.count();
            assertEquals(count, newCount + 3);
        }

        boolean bValue = mmkv.decodeBool("bool_1");
        assertEquals(bValue, false);

        int iValue = mmkv.decodeInt("int_1");
        assertEquals(iValue, 0);

        long lValue = mmkv.decodeLong("long_1");
        assertEquals(lValue, 0);

        float fValue = mmkv.decodeFloat("float_1");
        assertEquals(fValue, Float.MIN_VALUE, Delta);

        double dValue = mmkv.decodeDouble("double_1");
        assertEquals(dValue, Double.MIN_VALUE, Delta);

        String sValue = mmkv.decodeString("string_1");
        assertEquals(sValue, "hello");

        HashSet<String> hashSet = (HashSet<String>) mmkv.decodeStringSet("string_set_1");
        assertEquals(hashSet, set);

        byte[] byteValue = mmkv.decodeBytes("bytes_1");
        assertArrayEquals(bytes, byteValue);
    }

    @Test
    public void testIPCUpdateInt() {
        MMKV mmkv = MMKV.mmkvWithID(MMKVTestService.SharedMMKVID, MMKV.MULTI_PROCESS_MODE);
        mmkv.encode(MMKVTestService.SharedMMKVKey, 1024);

        Context appContext = InstrumentationRegistry.getTargetContext();
        Intent intent = new Intent(appContext, MMKVTestService.class);
        intent.putExtra(MMKVTestService.CMD_Key, MMKVTestService.CMD_Update);
        appContext.startService(intent);

        SystemClock.sleep(1000 * 3);
        int value = mmkv.decodeInt(MMKVTestService.SharedMMKVKey);
        assertEquals(value, 1024 + 1);
    }

    @Test
    public void testIPCLock() {
        Context appContext = InstrumentationRegistry.getTargetContext();

        Intent intent = new Intent(appContext, MMKVTestService.class);
        intent.putExtra(MMKVTestService.CMD_Key, MMKVTestService.CMD_Lock);
        appContext.startService(intent);

        SystemClock.sleep(1000 * 3);
        MMKV mmkv = MMKV.mmkvWithID(MMKVTestService.SharedMMKVID, MMKV.MULTI_PROCESS_MODE);
        boolean ret = mmkv.tryLock();
        assertEquals(ret, false);

        intent.putExtra(MMKVTestService.CMD_Key, MMKVTestService.CMD_Kill);
        appContext.startService(intent);

        SystemClock.sleep(1000 * 3);
        ret = mmkv.tryLock();
        assertEquals(ret, true);
    }
}


================================================
FILE: Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTestService.java
================================================
/*
 * Tencent is pleased to support the open source community by making
 * MMKV available.
 *
 * Copyright (C) 2018 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *       https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tencent.mmkv;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import androidx.annotation.Nullable;

public class MMKVTestService extends Service {
    public static final String SharedMMKVID = "SharedMMKVID";
    public static final String SharedMMKVKey = "SharedMMKVKey";

    public static final String CMD_Key = "CMD_Key";
    public static final String CMD_Update = "CMD_Update";
    public static final String CMD_Lock = "CMD_Lock";
    public static final String CMD_Kill = "CMD_Kill";

    @Override
    public void onCreate() {
        super.onCreate();

        MMKV.initialize(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MMKV mmkv = MMKV.mmkvWithID(SharedMMKVID, MMKV.MULTI_PROCESS_MODE);

        String cmd = intent.getStringExtra(CMD_Key);
        switch (cmd) {
            case CMD_Update:
                int value = mmkv.decodeInt(SharedMMKVKey);
                value += 1;
                mmkv.encode(SharedMMKVKey, value);
                break;
            case CMD_Lock:
                mmkv.lock();
                break;
            case CMD_Kill:
                stopSelf();
                break;
        }

        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Process.killProcess(Process.myPid());
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}


================================================
FILE: Android/MMKV/mmkv/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

================================================
FILE: Android/MMKV/mmkv/src/main/aidl/com/tencent/mmkv/ParcelableMMKV.aidl
================================================
// MMKV.aidl
package com.tencent.mmkv;

parcelable ParcelableMMKV;


================================================
FILE: Android/MMKV/mmkv/src/main/cpp/flutter-bridge.cpp
================================================
/*
 * Tencent is pleased to support the open source community by making
 * MMKV available.
 *
 * Copyright (C) 2020 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *       https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <MMKV/MMKVPredef.h>

#ifndef MMKV_DISABLE_FLUTTER

#    include <MMKV/MMKV.h>
#    include <MMKV/MMKVLog.h>
#    include <cstdint>
#    include <string>

using namespace mmkv;
using namespace std;

namespace mmkv {
extern int g_android_api;
extern string g_android_tmpDir;
}

#    ifdef MMKV_EXPORT
#       undef MMKV_EXPORT
#    endif
#    define MMKV_EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used))

using LogCallback_t = void (*)(uint32_t level, const char *file, int32_t line, const char *funcname, const char *message);
using ErrorCallback_t = int (*)(const char *mmapID, int32_t errorType);
using ContenctChangeCallback_t = void (*)(const char *mmapID);

class FlutterMMKVHandler : public mmkv::MMKVHandler {
public:
    LogCallback_t logCallback = nullptr;
    ErrorCallback_t errorCallback = nullptr;
    ContenctChangeCallback_t contentChangeCallback = nullptr;
    ContenctChangeCallback_t contentLoadedCallback = nullptr;

    void mmkvLog(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message) override {
        if (logCallback) {
            logCallback(level, file, line, function, message.c_str());
        }
    }

    MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) override {
        if (errorCallback) {
            return (MMKVRecoverStrategic) errorCallback(mmapID.c_str(), MMKVCRCCheckFail);
        }
        return OnErrorDiscard;
    }

    MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) override {
        if (errorCallback) {
            return (MMKVRecoverStrategic) errorCallback(mmapID.c_str(), MMKVFileLength);
        }
        return OnErrorDiscard;
    }

    void onContentChangedByOuterProcess(const std::string &mmapID) override {
        if (contentChangeCallback) {
            contentChangeCallback(mmapID.c_str());
        }
    }

    void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
        if (contentLoadedCallback) {
            contentLoadedCallback(mmapID.c_str());
        }
    }
};

static FlutterMMKVHandler g_flutterHandler;

MMKV_EXPORT void *mmkvInitialize_v2(const char *rootDir, const char *cacheDir, int32_t sdkInt, int32_t logLevel, LogCallback_t callback) {
    if (!rootDir) {
        return nullptr;
    }
    if (cacheDir) {
        g_android_tmpDir = string(cacheDir);
    }

    g_android_api = sdkInt;
#ifdef MMKV_STL_SHARED
    MMKVInfo("current API level = %d, libc++_shared=%d", g_android_api, MMKV_STL_SHARED);
#else
    MMKVInfo("current API level = %d, libc++_shared=?", g_android_api);
#endif

    if (callback) {
        g_flutterHandler.logCallback = callback;
        MMKV::initializeMMKV(rootDir, (MMKVLogLevel) logLevel, &g_flutterHandler);
    } else {
        MMKV::initializeMMKV(rootDir, (MMKVLogLevel) logLevel);
    }
    return (void *) MMKV::getRootDir().c_str();
}

MMKV_EXPORT void mmkvInitialize_v1(const char *rootDir, const char *cacheDir, int32_t sdkInt, int32_t logLevel) {
    mmkvInitialize_v2(rootDir, cacheDir, sdkInt, logLevel, nullptr);
}

MMKV_EXPORT void mmkvInitialize(const char *rootDir, int32_t logLevel) {
    mmkvInitialize_v2(rootDir, nullptr, 0, logLevel, nullptr);
}

MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath,
                                size_t expectedCapacity, bool fromNameSpace, bool aes256, int32_t enableKeyExpire,
                                int32_t expiredInSeconds, bool enableCompareBeforeSet, int32_t recover,
                                uint32_t itemSizeLimit) {
    MMKV *kv = nullptr;
    if (!mmapID) {
        return kv;
    }
    string str = mmapID;

    auto config = MMKVConfig();
    config.mode = (MMKVMode) mode;
    config.aes256 = aes256;
    config.expectedCapacity = expectedCapacity;
    if (enableKeyExpire >= 0) {
        config.enableKeyExpire = (enableKeyExpire != 0);
    }
    config.expiredInSeconds = expiredInSeconds;
    config.enableCompareBeforeSet = enableCompareBeforeSet;
    if (recover >= 0) {
        config.recover = static_cast<MMKVRecoverStrategic>(recover);
    }
    config.itemSizeLimit = itemSizeLimit;

    bool done = false;
    if (cryptKey) {
        string crypt = cryptKey;
        if (!crypt.empty()) {
            config.cryptKey = &crypt;
            if (rootPath) {
                string path = rootPath;
                if (fromNameSpace) {
                    auto ns = MMKV::nameSpace(path);
                    config.rootPath = &ns.getRootDir();
                    kv = ns.mmkvWithID(str, config);
                } else {
                    config.rootPath = &path;
                    kv = MMKV::mmkvWithID(str, config);
                }
            } else {
                kv = MMKV::mmkvWithID(str, config);
            }
            done = true;
        }
    }
    if (!done) {
        if (rootPath) {
            string path = rootPath;
            if (fromNameSpace) {
                auto ns = MMKV::nameSpace(path);
                config.rootPath = &ns.getRootDir();
                kv = ns.mmkvWithID(str, config);
            } else {
                config.rootPath = &path;
                kv = MMKV::mmkvWithID(str, config);
            }
        } else {
            kv = MMKV::mmkvWithID(str, config);
        }
    }

    return kv;
}

MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey, bool aes256, size_t expectedCapacity,
                                 int32_t enableKeyExpire, int32_t expiredInSeconds, bool enableCompareBeforeSet,
                                 int32_t recover, uint32_t itemSizeLimit) {
    MMKV *kv = nullptr;

    auto config = MMKVConfig();
    config.mode = (MMKVMode) mode;
    config.aes256 = aes256;
    config.expectedCapacity = expectedCapacity;
    if (enableKeyExpire >= 0) {
        config.enableKeyExpire = (enableKeyExpire != 0);
    }
    config.expiredInSeconds = expiredInSeconds;
    config.enableCompareBeforeSet = enableCompareBeforeSet;
    if (recover >= 0) {
        config.recover = static_cast<MMKVRecoverStrategic>(recover);
    }
    config.itemSizeLimit = itemSizeLimit;

    if (cryptKey) {
        string crypt = cryptKey;
        if (crypt.length() > 0) {
            config.cryptKey = &crypt;
            kv = MMKV::defaultMMKV(config);
        }
    }
    if (!kv) {
        kv = MMKV::defaultMMKV(config);
    }

    return kv;
}

MMKV_EXPORT const char *mmapID(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->mmapID().c_str();
    }
    return nullptr;
}

MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((bool) value, key);
    }
    return false;
}

MMKV_EXPORT bool encodeBool_v2(void *handle, const char *oKey, bool value, uint32_t expiration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((bool) value, key, expiration);
    }
    return false;
}

MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool defaultValue) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->getBool(key, defaultValue);
    }
    return defaultValue;
}

MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t value) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((int32_t) value, key);
    }
    return false;
}

MMKV_EXPORT bool encodeInt32_v2(void *handle, const char *oKey, int32_t value, uint32_t expiration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((int32_t) value, key, expiration);
    }
    return false;
}

MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->getInt32(key, defaultValue);
    }
    return defaultValue;
}

MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t value) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((int64_t) value, key);
    }
    return false;
}

MMKV_EXPORT bool encodeInt64_v2(void *handle, const char *oKey, int64_t value, uint32_t expiration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((int64_t) value, key, expiration);
    }
    return false;
}

MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->getInt64(key, defaultValue);
    }
    return defaultValue;
}

MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double value) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((double) value, key);
    }
    return false;
}

MMKV_EXPORT bool encodeDouble_v2(void *handle, const char *oKey, double value, uint32_t expiration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->set((double) value, key, expiration);
    }
    return false;
}

MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double defaultValue) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        return kv->getDouble(key, defaultValue);
    }
    return defaultValue;
}

MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        if (oValue) {
            auto value = MMBuffer(oValue, static_cast<size_t>(length), MMBufferNoCopy);
            return kv->set(value, key);
        } else {
            kv->removeValueForKey(key);
            return true;
        }
    }
    return false;
}

MMKV_EXPORT bool encodeBytes_v2(void *handle, const char *oKey, void *oValue, uint64_t length, uint32_t expiration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        if (oValue) {
            auto value = MMBuffer(oValue, static_cast<size_t>(length), MMBufferNoCopy);
            return kv->set(value, key, expiration);
        } else {
            kv->removeValueForKey(key);
            return true;
        }
    }
    return false;
}

MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        auto key = string(oKey);
        mmkv::MMBuffer value;
        auto hasValue = kv->getBytes(key, value);
        if (hasValue) {
            if (value.length() > 0) {
                if (value.isStoredOnStack()) {
                    auto result = malloc(value.length());
                    if (result) {
                        memcpy(result, value.getPtr(), value.length());
                        *lengthPtr = value.length();
                    }
                    return result;
                }
                void *result = value.getPtr();
                *lengthPtr = value.length();
                value.detach();
                return result;
            }
            *lengthPtr = 0;
            // this ptr is intended for checking existence of the value
            // don't free this ptr
            return value.getPtr();
        }
    }
    return nullptr;
}

#    ifndef MMKV_DISABLE_CRYPT

MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length, bool aes256) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        if (oKey && length > 0) {
            string key(oKey, length);
            return kv->reKey(key, aes256);
        } else {
            return kv->reKey(string(), aes256);
        }
    }
    return false;
}

MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && lengthPtr) {
        auto cryptKey = kv->cryptKey();
        if (cryptKey.length() > 0) {
            auto ptr = malloc(cryptKey.length());
            if (ptr) {
                memcpy(ptr, cryptKey.data(), cryptKey.length());
                *lengthPtr = cryptKey.length();
                return ptr;
            }
        }
    }
    return nullptr;
}

MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t length, bool aes256) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        if (oKey && length > 0) {
            string key(oKey, length);
            kv->checkReSetCryptKey(&key, aes256);
        } else {
            kv->checkReSetCryptKey(nullptr, aes256);
        }
    }
}

#    endif // MMKV_DISABLE_CRYPT

MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key(oKey);
        auto ret = kv->getValueSize(key, actualSize);
        return static_cast<uint32_t>(ret);
    }
    return 0;
}

MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *pointer, uint32_t size) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key(oKey);
        return kv->writeValueToBuffer(key, pointer, size);
    }
    return -1;
}

MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr, bool filterExpire) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        auto keys = kv->allKeys(filterExpire);
        if (!keys.empty()) {
            auto keyArray = (char **) malloc(keys.size() * sizeof(void *));
            auto sizeArray = (uint32_t *) malloc(keys.size() * sizeof(uint32_t *));
            if (!keyArray || !sizeArray) {
                free(keyArray);
                free(sizeArray);
                return 0;
            }
            *keyArrayPtr = keyArray;
            *sizeArrayPtr = sizeArray;

            for (size_t index = 0; index < keys.size(); index++) {
                auto &key = keys[index];
                sizeArray[index] = static_cast<uint32_t>(key.length());
                keyArray[index] = (char *) malloc(key.length());
                if (keyArray[index]) {
                    memcpy(keyArray[index], key.data(), key.length());
                }
            }
        }
        return keys.size();
    }
    return 0;
}

MMKV_EXPORT bool containsKey(void *handle, char *oKey) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key(oKey);
        return kv->containsKey(key);
    }
    return false;
}

MMKV_EXPORT uint64_t count(void *handle, bool filterExpire) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->count(filterExpire);
    }
    return 0;
}

MMKV_EXPORT uint64_t totalSize(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->totalSize();
    }
    return 0;
}

MMKV_EXPORT uint64_t actualSize(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->actualSize();
    }
    return 0;
}

MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key(oKey);
        kv->removeValueForKey(key);
    }
}

MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint32_t *sizeArray, uint64_t count) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv && keyArray && sizeArray && count > 0) {
        vector<string> arrKeys;
        arrKeys.reserve(count);
        for (uint64_t index = 0; index < count; index++) {
            if (sizeArray[index] > 0 && keyArray[index]) {
                arrKeys.emplace_back(keyArray[index], sizeArray[index]);
            }
        }
        if (!arrKeys.empty()) {
            kv->removeValuesForKeys(arrKeys);
        }
    }
}

MMKV_EXPORT void clearAll(void *handle, bool keepSpace) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->clearAll(keepSpace);
    }
}

MMKV_EXPORT void mmkvSync(void *handle, bool sync) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->sync((SyncFlag) sync);
    }
}

MMKV_EXPORT void clearMemoryCache(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->clearMemoryCache();
    }
}

MMKV_EXPORT int32_t pageSize() {
    return static_cast<int32_t>(DEFAULT_MMAP_SIZE);
}

MMKV_EXPORT const char *version() {
    return MMKV_VERSION;
}

MMKV_EXPORT void trim(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->trim();
    }
}

MMKV_EXPORT void mmkvClose(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->close();
    }
}

MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) {
    memcpy(dst, src, size);
}

MMKV_EXPORT bool backupOne(const char *mmapID, const char *dstDir, const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::backupOneToDirectory(mmapID, dstDir, &root);
        }
    }
    return MMKV::backupOneToDirectory(mmapID, dstDir);
}

MMKV_EXPORT bool restoreOne(const char *mmapID, const char *srcDir, const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::restoreOneFromDirectory(mmapID, srcDir, &root);
        }
    }
    return MMKV::restoreOneFromDirectory(mmapID, srcDir);
}

MMKV_EXPORT uint64_t backupAll(const char *dstDir/*, const char *rootPath*/) {
    // historically Android mistakenly use mmapKey as mmapID
    // makes everything tricky with customize root
    /*if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::backupAllToDirectory(dstDir, &root);
        }
    }*/
    return MMKV::backupAllToDirectory(dstDir);
}

MMKV_EXPORT uint64_t restoreAll(const char *srcDir/*, const char *rootPath*/) {
    // historically Android mistakenly use mmapKey as mmapID
    // makes everything tricky with customize root
    /*if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::restoreAllFromDirectory(srcDir, &root);
        }
    }*/
    return MMKV::restoreAllFromDirectory(srcDir);
}

MMKV_EXPORT bool enableAutoExpire(void *handle, uint32_t expireDuration) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->enableAutoKeyExpire(expireDuration);
    }
    return false;
}

MMKV_EXPORT bool disableAutoExpire(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->disableAutoKeyExpire();
    }
    return false;
}

MMKV_EXPORT bool enableCompareBeforeSet(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->enableCompareBeforeSet();
    }
    return false;
}

MMKV_EXPORT bool disableCompareBeforeSet(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->disableCompareBeforeSet();
    }
    return false;
}

MMKV_EXPORT bool isFileValid(const char *mmapID, const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::isFileValid(mmapID, &root);
        }
    }
    return MMKV::isFileValid(mmapID, nullptr);
}

MMKV_EXPORT bool removeStorage(const char *mmapID, const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::removeStorage(mmapID, &root);
        }
    }
    return MMKV::removeStorage(mmapID, nullptr);
}

MMKV_EXPORT bool isMultiProcess(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->isMultiProcess();
    }
    return false;
}

MMKV_EXPORT bool isReadOnly(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        return kv->isReadOnly();
    }
    return false;
}

MMKV_EXPORT void registerErrorHandler(ErrorCallback_t callback) {
    g_flutterHandler.errorCallback = callback;
    if (callback || g_flutterHandler.logCallback || g_flutterHandler.contentChangeCallback || g_flutterHandler.contentLoadedCallback) {
        MMKV::registerHandler(&g_flutterHandler);
    }
}

MMKV_EXPORT void registerContentChangeNotify(ContenctChangeCallback_t callback) {
    g_flutterHandler.contentChangeCallback = callback;
    if (callback || g_flutterHandler.logCallback || g_flutterHandler.errorCallback || g_flutterHandler.contentLoadedCallback) {
        MMKV::registerHandler(&g_flutterHandler);
    }
}

MMKV_EXPORT void registerContentLoadedNotify(ContenctChangeCallback_t callback) {
    g_flutterHandler.contentLoadedCallback = callback;
    if (callback || g_flutterHandler.logCallback || g_flutterHandler.errorCallback || g_flutterHandler.contentChangeCallback) {
        MMKV::registerHandler(&g_flutterHandler);
    }
}

MMKV_EXPORT void checkContentChanged(void *handle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    if (kv) {
        kv->checkContentChanged();
    }
}

MMKV_EXPORT bool getNameSpace(const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (!root.empty()) {
            MMKV::nameSpace(root);
            return true;
        }
    }
    return false;
}

MMKV_EXPORT bool checkExist(const char *mmapID, const char *rootPath) {
    if (rootPath) {
        auto root = string(rootPath);
        if (root.length() > 0) {
            return MMKV::checkExist(mmapID, &root);
        }
    }
    return MMKV::checkExist(mmapID, nullptr);
}

MMKV_EXPORT size_t importFrom(void *handle, void *srcHandle) {
    MMKV *kv = static_cast<MMKV *>(handle);
    MMKV *kvSrc = static_cast<MMKV *>(srcHandle);
    if (kv && kvSrc) {
        return kv->importFrom(kvSrc);
    }
    return 0;
}

#endif // MMKV_DISABLE_FLUTTER


================================================
FILE: Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp
================================================
/*
 * Tencent is pleased to support the open source community by making
 * MMKV available.
 *
 * Copyright (C) 2018 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *       https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <MMKV/MMKVPredef.h>

#ifdef MMKV_ANDROID

#    include <MMKV/MMBuffer.h>
#    include <MMKV/MMKV.h>
#    include <MMKV/MMKVLog.h>
#    include <MMKV/MemoryFile.h>
#    include <cstdint>
#    include <jni.h>
#    include <string>
#    include <android/api-level.h>

using namespace std;
using namespace mmkv;

static jclass g_cls = nullptr;
static jfieldID g_fileID = nullptr;
static jmethodID g_callbackOnCRCFailID = nullptr;
static jmethodID g_callbackOnFileLengthErrorID = nullptr;
static jmethodID g_mmkvLogID = nullptr;
static jmethodID g_callbackOnContentChange = nullptr;
static jmethodID g_callbackOnContentLoaded = nullptr;
static JavaVM *g_currentJVM = nullptr;

static int registerNativeMethods(JNIEnv *env, jclass cls);
extern "C" void internalLogWithLevel(MMKVLogLevel level, const char *filename, const char *func, int line, const char *format, ...);
extern MMKVLogLevel g_currentLogLevel;

namespace mmkv {
    static void mmkvLog(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message);

    typedef void (*AndroidLogHandler)(MMKVLogLevel level, const char *file, int line, const char *function, const char *message);
    static AndroidLogHandler g_androidLogHandler = nullptr;
    static void androidLogWrapper(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message);

    static JNIEnv *getCurrentEnv();
    static jstring string2jstring(JNIEnv *env, const string &str);

// C++ adapter class that bridges mmkv::MMKVHandler to JNI
class JNIMMKVHandler : public mmkv::MMKVHandler {
    bool m_logRedirecting = false;
    bool m_hasCallback = false;
    bool m_wantsContentChange = false;
public:
    void setLogRedirecting(bool logRedirecting) { m_logRedirecting = logRedirecting; }
    void setHasCallback(bool hasCallback) { m_hasCallback = hasCallback; }
    void setWantsContentChange(bool wantsContentChange) { m_wantsContentChange = wantsContentChange; }
    bool isLogRedirecting() const { return m_logRedirecting; }

    void mmkvLog(MMKVLogLevel level, const char *file, int line, const char *function, MMKVLog_t message) override {
        if (m_logRedirecting) {
            if (g_androidLogHandler) {
                g_androidLogHandler(level, file, line, function, message.c_str());
            } else {
                mmkv::mmkvLog(level, file, line, function, message);
            }
        }
    }

    MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) override {
        if (!m_hasCallback) {
            return OnErrorDiscard;
        }
        auto currentEnv = getCurrentEnv();
        if (currentEnv && g_callbackOnCRCFailID) {
            jstring str = string2jstring(currentEnv, mmapID);
            auto strategic = currentEnv->CallStaticIntMethod(g_cls, g_callbackOnCRCFailID, str);
            currentEnv->DeleteLocalRef(str);
            return static_cast<MMKVRecoverStrategic>(strategic);
        }
        return OnErrorDiscard;
    }

    MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) override {
        if (!m_hasCallback) {
            return OnErrorDiscard;
        }
        auto currentEnv = getCurrentEnv();
        if (currentEnv && g_callbackOnFileLengthErrorID) {
            jstring str = string2jstring(currentEnv, mmapID);
            auto strategic = currentEnv->CallStaticIntMethod(g_cls, g_callbackOnFileLengthErrorID, str);
            currentEnv->DeleteLocalRef(str);
            return static_cast<MMKVRecoverStrategic>(strategic);
        }
        return OnErrorDiscard;
    }

    void onContentChangedByOuterProcess(const std::string &mmapID) override {
        auto currentEnv = getCurrentEnv();
        if (currentEnv && g_callbackOnContentChange) {
            jstring str = string2jstring(currentEnv, mmapID);
            currentEnv->CallStaticVoidMethod(g_cls, g_callbackOnContentChange, str);
            currentEnv->DeleteLocalRef(str);
        }
    }

    void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
        auto currentEnv = getCurrentEnv();
        if (currentEnv && g_callbackOnContentLoaded) {
            jstring str = string2jstring(currentEnv, mmapID);
            currentEnv->CallStaticVoidMethod(g_cls, g_callbackOnContentLoaded, str);
            currentEnv->DeleteLocalRef(str);
        }
    }
};

static JNIMMKVHandler g_jniHandler;
}

#define InternalLogError(format, ...) \
    internalLogWithLevel(MMKV_NAMESPACE_PREFIX::MMKVLogError, __MMKV_FILE_NAME__, __func__, __LINE__, format, ##__VA_ARGS__)

#define InternalLogInfo(format, ...) \
    internalLogWithLevel(MMKV_NAMESPACE_PREFIX::MMKVLogInfo, __MMKV_FILE_NAME__, __func__, __LINE__, format, ##__VA_ARGS__)

extern "C" JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    g_currentJVM = vm;
    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    if (g_cls) {
        env->DeleteGlobalRef(g_cls);
    }
    static const char *clsName = "com/tencent/mmkv/MMKV";
    jclass instance = env->FindClass(clsName);
    if (!instance) {
        MMKVError("fail to locate class: %s", clsName);
        return -2;
    }
    g_cls = reinterpret_cast<jclass>(env->NewGlobalRef(instance));
    if (!g_cls) {
        MMKVError("fail to create global reference for %s", clsName);
        return -3;
    }
    g_mmkvLogID =
        env->GetStaticMethodID(g_cls, "mmkvLogImp", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V");
    if (!g_mmkvLogID) {
        MMKVError("fail to get method id for mmkvLogImp");
    }
    // every code from now on can use InternalLogXXX()

    int ret = registerNativeMethods(env, g_cls);
    if (ret != 0) {
        InternalLogError("fail to register native methods for class %s, ret = %d", clsName, ret);
        return -4;
    }
    g_fileID = env->GetFieldID(g_cls, "nativeHandle", "J");
    if (!g_fileID) {
        InternalLogError("fail to locate fileID");
        return -5;
    }

    g_callbackOnCRCFailID = env->GetStaticMethodID(g_cls, "onMMKVCRCCheckFail", "(Ljava/lang/String;)I");
    if (!g_callbackOnCRCFailID) {
        InternalLogError("fail to get method id for onMMKVCRCCheckFail");
    }
    g_callbackOnFileLengthErrorID = env->GetStaticMethodID(g_cls, "onMMKVFileLengthError", "(Ljava/lang/String;)I");
    if (!g_callbackOnFileLengthErrorID) {
        InternalLogError("fail to get method id for onMMKVFileLengthError");
    }
    g_callbackOnContentChange =
        env->GetStaticMethodID(g_cls, "onContentChangedByOuterProcess", "(Ljava/lang/String;)V");
    if (!g_callbackOnContentChange) {
        InternalLogError("fail to get method id for onContentChangedByOuterProcess()");
    }
    g_callbackOnContentLoaded =
        env->GetStaticMethodID(g_cls, "onMMKVContentLoadSuccessfully", "(Ljava/lang/String;)V");
    if (!g_callbackOnContentLoaded) {
        InternalLogError("fail to get method id for onMMKVContentLoadSuccessfully()");
    }

    // Note: If you use NDK r23 or older, you can get API level by accessing android.os.Build.VERSION.SDK_INT
    g_android_api = android_get_device_api_level();
#ifdef MMKV_STL_SHARED
    InternalLogInfo("current API level = %d, libc++_shared=%d", g_android_api, MMKV_STL_SHARED);
#else
    InternalLogInfo("current API level = %d, libc++_shared=?", g_android_api);
#endif

    return JNI_VERSION_1_6;
}

//#define MMKV_JNI extern "C" JNIEXPORT JNICALL
#    define MMKV_JNI static

namespace mmkv {

static string jstring2string(JNIEnv *env, jstring str);

MMKV_JNI void jniInitialize(JNIEnv *env, jobject obj, jstring rootDir, jstring cacheDir, jint logLevel, jboolean logReDirecting, jboolean hasCallback, jlong nativeLogHandler) {
    if (!rootDir) {
        return;
    }
    const char *kstr = env->GetStringUTFChars(rootDir, nullptr);
    if (kstr) {
        g_jniHandler.setLogRedirecting(logReDirecting == JNI_TRUE);
        g_jniHandler.setHasCallback(hasCallback == JNI_TRUE);
        if (logReDirecting && nativeLogHandler != 0) {
            g_androidLogHandler = (AndroidLogHandler) nativeLogHandler;
        } else {
            g_androidLogHandler = nullptr;
        }
        mmkv::MMKVHandler *handler = (logReDirecting || hasCallback) ? &g_jniHandler : nullptr;
        MMKV::initializeMMKV(kstr, (MMKVLogLevel) logLevel, handler);
        env->ReleaseStringUTFChars(rootDir, kstr);

        g_android_tmpDir = jstring2string(env, cacheDir);

        if (hasCallback == JNI_TRUE || logReDirecting == JNI_TRUE) {
            MMKV::registerHandler(&g_jniHandler);
        } else {
            MMKV::unRegisterHandler();
        }
    }
}

MMKV_JNI void onExit(JNIEnv *env, jobject obj) {
    MMKV::onExit();
}

static MMKV *getMMKV(JNIEnv *env, jobject obj) {
    jlong handle = env->GetLongField(obj, g_fileID);
    return reinterpret_cast<MMKV *>(handle);
}

static string jstring2string(JNIEnv *env, jstring str) {
    if (str) {
        const char *kstr = env->GetStringUTFChars(str, nullptr);
        if (kstr) {
            string result(kstr);
            env->ReleaseStringUTFChars(str, kstr);
            return result;
        }
    }
    return "";
}

static jstring string2jstring(JNIEnv *env, const string &str) {
    return env->NewStringUTF(str.c_str());
}

static vector<string> jarray2vector(JNIEnv *env, jobjectArray array) {
    vector<string> keys;
    if (array) {
        jsize size = env->GetArrayLength(array);
        keys.reserve(size);
        for (jsize i = 0; i < size; i++) {
            jstring str = (jstring) env->GetObjectArrayElement(array, i);
            if (str) {
                keys.push_back(jstring2string(env, str));
                env->DeleteLocalRef(str);
            }
        }
    }
    return keys;
}

static jobjectArray vector2jarray(JNIEnv *env, const vector<string> &arr) {
    jobjectArray result = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
    if (result) {
        for (size_t index = 0; index < arr.size(); index++) {
            jstring value = string2jstring(env, arr[index]);
            env->SetObjectArrayElement(result, index, value);
            env->DeleteLocalRef(value);
        }
    }
    return result;
}

static JNIEnv *getCurrentEnv() {
    if (g_currentJVM) {
        JNIEnv *currentEnv = nullptr;
        auto ret = g_currentJVM->GetEnv(reinterpret_cast<void **>(&currentEnv), JNI_VERSION_1_6);
        if (ret == JNI_OK) {
            return currentEnv;
        } else {
            MMKVError("fail to get current JNIEnv: %d", ret);
        }
    }
    return nullptr;
}

extern "C" void internalLogWithLevel(MMKVLogLevel level, const char *filename, const char *func, int line, const char *format, ...) {
    if (level >= g_currentLogLevel) {
        std::string message;
        char buffer[16];

        va_list args;
        va_start(args, format);
        auto length = std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);

        if (length < 0) { // something wrong
            message = {};
        } else if (length < sizeof(buffer)) {
            message = std::string(buffer, static_cast<unsigned long>(length));
        } else {
            message.resize(static_cast<unsigned long>(length), '\0');
            va_start(args, format);
            std::vsnprintf(const_cast<char *>(message.data()), static_cast<size_t>(length) + 1, format, args);
            va_end(args);
        }

        if (g_cls && g_mmkvLogID) {
            mmkvLog(level, filename, line, func, message);
        } else {
            _MMKVLogWithLevel(level, filename, func, line, message.c_str());
        }
    }
}

static void mmkvLog(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message) {
    auto currentEnv = getCurrentEnv();
    if (currentEnv && g_mmkvLogID) {
        jstring oFile = string2jstring(currentEnv, string(file));
        jstring oFunction = string2jstring(currentEnv, string(function));
        jstring oMessage = string2jstring(currentEnv, message);
        int readLevel = level;

        currentEnv->CallStaticVoidMethod(g_cls, g_mmkvLogID, readLevel, oFile, line, oFunction, oMessage);

        currentEnv->DeleteLocalRef(oMessage);
        currentEnv->DeleteLocalRef(oFunction);
        currentEnv->DeleteLocalRef(oFile);
    }
}

static void androidLogWrapper(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message) {
    g_androidLogHandler(level, file, line, function, message.c_str());
}

MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jint mode, jstring cryptKey, jstring rootPath,
                             jlong expectedCapacity, jboolean aes256, jint enableKeyExpire, jint expiredInSeconds,
                             jboolean enableCompareBeforeSet, jint recover, jint itemSizeLimit) {
    MMKV *kv = nullptr;
    if (!mmapID) {
        return (jlong) kv;
    }
    string str = jstring2string(env, mmapID);

    auto config = MMKVConfig();
    config.mode = (MMKVMode) mode;
    config.aes256 = aes256;
    config.expectedCapacity = expectedCapacity;
    if (enableKeyExpire >= 0) {
        config.enableKeyExpire = (enableKeyExpire != 0);
    }
    config.expiredInSeconds = expiredInSeconds;
    config.enableCompareBeforeSet = enableCompareBeforeSet;
    if (recover >= 0) {
        config.recover = static_cast<MMKVRecoverStrategic>(recover);
    }
    config.itemSizeLimit = itemSizeLimit;

    bool done = false;
    if (cryptKey) {
        string crypt = jstring2string(env, cryptKey);
        if (crypt.length() > 0) {
            config.cryptKey = &crypt;
            if (rootPath) {
                string path = jstring2string(env, rootPath);
                config.rootPath = &path;
                kv = MMKV::mmkvWithID(str, config);
            } else {
                kv = MMKV::mmkvWithID(str, config);
            }
            done = true;
        }
    }
    if (!done) {
        if (rootPath) {
            string path = jstring2string(env, rootPath);
            config.rootPath = &path;
            kv = MMKV::mmkvWithID(str, config);
        } else {
            kv = MMKV::mmkvWithID(str, config);
        }
    }

    return (jlong) kv;
}

MMKV_JNI jlong getDefaultMMKV(JNIEnv *env, jobject obj, jint mode, jstring cryptKey, jlong expectedCapacity,
                              jboolean aes256, jint enableKeyExpire, jint expiredInSeconds,
                              jboolean enableCompareBeforeSet, jint recover, jint itemSizeLimit) {
    MMKV *kv = nullptr;

    auto config = MMKVConfig();
    config.mode = (MMKVMode) mode;
    config.aes256 = aes256;
    config.expectedCapacity = expectedCapacity;
    if (enableKeyExpire >= 0) {
        config.enableKeyExpire = (enableKeyExpire != 0);
    }
    config.expiredInSeconds = expiredInSeconds;
    config.enableCompareBeforeSet = enableCompareBeforeSet;
    if (recover >= 0) {
        config.recover = static_cast<MMKVRecoverStrategic>(recover);
    }
    config.itemSizeLimit = itemSizeLimit;

    if (cryptKey) {
        string crypt = jstring2string(env, cryptKey);
        if (crypt.length() > 0) {
            config.cryptKey = &crypt;
            kv = MMKV::defaultMMKV(config);
        }
    }
    if (!kv) {
        kv = MMKV::defaultMMKV(config);
    }

    return (jlong) kv;
}

MMKV_JNI jlong getMMKVWithAshmemFD(JNIEnv *env, jobject obj, jstring mmapID, jint fd, jint metaFD, jstring cryptKey,
                                   jboolean aes256) {
    MMKV *kv = nullptr;
    if (!mmapID || fd < 0 || metaFD < 0) {
        return (jlong) kv;
    }
    string id = jstring2string(env, mmapID);

    if (cryptKey) {
        string crypt = jstring2string(env, cryptKey);
        if (crypt.length() > 0) {
            kv = MMKV::mmkvWithAshmemFD(id, fd, metaFD, &crypt, aes256);
        }
    }
    if (!kv) {
        kv = MMKV::mmkvWithAshmemFD(id, fd, metaFD, nullptr, aes256);
    }

    return (jlong) kv;
}

MMKV_JNI jstring mmapID(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return string2jstring(env, kv->mmapID());
    }
    return nullptr;
}

MMKV_JNI jint ashmemFD(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return kv->ashmemFD();
    }
    return -1;
}

MMKV_JNI jint ashmemMetaFD(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return kv->ashmemMetaFD();
    }
    return -1;
}

MMKV_JNI jboolean checkProcessMode(JNIEnv *env, jobject, jlong handle) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv) {
        return kv->checkProcessMode();
    }
    return false;
}

MMKV_JNI jboolean encodeBool(JNIEnv *env, jobject, jlong handle, jstring oKey, jboolean value) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((bool) value, key);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeBool_2(JNIEnv *env, jobject, jlong handle, jstring oKey, jboolean value, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((bool) value, key, (uint32_t) expiration);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean decodeBool(JNIEnv *env, jobject, jlong handle, jstring oKey, jboolean defaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->getBool(key, defaultValue);
    }
    return defaultValue;
}

MMKV_JNI jboolean encodeInt(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jint value) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((int32_t) value, key);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeInt_2(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jint value, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((int32_t) value, key, (uint32_t) expiration);
    }
    return (jboolean) false;
}

MMKV_JNI jint decodeInt(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jint defaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jint) kv->getInt32(key, defaultValue);
    }
    return defaultValue;
}

MMKV_JNI jboolean encodeLong(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jlong value) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((int64_t) value, key);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeLong_2(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jlong value, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((int64_t) value, key, (uint32_t) expiration);
    }
    return (jboolean) false;
}

MMKV_JNI jlong decodeLong(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jlong defaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jlong) kv->getInt64(key, defaultValue);
    }
    return defaultValue;
}

MMKV_JNI jboolean encodeFloat(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jfloat value) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((float) value, key);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeFloat_2(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jfloat value, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((float) value, key, (uint32_t) expiration);
    }
    return (jboolean) false;
}

MMKV_JNI jfloat decodeFloat(JNIEnv *env, jobject, jlong handle, jstring oKey, jfloat defaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jfloat) kv->getFloat(key, defaultValue);
    }
    return defaultValue;
}

MMKV_JNI jboolean encodeDouble(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jdouble value) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((double) value, key);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeDouble_2(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jdouble value, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->set((double) value, key, (uint32_t) expiration);
    }
    return (jboolean) false;
}

MMKV_JNI jdouble decodeDouble(JNIEnv *env, jobject, jlong handle, jstring oKey, jdouble defaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jdouble) kv->getDouble(key, defaultValue);
    }
    return defaultValue;
}

MMKV_JNI jboolean encodeString(JNIEnv *env, jobject, jlong handle, jstring oKey, jstring oValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (oValue) {
            string value = jstring2string(env, oValue);
            return (jboolean) kv->set(value, key);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeString_2(JNIEnv *env, jobject, jlong handle, jstring oKey, jstring oValue, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (oValue) {
            string value = jstring2string(env, oValue);
            return (jboolean) kv->set(value, key, (uint32_t) expiration);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jstring decodeString(JNIEnv *env, jobject obj, jlong handle, jstring oKey, jstring oDefaultValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        string value;
        bool hasValue = kv->getString(key, value);
        if (hasValue) {
            return string2jstring(env, value);
        }
    }
    return oDefaultValue;
}

MMKV_JNI jboolean encodeBytes(JNIEnv *env, jobject, jlong handle, jstring oKey, jbyteArray oValue) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (oValue) {
            MMBuffer value(0);
            {
                jsize len = env->GetArrayLength(oValue);
                void *bufferPtr = env->GetPrimitiveArrayCritical(oValue, nullptr);
                if (bufferPtr) {
                    value = MMBuffer(bufferPtr, len);
                    env->ReleasePrimitiveArrayCritical(oValue, bufferPtr, JNI_ABORT);
                } else {
                    MMKVError("fail to get array: %s=%p", key.c_str(), oValue);
                }
            }
            return (jboolean) kv->set(value, key);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeBytes_2(JNIEnv *env, jobject, jlong handle, jstring oKey, jbyteArray oValue, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (oValue) {
            MMBuffer value(0);
            {
                jsize len = env->GetArrayLength(oValue);
                void *bufferPtr = env->GetPrimitiveArrayCritical(oValue, nullptr);
                if (bufferPtr) {
                    value = MMBuffer(bufferPtr, len);
                    env->ReleasePrimitiveArrayCritical(oValue, bufferPtr, JNI_ABORT);
                } else {
                    MMKVError("fail to get array: %s=%p", key.c_str(), oValue);
                }
            }
            return (jboolean) kv->set(value, key, (uint32_t) expiration);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jbyteArray decodeBytes(JNIEnv *env, jobject obj, jlong handle, jstring oKey) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        mmkv::MMBuffer value;
        auto hasValue = kv->getBytes(key, value);
        if (hasValue) {
            jbyteArray result = env->NewByteArray(value.length());
            env->SetByteArrayRegion(result, 0, value.length(), (const jbyte *) value.getPtr());
            return result;
        }
    }
    return nullptr;
}

MMKV_JNI jobjectArray allKeys(JNIEnv *env, jobject instance, jlong handle, jboolean filterExpire) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv) {
        vector<string> keys = kv->allKeys((bool) filterExpire);
        return vector2jarray(env, keys);
    }
    return nullptr;
}

MMKV_JNI jboolean containsKey(JNIEnv *env, jobject instance, jlong handle, jstring oKey) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return (jboolean) kv->containsKey(key);
    }
    return (jboolean) false;
}

MMKV_JNI jlong count(JNIEnv *env, jobject instance, jlong handle, jboolean filterExpire) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv) {
        jlong size = kv->count((bool) filterExpire);
        return size;
    }
    return 0;
}

MMKV_JNI jlong totalSize(JNIEnv *env, jobject instance, jlong handle) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv) {
        jlong size = kv->totalSize();
        return size;
    }
    return 0;
}

MMKV_JNI jlong actualSize(JNIEnv *env, jobject instance, jlong handle) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv) {
        jlong size = kv->actualSize();
        return size;
    }
    return 0;
}

MMKV_JNI void removeValueForKey(JNIEnv *env, jobject instance, jlong handle, jstring oKey) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        kv->removeValueForKey(key);
    }
}

MMKV_JNI void removeValuesForKeys(JNIEnv *env, jobject instance, jobjectArray arrKeys) {
    MMKV *kv = getMMKV(env, instance);
    if (kv && arrKeys) {
        vector<string> keys = jarray2vector(env, arrKeys);
        if (!keys.empty()) {
            kv->removeValuesForKeys(keys);
        }
    }
}

MMKV_JNI void clearAll(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->clearAll();
    }
}

MMKV_JNI void sync(JNIEnv *env, jobject instance, jboolean sync) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->sync((SyncFlag) sync);
    }
}

MMKV_JNI jboolean isFileValid(JNIEnv *env, jclass type, jstring oMmapID, jstring rootPath) {
    if (oMmapID) {
        string mmapID = jstring2string(env, oMmapID);
        if (!rootPath) {
            return (jboolean) MMKV::isFileValid(mmapID, nullptr);
        } else {
            auto root = jstring2string(env, rootPath);
            return (jboolean) MMKV::isFileValid(mmapID, &root);
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean removeStorage(JNIEnv *env, jclass type, jstring oMmapID, jstring rootPath) {
    if (oMmapID) {
        string mmapID = jstring2string(env, oMmapID);
        if (!rootPath) {
            return (jboolean) MMKV::removeStorage(mmapID, nullptr);
        } else {
            auto root = jstring2string(env, rootPath);
            return (jboolean) MMKV::removeStorage(mmapID, &root);
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeSet(JNIEnv *env, jobject, jlong handle, jstring oKey, jobjectArray arrStr) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (arrStr) {
            vector<string> value = jarray2vector(env, arrStr);
            return (jboolean) kv->set(value, key);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean encodeSet_2(JNIEnv *env, jobject, jlong handle, jstring oKey, jobjectArray arrStr, jint expiration) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        if (arrStr) {
            vector<string> value = jarray2vector(env, arrStr);
            return (jboolean) kv->set(value, key, (uint32_t) expiration);
        } else {
            kv->removeValueForKey(key);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jobjectArray decodeStringSet(JNIEnv *env, jobject, jlong handle, jstring oKey) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        vector<string> value;
        bool hasValue = kv->getVector(key, value);
        if (hasValue) {
            return vector2jarray(env, value);
        }
    }
    return nullptr;
}

MMKV_JNI void clearMemoryCache(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->clearMemoryCache();
    }
}

MMKV_JNI void lock(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->lock();
    }
}

MMKV_JNI void unlock(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->unlock();
    }
}

MMKV_JNI jboolean tryLock(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return (jboolean) kv->try_lock();
    }
    return jboolean(false);
}

MMKV_JNI jint pageSize(JNIEnv *env, jclass type) {
    return DEFAULT_MMAP_SIZE;
}

MMKV_JNI jstring version(JNIEnv *env, jclass type) {
    return string2jstring(env, MMKV_VERSION);
}

#    ifndef MMKV_DISABLE_CRYPT

MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        string cryptKey = kv->cryptKey();
        if (cryptKey.length() > 0) {
            return string2jstring(env, cryptKey);
        }
    }
    return nullptr;
}

MMKV_JNI jboolean doReKey(JNIEnv *env, jobject instance, jstring cryptKey, jboolean aes256) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        string newKey;
        if (cryptKey) {
            newKey = jstring2string(env, cryptKey);
        }
        return (jboolean) kv->reKey(newKey, aes256);
    }
    return (jboolean) false;
}

MMKV_JNI void doCheckReSetCryptKey(JNIEnv *env, jobject instance, jstring cryptKey, jboolean aes256) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        string newKey;
        if (cryptKey) {
            newKey = jstring2string(env, cryptKey);
        }

        if (!cryptKey || newKey.empty()) {
            kv->checkReSetCryptKey(nullptr, aes256);
        } else {
            kv->checkReSetCryptKey(&newKey, aes256);
        }
    }
}

#    else

MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    return nullptr;
}

#    endif // MMKV_DISABLE_CRYPT

MMKV_JNI void trim(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->trim();
    }
}

MMKV_JNI void close(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->close();
        env->SetLongField(instance, g_fileID, 0);
    }
}

MMKV_JNI jint valueSize(JNIEnv *env, jobject, jlong handle, jstring oKey, jboolean actualSize) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return static_cast<jint>(kv->getValueSize(key, (bool) actualSize));
    }
    return 0;
}

MMKV_JNI void setLogLevel(JNIEnv *env, jclass type, jint level) {
    MMKV::setLogLevel((MMKVLogLevel) level);
}

MMKV_JNI void setCallbackHandler(JNIEnv *env, jclass type, jboolean logReDirecting, jboolean hasCallback, jlong nativeHandler) {
    g_jniHandler.setLogRedirecting(logReDirecting == JNI_TRUE);
    g_jniHandler.setHasCallback(hasCallback == JNI_TRUE);
    if (logReDirecting && nativeHandler != 0) {
        g_androidLogHandler = (AndroidLogHandler) nativeHandler;
    } else {
        g_androidLogHandler = nullptr;
    }

    if (hasCallback == JNI_TRUE || logReDirecting == JNI_TRUE) {
        MMKV::registerHandler(&g_jniHandler);
    } else {
        MMKV::unRegisterHandler();
    }
}

MMKV_JNI jlong createNB(JNIEnv *env, jobject instance, jint size) {
    auto ptr = malloc(static_cast<size_t>(size));
    if (!ptr) {
        MMKVError("fail to create NativeBuffer:%s", strerror(errno));
        return 0;
    }
    return reinterpret_cast<jlong>(ptr);
}

MMKV_JNI void destroyNB(JNIEnv *env, jobject instance, jlong pointer, jint size) {
    free(reinterpret_cast<void *>(pointer));
}

MMKV_JNI jint writeValueToNB(JNIEnv *env, jobject instance, jlong handle, jstring oKey, jlong pointer, jint size) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    if (kv && oKey) {
        string key = jstring2string(env, oKey);
        return kv->writeValueToBuffer(key, reinterpret_cast<void *>(pointer), size);
    }
    return -1;
}

MMKV_JNI void setWantsContentChangeNotify(JNIEnv *env, jclass type, jboolean notify) {
    g_jniHandler.setWantsContentChange(notify == JNI_TRUE);
    // ensure handler is registered when content change is wanted
    if (notify == JNI_TRUE) {
        MMKV::registerHandler(&g_jniHandler);
    }
}

MMKV_JNI void checkContentChanged(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->checkContentChanged();
    }
}

MMKV_JNI jboolean backupOne(JNIEnv *env, jobject obj, jstring mmapID, jstring dstDir, jstring rootPath) {
    if (rootPath) {
        string root = jstring2string(env, rootPath);
        if (root.length() > 0) {
            return (jboolean) MMKV::backupOneToDirectory(jstring2string(env, mmapID), jstring2string(env, dstDir), &root);
        }
    }
    return (jboolean) MMKV::backupOneToDirectory(jstring2string(env, mmapID), jstring2string(env, dstDir));
}

MMKV_JNI jboolean restoreOne(JNIEnv *env, jobject obj, jstring mmapID, jstring srcDir, jstring rootPath) {
    if (rootPath) {
        string root = jstring2string(env, rootPath);
        if (root.length() > 0) {
            return (jboolean) MMKV::restoreOneFromDirectory(jstring2string(env, mmapID), jstring2string(env, srcDir), &root);
        }
    }
    return (jboolean) MMKV::restoreOneFromDirectory(jstring2string(env, mmapID), jstring2string(env, srcDir));
}

MMKV_JNI jlong backupAll(JNIEnv *env, jobject obj, jstring dstDir/*, jstring rootPath*/) {
    // historically Android mistakenly use mmapKey as mmapID
    // makes everything tricky with customize root
    /*if (rootPath) {
        string root = jstring2string(env, rootPath);
        if (root.length() > 0) {
            return (jlong) MMKV::backupAllToDirectory(jstring2string(env, dstDir), &root);
        }
    }*/
    return (jlong) MMKV::backupAllToDirectory(jstring2string(env, dstDir));
}

MMKV_JNI jlong restoreAll(JNIEnv *env, jobject obj, jstring srcDir/*, jstring rootPath*/) {
    // historically Android mistakenly use mmapKey as mmapID
    // makes everything tricky with customize root
    /*if (rootPath) {
        string root = jstring2string(env, rootPath);
        if (root.length() > 0) {
            return (jlong) MMKV::restoreAllFromDirectory(jstring2string(env, srcDir), &root);
        }
    }*/
    return (jlong) MMKV::restoreAllFromDirectory(jstring2string(env, srcDir));
}

MMKV_JNI jboolean enableAutoExpire(JNIEnv *env, jobject instance, jint expireDuration) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return (jboolean) kv->enableAutoKeyExpire(expireDuration);
    }
    return (jboolean) false;
}

MMKV_JNI jboolean disableAutoExpire(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return (jboolean) kv->disableAutoKeyExpire();
    }
    return (jboolean) false;
}

MMKV_JNI void enableCompareBeforeSet(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->enableCompareBeforeSet();
    }
}

MMKV_JNI void disableCompareBeforeSet(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->disableCompareBeforeSet();
    }
}

MMKV_JNI bool isCompareBeforeSetEnabled(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return kv->isCompareBeforeSetEnabled();
    }
    return false;
}

MMKV_JNI bool isEncryptionEnabled(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return kv->isEncryptionEnabled();
    }
    return false;
}

MMKV_JNI bool isExpirationEnabled(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return kv->isExpirationEnabled();
    }
    return false;
}

MMKV_JNI void clearAllWithKeepingSpace(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        kv->clearAll(true);
    }
}

MMKV_JNI jboolean isMultiProcess(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return (jboolean) kv->isMultiProcess();
    }
    return jboolean(false);
}

MMKV_JNI jboolean isReadOnly(JNIEnv *env, jobject instance) {
    MMKV *kv = getMMKV(env, instance);
    if (kv) {
        return (jboolean) kv->isReadOnly();
    }
    return jboolean(false);
}

MMKV_JNI jboolean getNameSpace(JNIEnv *env, jclass type, jstring rootPath) {
    if (rootPath) {
        auto root = jstring2string(env, rootPath);
        if (!root.empty()) {
            MMKV::nameSpace(root);
            return (jboolean) true;
        }
    }
    return (jboolean) false;
}

MMKV_JNI jboolean checkExist(JNIEnv *env, jclass type, jstring oMmapID, jstring rootPath) {
    if (oMmapID) {
        string mmapID = jstring2string(env, oMmapID);
        if (!rootPath) {
            return (jboolean) MMKV::checkExist(mmapID, nullptr);
        } else {
            auto root = jstring2string(env, rootPath);
            return (jboolean) MMKV::checkExist(mmapID, &root);
        }
    }
    return (jboolean) false;
}

MMKV_JNI void enableDisableProcessMode(JNIEnv *env, jclass type, jboolean notify) {
    if (notify == JNI_TRUE) {
        MMKV::enableDisableProcessMode(true);
    } else {
        MMKV::enableDisableProcessMode(false);
    }
}

MMKV_JNI jlong importFrom(JNIEnv *env, jobject instance, jlong handle, jlong srcHandle) {
    MMKV *kv = reinterpret_cast<MMKV *>(handle);
    MMKV *src = reinterpret_cast<MMKV *>(srcHandle);
    if (kv && src) {
        jlong size = kv->importFrom(src);
        return size;
    }
    return 0;
}

} // namespace mmkv

static JNINativeMethod g_methods[] = {
    {"onExit", "()V", (void *) mmkv::onExit},
    {"cryptKey", "()Ljava/lang/String;", (void *) mmkv::cryptKey},
#    ifndef MMKV_DISABLE_CRYPT
    {"doReKey", "(Ljava/lang/String;Z)Z", (void *) mmkv::doReKey},
    {"doCheckReSetCryptKey", "(Ljava/lang/String;Z)V", (void *) mmkv::doCheckReSetCryptKey},
#    endif
    {"pageSize", "()I", (void *) mmkv::pageSize},
    {"mmapID", "()Ljava/lang/String;", (void *) mmkv::mmapID},
    {"version", "()Ljava/lang/String;", (void *) mmkv::version},
    {"lock", "()V", (void *) mmkv::lock},
    {"unlock", "()V", (void *) mmkv::unlock},
    {"tryLock", "()Z", (void *) mmkv::tryLock},
    {"allKeys", "(JZ)[Ljava/lang/String;", (void *) mmkv::allKeys},
    {"removeValuesForKeys", "([Ljava/lang/String;)V", (void *) mmkv::removeValuesForKeys},
    {"clearAll", "()V", (void *) mmkv::clearAll},
    {"trim", "()V", (void *) mmkv::trim},
    {"close", "()V", (void *) mmkv::close},
    {"clearMemoryCache", "()V", (void *) mmkv::clearMemoryCache},
    {"sync", "(Z)V", (void *) mmkv::sync},
    {"isFileValid", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::isFileValid},
    {"removeStorage", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::removeStorage},
    {"ashmemFD", "()I", (void *) mmkv::ashmemFD},
    {"ashmemMetaFD", "()I", (void *) mmkv::ashmemMetaFD},
    {"jniInitialize", "(Ljava/lang/String;Ljava/lang/String;IZZJ)V", (void *) mmkv::jniInitialize},
    {"getMMKVWithID", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JZIIZII)J", (void *) mmkv::getMMKVWithID},
    {"getDefaultMMKV", "(ILjava/lang/String;JZIIZII)J", (void *) mmkv::getDefaultMMKV},
    {"getMMKVWithAshmemFD", "(Ljava/lang/String;IILjava/lang/String;Z)J", (void *) mmkv::getMMKVWithAshmemFD},
    {"encodeBool", "(JLjava/lang/String;Z)Z", (void *) mmkv::encodeBool},
    {"encodeBool_2", "(JLjava/lang/String;ZI)Z", (void *) mmkv::encodeBool_2},
    {"decodeBool", "(JLjava/lang/String;Z)Z", (void *) mmkv::decodeBool},
    {"encodeInt", "(JLjava/lang/String;I)Z", (void *) mmkv::encodeInt},
    {"encodeInt_2", "(JLjava/lang/String;II)Z", (void *) mmkv::encodeInt_2},
    {"decodeInt", "(JLjava/lang/String;I)I", (void *) mmkv::decodeInt},
    {"encodeLong", "(JLjava/lang/String;J)Z", (void *) mmkv::encodeLong},
    {"encodeLong_2", "(JLjava/lang/String;JI)Z", (void *) mmkv::encodeLong_2},
    {"decodeLong", "(JLjava/lang/String;J)J", (void *) mmkv::decodeLong},
    {"encodeFloat", "(JLjava/lang/String;F)Z", (void *) mmkv::encodeFloat},
    {"encodeFloat_2", "(JLjava/lang/String;FI)Z", (void *) mmkv::encodeFloat_2},
    {"decodeFloat", "(JLjava/lang/String;F)F", (void *) mmkv::decodeFloat},
    {"encodeDouble", "(JLjava/lang/String;D)Z", (void *) mmkv::encodeDouble},
    {"encodeDouble_2", "(JLjava/lang/String;DI)Z", (void *) mmkv::encodeDouble_2},
    {"decodeDouble", "(JLjava/lang/String;D)D", (void *) mmkv::decodeDouble},
    {"encodeString", "(JLjava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::encodeString},
    {"encodeString_2", "(JLjava/lang/String;Ljava/lang/String;I)Z", (void *) mmkv::encodeString_2},
    {"decodeString", "(JLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) mmkv::decodeString},
    {"encodeSet", "(JLjava/lang/String;[Ljava/lang/String;)Z", (void *) mmkv::encodeSet},
    {"encodeSet_2", "(JLjava/lang/String;[Ljava/lang/String;I)Z", (void *) mmkv::encodeSet_2},
    {"decodeStringSet", "(JLjava/lang/String;)[Ljava/lang/String;", (void *) mmkv::decodeStringSet},
    {"encodeBytes", "(JLjava/lang/String;[B)Z", (void *) mmkv::encodeBytes},
    {"encodeBytes_2", "(JLjava/lang/String;[BI)Z", (void *) mmkv::encodeBytes_2},
    {"decodeBytes", "(JLjava/lang/String;)[B", (void *) mmkv::decodeBytes},
    {"containsKey", "(JLjava/lang/String;)Z", (void *) mmkv::containsKey},
    {"count", "(JZ)J", (void *) mmkv::count},
    {"totalSize", "(J)J", (void *) mmkv::totalSize},
    {"actualSize", "(J)J", (void *) mmkv::actualSize},
    {"removeValueForKey", "(JLjava/lang/String;)V", (void *) mmkv::removeValueForKey},
    {"valueSize", "(JLjava/lang/String;Z)I", (void *) mmkv::valueSize},
    {"setLogLevel", "(I)V", (void *) mmkv::setLogLevel},
    {"setCallbackHandler", "(ZZJ)V", (void *) mmkv::setCallbackHandler},
    {"createNB", "(I)J", (void *) mmkv::createNB},
    {"destroyNB", "(JI)V", (void *) mmkv::destroyNB},
    {"writeValueToNB", "(JLjava/lang/String;JI)I", (void *) mmkv::writeValueToNB},
    {"setWantsContentChangeNotify", "(Z)V", (void *) mmkv::setWantsContentChangeNotify},
    {"checkContentChangedByOuterProcess", "()V", (void *) mmkv::checkContentChanged},
    {"checkProcessMode", "(J)Z", (void *) mmkv::checkProcessMode},
    {"backupOneToDirectory", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::backupOne},
    {"restoreOneMMKVFromDirectory", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::restoreOne},
    {"backupAllToDirectory", "(Ljava/lang/String;)J", (void *) mmkv::backupAll},
    {"restoreAllFromDirectory", "(Ljava/lang/String;)J", (void *) mmkv::restoreAll},
    {"enableAutoKeyExpire", "(I)Z", (void *) mmkv::enableAutoExpire},
    {"disableAutoKeyExpire", "()Z", (void *) mmkv::disableAutoExpire},
    {"nativeEnableCompareBeforeSet", "()V", (void *) mmkv::enableCompareBeforeSet},
    {"disableCompareBeforeSet", "()V", (void *) mmkv::disableCompareBeforeSet},
    {"isCompareBeforeSetEnabled", "()Z", (void *) mmkv::isCompareBeforeSetEnabled},
    {"isEncryptionEnabled", "()Z", (void *) mmkv::isEncryptionEnabled},
    {"isExpirationEnabled", "()Z", (void *) mmkv::isExpirationEnabled},
    {"clearAllWithKeepingSpace", "()V", (void *) mmkv::clearAllWithKeepingSpace},
    {"isMultiProcess", "()Z", (void *) mmkv::isMultiProcess},
    {"isReadOnly", "()Z", (void *) mmkv::isReadOnly},
    {"getNameSpace", "(Ljava/lang/String;)Z", (void *)mmkv::getNameSpace},
    {"checkExist", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *) mmkv::checkExist},
    {"enableDisableProcessMode", "(Z)V", (void *) mmkv::enableDisableProcessMode},
    {"importFrom", "(JJ)J", (void *) mmkv::importFrom},
};

static int registerNativeMethods(JNIEnv *env, jclass cls) {
    return env->RegisterNatives(cls, g_methods, sizeof(g_methods) / sizeof(g_methods[0]));
}

#endif // MMKV_ANDROID


================================================
FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java
================================================
/*
 * Tencent is pleased to support the open source community by making
 * MMKV available.
 *
 * Copyright (C) 2018 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *       https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tencent.mmkv;

import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.jetbrains.annotations.Contract;

import dalvik.annotation.optimization.FastNative;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * An highly efficient, reliable, multi-process key-value storage framework.
 * THE PERFECT drop-in replacement for SharedPreferences and MultiProcessSharedPreferences.
 */
public class MMKV implements SharedPreferences, SharedPreferences.Editor {

    private static final EnumMap<MMKVRecoverStrategic, Integer> recoverIndex;
    private static final EnumMap<MMKVLogLevel, Integer> logLevel2Index;
    private static final MMKVLogLevel[] index2LogLevel;
    private static final Set<Long> checkedHandleSet;

    static {
        recoverIndex = new EnumMap<>(MMKVRecoverStrategic.class);
        recoverIndex.put(MMKVRecoverStrategic.OnErrorDiscard, 0);
        recoverIndex.put(MMKVRecoverStrategic.OnErrorRecover, 1);

        logLevel2Index = new EnumMap<>(MMKVLogLevel.class);
        logLevel2Index.put(MMKVLogLevel.LevelDebug, 0);
        logLevel2Index.put(MMKVLogLevel.LevelInfo, 1);
        logLevel2Index.put(MMKVLogLevel.LevelWarning, 2);
        logLevel2Index.put(MMKVLogLevel.LevelError, 3);
        logLevel2Index.put(MMKVLogLevel.LevelNone, 4);

        index2LogLevel = new MMKVLogLevel[]{MMKVLogLevel.LevelDebug, MMKVLogLevel.LevelInfo, MMKVLogLevel.LevelWarning,
                MMKVLogLevel.LevelError, MMKVLogLevel.LevelNone};

        checkedHandleSet = new HashSet<Long>();
    }

    /**
     * The interface for providing a 3rd library loader (the ReLinker https://github.com/KeepSafe/ReLinker, etc).
     */
    public interface LibLoader {
        void loadLibrary(String libName);
    }

    /**
     * Initialize MMKV with default configuration.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context The context of Android App, usually from Application.
     * @return The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     */
    public static String initialize(@NonNull Context context) {
        String root = context.getFilesDir().getAbsolutePath() + "/mmkv";
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return initialize(context, root, null, logLevel, null);
    }

    /**
     * Initialize MMKV with customize log level.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context  The context of Android App, usually from Application.
     * @param logLevel The log level of MMKV, defaults to {@link MMKVLogLevel#LevelInfo}.
     * @return The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     */
    public static String initialize(@NonNull Context context, MMKVLogLevel logLevel) {
        String root = context.getFilesDir().getAbsolutePath() + "/mmkv";
        return initialize(context, root, null, logLevel, null);
    }

    /**
     * Initialize MMKV with a 3rd library loader.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context The context of Android App, usually from Application.
     * @param loader  The 3rd library loader (for example, the <a href="https://github.com/KeepSafe/ReLinker">ReLinker</a> .
     * @return The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     */
    public static String initialize(@NonNull Context context, LibLoader loader) {
        String root = context.getFilesDir().getAbsolutePath() + "/mmkv";
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return initialize(context, root, loader, logLevel, null);
    }

    /**
     * Initialize MMKV with a 3rd library loader, and customize log level.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context  The context of Android App, usually from Application.
     * @param loader   The 3rd library loader (for example, the <a href="https://github.com/KeepSafe/ReLinker">ReLinker</a> .
     * @param logLevel The log level of MMKV, defaults to {@link MMKVLogLevel#LevelInfo}.
     * @return The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     */
    public static String initialize(@NonNull Context context, LibLoader loader, MMKVLogLevel logLevel) {
        String root = context.getFilesDir().getAbsolutePath() + "/mmkv";
        return initialize(context, root, loader, logLevel, null);
    }

    /**
     * Initialize MMKV with customize root folder.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context The context of Android App, usually from Application.
     * @param rootDir The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     * @return The root folder of MMKV.
     */
    public static String initialize(Context context, String rootDir) {
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return initialize(context, rootDir, null, logLevel, null);
    }

    /**
     * Initialize MMKV with customize root folder, and log level.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context  The context of Android App, usually from Application.
     * @param rootDir  The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     * @param logLevel The log level of MMKV, defaults to {@link MMKVLogLevel#LevelInfo}.
     * @return The root folder of MMKV.
     */
    public static String initialize(Context context, String rootDir, MMKVLogLevel logLevel) {
        return initialize(context, rootDir, null, logLevel, null);
    }

    /**
     * Initialize MMKV with customize root folder, and a 3rd library loader.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context The context of Android App, usually from Application.
     * @param rootDir The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     * @param loader  The 3rd library loader (for example, the <a href="https://github.com/KeepSafe/ReLinker">ReLinker</a> .
     * @return The root folder of MMKV.
     */
    public static String initialize(Context context, String rootDir, LibLoader loader) {
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return initialize(context, rootDir, loader, logLevel, null);
    }

    /**
     * Initialize MMKV with customize settings.
     * You must call one of the initialize() methods on App startup process before using MMKV.
     *
     * @param context  The context of Android App, usually from Application.
     * @param rootDir  The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     * @param loader   The 3rd library loader (for example, the <a href="https://github.com/KeepSafe/ReLinker">ReLinker</a> .
     * @param logLevel The log level of MMKV, defaults to {@link MMKVLogLevel#LevelInfo}.
     * @return The root folder of MMKV.
     */
    public static String initialize(Context context, String rootDir, LibLoader loader, MMKVLogLevel logLevel) {
        return initialize(context, rootDir, loader, logLevel, null);
    }

    public static String initialize(@NonNull Context context, String rootDir, LibLoader loader, MMKVLogLevel logLevel, MMKVHandler handler) {
        if (!Process.is64Bit()) {
            throw new UnsupportedArchitectureException("MMKV 2.0+ requires 64-bit App, use 1.3.x instead.");
        }
        String cacheDir = context.getCacheDir().getAbsolutePath();

        gCallbackHandler = handler;
        boolean hasCallback = false;
        long nativeLogHandler = 0;
        if (handler != null) {
            hasCallback = true;
            if (handler.wantLogRedirecting()) {
                gWantLogReDirecting = true;
                nativeLogHandler = handler.getNativeLogHandler();
            }
        }

        String ret = doInitialize(rootDir, cacheDir, loader, logLevel, gWantLogReDirecting, hasCallback, nativeLogHandler);

        if (handler != null && handler.wantContentChangeNotification()) {
            setWantsContentChangeNotify(true);
        }

        // disable process mode in release build
        // FIXME: Find a better way to getApplicationInfo() without using context.
        //  If any one knows how, you're welcome to make a contribution.
        if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
            disableProcessModeChecker();
        } else {
            enableProcessModeChecker();
        }

        return ret;
    }

    private static String doInitialize(String rootDir, String cacheDir, LibLoader loader, MMKVLogLevel logLevel, boolean wantLogReDirecting, boolean hasCallback, long nativeHandler) {
        tryLoadNativeLib(loader);
        jniInitialize(rootDir, cacheDir, logLevel2Int(logLevel), wantLogReDirecting, hasCallback, nativeHandler);
        MMKV.rootDir = rootDir;
        return MMKV.rootDir;
    }

    private static boolean isNativeLibLoaded = false;

    private static void tryLoadNativeLib(@Nullable LibLoader loader) {
        if (isNativeLibLoaded) {
            return;
        }
        if (loader != null) {
            if (BuildConfig.FLAVOR.equals("SharedCpp")) {
                loader.loadLibrary("c++_shared");
            }
            loader.loadLibrary("mmkv");
        } else {
            if (BuildConfig.FLAVOR.equals("SharedCpp")) {
                System.loadLibrary("c++_shared");
            }
            System.loadLibrary("mmkv");
        }
        isNativeLibLoaded = true;
    }

    /**
     * @deprecated This method is deprecated due to failing to automatically disable checkProcessMode() without Context.
     * Use the {@link #initialize(Context, String)} method instead.
     */
    @Deprecated
    public static String initialize(String rootDir) {
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return doInitialize(rootDir, rootDir + "/.tmp", null, logLevel, false, false, 0);
    }

    /**
     * @deprecated This method is deprecated due to failing to automatically disable checkProcessMode() without Context.
     * Use the {@link #initialize(Context, String, MMKVLogLevel)} method instead.
     */
    @Deprecated
    public static String initialize(String rootDir, MMKVLogLevel logLevel) {
        return doInitialize(rootDir, rootDir + "/.tmp", null, logLevel, false, false, 0);
    }

    /**
     * @deprecated This method is deprecated due to failing to automatically disable checkProcessMode() without Context.
     * Use the {@link #initialize(Context, String, LibLoader)} method instead.
     */
    @Deprecated
    public static String initialize(String rootDir, LibLoader loader) {
        MMKVLogLevel logLevel = BuildConfig.DEBUG ? MMKVLogLevel.LevelDebug : MMKVLogLevel.LevelInfo;
        return doInitialize(rootDir, rootDir + "/.tmp", loader, logLevel, false, false, 0);
    }

    /**
     * @deprecated This method is deprecated due to failing to automatically disable checkProcessMode() without Context.
     * Use the {@link #initialize(Context, String, LibLoader, MMKVLogLevel)} method instead.
     */
    @Deprecated
    public static String initialize(String rootDir, LibLoader loader, MMKVLogLevel logLevel) {
        return doInitialize(rootDir, rootDir + "/.tmp", loader, logLevel, false, false, 0);
    }

    /**
     * @param dir the customize root directory of a NameSpace
     * @return a NameSpace with custom root dir
     * @throws RuntimeException if there's an runtime error.
     */
    public static NameSpace nameSpace(String dir) throws RuntimeException {
        tryLoadNativeLib(null);
        if (getNameSpace(dir)) {
            return new NameSpace(dir);
        }
        throw new RuntimeException("Fail to get NameSpace[" + dir + "] in JNI.");
    }

    /**
     * identical with the original MMKV with the global root dir
     * @throws RuntimeException if there's an runtime error.
     */
    public static NameSpace defaultNameSpace() throws RuntimeException {
        if (rootDir == null) {
            throw new IllegalStateException("You should Call MMKV.initialize() first.");
        }
        return new NameSpace(rootDir);
    }

    static private String rootDir = null;

    /**
     * @return The root folder of MMKV, defaults to $(FilesDir)/mmkv.
     */
    public static String getRootDir() {
        return rootDir;
    }

    @Contract(pure = true)
    private static int logLevel2Int(@NonNull MMKVLogLevel level) {
        int realLevel;
        switch (level) {
            case LevelDebug:
                realLevel = 0;
                break;
            case LevelWarning:
                realLevel = 2;
                break;
            case LevelError:
                realLevel = 3;
                break;
            case LevelNone:
                realLevel = 4;
                break;
            case LevelInfo:
            default:
                realLevel = 1;
                break;
        }
        return realLevel;
    }

    /**
     * Set the log level of MMKV.
     *
     * @param level Defaults to {@link MMKVLogLevel#LevelInfo}.
     */
    public static void setLogLevel(MMKVLogLevel level) {
        int realLevel = logLevel2Int(level);
        setLogLevel(realLevel);
    }

    /**
     * Notify MMKV that App is about to exit. It's totally fine not calling it at all.
     */
    public static native void onExit();

    /**
     * Single-process mode. The default mode on an MMKV instance.
     */
    static public final int SINGLE_PROCESS_MODE = 1 << 0;

    /**
     * Multi-process mode.
     * To enable multi-process accessing of an MMKV instance, you must set this mode whenever you getting that instance.
     */
    static public final int MULTI_PROCESS_MODE = 1 << 1;

    // in case someone mistakenly pass Context.MODE_MULTI_PROCESS
    static private final int CONTEXT_MODE_MULTI_PROCESS = 1 << 2;

    static private final int ASHMEM_MODE = 1 << 3;

    static private final int BACKUP_MODE = 1 << 4;

    /**
     * Read-only mode.
     */
    static public final int READ_ONLY_MODE = 1 << 5;

    /**
     * Create an MMKV instance with an unique ID (in single-process mode).
     *
     * @param mmapID The unique ID of the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID) throws RuntimeException {
        return mmkvWithID(mmapID, new MMKVConfig());
    }

    /**
     * Create an MMKV instance with an unique ID (in single-process mode).
     *
     * @param mmapID The unique ID of the MMKV instance.
     * @param config The all-in-one configuration for the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, MMKVConfig config) throws RuntimeException {
        if (rootDir == null) {
            throw new IllegalStateException("You should Call MMKV.initialize() first.");
        }

        int enableKeyExpire = (config.enableKeyExpire != null) ? (config.enableKeyExpire ? 1 : 0) : -1;
        Integer value = recoverIndex.get(config.recover);
        int recover = (value == null) ? -1 : value;

        long handle = getMMKVWithID(mmapID, config.mode, config.cryptKey, config.rootPath, config.expectedCapacity,
                config.aes256, enableKeyExpire, config.expiredInSeconds, config.enableCompareBeforeSet,
                recover, config.itemSizeLimit);

        return checkProcessMode(handle, mmapID, config.mode);
    }

    /**
     * Create an MMKV instance in single-process or multi-process mode.
     *
     * @param mmapID The unique ID of the MMKV instance.
     * @param mode   The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance in single-process or multi-process mode.
     *
     * @param mmapID The unique ID of the MMKV instance.
     * @param mode   The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param expectedCapacity The file size you expected when opening or creating file
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, long expectedCapacity) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.expectedCapacity = expectedCapacity;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance in customize process mode, with an encryption key.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.cryptKey = cryptKey;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance in customize process mode, with an encryption key.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256 Use AES 256 key length
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey, boolean aes256) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.aes256 = aes256;
        config.cryptKey = cryptKey;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance in customize folder.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, String rootPath) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.rootPath = rootPath;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance in customize folder.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @param expectedCapacity The file size you expected when opening or creating file
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, String rootPath, long expectedCapacity) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.rootPath = rootPath;
        config.expectedCapacity = expectedCapacity;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @param expectedCapacity The file size you expected when opening or creating file
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey, String rootPath, long expectedCapacity)
            throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        config.expectedCapacity = expectedCapacity;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256   Use AES 256 key length
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @param expectedCapacity The file size you expected when opening or creating file
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey, boolean aes256, String rootPath,
                                  long expectedCapacity) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.aes256 = aes256;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        config.expectedCapacity = expectedCapacity;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey, String rootPath)
            throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256   Use AES 256 key length.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithID(String mmapID, int mode, @Nullable String cryptKey, boolean aes256, String rootPath)
            throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.aes256 = aes256;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Get an backed-up MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @param rootPath The backup folder of the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV backedUpMMKVWithID(String mmapID, int mode, @Nullable String cryptKey, String rootPath)
            throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Get an backed-up MMKV instance with customize settings all in one.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256   Use AES 256 key length.
     * @param rootPath The backup folder of the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV backedUpMMKVWithID(String mmapID, int mode, @Nullable String cryptKey, boolean aes256, String rootPath)
            throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        mode |= BACKUP_MODE;
        config.mode = mode;
        config.cryptKey = cryptKey;
        config.rootPath = rootPath;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
     *
     * @param context  The context of Android App, usually from Application.
     * @param mmapID   The unique ID of the MMKV instance.
     * @param size     The maximum size of the underlying Anonymous Shared Memory.
     *                 Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, @Nullable String cryptKey)
            throws RuntimeException {
        return mmkvWithAshmemID(context, mmapID, size, mode, cryptKey, false);
    }

    /**
     * Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
     *
     * @param context  The context of Android App, usually from Application.
     * @param mmapID   The unique ID of the MMKV instance.
     * @param size     The maximum size of the underlying Anonymous Shared Memory.
     *                 Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation.
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256   Use AES 256 key length.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, @Nullable String cryptKey,
                                        boolean aes256) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode | ASHMEM_MODE;
        config.expectedCapacity = size;
        config.aes256 = aes256;
        config.cryptKey = cryptKey;
        return mmkvWithAshmemID(context, mmapID, config);
    }

    /**
     * Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
     *
     * @param context  The context of Android App, usually from Application.
     * @param mmapID   The unique ID of the MMKV instance.
     * @param config   The all-in-one configuration for the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV mmkvWithAshmemID(Context context, String mmapID, MMKVConfig config) throws RuntimeException {
        if (rootDir == null) {
            throw new IllegalStateException("You should Call MMKV.initialize() first.");
        }

        String processName = MMKVContentProvider.getProcessNameByPID(context, Process.myPid());
        if (processName == null || processName.isEmpty()) {
            String message = "process name detect fail, try again later";
            simpleLog(MMKVLogLevel.LevelError, message);
            throw new IllegalStateException(message);
        }
        if (processName.contains(":")) {
            Uri uri = MMKVContentProvider.contentUri(context);
            if (uri == null) {
                String message = "MMKVContentProvider has invalid authority";
                simpleLog(MMKVLogLevel.LevelError, message);
                throw new IllegalStateException(message);
            }
            simpleLog(MMKVLogLevel.LevelInfo, "getting parcelable mmkv in process, Uri = " + uri);

            Bundle extras = new Bundle();
            extras.putInt(MMKVContentProvider.KEY_SIZE, (int) config.expectedCapacity);
            extras.putInt(MMKVContentProvider.KEY_MODE, config.mode);
            if (config.cryptKey != null) {
                extras.putString(MMKVContentProvider.KEY_CRYPT, config.cryptKey);
            }
            ContentResolver resolver = context.getContentResolver();
            Bundle result = resolver.call(uri, MMKVContentProvider.FUNCTION_NAME, mmapID, extras);
            if (result != null) {
                result.setClassLoader(ParcelableMMKV.class.getClassLoader());
                ParcelableMMKV parcelableMMKV = result.getParcelable(MMKVContentProvider.KEY);
                if (parcelableMMKV != null) {
                    MMKV mmkv = parcelableMMKV.toMMKV();
                    if (mmkv != null) {
                        simpleLog(MMKVLogLevel.LevelInfo,
                                mmkv.mmapID() + " fd = " + mmkv.ashmemFD() + ", meta fd = " + mmkv.ashmemMetaFD());
                        return mmkv;
                    }
                }
            }
        }
        simpleLog(MMKVLogLevel.LevelInfo, "getting mmkv in main process");

        config.mode = config.mode | ASHMEM_MODE;
        return mmkvWithID(mmapID, config);
    }

    /**
     * Create the default MMKV instance in single-process mode.
     *
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV defaultMMKV() throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        return defaultMMKV(config);
    }

    /**
     * Create the default MMKV instance in customize process mode, with an encryption key.
     *
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes).
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV defaultMMKV(int mode, @Nullable String cryptKey) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.cryptKey = cryptKey;
        return defaultMMKV(config);
    }

    /**
     * Create the default MMKV instance in customize process mode, with an encryption key.
     *
     * @param mode     The process mode of the MMKV instance, defaults to {@link #SINGLE_PROCESS_MODE}.
     * @param cryptKey The encryption key of the MMKV instance (no more than 32 bytes).
     * @param aes256   Use AES 256 key length.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV defaultMMKV(int mode, @Nullable String cryptKey, boolean aes256) throws RuntimeException {
        MMKVConfig config = new MMKVConfig();
        config.mode = mode;
        config.aes256 = aes256;
        config.cryptKey = cryptKey;
        return defaultMMKV(config);
    }

    /**
     * Create the default MMKV instance in customize configuration.
     *
     * @param config     The all-in-one configuration for the MMKV instance.
     * @throws RuntimeException if there's an runtime error.
     */
    @NonNull
    public static MMKV defaultMMKV(MMKVConfig config) throws RuntimeException {
        if (rootDir == null) {
            throw new IllegalStateException("You should Call MMKV.initialize() first.");
        }

        int enableKeyExpire = (config.enableKeyExpire != null) ? (config.enableKeyExpire ? 1 : 0) : -1;
        Integer value = recoverIndex.get(config.recover);
        int recover = (value == null) ? -1 : value;

        long handle = getDefaultMMKV(config.mode, config.cryptKey, config.expectedCapacity, config.aes256,
                enableKeyExpire, config.expiredInSeconds, config.enableCompareBeforeSet, recover, config.itemSizeLimit);

        return checkProcessMode(handle, "DefaultMMKV", config.mode);
    }

    @NonNull
    @Contract("_, _, _ -> new")
    static MMKV checkProcessMode(long handle, String mmapID, int mode) throws RuntimeException {
        if (handle == 0) {
            throw new RuntimeException("Fail to create an MMKV instance [" + mmapID + "] in JNI");
        }
        if (!isProcessModeCheckerEnabled) {
            return new MMKV(handle);
        }
        synchronized (checkedHandleSet) {
            if (!checkedHandleSet.contains(handle)) {
                if (!checkProcessMode(handle)) {
                    String message;
                    if (mode == SINGLE_PROCESS_MODE) {
                        message = "Opening a multi-process MMKV instance [" + mmapID + "] with SINGLE_PROCESS_MODE!";
                    } else {
                        message = "Opening an MMKV instance [" + mmapID + "] with MULTI_PROCESS_MODE, ";
                        message += "while it's already been opened with SINGLE_PROCESS_MODE by someone somewhere else!";
                    }
                    throw new IllegalArgumentException(message);
                }
                checkedHandleSet.add(handle);
            }
        }
        return new MMKV(handle);
    }

    // Enable checkProcessMode() when initializing an MMKV instance, it's automatically enabled on debug build.
    private static boolean isProcessModeCheckerEnabled = true;

    /**
     * Manually enable the process mode checker.
     * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
     * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
     */
    public static void enableProcessModeChecker() {
        synchronized (checkedHandleSet) {
            isProcessModeCheckerEnabled = true;
        }
        enableDisableProcessMode(true);
        Log.i("MMKV", "Enable checkProcessMode()");
    }

    /**
     * Manually disable the process mode checker.
     * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
     * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
     */
    public static void disableProcessModeChecker() {
        synchronized (checkedHandleSet) {
            isProcessModeCheckerEnabled = false;
        }
        enableDisableProcessMode(false);
        Log.i("MMKV", "Disable checkProcessMode()");
    }

    /**
     * @return The encryption key (no more than 16 bytes).
     */
    @Nullable
    public native String cryptKey();

    /**
     * Transform plain text into encrypted text, or vice versa by passing a null encryption key.
     * You can also change existing crypt key with a different cryptKey.
     *
     * @param cryptKey The new encryption key (no more than 16 bytes).
     * @return True if success, otherwise False.
     */
    public boolean reKey(@Nullable String cryptKey) {
        return doReKey(cryptKey, false);
    }

    /**
     * Transform plain text into encrypted text, or vice versa by passing a null encryption key.
     * You can also change existing crypt key with a different cryptKey.
     *
     * @param cryptKey The new encryption key (no more than 32 bytes).
     * @param aes256 Use AES 256 key length
     * @return True if success, otherwise False.
     */
    public boolean reKey(@Nullable String cryptKey, boolean aes256) {
        return doReKey(cryptKey, aes256);
    }
    private native boolean doReKey(@Nullable String cryptKey, boolean aes256);

    /**
     * Just reset the encryption key (will not encrypt or decrypt anything).
     * Usually you should call this method after another process has {@link #reKey(String)} the multi-process MMKV instance.
     *
     * @param cryptKey The new encryption key (no more than 16 bytes).
     */
    public void checkReSetCryptKey(@Nullable String cryptKey) {
        doCheckReSetCryptKey(cryptKey, false);
    }

    /**
     * Just reset the encryption key (will not encrypt or decrypt anything).
     * Usually you should call this method after another process has {@link #reKey(String)} the multi-process MMKV instance.
     *
     * @param cryptKey The new encryption key (no more than 16 bytes).
     * @param aes256 Use AES 256 key length
     */
    public void checkReSetCryptKey(@Nullable String cryptKey, boolean aes256) {
        doCheckReSetCryptKey(cryptKey, aes256);
    }
    private native void doCheckReSetCryptKey(@Nullable String cryptKey, boolean aes256);

    /**
     * @return The device's memory page size.
     */
    public static native int pageSize();

    /**
     * @return The version of MMKV.
     */
    public static native String version();

    /**
     * @return The unique ID of the MMKV instance.
     */
    public native String mmapID();

    /**
     * Exclusively inter-process lock the MMKV instance.
     * It will block and wait until it successfully locks the file.
     * It will make no effect if the MMKV instance is created with {@link #SINGLE_PROCESS_MODE}.
     */
    public native void lock();

    /**
     * Exclusively inter-process unlock the MMKV instance.
     * It will make no effect if the MMKV instance is created with {@link #SINGLE_PROCESS_MODE}.
     */
    public native void unlock();

    /**
     * Try exclusively inter-process lock the MMKV instance.
     * It will not block if the file has already been locked by another process.
     * It will make no effect if the MMKV instance is created with {@link #SINGLE_PROCESS_MODE}.
     *
     * @return True if successfully locked, otherwise return immediately with False.
     */
    public native boolean tryLock();

    public boolean encode(String key, boolean value) {
        return encodeBool(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, boolean value, int expireDurationInSecond) {
        return encodeBool_2(nativeHandle, key, value, expireDurationInSecond);
    }

    public boolean decodeBool(String key) {
        return decodeBool(nativeHandle, key, false);
    }

    public boolean decodeBool(String key, boolean defaultValue) {
        return decodeBool(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, int value) {
        return encodeInt(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, int value, int expireDurationInSecond) {
        return encodeInt_2(nativeHandle, key, value, expireDurationInSecond);
    }

    public int decodeInt(String key) {
        return decodeInt(nativeHandle, key, 0);
    }

    public int decodeInt(String key, int defaultValue) {
        return decodeInt(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, long value) {
        return encodeLong(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, long value, int expireDurationInSecond) {
        return encodeLong_2(nativeHandle, key, value, expireDurationInSecond);
    }

    public long decodeLong(String key) {
        return decodeLong(nativeHandle, key, 0);
    }

    public long decodeLong(String key, long defaultValue) {
        return decodeLong(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, float value) {
        return encodeFloat(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, float value, int expireDurationInSecond) {
        return encodeFloat_2(nativeHandle, key, value, expireDurationInSecond);
    }

    public float decodeFloat(String key) {
        return decodeFloat(nativeHandle, key, 0);
    }

    public float decodeFloat(String key, float defaultValue) {
        return decodeFloat(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, double value) {
        return encodeDouble(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, double value, int expireDurationInSecond) {
        return encodeDouble_2(nativeHandle, key, value, expireDurationInSecond);
    }

    public double decodeDouble(String key) {
        return decodeDouble(nativeHandle, key, 0);
    }

    public double decodeDouble(String key, double defaultValue) {
        return decodeDouble(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, @Nullable String value) {
        return encodeString(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, @Nullable String value, int expireDurationInSecond) {
        return encodeString_2(nativeHandle, key, value, expireDurationInSecond);
    }

    @Nullable
    public String decodeString(String key) {
        return decodeString(nativeHandle, key, null);
    }

    @Nullable
    public String decodeString(String key, @Nullable String defaultValue) {
        return decodeString(nativeHandle, key, defaultValue);
    }

    public boolean encode(String key, @Nullable Set<String> value) {
        return encodeSet(nativeHandle, key, (value == null) ? null : value.toArray(new String[0]));
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, @Nullable Set<String> value, int expireDurationInSecond) {
        return encodeSet_2(nativeHandle, key, (value == null) ? null : value.toArray(new String[0]), expireDurationInSecond);
    }

    @Nullable
    public Set<String> decodeStringSet(String key) {
        return decodeStringSet(key, null);
    }

    @Nullable
    public Set<String> decodeStringSet(String key, @Nullable Set<String> defaultValue) {
        return decodeStringSet(key, defaultValue, HashSet.class);
    }

    @SuppressWarnings("unchecked")
    @Nullable
    public Set<String> decodeStringSet(String key, @Nullable Set<String> defaultValue, Class<? extends Set> cls) {
        String[] result = decodeStringSet(nativeHandle, key);
        if (result == null) {
            return defaultValue;
        }
        Set<String> a;
        try {
            a = cls.newInstance();
        } catch (IllegalAccessException | InstantiationException e) {
            return defaultValue;
        }
        a.addAll(Arrays.asList(result));
        return a;
    }

    public boolean encode(String key, @Nullable byte[] value) {
        return encodeBytes(nativeHandle, key, value);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, @Nullable byte[] value, int expireDurationInSecond) {
        return encodeBytes_2(nativeHandle, key, value, expireDurationInSecond);
    }

    @Nullable
    public byte[] decodeBytes(String key) {
        return decodeBytes(key, null);
    }

    @Nullable
    public byte[] decodeBytes(String key, @Nullable byte[] defaultValue) {
        byte[] ret = decodeBytes(nativeHandle, key);
        return (ret != null) ? ret : defaultValue;
    }

    private static final HashMap<String, Parcelable.Creator<?>> mCreators = new HashMap<>();

    private byte[] getParcelableByte(@NonNull Parcelable value) {
        Parcel source = Parcel.obtain();
        value.writeToParcel(source, 0);
        byte[] bytes = source.marshall();
        source.recycle();
        return bytes;
    }

    public boolean encode(String key, @Nullable Parcelable value) {
        if (value == null) {
            return encodeBytes(nativeHandle, key, null);
        }
        byte[] bytes = getParcelableByte(value);
        return encodeBytes(nativeHandle, key, bytes);
    }

    /**
     * Set value with customize expiration in seconds.
     *
     * @param expireDurationInSecond override the default duration, {@link #ExpireNever} (0) means never expire.
     */
    public boolean encode(String key, @Nullable Parcelable value, int expireDurationInSecond) {
        if (value == null) {
            return encodeBytes_2(nativeHandle, key, null, expireDurationInSecond);
        }
        byte[] bytes = getParcelableByte(value);
        return encodeBytes_2(nativeHandle, key, bytes, expireDurationInSecond);
    }

    @Nullable
    public <T extends Parcelable> T decodeParcelable(String key, Class<T> tClass) {
        return decodeParcelable(key, tClass, null);
    }

    @SuppressWarnings("unchecked")
    @Nullable
    public <T extends Parcelable> T decodeParcelable(String key, Class<T> tClass, @Nullable T defaultValue) {
        if (tClass == null) {
            return defaultValue;
        }

        byte[] bytes = decodeBytes(nativeHandle, key);
        if (bytes == null) {
            return defaultValue;
        }

        Parcel source = Parcel.obtain();
        source.unmarshall(bytes, 0, bytes.length);
        source.setDataPosition(0);

        try {
            String name = tClass.toString();
            Parcelable.Creator<T> creator;
            synchronized (mCreators) {
                creator = (Parcelable.Creator<T>) mCreators.get(name);
                if (creator == null) {
                    Field f = tClass.getField("CREATOR");
                    creator = (Parcelable.Creator<T>) f.get(null);
                    if (creator != null) {
                        mCreators.put(name, creator);
                    }
                }
            }
            if (creator != null) {
                return creator.createFromParcel(source);
            } else {
                throw new Exception("Parcelable protocol requires a "
                        + "non-null static Parcelable.Creator object called "
                        + "CREATOR on class " + name);
            }
        } catch (Exception e) {
            simpleLog(MMKVLogLevel.LevelError, e.toString());
        } finally {
            source.recycle();
        }
        return defaultValue;
    }

    /**
     * Get the actual size consumption of the key's value.
     * Note: might be a little bigger than value's length.
     *
     * @param key The key of the value.
     */
    public int getValueSize(String key) {
        return valueSize(nativeHandle, key, false);
    }

    /**
     * Get the actual size of the key's value. String's length or byte[]'s length, etc.
     *
     * @param key The key of the value.
     */
    public int getValueActualSize(String key) {
        return valueSize(nativeHandle, key, true);
    }

    /**
     * Check whether or not MMKV contains the key.
     *
     * @param key The key of the value.
     */
    public boolean containsKey(String key) {
        return containsKey(nativeHandle, key);
    }

    /**
     * @return All the keys.
     */
    @Nullable
    public String[] allKeys() {
        return allKeys(nativeHandle, false);
    }

    /**
     * @return All non-expired keys. Note that this call has costs.
     */
    @Nullable
    public String[] allNonExpireKeys() {
        return allKeys(nativeHandle, true);
    }

    /**
     * @return The total count of all the keys.
     */
    public long count() {
        return count(nativeHandle, false);
    }

    /**
     * @return The total count of all non-expired keys. Note that this call has costs.
     */
    public long countNonExpiredKeys() {
        return count(nativeHandle, true);
    }

    /**
     * Get the size of the underlying file. Align to the disk block size, typically 4K for an Android device.
     */
    public long totalSize() {
        return totalSize(nativeHandle);
    }

    /**
     * Get the actual used size of the MMKV instance.
     * This size might increase and decrease as MMKV doing insertion and full write back.
     */
    public long actualSize() {
        return actualSize(nativeHandle);
    }

    public void removeValueForKey(String key) {
        removeValueForKey(nativeHandle, key);
    }

    /**
     * Batch remove some keys from the MMKV instance.
     *
     * @param arrKeys The keys to be removed.
     */
    public native void removeValuesForKeys(String[] arrKeys);

    /**
     * Clear all the key-values inside the MMKV instance.
     * The data file will be trimmed down to `pageSize`, and some sync operations will be called
     * If you do not want to trim the file, use {@link #clearAllWithKeepingSpace()} instead for better performance
     */
    public native void clearAll();

    /**
     * Faster {@link #clearAll()} implementation
     * The file size is kept as previous for later use
     */
    public native void clearAllWithKeepingSpace();

    /**
     * The {@link #totalSize()} of an MMKV instance won't reduce after deleting key-values,
     * call this method after lots of deleting if you care about disk usage.
     * Note that {@link #clearAll()}  has a similar effect.
     */
    public native void trim();

    /**
     * import all key-value items from src
     * @return count of items imported
     */
    public long importFrom(MMKV src) {
        return importFrom(nativeHandle, src.nativeHandle);
    }

    /**
     * Call this method if the MMKV instance is no longer needed in the near future.
     * Any subsequent call to any MMKV instances with the same ID is undefined behavior.
     */
    public native void close();

    /**
     * Clear memory cache of the MMKV instance.
     * You can call it on memory warning.
     * Any subsequent call to the MMKV instance will trigger all key-values loading from the file again.
     */
    public native void clearMemoryCache();

    /**
     * Save all mmap memory to file synchronously.
     * You don't need to call this, really, I mean it.
     * Unless you worry about the device running out of battery.
     */
    public void sync() {
        sync(true);
    }

    /**
     * Save all mmap memory to file asynchronously.
     * No need to call this unless you worry about the device running out of battery.
     */
    public void async() {
        sync(false);
    }

    private native void sync(boolean sync);

    /**
     * Check whether the MMKV file is valid or not.
     * Note: Don't use this to check the existence of the instance, the result is undefined on nonexistent files.
     */
    public static boolean isFileValid(String mmapID) {
        return isFileValid(mmapID, null);
    }

    /**
     * Check whether the MMKV file is valid or not on customize folder.
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     */
    public static native boolean isFileValid(String mmapID, @Nullable String rootPath);

    /**
     * remove the storage of the MMKV, including the data file & meta file (.crc)
     * Note: the existing instance (if any) will be closed & destroyed
     *
     * @param mmapID   The unique ID of the MMKV instance.
     */
    public static boolean removeStorage(String mmapID) {
        return removeStorage(mmapID, null);
    }

    /**
     * remove the storage of the MMKV, including the data file & meta file (.crc)
     * Note: the existing instance (if any) will be closed & destroyed
     *
     * @param mmapID   The unique ID of the MMKV instance.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     */
    public static native boolean removeStorage(String mmapID, @Nullable String rootPath);

    /**
     * check existence of the MMKV file
     * @param mmapID   The unique ID of the MMKV instance.
     */
    public static boolean checkExist(String mmapID) {
        return checkExist(mmapID, null);
    }

    /**
     * check existence of the MMKV file
     * @param mmapID   The unique ID of the MMKV instance.
     * @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv.
     */
    public static native boolean checkExist(String mmapID, @Nullable String rootPath);

    /**
     * Atomically migrate all key-values from an existent SharedPreferences to the MMKV instance.
     *
     * @param preferences The SharedPreferences to import from.
     * @return The total count of key-values imported.
     */
    @SuppressWarnings("unchecked")
    public int importFromSharedPreferences(@NonNull SharedPreferences preferences) {
        Map<String, ?> kvs = preferences.getAll();
        if (kvs == null || kvs.size() <= 0) {
            return 0;
        }

        for (Map.Entry<String, ?> entry : kvs.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key == null || value == null) {
                continue;
            }

            if (value instanceof Boolean) {
                encodeBool(nativeHandle, key, (boolean) value);
            } else if (value instanceof Integer) {
                encodeInt(nativeHandle, key, (int) value);
            } else if (value instanceof Long) {
                encodeLong(nativeHandle, key, (long) value);
            } else if (value instanceof Float) {
                encodeFloat(nativeHandle, key, (float) value);
            } else if (value instanceof Double) {
                encodeDouble(nativeHandle, key, (double) value);
            } else if (value instanceof String) {
                encodeString(nativeHandle, key, (String) value);
            } else if (value instanceof Set) {
                encode(key, (Set<String>) value);
            } else {
                simpleLog(MMKVLogLevel.LevelError, "unknown type: " + value.getClass());
            }
        }
        return kvs.size();
    }

    /**
     * backup one MMKV instance to dstDir
     *
     * @param mmapID   the MMKV ID to backup
     * @param rootPath the customize root path of the MMKV, if null then backup from the root dir of MMKV
     * @param dstDir   the backup destination directory
     */
    public static native boolean backupOneToDirectory(String mmapID, String dstDir, @Nullable String rootPath);

    /**
     * restore one MMKV instance from srcDir
     *
     * @param mmapID   the MMKV ID to restore
     * @param srcDir   the restore source directory
     * @param rootPath the customize root path of the MMKV, if null then restore to the root dir of MMKV
     */
    public static native boolean restoreOneMMKVFromDirectory(String mmapID, String srcDir, @Nullable String rootPath);

    /**
     * backup all MMKV instance from default root dir to dstDir
     *
     * @param dstDir the backup destination directory
     * @return count of MMKV successfully backuped
     */
    public static native long backupAllToDirectory(String dstDir);

    /**
     * restore all MMKV instance from srcDir to default root dir
     *
     * @param srcDir the restore source directory
     * @return count of MMKV successfully restored
     */
    public static native long restoreAllFromDirectory(String srcDir);

    // TODO: we can't have these functionality because we can't know for sure
    //  that each instance inside NameSpace has been upgraded successfully or not.
    //  The workaround is to manually call backup/restore on each instance of NameSpace.
//    /**
//     * backup all MMKV instance from srcDir to dstDir
//     *
//     * @param dstDir the backup destination directory
//     * @param srcDir the backup source directory
//     * @return count of MMKV successfully backuped
//     */
//    public static native long backupAllToDirectory(String dstDir, String srcDir);
//
//    /**
//     * restore all MMKV instance from srcDir to dstDir
//     *
//     * @param srcDir the restore source directory
//     * @param dstDir the restore destination directory
//     * @return count of MMKV successfully restored
//     */
//    public static native long restoreAllFromDirectory(String srcDir, String dstDir);

    public static final int ExpireNever = 0;
    public static final int ExpireInMinute = 60;
    public static final int ExpireInHour = 60 * 60;
    public static final int ExpireInDay = 24 * 60 * 60;
    public static final int ExpireInMonth = 30 * 24 * 60 * 60;
    public static final int ExpireInYear = 365 * 30 * 24 * 60 * 60;

    /**
     * Enable auto key expiration. This is a upgrade operation, the file format will change.
     * And the file won't be accessed correctly by older version (v1.2.16) of MMKV.
     * NOTICE: enableCompareBeforeSet will be invalid when Expiration is on
     * @param expireDurationInSecond the expire duration for all keys, {@link #ExpireNever} (0) means no default duration (aka each key will have it's own expire date)
     */
    public native boolean enableAutoKeyExpire(int expireDurationInSecond);

    /**
     * Disable auto key expiration. This is a downgrade operation.
     */
    public native boolean disableAutoKeyExpire();

    /**
     * Enable data compare before set, for better performance.
     * If data for key seldom changes, use it.
     * When encryption or expiration is on, compare-before-set will be invalid.
     * For encryption, compare operation must decrypt data which is time consuming.
     * For expiration, compare is useless because in most cases the expiration time changes every time.
     */
    public void enableCompareBeforeSet() {
        if (isExpirationEnabled()) {
            Log.e("MMKV", "enableCompareBeforeSet is invalid when Expiration is on");
            if (BuildConfig.DEBUG) {
                throw new RuntimeException("enableCompareBeforeSet is invalid when Expiration is on");
            }
        }
        if (isEncryptionEnabled()) {
            Log.e("MMKV", "enableCompareBeforeSet is invalid when key encryption is on");
            if (BuildConfig.DEBUG) {
                throw new RuntimeException("enableCompareBeforeSet is invalid when Expiration is on");
            }
        }
        nativeEnableCompareBeforeSet();
    }

    @FastNative
    private native void nativeEnableCompareBeforeSet();

    /**
     * Disable data compare before set
     * disabled at default
     */
    public native void disableCompareBeforeSet();

    /**
     * Intentionally Not Supported. Because MMKV does type-eraser inside to get better performance.
     */
    @Override
    public Map<String, ?> getAll() {
        throw new UnsupportedOperationException(
                "Intentionally Not Supported. Use allKeys() instead, getAll() not implement because type-erasure inside mmkv");
    }

    @Nullable
    @Override
    public String getString(String key, @Nullable String defValue) {
        return decodeString(nativeHandle, key, defValue);
    }

    @Override
    public Editor putString(String key, @Nullable String value) {
        encodeString(nativeHandle, key, value);
        return this;
    }

    public Editor putString(String key, @Nullable String value, int expireDurationInSecond) {
        encodeString_2(nativeHandle, key, value, expireDurationInSecond);
        return this;
    }

    @Nullable
    @Override
    public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
        return decodeStringSet(key, defValues);
    }

    @Override
    public Editor putStringSet(String key, @Nullable Set<String> values) {
        encode(key, values);
        return this;
    }

    public Editor putStringSet(String key, @Nullable Set<String> values, int expireDurationInSecond) {
        encode(key, values, expireDurationInSecond);
        return this;
    }

    public Editor putBytes(String key, @Nullable byte[] bytes) {
        encode(key, bytes);
        return this;
    }

    public Editor putBytes(String key, @Nullable byte[] bytes, int expireDurationInSecond) {
        encode(key, bytes, expireDurationInSecond);
        return this;
    }

    public byte[] getBytes(String key, @Nullable byte[] defValue) {
        return decodeBytes(key, defValue);
    }

    @Override
    public int getInt(String key, int defValue) {
        return decodeInt(nativeHandle, key, defValue);
    }

    @Override
    public Editor putInt(String key, int value) {
        encodeInt(nativeHandle, key, value);
        return this;
    }

    public Editor putInt(String key, int value, int expireDurationInSecond) {
        encodeInt_2(nativeHandle, key, value, expireDurationInSecond);
        return this;
    }

    @Override
    public long getLong(String key, long defValue) {
        return decodeLong(nativeHandle, key, defValue);
    }

    @Override
    public Editor putLong(String key, long value) {
        encodeLong(nativeHandle, key, value);
        return this;
    }

    public Editor putLong(String key, long value, int expireDurationInSecond) {
        encodeLong_2(nativeHandle, key, value, expireDurationInSecond);
        return this;
    }

    @Override
    public float getFloat(String key, float defValue) {
        return decodeFloat(nativeHandle, key, defValue);
    }

    @Override
    public Editor putFloat(String key, float value) {
        encodeFloat(nativeHandle, key, value);
        return this;
    }

    public Editor putFloat(String key, float value, int expireDurationInSecond) {
        encodeFloat_2(nativeHandle, key, value, expireDurationInSecond);
 
Download .txt
gitextract_t9qzaftc/

├── .clang-format
├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       └── bug_report.md
├── .gitignore
├── .gitmodules
├── Android/
│   └── MMKV/
│       ├── .gitignore
│       ├── build.gradle
│       ├── checkstyle.xml
│       ├── debug.keystore
│       ├── gradle/
│       │   ├── android-publish-private.gradle
│       │   ├── android-publish.gradle
│       │   ├── build_library.gradle
│       │   ├── check.gradle
│       │   └── wrapper/
│       │       ├── gradle-wrapper.jar
│       │       └── gradle-wrapper.properties
│       ├── gradle.properties
│       ├── gradlew
│       ├── gradlew.bat
│       ├── mmkv/
│       │   ├── .gitignore
│       │   ├── CMakeLists.txt
│       │   ├── build.gradle
│       │   ├── gradle.properties
│       │   ├── proguard-rules.pro
│       │   └── src/
│       │       ├── androidTest/
│       │       │   ├── AndroidManifest.xml
│       │       │   └── java/
│       │       │       └── com/
│       │       │           └── tencent/
│       │       │               └── mmkv/
│       │       │                   ├── MMKVTest.java
│       │       │                   └── MMKVTestService.java
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           ├── aidl/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkv/
│       │           │               └── ParcelableMMKV.aidl
│       │           ├── cpp/
│       │           │   ├── flutter-bridge.cpp
│       │           │   └── native-bridge.cpp
│       │           └── java/
│       │               └── com/
│       │                   └── tencent/
│       │                       └── mmkv/
│       │                           ├── MMKV.java
│       │                           ├── MMKVConfig.java
│       │                           ├── MMKVContentChangeNotification.java
│       │                           ├── MMKVContentProvider.java
│       │                           ├── MMKVHandler.java
│       │                           ├── MMKVLogLevel.java
│       │                           ├── MMKVProcessUtil.java
│       │                           ├── MMKVRecoverStrategic.java
│       │                           ├── NameSpace.java
│       │                           ├── NativeBuffer.java
│       │                           ├── ParcelableMMKV.java
│       │                           └── UnsupportedArchitectureException.java
│       ├── mmkvannotation/
│       │   ├── .gitignore
│       │   ├── build.gradle
│       │   └── src/
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           └── java/
│       │               └── dalvik/
│       │                   └── annotation/
│       │                       └── optimization/
│       │                           └── FastNative.java
│       ├── mmkvdemo/
│       │   ├── .gitignore
│       │   ├── build.gradle
│       │   ├── proguard-rules.pro
│       │   └── src/
│       │       └── main/
│       │           ├── AndroidManifest.xml
│       │           ├── aidl/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkvdemo/
│       │           │               └── IAshmemMMKV.aidl
│       │           ├── cpp/
│       │           │   ├── CMakeLists.txt
│       │           │   └── mmkvdemo.cpp
│       │           ├── java/
│       │           │   └── com/
│       │           │       └── tencent/
│       │           │           └── mmkvdemo/
│       │           │               ├── Baseline.java
│       │           │               ├── BenchMarkBaseService.java
│       │           │               ├── FakeInfo.java
│       │           │               ├── Info.java
│       │           │               ├── MainActivity.java
│       │           │               ├── MultiProcessSharedPreferences.java
│       │           │               ├── MyApplication.java
│       │           │               ├── MyService.java
│       │           │               ├── MyService_1.java
│       │           │               ├── SQLiteKV.java
│       │           │               └── TestParcelable.java
│       │           ├── kotlin/
│       │           │   └── KotlinUsecase.kt
│       │           └── res/
│       │               ├── drawable/
│       │               │   └── ic_launcher_background.xml
│       │               ├── drawable-v24/
│       │               │   └── ic_launcher_foreground.xml
│       │               ├── layout/
│       │               │   └── activity_main.xml
│       │               ├── mipmap-anydpi-v26/
│       │               │   ├── ic_launcher.xml
│       │               │   └── ic_launcher_round.xml
│       │               └── values/
│       │                   ├── colors.xml
│       │                   ├── strings.xml
│       │                   └── styles.xml
│       ├── pmd-ruleset.xml
│       ├── proguard-rules/
│       │   ├── proguard-rules-android-lib.pro
│       │   └── proguard-rules-test.pro
│       └── settings.gradle
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Core/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── CodedInputData.cpp
│   ├── CodedInputData.h
│   ├── CodedInputDataCrypt.cpp
│   ├── CodedInputDataCrypt.h
│   ├── CodedInputDataCrypt_OSX.cpp
│   ├── CodedInputData_OSX.cpp
│   ├── CodedOutputData.cpp
│   ├── CodedOutputData.h
│   ├── Core.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           ├── Core.xcscheme
│   │           └── MMKVWatchCore.xcscheme
│   ├── InterProcessLock.cpp
│   ├── InterProcessLock.h
│   ├── InterProcessLock_Android.cpp
│   ├── InterProcessLock_Win32.cpp
│   ├── KeyValueHolder.cpp
│   ├── KeyValueHolder.h
│   ├── MMBuffer.cpp
│   ├── MMBuffer.h
│   ├── MMKV.cpp
│   ├── MMKV.h
│   ├── MMKVHandler.h
│   ├── MMKVLog.cpp
│   ├── MMKVLog.h
│   ├── MMKVLog_Android.cpp
│   ├── MMKVMetaInfo.hpp
│   ├── MMKVPredef.h
│   ├── MMKV_Android.cpp
│   ├── MMKV_IO.cpp
│   ├── MMKV_IO.h
│   ├── MMKV_OSX.cpp
│   ├── MMKV_OSX.h
│   ├── MemoryFile.cpp
│   ├── MemoryFile.h
│   ├── MemoryFile_Android.cpp
│   ├── MemoryFile_Linux.cpp
│   ├── MemoryFile_OSX.cpp
│   ├── MemoryFile_Win32.cpp
│   ├── MiniPBCoder.cpp
│   ├── MiniPBCoder.h
│   ├── MiniPBCoder_OSX.cpp
│   ├── PBEncodeItem.hpp
│   ├── PBUtility.cpp
│   ├── PBUtility.h
│   ├── ScopedLock.hpp
│   ├── ThreadLock.cpp
│   ├── ThreadLock.h
│   ├── ThreadLock_Win32.cpp
│   ├── aes/
│   │   ├── AESCrypt.cpp
│   │   ├── AESCrypt.h
│   │   └── openssl/
│   │       ├── openssl_aes.h
│   │       ├── openssl_aes_core.cpp
│   │       ├── openssl_aes_locl.h
│   │       ├── openssl_aesv8-armx.S
│   │       ├── openssl_arm_arch.h
│   │       ├── openssl_cfb128.cpp
│   │       ├── openssl_md32_common.h
│   │       ├── openssl_md5.h
│   │       ├── openssl_md5_dgst.cpp
│   │       ├── openssl_md5_locl.h
│   │       ├── openssl_md5_one.cpp
│   │       └── openssl_opensslconf.h
│   ├── core.vcxproj
│   ├── core.vcxproj.filters
│   ├── crc32/
│   │   ├── CMakeLists.txt
│   │   ├── Checksum.h
│   │   ├── crc32_armv8.cpp
│   │   └── zlib/
│   │       ├── crc32.cpp
│   │       ├── crc32.h
│   │       ├── zconf.h
│   │       └── zutil.h
│   └── fakeinclude/
│       └── MMKVCore/
│           ├── MMBuffer.h
│           ├── MMKV.h
│           ├── MMKVHandler.h
│           ├── MMKVLog.h
│           ├── MMKVPredef.h
│           ├── MemoryFile.h
│           ├── MiniPBCoder.h
│           ├── ScopedLock.hpp
│           └── ThreadLock.h
├── Dockerfile
├── LICENSE.TXT
├── MMKV.podspec
├── MMKV.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcshareddata/
│       └── IDEWorkspaceChecks.plist
├── MMKVAppExtension.podspec
├── MMKVCore.podspec
├── MMKVWatchExtension.podspec
├── Makefile
├── OpenHarmony/
│   ├── .gitignore
│   ├── AppScope/
│   │   ├── app.json5
│   │   └── resources/
│   │       └── base/
│   │           └── element/
│   │               └── string.json
│   ├── MMKV/
│   │   ├── .gitignore
│   │   ├── BuildProfile.ets
│   │   ├── CHANGELOG.md
│   │   ├── Index.ets
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── build-profile.json5
│   │   ├── consumer-rules.txt
│   │   ├── example/
│   │   │   ├── Index.ets
│   │   │   └── Util.ets
│   │   ├── hvigorfile.ts
│   │   ├── obfuscation-rules.txt
│   │   ├── oh-package.json5
│   │   └── src/
│   │       └── main/
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── flutter-bridge.cpp
│   │           │   ├── native_bridge.cpp
│   │           │   └── types/
│   │           │       └── libmmkv/
│   │           │           ├── index.d.ts
│   │           │           └── oh-package.json5
│   │           ├── ets/
│   │           │   └── utils/
│   │           │       ├── MMKV.ets
│   │           │       ├── MMKVConfig.ets
│   │           │       ├── MMKVHandler.ets
│   │           │       ├── MMKVLogLevel.ets
│   │           │       ├── NativeBuffer.ets
│   │           │       └── Util.ts
│   │           └── module.json5
│   ├── build-profile.json5
│   ├── dependencies/
│   │   ├── hvigor-4.3.0.tgz
│   │   └── hvigor-ohos-plugin-4.3.0.tgz
│   ├── entry/
│   │   ├── .gitignore
│   │   ├── build-profile.json5
│   │   ├── hvigorfile.ts
│   │   ├── obfuscation-rules.txt
│   │   ├── oh-package.json5
│   │   └── src/
│   │       ├── main/
│   │       │   ├── cpp/
│   │       │   │   ├── CMakeLists.txt
│   │       │   │   ├── napi_init.cpp
│   │       │   │   └── types/
│   │       │   │       └── libentry/
│   │       │   │           ├── index.d.ts
│   │       │   │           └── oh-package.json5
│   │       │   ├── ets/
│   │       │   │   ├── Util/
│   │       │   │   │   ├── Baseline.ets
│   │       │   │   │   ├── MyMMKVHandler.ets
│   │       │   │   │   └── Util.ets
│   │       │   │   ├── entryability/
│   │       │   │   │   └── EntryAbility.ets
│   │       │   │   ├── pages/
│   │       │   │   │   └── Index.ets
│   │       │   │   └── process/
│   │       │   │       └── DemoProcess.ets
│   │       │   ├── module.json5
│   │       │   └── resources/
│   │       │       ├── base/
│   │       │       │   ├── element/
│   │       │       │   │   ├── color.json
│   │       │       │   │   └── string.json
│   │       │       │   ├── media/
│   │       │       │   │   └── layered_image.json
│   │       │       │   └── profile/
│   │       │       │       └── main_pages.json
│   │       │       ├── en_US/
│   │       │       │   └── element/
│   │       │       │       └── string.json
│   │       │       └── zh_CN/
│   │       │           └── element/
│   │       │               └── string.json
│   │       ├── mock/
│   │       │   └── mock-config.json5
│   │       ├── ohosTest/
│   │       │   ├── ets/
│   │       │   │   ├── test/
│   │       │   │   │   ├── Ability.test.ets
│   │       │   │   │   └── List.test.ets
│   │       │   │   ├── testability/
│   │       │   │   │   ├── TestAbility.ets
│   │       │   │   │   └── pages/
│   │       │   │   │       └── Index.ets
│   │       │   │   └── testrunner/
│   │       │   │       └── OpenHarmonyTestRunner.ets
│   │       │   ├── module.json5
│   │       │   └── resources/
│   │       │       └── base/
│   │       │           ├── element/
│   │       │           │   ├── color.json
│   │       │           │   └── string.json
│   │       │           └── profile/
│   │       │               └── test_pages.json
│   │       └── test/
│   │           ├── List.test.ets
│   │           └── LocalUnit.test.ets
│   ├── hvigor/
│   │   └── hvigor-config.json5
│   ├── hvigorfile.ts
│   └── oh-package.json5
├── POSIX/
│   ├── CMakeLists.txt
│   ├── demo/
│   │   ├── CMakeLists.txt
│   │   ├── TestInterProcessLock.cpp
│   │   ├── UnitTest.cpp
│   │   ├── demo.cpp
│   │   └── process.cpp
│   ├── golang/
│   │   ├── .gitignore
│   │   ├── CMakeLists.txt
│   │   ├── callback.go
│   │   ├── go.mod
│   │   ├── golang-bridge.cpp
│   │   ├── golang-bridge.h
│   │   ├── mmkv.go
│   │   ├── mmkv_test.go
│   │   └── test/
│   │       ├── go.mod
│   │       └── main.go
│   └── src/
│       ├── CMakeLists.txt
│       └── libmmkv.cpp
├── Package.swift
├── Python/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── demo.py
│   ├── libmmkv_python.cpp
│   ├── setup.py
│   └── unit_test.py
├── README.md
├── README_CN.md
├── SECURITY.md
├── Script/
│   ├── dumpJavaSignature.py
│   └── formatCode.py
├── Win32/
│   ├── .clang-format
│   ├── Win32.sln
│   ├── Win32Demo/
│   │   ├── Win32Demo.cpp
│   │   ├── Win32Demo.vcxproj
│   │   ├── Win32Demo.vcxproj.filters
│   │   ├── pch.cpp
│   │   └── pch.h
│   └── Win32DemoProcess/
│       ├── Win32DemoProcess.cpp
│       ├── Win32DemoProcess.vcxproj
│       ├── Win32DemoProcess.vcxproj.filters
│       ├── pch.cpp
│       └── pch.h
├── flutter/
│   ├── .gitignore
│   ├── .metadata
│   ├── .vscode/
│   │   ├── launch.json
│   │   └── settings.json
│   ├── mmkv/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── example/
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── android/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── app/
│   │   │   │   │   ├── build.gradle
│   │   │   │   │   └── src/
│   │   │   │   │       ├── main/
│   │   │   │   │       │   ├── AndroidManifest.xml
│   │   │   │   │       │   ├── java/
│   │   │   │   │       │   │   └── com/
│   │   │   │   │       │   │       └── tencent/
│   │   │   │   │       │   │           └── mmkv_example/
│   │   │   │   │       │   │               └── MainActivity.java
│   │   │   │   │       │   └── res/
│   │   │   │   │       │       ├── drawable/
│   │   │   │   │       │       │   └── launch_background.xml
│   │   │   │   │       │       └── values/
│   │   │   │   │       │           └── styles.xml
│   │   │   │   │       └── profile/
│   │   │   │   │           └── AndroidManifest.xml
│   │   │   │   ├── build.gradle
│   │   │   │   ├── gradle/
│   │   │   │   │   └── wrapper/
│   │   │   │   │       └── gradle-wrapper.properties
│   │   │   │   ├── gradle.properties
│   │   │   │   ├── settings.gradle
│   │   │   │   └── settings_aar.gradle
│   │   │   ├── ios/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Flutter/
│   │   │   │   │   ├── AppFrameworkInfo.plist
│   │   │   │   │   ├── Debug.xcconfig
│   │   │   │   │   ├── Release.xcconfig
│   │   │   │   │   └── ephemeral/
│   │   │   │   │       ├── flutter_lldb_helper.py
│   │   │   │   │       └── flutter_lldbinit
│   │   │   │   ├── Podfile
│   │   │   │   ├── Runner/
│   │   │   │   │   ├── AppDelegate.h
│   │   │   │   │   ├── AppDelegate.m
│   │   │   │   │   ├── Assets.xcassets/
│   │   │   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   │   │   └── Contents.json
│   │   │   │   │   │   └── LaunchImage.imageset/
│   │   │   │   │   │       ├── Contents.json
│   │   │   │   │   │       └── README.md
│   │   │   │   │   ├── Base.lproj/
│   │   │   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   │   │   └── Main.storyboard
│   │   │   │   │   ├── Info.plist
│   │   │   │   │   ├── Runner.entitlements
│   │   │   │   │   └── main.m
│   │   │   │   ├── Runner.xcodeproj/
│   │   │   │   │   ├── project.pbxproj
│   │   │   │   │   ├── project.xcworkspace/
│   │   │   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   │   │   └── xcshareddata/
│   │   │   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       └── xcschemes/
│   │   │   │   │           └── Runner.xcscheme
│   │   │   │   └── Runner.xcworkspace/
│   │   │   │       ├── contents.xcworkspacedata
│   │   │   │       └── xcshareddata/
│   │   │   │           ├── IDEWorkspaceChecks.plist
│   │   │   │           └── WorkspaceSettings.xcsettings
│   │   │   ├── lib/
│   │   │   │   └── main.dart
│   │   │   ├── linux/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── CMakeLists.txt
│   │   │   │   ├── flutter/
│   │   │   │   │   ├── CMakeLists.txt
│   │   │   │   │   ├── generated_plugin_registrant.cc
│   │   │   │   │   ├── generated_plugin_registrant.h
│   │   │   │   │   └── generated_plugins.cmake
│   │   │   │   └── runner/
│   │   │   │       ├── CMakeLists.txt
│   │   │   │       ├── main.cc
│   │   │   │       ├── my_application.cc
│   │   │   │       └── my_application.h
│   │   │   ├── macos/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── Flutter/
│   │   │   │   │   ├── Flutter-Debug.xcconfig
│   │   │   │   │   ├── Flutter-Release.xcconfig
│   │   │   │   │   └── GeneratedPluginRegistrant.swift
│   │   │   │   ├── Podfile
│   │   │   │   ├── Runner/
│   │   │   │   │   ├── AppDelegate.swift
│   │   │   │   │   ├── Assets.xcassets/
│   │   │   │   │   │   └── AppIcon.appiconset/
│   │   │   │   │   │       └── Contents.json
│   │   │   │   │   ├── Base.lproj/
│   │   │   │   │   │   └── MainMenu.xib
│   │   │   │   │   ├── Configs/
│   │   │   │   │   │   ├── AppInfo.xcconfig
│   │   │   │   │   │   ├── Debug.xcconfig
│   │   │   │   │   │   ├── Release.xcconfig
│   │   │   │   │   │   └── Warnings.xcconfig
│   │   │   │   │   ├── DebugProfile.entitlements
│   │   │   │   │   ├── Info.plist
│   │   │   │   │   ├── MainFlutterWindow.swift
│   │   │   │   │   └── Release.entitlements
│   │   │   │   ├── Runner.xcodeproj/
│   │   │   │   │   ├── project.pbxproj
│   │   │   │   │   ├── project.xcworkspace/
│   │   │   │   │   │   └── xcshareddata/
│   │   │   │   │   │       └── IDEWorkspaceChecks.plist
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       └── xcschemes/
│   │   │   │   │           └── Runner.xcscheme
│   │   │   │   ├── Runner.xcworkspace/
│   │   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   │   └── xcshareddata/
│   │   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   │   └── RunnerTests/
│   │   │   │       └── RunnerTests.swift
│   │   │   ├── ohos/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── AppScope/
│   │   │   │   │   ├── app.json5
│   │   │   │   │   └── resources/
│   │   │   │   │       └── base/
│   │   │   │   │           └── element/
│   │   │   │   │               └── string.json
│   │   │   │   ├── build-profile.json5
│   │   │   │   ├── entry/
│   │   │   │   │   ├── .gitignore
│   │   │   │   │   ├── build-profile.json5
│   │   │   │   │   ├── hvigorfile.ts
│   │   │   │   │   ├── oh-package.json5
│   │   │   │   │   └── src/
│   │   │   │   │       ├── main/
│   │   │   │   │       │   ├── ets/
│   │   │   │   │       │   │   ├── entryability/
│   │   │   │   │       │   │   │   └── EntryAbility.ets
│   │   │   │   │       │   │   ├── pages/
│   │   │   │   │       │   │   │   └── Index.ets
│   │   │   │   │       │   │   └── plugins/
│   │   │   │   │       │   │       └── GeneratedPluginRegistrant.ets
│   │   │   │   │       │   ├── module.json5
│   │   │   │   │       │   └── resources/
│   │   │   │   │       │       ├── base/
│   │   │   │   │       │       │   ├── element/
│   │   │   │   │       │       │   │   ├── color.json
│   │   │   │   │       │       │   │   └── string.json
│   │   │   │   │       │       │   └── profile/
│   │   │   │   │       │       │       └── main_pages.json
│   │   │   │   │       │       ├── en_US/
│   │   │   │   │       │       │   └── element/
│   │   │   │   │       │       │       └── string.json
│   │   │   │   │       │       └── zh_CN/
│   │   │   │   │       │           └── element/
│   │   │   │   │       │               └── string.json
│   │   │   │   │       └── ohosTest/
│   │   │   │   │           ├── ets/
│   │   │   │   │           │   ├── test/
│   │   │   │   │           │   │   ├── Ability.test.ets
│   │   │   │   │           │   │   └── List.test.ets
│   │   │   │   │           │   ├── testability/
│   │   │   │   │           │   │   ├── TestAbility.ets
│   │   │   │   │           │   │   └── pages/
│   │   │   │   │           │   │       └── Index.ets
│   │   │   │   │           │   └── testrunner/
│   │   │   │   │           │       └── OpenHarmonyTestRunner.ts
│   │   │   │   │           ├── module.json5
│   │   │   │   │           └── resources/
│   │   │   │   │               └── base/
│   │   │   │   │                   ├── element/
│   │   │   │   │                   │   ├── color.json
│   │   │   │   │                   │   └── string.json
│   │   │   │   │                   └── profile/
│   │   │   │   │                       └── test_pages.json
│   │   │   │   ├── hvigor/
│   │   │   │   │   └── hvigor-config.json5
│   │   │   │   ├── hvigorfile.ts
│   │   │   │   └── oh-package.json5
│   │   │   ├── pubspec.yaml
│   │   │   └── windows/
│   │   │       ├── .gitignore
│   │   │       ├── CMakeLists.txt
│   │   │       ├── flutter/
│   │   │       │   ├── CMakeLists.txt
│   │   │       │   ├── generated_plugin_registrant.cc
│   │   │       │   ├── generated_plugin_registrant.h
│   │   │       │   └── generated_plugins.cmake
│   │   │       └── runner/
│   │   │           ├── CMakeLists.txt
│   │   │           ├── Runner.rc
│   │   │           ├── flutter_window.cpp
│   │   │           ├── flutter_window.h
│   │   │           ├── main.cpp
│   │   │           ├── resource.h
│   │   │           ├── runner.exe.manifest
│   │   │           ├── utils.cpp
│   │   │           ├── utils.h
│   │   │           ├── win32_window.cpp
│   │   │           └── win32_window.h
│   │   ├── lib/
│   │   │   └── mmkv.dart
│   │   ├── mmkv.iml
│   │   ├── pubspec.yaml
│   │   ├── test/
│   │   │   └── mmkv_test.dart
│   │   └── tool/
│   │       ├── fix_mmkv_plugin_name.rb
│   │       └── mmkvpodhelper.rb
│   ├── mmkv.iml
│   ├── mmkv_android/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── android/
│   │   │   ├── .gitignore
│   │   │   ├── build.gradle
│   │   │   ├── gradle/
│   │   │   │   └── wrapper/
│   │   │   │       ├── gradle-wrapper.jar
│   │   │   │       └── gradle-wrapper.properties
│   │   │   ├── gradle.properties
│   │   │   ├── gradlew
│   │   │   ├── gradlew.bat
│   │   │   ├── settings.gradle
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           └── java/
│   │   │               └── com/
│   │   │                   └── tencent/
│   │   │                       └── mmkv/
│   │   │                           └── MMKVPlugin.java
│   │   ├── lib/
│   │   │   └── mmkv_android.dart
│   │   └── pubspec.yaml
│   ├── mmkv_ios/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── darwin/
│   │   │   ├── .gitignore
│   │   │   ├── Classes/
│   │   │   │   ├── MMKVPlugin.h
│   │   │   │   ├── MMKVPlugin.mm
│   │   │   │   ├── flutter-bridge.h
│   │   │   │   └── flutter-bridge.mm
│   │   │   └── mmkv_ios.podspec
│   │   ├── lib/
│   │   │   └── mmkv_ios.dart
│   │   └── pubspec.yaml
│   ├── mmkv_linux/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── lib/
│   │   │   └── mmkv_linux.dart
│   │   ├── linux/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── flutter-bridge.cpp
│   │   │   ├── include/
│   │   │   │   └── mmkv_linux/
│   │   │   │       └── mmkv_linux_plugin.h
│   │   │   └── mmkv_linux_plugin.cc
│   │   └── pubspec.yaml
│   ├── mmkv_ohos/
│   │   ├── .gitignore
│   │   ├── .metadata
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── analysis_options.yaml
│   │   ├── lib/
│   │   │   └── mmkv_ohos.dart
│   │   ├── ohos/
│   │   │   ├── .gitignore
│   │   │   ├── build-profile.json5
│   │   │   ├── hvigorfile.ts
│   │   │   ├── index.ets
│   │   │   ├── oh-package.json5
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── ets/
│   │   │           │   └── components/
│   │   │           │       └── plugin/
│   │   │           │           └── MMKVPlugin.ets
│   │   │           └── module.json5
│   │   └── pubspec.yaml
│   ├── mmkv_platform_interface/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── mmkv_platform_ffi.dart
│   │   │   └── mmkv_platform_interface.dart
│   │   └── pubspec.yaml
│   └── mmkv_win32/
│       ├── .gitignore
│       ├── .metadata
│       ├── CHANGELOG.md
│       ├── LICENSE
│       ├── README.md
│       ├── analysis_options.yaml
│       ├── lib/
│       │   └── mmkv_win32.dart
│       └── pubspec.yaml
└── iOS/
    ├── MMKV/
    │   ├── MMKV/
    │   │   ├── AutoCleanInfo.hpp
    │   │   ├── MMKV.h
    │   │   ├── MMKVAppExtension/
    │   │   │   ├── include/
    │   │   │   │   └── MMKVAppExtension/
    │   │   │   │       └── MMKV.h
    │   │   │   └── libMMKV.mm
    │   │   ├── MMKVHandler.h
    │   │   ├── Resources/
    │   │   │   ├── Info.plist
    │   │   │   └── PrivacyInfo.xcprivacy
    │   │   ├── fakeinclude/
    │   │   │   └── MMKV/
    │   │   │       └── MMKV.h
    │   │   └── libMMKV.mm
    │   └── MMKV.xcodeproj/
    │       ├── project.pbxproj
    │       ├── project.xcworkspace/
    │       │   ├── contents.xcworkspacedata
    │       │   └── xcshareddata/
    │       │       └── IDEWorkspaceChecks.plist
    │       └── xcshareddata/
    │           └── xcschemes/
    │               ├── MMKV For App Extension.xcscheme
    │               ├── MMKV Static.xcscheme
    │               ├── MMKV.xcscheme
    │               └── MMKVWatchExtension.xcscheme
    └── MMKVDemo/
        ├── Config.xcconfig
        ├── MMKVCatalystDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── Assets.xcassets/
        │   │   ├── AccentColor.colorset/
        │   │   │   └── Contents.json
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   ├── LaunchScreen.storyboard
        │   │   └── Main.storyboard
        │   ├── Info.plist
        │   ├── MMKVCatalystDemo.entitlements
        │   ├── SceneDelegate.h
        │   ├── SceneDelegate.m
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── DemoSwiftUsage.swift
        │   ├── MMKVDemo-Bridging-Header.h
        │   ├── Resources/
        │   │   ├── Assets.xcassets/
        │   │   │   └── AppIcon.appiconset/
        │   │   │       └── Contents.json
        │   │   ├── Base.lproj/
        │   │   │   ├── LaunchScreen.storyboard
        │   │   │   └── Main.storyboard
        │   │   ├── Info.plist
        │   │   ├── MMKVDemo.entitlements
        │   │   ├── testReadOnly
        │   │   └── testReadOnly.crc
        │   ├── TestMMKVCpp.cpp
        │   ├── TestMMKVCpp.hpp
        │   ├── ViewController+TestCaseBad.h
        │   ├── ViewController+TestCaseBad.mm
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVDemo.xcodeproj/
        │   ├── project.pbxproj
        │   ├── project.xcworkspace/
        │   │   ├── contents.xcworkspacedata
        │   │   └── xcshareddata/
        │   │       ├── IDEWorkspaceChecks.plist
        │   │       └── WorkspaceSettings.xcsettings
        │   └── xcshareddata/
        │       └── xcschemes/
        │           ├── MMKVDemo.xcscheme
        │           ├── MMKVMacDemo.xcscheme
        │           ├── MMKVTodayExtensionDemo.xcscheme
        │           ├── WatchApp (Notification).xcscheme
        │           ├── WatchApp.xcscheme
        │           └── kvdemo.xcscheme
        ├── MMKVDemoTests/
        │   ├── Info.plist
        │   ├── MMKVDemoTests.mm
        │   └── MMKVPerformanceTest.mm
        ├── MMKVMacDemo/
        │   ├── AppDelegate.h
        │   ├── AppDelegate.m
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   └── Main.storyboard
        │   ├── Info.plist
        │   ├── MMKVMacDemo.entitlements
        │   ├── ViewController.h
        │   ├── ViewController.mm
        │   └── main.m
        ├── MMKVTodayExtensionDemo/
        │   ├── Base.lproj/
        │   │   └── MainInterface.storyboard
        │   ├── Info.plist
        │   ├── MMKVTodayExtensionDemo.entitlements
        │   ├── TodayViewController.h
        │   └── TodayViewController.m
        ├── MMKVVisionDemo/
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.solidimagestack/
        │   │   │   ├── Back.solidimagestacklayer/
        │   │   │   │   ├── Content.imageset/
        │   │   │   │   │   └── Contents.json
        │   │   │   │   └── Contents.json
        │   │   │   ├── Contents.json
        │   │   │   ├── Front.solidimagestacklayer/
        │   │   │   │   ├── Content.imageset/
        │   │   │   │   │   └── Contents.json
        │   │   │   │   └── Contents.json
        │   │   │   └── Middle.solidimagestacklayer/
        │   │   │       ├── Content.imageset/
        │   │   │       │   └── Contents.json
        │   │   │       └── Contents.json
        │   │   └── Contents.json
        │   ├── ContentView.swift
        │   ├── Info.plist
        │   ├── MMKVVisionDemoApp.swift
        │   └── Preview Content/
        │       └── Preview Assets.xcassets/
        │           └── Contents.json
        ├── WatchApp/
        │   ├── Assets.xcassets/
        │   │   ├── AppIcon.appiconset/
        │   │   │   └── Contents.json
        │   │   └── Contents.json
        │   ├── Base.lproj/
        │   │   └── Interface.storyboard
        │   └── Info.plist
        ├── WatchApp Extension/
        │   ├── Assets.xcassets/
        │   │   ├── Complication.complicationset/
        │   │   │   ├── Circular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Contents.json
        │   │   │   ├── Extra Large.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Bezel.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Circular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Corner.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Extra Large.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Graphic Large Rectangular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   ├── Modular.imageset/
        │   │   │   │   └── Contents.json
        │   │   │   └── Utilitarian.imageset/
        │   │   │       └── Contents.json
        │   │   └── Contents.json
        │   ├── ExtensionDelegate.h
        │   ├── ExtensionDelegate.mm
        │   ├── Info.plist
        │   ├── InterfaceController.h
        │   ├── InterfaceController.m
        │   ├── NotificationController.h
        │   ├── NotificationController.m
        │   └── PushNotificationPayload.apns
        └── kvdemo/
            ├── AppDelegate.h
            ├── AppDelegate.m
            ├── Assets.xcassets/
            │   ├── AccentColor.colorset/
            │   │   └── Contents.json
            │   ├── AppIcon.appiconset/
            │   │   └── Contents.json
            │   └── Contents.json
            ├── Base.lproj/
            │   ├── LaunchScreen.storyboard
            │   └── Main.storyboard
            ├── Info.plist
            ├── SceneDelegate.h
            ├── SceneDelegate.m
            ├── ViewController.h
            ├── ViewController.m
            ├── kvdemo.entitlements
            └── main.m
Download .txt
SYMBOL INDEX (1947 symbols across 137 files)

FILE: Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTest.java
  class MMKVTest (line 34) | public class MMKVTest {
    method setUp (line 40) | @BeforeClass
    method tearDown (line 48) | @AfterClass
    method testBool (line 53) | @Test
    method testInt (line 68) | @Test
    method testLong (line 83) | @Test
    method testFloat (line 98) | @Test
    method testDouble (line 113) | @Test
    method testString (line 128) | @Test
    method testStringSet (line 144) | @Test
    method testBytes (line 168) | @Test
    method testRemove (line 178) | @Test
    method testIPCUpdateInt (line 235) | @Test
    method testIPCLock (line 250) | @Test

FILE: Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTestService.java
  class MMKVTestService (line 29) | public class MMKVTestService extends Service {
    method onCreate (line 38) | @Override
    method onStartCommand (line 45) | @Override
    method onDestroy (line 67) | @Override
    method onBind (line 74) | @Nullable

FILE: Android/MMKV/mmkv/src/main/cpp/flutter-bridge.cpp
  type mmkv (line 33) | namespace mmkv {
  class FlutterMMKVHandler (line 47) | class FlutterMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 54) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 60) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 67) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 74) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 80) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function MMKV_EXPORT (line 89) | MMKV_EXPORT void *mmkvInitialize_v2(const char *rootDir, const char *cac...
  function MMKV_EXPORT (line 113) | MMKV_EXPORT void mmkvInitialize_v1(const char *rootDir, const char *cach...
  function MMKV_EXPORT (line 117) | MMKV_EXPORT void mmkvInitialize(const char *rootDir, int32_t logLevel) {
  function MMKV_EXPORT (line 121) | MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const ...
  function MMKV_EXPORT (line 185) | MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey, boo...
  function MMKV_EXPORT (line 218) | MMKV_EXPORT const char *mmapID(void *handle) {
  function MMKV_EXPORT (line 226) | MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) {
  function MMKV_EXPORT (line 235) | MMKV_EXPORT bool encodeBool_v2(void *handle, const char *oKey, bool valu...
  function MMKV_EXPORT (line 244) | MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool default...
  function MMKV_EXPORT (line 253) | MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t val...
  function MMKV_EXPORT (line 262) | MMKV_EXPORT bool encodeInt32_v2(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 271) | MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 280) | MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t val...
  function MMKV_EXPORT (line 289) | MMKV_EXPORT bool encodeInt64_v2(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 298) | MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 307) | MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double val...
  function MMKV_EXPORT (line 316) | MMKV_EXPORT bool encodeDouble_v2(void *handle, const char *oKey, double ...
  function MMKV_EXPORT (line 325) | MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double d...
  function MMKV_EXPORT (line 334) | MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValu...
  function MMKV_EXPORT (line 349) | MMKV_EXPORT bool encodeBytes_v2(void *handle, const char *oKey, void *oV...
  function MMKV_EXPORT (line 364) | MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *...
  function MMKV_EXPORT (line 396) | MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length, bool a...
  function MMKV_EXPORT (line 409) | MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) {
  function MMKV_EXPORT (line 425) | MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t l...
  function MMKV_EXPORT (line 439) | MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) {
  function MMKV_EXPORT (line 449) | MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *point...
  function MMKV_EXPORT (line 458) | MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t...
  function MMKV_EXPORT (line 487) | MMKV_EXPORT bool containsKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 496) | MMKV_EXPORT uint64_t count(void *handle, bool filterExpire) {
  function MMKV_EXPORT (line 504) | MMKV_EXPORT uint64_t totalSize(void *handle) {
  function MMKV_EXPORT (line 512) | MMKV_EXPORT uint64_t actualSize(void *handle) {
  function MMKV_EXPORT (line 520) | MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 528) | MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint...
  function MMKV_EXPORT (line 544) | MMKV_EXPORT void clearAll(void *handle, bool keepSpace) {
  function MMKV_EXPORT (line 551) | MMKV_EXPORT void mmkvSync(void *handle, bool sync) {
  function MMKV_EXPORT (line 558) | MMKV_EXPORT void clearMemoryCache(void *handle) {
  function MMKV_EXPORT (line 565) | MMKV_EXPORT int32_t pageSize() {
  function MMKV_EXPORT (line 569) | MMKV_EXPORT const char *version() {
  function MMKV_EXPORT (line 573) | MMKV_EXPORT void trim(void *handle) {
  function MMKV_EXPORT (line 580) | MMKV_EXPORT void mmkvClose(void *handle) {
  function MMKV_EXPORT (line 587) | MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) {
  function MMKV_EXPORT (line 591) | MMKV_EXPORT bool backupOne(const char *mmapID, const char *dstDir, const...
  function MMKV_EXPORT (line 601) | MMKV_EXPORT bool restoreOne(const char *mmapID, const char *srcDir, cons...
  function MMKV_EXPORT (line 611) | MMKV_EXPORT uint64_t backupAll(const char *dstDir/*, const char *rootPat...
  function MMKV_EXPORT (line 623) | MMKV_EXPORT uint64_t restoreAll(const char *srcDir/*, const char *rootPa...
  function MMKV_EXPORT (line 635) | MMKV_EXPORT bool enableAutoExpire(void *handle, uint32_t expireDuration) {
  function MMKV_EXPORT (line 643) | MMKV_EXPORT bool disableAutoExpire(void *handle) {
  function MMKV_EXPORT (line 651) | MMKV_EXPORT bool enableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 659) | MMKV_EXPORT bool disableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 667) | MMKV_EXPORT bool isFileValid(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 677) | MMKV_EXPORT bool removeStorage(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 687) | MMKV_EXPORT bool isMultiProcess(void *handle) {
  function MMKV_EXPORT (line 695) | MMKV_EXPORT bool isReadOnly(void *handle) {
  function MMKV_EXPORT (line 703) | MMKV_EXPORT void registerErrorHandler(ErrorCallback_t callback) {
  function MMKV_EXPORT (line 710) | MMKV_EXPORT void registerContentChangeNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 717) | MMKV_EXPORT void registerContentLoadedNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 724) | MMKV_EXPORT void checkContentChanged(void *handle) {
  function MMKV_EXPORT (line 731) | MMKV_EXPORT bool getNameSpace(const char *rootPath) {
  function MMKV_EXPORT (line 742) | MMKV_EXPORT bool checkExist(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 752) | MMKV_EXPORT size_t importFrom(void *handle, void *srcHandle) {

FILE: Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp
  type mmkv (line 50) | namespace mmkv {
    class JNIMMKVHandler (line 61) | class JNIMMKVHandler : public mmkv::MMKVHandler {
      method setLogRedirecting (line 66) | void setLogRedirecting(bool logRedirecting) { m_logRedirecting = log...
      method setHasCallback (line 67) | void setHasCallback(bool hasCallback) { m_hasCallback = hasCallback; }
      method setWantsContentChange (line 68) | void setWantsContentChange(bool wantsContentChange) { m_wantsContent...
      method isLogRedirecting (line 69) | bool isLogRedirecting() const { return m_logRedirecting; }
      method mmkvLog (line 71) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const c...
      method MMKVRecoverStrategic (line 81) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) o...
      method MMKVRecoverStrategic (line 95) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID...
      method onContentChangedByOuterProcess (line 109) | void onContentChangedByOuterProcess(const std::string &mmapID) overr...
      method onMMKVContentLoadSuccessfully (line 118) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) overri...
    function MMKV_JNI (line 213) | MMKV_JNI void jniInitialize(JNIEnv *env, jobject obj, jstring rootDir,...
    function MMKV_JNI (line 240) | MMKV_JNI void onExit(JNIEnv *env, jobject obj) {
    function MMKV (line 244) | static MMKV *getMMKV(JNIEnv *env, jobject obj) {
    function string (line 249) | static string jstring2string(JNIEnv *env, jstring str) {
    function jstring (line 261) | static jstring string2jstring(JNIEnv *env, const string &str) {
    function jarray2vector (line 265) | static vector<string> jarray2vector(JNIEnv *env, jobjectArray array) {
    function jobjectArray (line 281) | static jobjectArray vector2jarray(JNIEnv *env, const vector<string> &a...
    function JNIEnv (line 293) | static JNIEnv *getCurrentEnv() {
    function internalLogWithLevel (line 306) | void internalLogWithLevel(MMKVLogLevel level, const char *filename, co...
    function mmkvLog (line 335) | static void mmkvLog(MMKVLogLevel level, const char *file, int line, co...
    function androidLogWrapper (line 351) | static void androidLogWrapper(MMKVLogLevel level, const char *file, in...
    function MMKV_JNI (line 355) | MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jin...
    function MMKV_JNI (line 406) | MMKV_JNI jlong getDefaultMMKV(JNIEnv *env, jobject obj, jint mode, jst...
    function MMKV_JNI (line 439) | MMKV_JNI jlong getMMKVWithAshmemFD(JNIEnv *env, jobject obj, jstring m...
    function MMKV_JNI (line 460) | MMKV_JNI jstring mmapID(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 468) | MMKV_JNI jint ashmemFD(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 476) | MMKV_JNI jint ashmemMetaFD(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 484) | MMKV_JNI jboolean checkProcessMode(JNIEnv *env, jobject, jlong handle) {
    function MMKV_JNI (line 492) | MMKV_JNI jboolean encodeBool(JNIEnv *env, jobject, jlong handle, jstri...
    function MMKV_JNI (line 501) | MMKV_JNI jboolean encodeBool_2(JNIEnv *env, jobject, jlong handle, jst...
    function MMKV_JNI (line 510) | MMKV_JNI jboolean decodeBool(JNIEnv *env, jobject, jlong handle, jstri...
    function MMKV_JNI (line 519) | MMKV_JNI jboolean encodeInt(JNIEnv *env, jobject obj, jlong handle, js...
    function MMKV_JNI (line 528) | MMKV_JNI jboolean encodeInt_2(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 537) | MMKV_JNI jint decodeInt(JNIEnv *env, jobject obj, jlong handle, jstrin...
    function MMKV_JNI (line 546) | MMKV_JNI jboolean encodeLong(JNIEnv *env, jobject obj, jlong handle, j...
    function MMKV_JNI (line 555) | MMKV_JNI jboolean encodeLong_2(JNIEnv *env, jobject obj, jlong handle,...
    function MMKV_JNI (line 564) | MMKV_JNI jlong decodeLong(JNIEnv *env, jobject obj, jlong handle, jstr...
    function MMKV_JNI (line 573) | MMKV_JNI jboolean encodeFloat(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 582) | MMKV_JNI jboolean encodeFloat_2(JNIEnv *env, jobject obj, jlong handle...
    function MMKV_JNI (line 591) | MMKV_JNI jfloat decodeFloat(JNIEnv *env, jobject, jlong handle, jstrin...
    function MMKV_JNI (line 600) | MMKV_JNI jboolean encodeDouble(JNIEnv *env, jobject obj, jlong handle,...
    function MMKV_JNI (line 609) | MMKV_JNI jboolean encodeDouble_2(JNIEnv *env, jobject obj, jlong handl...
    function MMKV_JNI (line 618) | MMKV_JNI jdouble decodeDouble(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 627) | MMKV_JNI jboolean encodeString(JNIEnv *env, jobject, jlong handle, jst...
    function MMKV_JNI (line 642) | MMKV_JNI jboolean encodeString_2(JNIEnv *env, jobject, jlong handle, j...
    function MMKV_JNI (line 657) | MMKV_JNI jstring decodeString(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 670) | MMKV_JNI jboolean encodeBytes(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 695) | MMKV_JNI jboolean encodeBytes_2(JNIEnv *env, jobject, jlong handle, js...
    function MMKV_JNI (line 720) | MMKV_JNI jbyteArray decodeBytes(JNIEnv *env, jobject obj, jlong handle...
    function MMKV_JNI (line 735) | MMKV_JNI jobjectArray allKeys(JNIEnv *env, jobject instance, jlong han...
    function MMKV_JNI (line 744) | MMKV_JNI jboolean containsKey(JNIEnv *env, jobject instance, jlong han...
    function MMKV_JNI (line 753) | MMKV_JNI jlong count(JNIEnv *env, jobject instance, jlong handle, jboo...
    function MMKV_JNI (line 762) | MMKV_JNI jlong totalSize(JNIEnv *env, jobject instance, jlong handle) {
    function MMKV_JNI (line 771) | MMKV_JNI jlong actualSize(JNIEnv *env, jobject instance, jlong handle) {
    function MMKV_JNI (line 780) | MMKV_JNI void removeValueForKey(JNIEnv *env, jobject instance, jlong h...
    function MMKV_JNI (line 788) | MMKV_JNI void removeValuesForKeys(JNIEnv *env, jobject instance, jobje...
    function MMKV_JNI (line 798) | MMKV_JNI void clearAll(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 805) | MMKV_JNI void sync(JNIEnv *env, jobject instance, jboolean sync) {
    function MMKV_JNI (line 812) | MMKV_JNI jboolean isFileValid(JNIEnv *env, jclass type, jstring oMmapI...
    function MMKV_JNI (line 825) | MMKV_JNI jboolean removeStorage(JNIEnv *env, jclass type, jstring oMma...
    function MMKV_JNI (line 838) | MMKV_JNI jboolean encodeSet(JNIEnv *env, jobject, jlong handle, jstrin...
    function MMKV_JNI (line 853) | MMKV_JNI jboolean encodeSet_2(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 868) | MMKV_JNI jobjectArray decodeStringSet(JNIEnv *env, jobject, jlong hand...
    function MMKV_JNI (line 881) | MMKV_JNI void clearMemoryCache(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 888) | MMKV_JNI void lock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 895) | MMKV_JNI void unlock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 902) | MMKV_JNI jboolean tryLock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 910) | MMKV_JNI jint pageSize(JNIEnv *env, jclass type) {
    function MMKV_JNI (line 914) | MMKV_JNI jstring version(JNIEnv *env, jclass type) {
    function MMKV_JNI (line 920) | MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 931) | MMKV_JNI jboolean doReKey(JNIEnv *env, jobject instance, jstring crypt...
    function MMKV_JNI (line 943) | MMKV_JNI void doCheckReSetCryptKey(JNIEnv *env, jobject instance, jstr...
    function MMKV_JNI (line 961) | MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 967) | MMKV_JNI void trim(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 974) | MMKV_JNI void close(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 982) | MMKV_JNI jint valueSize(JNIEnv *env, jobject, jlong handle, jstring oK...
    function MMKV_JNI (line 991) | MMKV_JNI void setLogLevel(JNIEnv *env, jclass type, jint level) {
    function MMKV_JNI (line 995) | MMKV_JNI void setCallbackHandler(JNIEnv *env, jclass type, jboolean lo...
    function MMKV_JNI (line 1011) | MMKV_JNI jlong createNB(JNIEnv *env, jobject instance, jint size) {
    function MMKV_JNI (line 1020) | MMKV_JNI void destroyNB(JNIEnv *env, jobject instance, jlong pointer, ...
    function MMKV_JNI (line 1024) | MMKV_JNI jint writeValueToNB(JNIEnv *env, jobject instance, jlong hand...
    function MMKV_JNI (line 1033) | MMKV_JNI void setWantsContentChangeNotify(JNIEnv *env, jclass type, jb...
    function MMKV_JNI (line 1041) | MMKV_JNI void checkContentChanged(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1048) | MMKV_JNI jboolean backupOne(JNIEnv *env, jobject obj, jstring mmapID, ...
    function MMKV_JNI (line 1058) | MMKV_JNI jboolean restoreOne(JNIEnv *env, jobject obj, jstring mmapID,...
    function MMKV_JNI (line 1068) | MMKV_JNI jlong backupAll(JNIEnv *env, jobject obj, jstring dstDir/*, j...
    function MMKV_JNI (line 1080) | MMKV_JNI jlong restoreAll(JNIEnv *env, jobject obj, jstring srcDir/*, ...
    function MMKV_JNI (line 1092) | MMKV_JNI jboolean enableAutoExpire(JNIEnv *env, jobject instance, jint...
    function MMKV_JNI (line 1100) | MMKV_JNI jboolean disableAutoExpire(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1108) | MMKV_JNI void enableCompareBeforeSet(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1115) | MMKV_JNI void disableCompareBeforeSet(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1122) | MMKV_JNI bool isCompareBeforeSetEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1130) | MMKV_JNI bool isEncryptionEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1138) | MMKV_JNI bool isExpirationEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1146) | MMKV_JNI void clearAllWithKeepingSpace(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1153) | MMKV_JNI jboolean isMultiProcess(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1161) | MMKV_JNI jboolean isReadOnly(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1169) | MMKV_JNI jboolean getNameSpace(JNIEnv *env, jclass type, jstring rootP...
    function MMKV_JNI (line 1180) | MMKV_JNI jboolean checkExist(JNIEnv *env, jclass type, jstring oMmapID...
    function MMKV_JNI (line 1193) | MMKV_JNI void enableDisableProcessMode(JNIEnv *env, jclass type, jbool...
    function MMKV_JNI (line 1201) | MMKV_JNI jlong importFrom(JNIEnv *env, jobject instance, jlong handle,...
  function JNIEXPORT (line 137) | JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  type mmkv (line 209) | namespace mmkv {
    class JNIMMKVHandler (line 61) | class JNIMMKVHandler : public mmkv::MMKVHandler {
      method setLogRedirecting (line 66) | void setLogRedirecting(bool logRedirecting) { m_logRedirecting = log...
      method setHasCallback (line 67) | void setHasCallback(bool hasCallback) { m_hasCallback = hasCallback; }
      method setWantsContentChange (line 68) | void setWantsContentChange(bool wantsContentChange) { m_wantsContent...
      method isLogRedirecting (line 69) | bool isLogRedirecting() const { return m_logRedirecting; }
      method mmkvLog (line 71) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const c...
      method MMKVRecoverStrategic (line 81) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) o...
      method MMKVRecoverStrategic (line 95) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID...
      method onContentChangedByOuterProcess (line 109) | void onContentChangedByOuterProcess(const std::string &mmapID) overr...
      method onMMKVContentLoadSuccessfully (line 118) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) overri...
    function MMKV_JNI (line 213) | MMKV_JNI void jniInitialize(JNIEnv *env, jobject obj, jstring rootDir,...
    function MMKV_JNI (line 240) | MMKV_JNI void onExit(JNIEnv *env, jobject obj) {
    function MMKV (line 244) | static MMKV *getMMKV(JNIEnv *env, jobject obj) {
    function string (line 249) | static string jstring2string(JNIEnv *env, jstring str) {
    function jstring (line 261) | static jstring string2jstring(JNIEnv *env, const string &str) {
    function jarray2vector (line 265) | static vector<string> jarray2vector(JNIEnv *env, jobjectArray array) {
    function jobjectArray (line 281) | static jobjectArray vector2jarray(JNIEnv *env, const vector<string> &a...
    function JNIEnv (line 293) | static JNIEnv *getCurrentEnv() {
    function internalLogWithLevel (line 306) | void internalLogWithLevel(MMKVLogLevel level, const char *filename, co...
    function mmkvLog (line 335) | static void mmkvLog(MMKVLogLevel level, const char *file, int line, co...
    function androidLogWrapper (line 351) | static void androidLogWrapper(MMKVLogLevel level, const char *file, in...
    function MMKV_JNI (line 355) | MMKV_JNI jlong getMMKVWithID(JNIEnv *env, jobject, jstring mmapID, jin...
    function MMKV_JNI (line 406) | MMKV_JNI jlong getDefaultMMKV(JNIEnv *env, jobject obj, jint mode, jst...
    function MMKV_JNI (line 439) | MMKV_JNI jlong getMMKVWithAshmemFD(JNIEnv *env, jobject obj, jstring m...
    function MMKV_JNI (line 460) | MMKV_JNI jstring mmapID(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 468) | MMKV_JNI jint ashmemFD(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 476) | MMKV_JNI jint ashmemMetaFD(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 484) | MMKV_JNI jboolean checkProcessMode(JNIEnv *env, jobject, jlong handle) {
    function MMKV_JNI (line 492) | MMKV_JNI jboolean encodeBool(JNIEnv *env, jobject, jlong handle, jstri...
    function MMKV_JNI (line 501) | MMKV_JNI jboolean encodeBool_2(JNIEnv *env, jobject, jlong handle, jst...
    function MMKV_JNI (line 510) | MMKV_JNI jboolean decodeBool(JNIEnv *env, jobject, jlong handle, jstri...
    function MMKV_JNI (line 519) | MMKV_JNI jboolean encodeInt(JNIEnv *env, jobject obj, jlong handle, js...
    function MMKV_JNI (line 528) | MMKV_JNI jboolean encodeInt_2(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 537) | MMKV_JNI jint decodeInt(JNIEnv *env, jobject obj, jlong handle, jstrin...
    function MMKV_JNI (line 546) | MMKV_JNI jboolean encodeLong(JNIEnv *env, jobject obj, jlong handle, j...
    function MMKV_JNI (line 555) | MMKV_JNI jboolean encodeLong_2(JNIEnv *env, jobject obj, jlong handle,...
    function MMKV_JNI (line 564) | MMKV_JNI jlong decodeLong(JNIEnv *env, jobject obj, jlong handle, jstr...
    function MMKV_JNI (line 573) | MMKV_JNI jboolean encodeFloat(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 582) | MMKV_JNI jboolean encodeFloat_2(JNIEnv *env, jobject obj, jlong handle...
    function MMKV_JNI (line 591) | MMKV_JNI jfloat decodeFloat(JNIEnv *env, jobject, jlong handle, jstrin...
    function MMKV_JNI (line 600) | MMKV_JNI jboolean encodeDouble(JNIEnv *env, jobject obj, jlong handle,...
    function MMKV_JNI (line 609) | MMKV_JNI jboolean encodeDouble_2(JNIEnv *env, jobject obj, jlong handl...
    function MMKV_JNI (line 618) | MMKV_JNI jdouble decodeDouble(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 627) | MMKV_JNI jboolean encodeString(JNIEnv *env, jobject, jlong handle, jst...
    function MMKV_JNI (line 642) | MMKV_JNI jboolean encodeString_2(JNIEnv *env, jobject, jlong handle, j...
    function MMKV_JNI (line 657) | MMKV_JNI jstring decodeString(JNIEnv *env, jobject obj, jlong handle, ...
    function MMKV_JNI (line 670) | MMKV_JNI jboolean encodeBytes(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 695) | MMKV_JNI jboolean encodeBytes_2(JNIEnv *env, jobject, jlong handle, js...
    function MMKV_JNI (line 720) | MMKV_JNI jbyteArray decodeBytes(JNIEnv *env, jobject obj, jlong handle...
    function MMKV_JNI (line 735) | MMKV_JNI jobjectArray allKeys(JNIEnv *env, jobject instance, jlong han...
    function MMKV_JNI (line 744) | MMKV_JNI jboolean containsKey(JNIEnv *env, jobject instance, jlong han...
    function MMKV_JNI (line 753) | MMKV_JNI jlong count(JNIEnv *env, jobject instance, jlong handle, jboo...
    function MMKV_JNI (line 762) | MMKV_JNI jlong totalSize(JNIEnv *env, jobject instance, jlong handle) {
    function MMKV_JNI (line 771) | MMKV_JNI jlong actualSize(JNIEnv *env, jobject instance, jlong handle) {
    function MMKV_JNI (line 780) | MMKV_JNI void removeValueForKey(JNIEnv *env, jobject instance, jlong h...
    function MMKV_JNI (line 788) | MMKV_JNI void removeValuesForKeys(JNIEnv *env, jobject instance, jobje...
    function MMKV_JNI (line 798) | MMKV_JNI void clearAll(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 805) | MMKV_JNI void sync(JNIEnv *env, jobject instance, jboolean sync) {
    function MMKV_JNI (line 812) | MMKV_JNI jboolean isFileValid(JNIEnv *env, jclass type, jstring oMmapI...
    function MMKV_JNI (line 825) | MMKV_JNI jboolean removeStorage(JNIEnv *env, jclass type, jstring oMma...
    function MMKV_JNI (line 838) | MMKV_JNI jboolean encodeSet(JNIEnv *env, jobject, jlong handle, jstrin...
    function MMKV_JNI (line 853) | MMKV_JNI jboolean encodeSet_2(JNIEnv *env, jobject, jlong handle, jstr...
    function MMKV_JNI (line 868) | MMKV_JNI jobjectArray decodeStringSet(JNIEnv *env, jobject, jlong hand...
    function MMKV_JNI (line 881) | MMKV_JNI void clearMemoryCache(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 888) | MMKV_JNI void lock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 895) | MMKV_JNI void unlock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 902) | MMKV_JNI jboolean tryLock(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 910) | MMKV_JNI jint pageSize(JNIEnv *env, jclass type) {
    function MMKV_JNI (line 914) | MMKV_JNI jstring version(JNIEnv *env, jclass type) {
    function MMKV_JNI (line 920) | MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 931) | MMKV_JNI jboolean doReKey(JNIEnv *env, jobject instance, jstring crypt...
    function MMKV_JNI (line 943) | MMKV_JNI void doCheckReSetCryptKey(JNIEnv *env, jobject instance, jstr...
    function MMKV_JNI (line 961) | MMKV_JNI jstring cryptKey(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 967) | MMKV_JNI void trim(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 974) | MMKV_JNI void close(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 982) | MMKV_JNI jint valueSize(JNIEnv *env, jobject, jlong handle, jstring oK...
    function MMKV_JNI (line 991) | MMKV_JNI void setLogLevel(JNIEnv *env, jclass type, jint level) {
    function MMKV_JNI (line 995) | MMKV_JNI void setCallbackHandler(JNIEnv *env, jclass type, jboolean lo...
    function MMKV_JNI (line 1011) | MMKV_JNI jlong createNB(JNIEnv *env, jobject instance, jint size) {
    function MMKV_JNI (line 1020) | MMKV_JNI void destroyNB(JNIEnv *env, jobject instance, jlong pointer, ...
    function MMKV_JNI (line 1024) | MMKV_JNI jint writeValueToNB(JNIEnv *env, jobject instance, jlong hand...
    function MMKV_JNI (line 1033) | MMKV_JNI void setWantsContentChangeNotify(JNIEnv *env, jclass type, jb...
    function MMKV_JNI (line 1041) | MMKV_JNI void checkContentChanged(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1048) | MMKV_JNI jboolean backupOne(JNIEnv *env, jobject obj, jstring mmapID, ...
    function MMKV_JNI (line 1058) | MMKV_JNI jboolean restoreOne(JNIEnv *env, jobject obj, jstring mmapID,...
    function MMKV_JNI (line 1068) | MMKV_JNI jlong backupAll(JNIEnv *env, jobject obj, jstring dstDir/*, j...
    function MMKV_JNI (line 1080) | MMKV_JNI jlong restoreAll(JNIEnv *env, jobject obj, jstring srcDir/*, ...
    function MMKV_JNI (line 1092) | MMKV_JNI jboolean enableAutoExpire(JNIEnv *env, jobject instance, jint...
    function MMKV_JNI (line 1100) | MMKV_JNI jboolean disableAutoExpire(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1108) | MMKV_JNI void enableCompareBeforeSet(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1115) | MMKV_JNI void disableCompareBeforeSet(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1122) | MMKV_JNI bool isCompareBeforeSetEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1130) | MMKV_JNI bool isEncryptionEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1138) | MMKV_JNI bool isExpirationEnabled(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1146) | MMKV_JNI void clearAllWithKeepingSpace(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1153) | MMKV_JNI jboolean isMultiProcess(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1161) | MMKV_JNI jboolean isReadOnly(JNIEnv *env, jobject instance) {
    function MMKV_JNI (line 1169) | MMKV_JNI jboolean getNameSpace(JNIEnv *env, jclass type, jstring rootP...
    function MMKV_JNI (line 1180) | MMKV_JNI jboolean checkExist(JNIEnv *env, jclass type, jstring oMmapID...
    function MMKV_JNI (line 1193) | MMKV_JNI void enableDisableProcessMode(JNIEnv *env, jclass type, jbool...
    function MMKV_JNI (line 1201) | MMKV_JNI jlong importFrom(JNIEnv *env, jobject instance, jlong handle,...
  function registerNativeMethods (line 1299) | static int registerNativeMethods(JNIEnv *env, jclass cls) {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java
  class MMKV (line 53) | public class MMKV implements SharedPreferences, SharedPreferences.Editor {
    type LibLoader (line 81) | public interface LibLoader {
      method loadLibrary (line 82) | void loadLibrary(String libName);
    method initialize (line 92) | public static String initialize(@NonNull Context context) {
    method initialize (line 106) | public static String initialize(@NonNull Context context, MMKVLogLevel...
    method initialize (line 119) | public static String initialize(@NonNull Context context, LibLoader lo...
    method initialize (line 134) | public static String initialize(@NonNull Context context, LibLoader lo...
    method initialize (line 147) | public static String initialize(Context context, String rootDir) {
    method initialize (line 161) | public static String initialize(Context context, String rootDir, MMKVL...
    method initialize (line 174) | public static String initialize(Context context, String rootDir, LibLo...
    method initialize (line 189) | public static String initialize(Context context, String rootDir, LibLo...
    method initialize (line 193) | public static String initialize(@NonNull Context context, String rootD...
    method doInitialize (line 228) | private static String doInitialize(String rootDir, String cacheDir, Li...
    method tryLoadNativeLib (line 237) | private static void tryLoadNativeLib(@Nullable LibLoader loader) {
    method initialize (line 259) | @Deprecated
    method initialize (line 269) | @Deprecated
    method initialize (line 278) | @Deprecated
    method initialize (line 288) | @Deprecated
    method nameSpace (line 298) | public static NameSpace nameSpace(String dir) throws RuntimeException {
    method defaultNameSpace (line 310) | public static NameSpace defaultNameSpace() throws RuntimeException {
    method getRootDir (line 322) | public static String getRootDir() {
    method logLevel2Int (line 326) | @Contract(pure = true)
    method setLogLevel (line 355) | public static void setLogLevel(MMKVLogLevel level) {
    method onExit (line 363) | public static native void onExit();
    method mmkvWithID (line 394) | @NonNull
    method mmkvWithID (line 406) | @NonNull
    method mmkvWithID (line 430) | @NonNull
    method mmkvWithID (line 445) | @NonNull
    method mmkvWithID (line 461) | @NonNull
    method mmkvWithID (line 478) | @NonNull
    method mmkvWithID (line 494) | @NonNull
    method mmkvWithID (line 509) | @NonNull
    method mmkvWithID (line 527) | @NonNull
    method mmkvWithID (line 549) | @NonNull
    method mmkvWithID (line 570) | @NonNull
    method mmkvWithID (line 590) | @NonNull
    method backedUpMMKVWithID (line 610) | @NonNull
    method backedUpMMKVWithID (line 630) | @NonNull
    method mmkvWithAshmemID (line 652) | @NonNull
    method mmkvWithAshmemID (line 670) | @NonNull
    method mmkvWithAshmemID (line 689) | @NonNull
    method defaultMMKV (line 742) | @NonNull
    method defaultMMKV (line 755) | @NonNull
    method defaultMMKV (line 771) | @NonNull
    method defaultMMKV (line 786) | @NonNull
    method checkProcessMode (line 802) | @NonNull
    method enableProcessModeChecker (line 837) | public static void enableProcessModeChecker() {
    method disableProcessModeChecker (line 850) | public static void disableProcessModeChecker() {
    method cryptKey (line 861) | @Nullable
    method reKey (line 871) | public boolean reKey(@Nullable String cryptKey) {
    method reKey (line 883) | public boolean reKey(@Nullable String cryptKey, boolean aes256) {
    method doReKey (line 886) | private native boolean doReKey(@Nullable String cryptKey, boolean aes2...
    method checkReSetCryptKey (line 894) | public void checkReSetCryptKey(@Nullable String cryptKey) {
    method checkReSetCryptKey (line 905) | public void checkReSetCryptKey(@Nullable String cryptKey, boolean aes2...
    method doCheckReSetCryptKey (line 908) | private native void doCheckReSetCryptKey(@Nullable String cryptKey, bo...
    method pageSize (line 913) | public static native int pageSize();
    method version (line 918) | public static native String version();
    method mmapID (line 923) | public native String mmapID();
    method lock (line 930) | public native void lock();
    method unlock (line 936) | public native void unlock();
    method tryLock (line 945) | public native boolean tryLock();
    method encode (line 947) | public boolean encode(String key, boolean value) {
    method encode (line 956) | public boolean encode(String key, boolean value, int expireDurationInS...
    method decodeBool (line 960) | public boolean decodeBool(String key) {
    method decodeBool (line 964) | public boolean decodeBool(String key, boolean defaultValue) {
    method encode (line 968) | public boolean encode(String key, int value) {
    method encode (line 977) | public boolean encode(String key, int value, int expireDurationInSecon...
    method decodeInt (line 981) | public int decodeInt(String key) {
    method decodeInt (line 985) | public int decodeInt(String key, int defaultValue) {
    method encode (line 989) | public boolean encode(String key, long value) {
    method encode (line 998) | public boolean encode(String key, long value, int expireDurationInSeco...
    method decodeLong (line 1002) | public long decodeLong(String key) {
    method decodeLong (line 1006) | public long decodeLong(String key, long defaultValue) {
    method encode (line 1010) | public boolean encode(String key, float value) {
    method encode (line 1019) | public boolean encode(String key, float value, int expireDurationInSec...
    method decodeFloat (line 1023) | public float decodeFloat(String key) {
    method decodeFloat (line 1027) | public float decodeFloat(String key, float defaultValue) {
    method encode (line 1031) | public boolean encode(String key, double value) {
    method encode (line 1040) | public boolean encode(String key, double value, int expireDurationInSe...
    method decodeDouble (line 1044) | public double decodeDouble(String key) {
    method decodeDouble (line 1048) | public double decodeDouble(String key, double defaultValue) {
    method encode (line 1052) | public boolean encode(String key, @Nullable String value) {
    method encode (line 1061) | public boolean encode(String key, @Nullable String value, int expireDu...
    method decodeString (line 1065) | @Nullable
    method decodeString (line 1070) | @Nullable
    method encode (line 1075) | public boolean encode(String key, @Nullable Set<String> value) {
    method encode (line 1084) | public boolean encode(String key, @Nullable Set<String> value, int exp...
    method decodeStringSet (line 1088) | @Nullable
    method decodeStringSet (line 1093) | @Nullable
    method decodeStringSet (line 1098) | @SuppressWarnings("unchecked")
    method encode (line 1115) | public boolean encode(String key, @Nullable byte[] value) {
    method encode (line 1124) | public boolean encode(String key, @Nullable byte[] value, int expireDu...
    method decodeBytes (line 1128) | @Nullable
    method decodeBytes (line 1133) | @Nullable
    method getParcelableByte (line 1141) | private byte[] getParcelableByte(@NonNull Parcelable value) {
    method encode (line 1149) | public boolean encode(String key, @Nullable Parcelable value) {
    method encode (line 1162) | public boolean encode(String key, @Nullable Parcelable value, int expi...
    method decodeParcelable (line 1170) | @Nullable
    method decodeParcelable (line 1175) | @SuppressWarnings("unchecked")
    method getValueSize (line 1225) | public int getValueSize(String key) {
    method getValueActualSize (line 1234) | public int getValueActualSize(String key) {
    method containsKey (line 1243) | public boolean containsKey(String key) {
    method allKeys (line 1250) | @Nullable
    method allNonExpireKeys (line 1258) | @Nullable
    method count (line 1266) | public long count() {
    method countNonExpiredKeys (line 1273) | public long countNonExpiredKeys() {
    method totalSize (line 1280) | public long totalSize() {
    method actualSize (line 1288) | public long actualSize() {
    method removeValueForKey (line 1292) | public void removeValueForKey(String key) {
    method removeValuesForKeys (line 1301) | public native void removeValuesForKeys(String[] arrKeys);
    method clearAll (line 1308) | public native void clearAll();
    method clearAllWithKeepingSpace (line 1314) | public native void clearAllWithKeepingSpace();
    method trim (line 1321) | public native void trim();
    method importFrom (line 1327) | public long importFrom(MMKV src) {
    method close (line 1335) | public native void close();
    method clearMemoryCache (line 1342) | public native void clearMemoryCache();
    method sync (line 1349) | public void sync() {
    method async (line 1357) | public void async() {
    method sync (line 1361) | private native void sync(boolean sync);
    method isFileValid (line 1367) | public static boolean isFileValid(String mmapID) {
    method isFileValid (line 1377) | public static native boolean isFileValid(String mmapID, @Nullable Stri...
    method removeStorage (line 1385) | public static boolean removeStorage(String mmapID) {
    method removeStorage (line 1396) | public static native boolean removeStorage(String mmapID, @Nullable St...
    method checkExist (line 1402) | public static boolean checkExist(String mmapID) {
    method checkExist (line 1411) | public static native boolean checkExist(String mmapID, @Nullable Strin...
    method importFromSharedPreferences (line 1419) | @SuppressWarnings("unchecked")
    method backupOneToDirectory (line 1461) | public static native boolean backupOneToDirectory(String mmapID, Strin...
    method restoreOneMMKVFromDirectory (line 1470) | public static native boolean restoreOneMMKVFromDirectory(String mmapID...
    method backupAllToDirectory (line 1478) | public static native long backupAllToDirectory(String dstDir);
    method restoreAllFromDirectory (line 1486) | public static native long restoreAllFromDirectory(String srcDir);
    method enableAutoKeyExpire (line 1522) | public native boolean enableAutoKeyExpire(int expireDurationInSecond);
    method disableAutoKeyExpire (line 1527) | public native boolean disableAutoKeyExpire();
    method enableCompareBeforeSet (line 1536) | public void enableCompareBeforeSet() {
    method nativeEnableCompareBeforeSet (line 1552) | @FastNative
    method disableCompareBeforeSet (line 1559) | public native void disableCompareBeforeSet();
    method getAll (line 1564) | @Override
    method getString (line 1570) | @Nullable
    method putString (line 1576) | @Override
    method putString (line 1582) | public Editor putString(String key, @Nullable String value, int expire...
    method getStringSet (line 1587) | @Nullable
    method putStringSet (line 1593) | @Override
    method putStringSet (line 1599) | public Editor putStringSet(String key, @Nullable Set<String> values, i...
    method putBytes (line 1604) | public Editor putBytes(String key, @Nullable byte[] bytes) {
    method putBytes (line 1609) | public Editor putBytes(String key, @Nullable byte[] bytes, int expireD...
    method getBytes (line 1614) | public byte[] getBytes(String key, @Nullable byte[] defValue) {
    method getInt (line 1618) | @Override
    method putInt (line 1623) | @Override
    method putInt (line 1629) | public Editor putInt(String key, int value, int expireDurationInSecond) {
    method getLong (line 1634) | @Override
    method putLong (line 1639) | @Override
    method putLong (line 1645) | public Editor putLong(String key, long value, int expireDurationInSeco...
    method getFloat (line 1650) | @Override
    method putFloat (line 1655) | @Override
    method putFloat (line 1661) | public Editor putFloat(String key, float value, int expireDurationInSe...
    method getBoolean (line 1666) | @Override
    method putBoolean (line 1671) | @Override
    method putBoolean (line 1677) | public Editor putBoolean(String key, boolean value, int expireDuration...
    method remove (line 1682) | @Override
    method clear (line 1691) | @Override
    method commit (line 1702) | @Override
    method apply (line 1714) | @Override
    method contains (line 1720) | @Override
    method edit (line 1725) | @Override
    method registerOnSharedPreferenceChangeListener (line 1734) | @Override
    method unregisterOnSharedPreferenceChangeListener (line 1742) | @Override
    method mmkvWithAshmemFD (line 1758) | @NonNull
    method mmkvWithAshmemFD (line 1776) | @NonNull
    method ashmemFD (line 1789) | public native int ashmemFD();
    method ashmemMetaFD (line 1794) | public native int ashmemMetaFD();
    method createNativeBuffer (line 1803) | @Nullable
    method destroyNativeBuffer (line 1815) | public static void destroyNativeBuffer(@NonNull NativeBuffer buffer) {
    method writeValueToNativeBuffer (line 1824) | public int writeValueToNativeBuffer(String key, @NonNull NativeBuffer ...
    method registerHandler (line 1838) | public static void registerHandler(MMKVHandler handler) {
    method unregisterHandler (line 1851) | public static void unregisterHandler() {
    method onMMKVCRCCheckFail (line 1859) | private static int onMMKVCRCCheckFail(String mmapID) {
    method onMMKVFileLengthError (line 1870) | private static int onMMKVFileLengthError(String mmapID) {
    method mmkvLogImp (line 1881) | private static void mmkvLogImp(int level, String file, int line, Strin...
    method simpleLog (line 1905) | private static void simpleLog(MMKVLogLevel level, String message) {
    method registerContentChangeNotify (line 1925) | @Deprecated
    method unregisterContentChangeNotify (line 1935) | @Deprecated
    method onContentChangedByOuterProcess (line 1941) | private static void onContentChangedByOuterProcess(String mmapID) {
    method onMMKVContentLoadSuccessfully (line 1950) | private static void onMMKVContentLoadSuccessfully(String mmapID) {
    method setWantsContentChangeNotify (line 1957) | private static native void setWantsContentChangeNotify(boolean needsNo...
    method checkContentChangedByOuterProcess (line 1962) | public native void checkContentChangedByOuterProcess();
    method isMultiProcess (line 1967) | public native boolean isMultiProcess();
    method isReadOnly (line 1972) | public native boolean isReadOnly();
    method MMKV (line 1977) | private MMKV(long handle) {
    method jniInitialize (line 1981) | private static native void jniInitialize(String rootDir, String cacheD...
    method getMMKVWithID (line 1983) | native static long
    method getDefaultMMKV (line 1988) | private native static long getDefaultMMKV(int mode, @Nullable String c...
    method getMMKVWithAshmemFD (line 1992) | private native static long getMMKVWithAshmemFD(String mmapID, int fd, ...
    method encodeBool (line 1994) | private native boolean encodeBool(long handle, String key, boolean val...
    method encodeBool_2 (line 1996) | private native boolean encodeBool_2(long handle, String key, boolean v...
    method decodeBool (line 1998) | private native boolean decodeBool(long handle, String key, boolean def...
    method encodeInt (line 2000) | private native boolean encodeInt(long handle, String key, int value);
    method encodeInt_2 (line 2002) | private native boolean encodeInt_2(long handle, String key, int value,...
    method decodeInt (line 2004) | private native int decodeInt(long handle, String key, int defaultValue);
    method encodeLong (line 2006) | private native boolean encodeLong(long handle, String key, long value);
    method encodeLong_2 (line 2008) | private native boolean encodeLong_2(long handle, String key, long valu...
    method decodeLong (line 2010) | private native long decodeLong(long handle, String key, long defaultVa...
    method encodeFloat (line 2012) | private native boolean encodeFloat(long handle, String key, float value);
    method encodeFloat_2 (line 2014) | private native boolean encodeFloat_2(long handle, String key, float va...
    method decodeFloat (line 2016) | private native float decodeFloat(long handle, String key, float defaul...
    method encodeDouble (line 2018) | private native boolean encodeDouble(long handle, String key, double va...
    method encodeDouble_2 (line 2020) | private native boolean encodeDouble_2(long handle, String key, double ...
    method decodeDouble (line 2022) | private native double decodeDouble(long handle, String key, double def...
    method encodeString (line 2024) | private native boolean encodeString(long handle, String key, @Nullable...
    method encodeString_2 (line 2026) | private native boolean encodeString_2(long handle, String key, @Nullab...
    method decodeString (line 2028) | @Nullable
    method encodeSet (line 2031) | private native boolean encodeSet(long handle, String key, @Nullable St...
    method encodeSet_2 (line 2033) | private native boolean encodeSet_2(long handle, String key, @Nullable ...
    method decodeStringSet (line 2035) | @Nullable
    method encodeBytes (line 2038) | private native boolean encodeBytes(long handle, String key, @Nullable ...
    method encodeBytes_2 (line 2040) | private native boolean encodeBytes_2(long handle, String key, @Nullabl...
    method decodeBytes (line 2042) | @Nullable
    method containsKey (line 2045) | private native boolean containsKey(long handle, String key);
    method allKeys (line 2047) | private native String[] allKeys(long handle, boolean filterExpire);
    method count (line 2049) | private native long count(long handle, boolean filterExpire);
    method totalSize (line 2051) | private native long totalSize(long handle);
    method actualSize (line 2053) | private native long actualSize(long handle);
    method removeValueForKey (line 2055) | private native void removeValueForKey(long handle, String key);
    method valueSize (line 2057) | private native int valueSize(long handle, String key, boolean actualSi...
    method setLogLevel (line 2059) | private static native void setLogLevel(int level);
    method setCallbackHandler (line 2061) | private static native void setCallbackHandler(boolean logReDirecting, ...
    method createNB (line 2063) | private static native long createNB(int size);
    method destroyNB (line 2065) | private static native void destroyNB(long pointer, int size);
    method writeValueToNB (line 2067) | private native int writeValueToNB(long handle, String key, long pointe...
    method isCompareBeforeSetEnabled (line 2069) | private native boolean isCompareBeforeSetEnabled();
    method isEncryptionEnabled (line 2071) | @FastNative
    method isExpirationEnabled (line 2074) | @FastNative
    method enableDisableProcessMode (line 2077) | private static native void enableDisableProcessMode(boolean enable);
    method checkProcessMode (line 2079) | private static native boolean checkProcessMode(long handle);
    method getNameSpace (line 2081) | private static native boolean getNameSpace(String rootPath);
    method importFrom (line 2083) | private native long importFrom(long handle, long srcHandle);

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVConfig.java
  class MMKVConfig (line 26) | public class MMKVConfig {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVContentChangeNotification.java
  type MMKVContentChangeNotification (line 28) | @Deprecated
    method onContentChangedByOuterProcess (line 35) | void onContentChangedByOuterProcess(String mmapID);

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVContentProvider.java
  class MMKVContentProvider (line 41) | public class MMKVContentProvider extends ContentProvider {
    method contentUri (line 50) | @Nullable
    method mmkvFromAshmemID (line 66) | @NonNull
    method queryAuthority (line 76) | @Nullable
    method onCreate (line 93) | @Override
    method getProcessNameByPID (line 103) | protected static String getProcessNameByPID(@NonNull Context context, ...
    method call (line 121) | @Nullable
    method getType (line 140) | @Nullable
    method query (line 146) | @Nullable
    method update (line 156) | @Override
    method delete (line 164) | @Override
    method insert (line 169) | @Nullable

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVHandler.java
  type MMKVHandler (line 27) | public interface MMKVHandler {
    method onMMKVCRCCheckFail (line 33) | MMKVRecoverStrategic onMMKVCRCCheckFail(String mmapID);
    method onMMKVFileLengthError (line 40) | MMKVRecoverStrategic onMMKVFileLengthError(String mmapID);
    method wantLogRedirecting (line 45) | boolean wantLogRedirecting();
    method mmkvLog (line 55) | void mmkvLog(MMKVLogLevel level, String file, int line, String functio...
    method getNativeLogHandler (line 62) | default long getNativeLogHandler() { return 0; }
    method wantContentChangeNotification (line 67) | default boolean wantContentChangeNotification() { return false; }
    method onContentChangedByOuterProcess (line 74) | default void onContentChangedByOuterProcess(String mmapID) {}
    method onMMKVContentLoadSuccessfully (line 80) | default void onMMKVContentLoadSuccessfully(String mmapID) {}

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVLogLevel.java
  type MMKVLogLevel (line 26) | public enum MMKVLogLevel {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVProcessUtil.java
  class MMKVProcessUtil (line 37) | class MMKVProcessUtil {
    method getCurrentProcessName (line 41) | public static String getCurrentProcessName(@NonNull Context context) {
    method getCurrentProcessNameByApplication (line 60) | @NonNull
    method getCurrentProcessNameByActivityThread (line 68) | @NonNull
    method getCurrentProcessNameByActivityManager (line 85) | private static String getCurrentProcessNameByActivityManager(@NonNull ...

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVRecoverStrategic.java
  type MMKVRecoverStrategic (line 26) | public enum MMKVRecoverStrategic {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/NameSpace.java
  class NameSpace (line 30) | public final class NameSpace {
    method NameSpace (line 34) | NameSpace(String dir) {
    method getRootDir (line 41) | public String getRootDir() {
    method mmkvWithID (line 51) | @NonNull
    method mmkvWithID (line 63) | @NonNull
    method mmkvWithID (line 82) | @NonNull
    method mmkvWithID (line 97) | @NonNull
    method mmkvWithID (line 113) | @NonNull
    method mmkvWithID (line 130) | @NonNull
    method mmkvWithID (line 148) | @NonNull
    method mmkvWithID (line 168) | @NonNull
    method backupOneToDirectory (line 185) | public boolean backupOneToDirectory(String mmapID, String dstDir) {
    method restoreOneMMKVFromDirectory (line 195) | public boolean restoreOneMMKVFromDirectory(String mmapID, String srcDi...
    method isFileValid (line 226) | public boolean isFileValid(String mmapID) {
    method removeStorage (line 236) | public boolean removeStorage(String mmapID) {
    method checkExist (line 244) | public boolean checkExist(String mmapID) {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/NativeBuffer.java
  class NativeBuffer (line 28) | public final class NativeBuffer {
    method NativeBuffer (line 32) | public NativeBuffer(long ptr, int length) {

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/ParcelableMMKV.java
  class ParcelableMMKV (line 37) | public final class ParcelableMMKV implements Parcelable {
    method ParcelableMMKV (line 43) | public ParcelableMMKV(@NonNull MMKV mmkv) {
    method ParcelableMMKV (line 50) | private ParcelableMMKV(String id, int fd, int metaFD, String key) {
    method toMMKV (line 57) | @Nullable
    method describeContents (line 65) | @Override
    method writeToParcel (line 70) | @Override
    method createFromParcel (line 88) | @Nullable
    method newArray (line 101) | @NonNull

FILE: Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/UnsupportedArchitectureException.java
  class UnsupportedArchitectureException (line 23) | public class UnsupportedArchitectureException extends RuntimeException {
    method UnsupportedArchitectureException (line 24) | public UnsupportedArchitectureException(String message) {

FILE: Android/MMKV/mmkvdemo/src/main/cpp/mmkvdemo.cpp
  function _MMKVLogWithLevel (line 33) | void _MMKVLogWithLevel(android_LogPriority level, const char *filename, ...
  function string (line 64) | static string jstring2string(JNIEnv *env, jstring str) {
  function string (line 76) | string to_string(const std::string& str) {  return str; }
  function string (line 79) | string to_string(const vector<T> &arr, const char* sp = ", ") {
  function functionalTest (line 93) | void functionalTest(MMKV *mmkv, bool decodeOnly) {
  function testNameSpaceInNative (line 171) | static void testNameSpaceInNative(JNIEnv *env, jobject obj, jstring root...
  type MMKVLogLevel (line 184) | enum MMKVLogLevel : int {
  function android_LogPriority (line 193) | static android_LogPriority MMKVLogLevelDesc(MMKVLogLevel level) {
  function mmkvLog (line 208) | static void mmkvLog(MMKVLogLevel level, const char *file, int line, cons...
  function jlong (line 213) | static jlong getNativeLogHandler(JNIEnv *env, jobject obj) {
  function registerNativeMethods (line 222) | static int registerNativeMethods(JNIEnv *env, jclass cls) {
  function JNIEXPORT (line 226) | JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java
  class Baseline (line 35) | public final class Baseline {
    method Baseline (line 47) | Baseline(Context context, int loops) {
    method mmkvBaselineTest (line 67) | public void mmkvBaselineTest() {
    method mmkvForTest (line 80) | private MMKV mmkvForTest() {
    method mmkvBatchWriteInt (line 85) | private void mmkvBatchWriteInt() {
    method mmkvBatchReadInt (line 99) | private void mmkvBatchReadInt() {
    method mmkvBatchWriteString (line 111) | private void mmkvBatchWriteString() {
    method mmkvBatchReadString (line 124) | private void mmkvBatchReadString() {
    method mmkvBatchDeleteString (line 136) | private void mmkvBatchDeleteString() {
    method sharedPreferencesBaselineTest (line 148) | public void sharedPreferencesBaselineTest() {
    method spBatchWriteInt (line 155) | private void spBatchWriteInt() {
    method spBatchReadInt (line 172) | private void spBatchReadInt() {
    method spBatchWriteString (line 184) | private void spBatchWriteString() {
    method spBatchReadString (line 200) | private void spBatchReadString() {
    method sqliteBaselineTest (line 212) | public void sqliteBaselineTest(boolean useTransaction) {
    method sqliteWriteInt (line 219) | private void sqliteWriteInt(boolean useTransaction) {
    method sqliteReadInt (line 240) | private void sqliteReadInt(boolean useTransaction) {
    method sqliteWriteString (line 259) | private void sqliteWriteString(boolean useTransaction) {
    method sqliteReadString (line 279) | private void sqliteReadString(boolean useTransaction) {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/BenchMarkBaseService.java
  class BenchMarkBaseService (line 34) | public abstract class BenchMarkBaseService extends Service {
    method onCreate (line 60) | @Override
    method onDestroy (line 91) | @Override
    method batchWriteInt (line 99) | protected void batchWriteInt(String caller) {
    method mmkvBatchWriteInt (line 105) | private void mmkvBatchWriteInt(String caller) {
    method sqliteWriteInt (line 121) | private void sqliteWriteInt(String caller, boolean useTransaction) {
    method spBatchWriteInt (line 142) | private void spBatchWriteInt(String caller) {
    method batchReadInt (line 160) | protected void batchReadInt(String caller) {
    method mmkvBatchReadInt (line 166) | private void mmkvBatchReadInt(String caller) {
    method sqliteReadInt (line 179) | private void sqliteReadInt(String caller, boolean useTransaction) {
    method spBatchReadInt (line 198) | private void spBatchReadInt(String caller) {
    method batchWriteString (line 211) | protected void batchWriteString(String caller) {
    method mmkvBatchWriteString (line 217) | private void mmkvBatchWriteString(String caller) {
    method sqliteWriteString (line 231) | private void sqliteWriteString(String caller, boolean useTransaction) {
    method spBatchWrieString (line 251) | private void spBatchWrieString(String caller) {
    method batchReadString (line 268) | protected void batchReadString(String caller) {
    method mmkvBatchReadString (line 274) | private void mmkvBatchReadString(String caller) {
    method sqliteReadString (line 287) | private void sqliteReadString(String caller, boolean useTransaction) {
    method spBatchReadStrinfg (line 306) | private void spBatchReadStrinfg(String caller) {
    method GetMMKV (line 321) | protected MMKV GetMMKV() {
    class AshmemMMKVGetter (line 329) | public class AshmemMMKVGetter extends IAshmemMMKV.Stub {
      method AshmemMMKVGetter (line 331) | private AshmemMMKVGetter() {
      method GetAshmemMMKV (line 346) | public ParcelableMMKV GetAshmemMMKV() {
    method onBind (line 351) | @Nullable
    method prepareAshmemMMKVByCP (line 358) | protected void prepareAshmemMMKVByCP() {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/FakeInfo.java
  class FakeInfo (line 27) | public class FakeInfo implements Parcelable {
    method FakeInfo (line 31) | public FakeInfo() {
    method toString (line 34) | @NonNull
    method FakeInfo (line 40) | protected FakeInfo(Parcel in) {
    method createFromParcel (line 46) | @Override
    method newArray (line 51) | @Override
    method describeContents (line 57) | @Override
    method writeToParcel (line 62) | @Override

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Info.java
  class Info (line 27) | class Info implements Parcelable {
    method Info (line 31) | public Info(String id, int pos) {
    method toString (line 36) | @NonNull
    method Info (line 42) | protected Info(Parcel in) {
    method createFromParcel (line 48) | @Override
    method newArray (line 53) | @Override
    method describeContents (line 59) | @Override
    method writeToParcel (line 64) | @Override

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java
  class MainActivity (line 51) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 54) | @Override
    method testCompareBeforeSet (line 159) | private void testCompareBeforeSet() {
    method testFastNativeSpeed (line 208) | private void testFastNativeSpeed() {
    method testInterProcessLogic (line 221) | private void testInterProcessLogic() {
    method testMMKV (line 235) | private MMKV testMMKV(String mmapID, String cryptKey, boolean aes256, ...
    method testMMKV (line 243) | static void testMMKV(MMKV kv, boolean decodeOnly) {
    method testImportSharedPreferences (line 324) | private void testImportSharedPreferences() {
    method testReKey (line 363) | private void testReKey() {
    method interProcessBaselineTest (line 380) | private void interProcessBaselineTest(String cmd) {
    method testAshmem (line 390) | private void testAshmem() {
    method prepareInterProcessAshmem (line 432) | private void prepareInterProcessAshmem() {
    method prepareInterProcessAshmemByContentProvider (line 438) | private void prepareInterProcessAshmemByContentProvider(String cryptKe...
    method testInterProcessReKey (line 452) | private void testInterProcessReKey() {
    method testHolderForMultiThread (line 459) | private void testHolderForMultiThread() {
    method testInterProcessLockPhase1 (line 482) | private void testInterProcessLockPhase1() {
    method testInterProcessLockPhase2 (line 491) | private void testInterProcessLockPhase2() {
    method testCornerSize (line 497) | private void testCornerSize() {
    method testFastRemoveCornerSize (line 511) | private void testFastRemoveCornerSize() {
    method testTrimNonEmptyInterProcess (line 533) | private void testTrimNonEmptyInterProcess() {
    method testItemSizeHolderOverride (line 550) | private void testItemSizeHolderOverride() {
    method testBackup (line 576) | private void testBackup() {
    method testRestore (line 622) | private void testRestore() {
    method testAutoExpire (line 672) | private void testAutoExpire(MMKV kv, boolean decodeOnly, int expiratio...
    method testAutoExpire (line 747) | private void testAutoExpire() {
    method addExtraRoundUp (line 788) | private int addExtraRoundUp(int len) {
    method testDiskFull (line 794) | private void testDiskFull() {
    method testClearAllKeepSpace (line 814) | private void testClearAllKeepSpace() {
    method testExpectedCapacity (line 824) | private void testExpectedCapacity() {
    method testRemoveStorageAndCheckExist (line 851) | private void testRemoveStorageAndCheckExist() {
    method overrideTest (line 880) | private void overrideTest() {
    method overrideTestEncrypt (line 934) | private void overrideTestEncrypt() {
    method encryptionTest (line 943) | private void encryptionTest(String value) {
    method encryptionTestKV (line 951) | private void encryptionTestKV(String key, String value) {
    method testReadOnly (line 978) | private void testReadOnly() {
    method testImport (line 1003) | private void testImport() {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MultiProcessSharedPreferences.java
  class MultiProcessSharedPreferences (line 60) | public class MultiProcessSharedPreferences extends ContentProvider imple...
    class ReflectionUtil (line 102) | private static class ReflectionUtil {
      method contentValuesNewInstance (line 104) | public static ContentValues contentValuesNewInstance(HashMap<String,...
      method editorPutStringSet (line 123) | public static Editor editorPutStringSet(Editor editor, String key, S...
      method editorApply (line 139) | public static void editorApply(Editor editor) {
    method checkInitAuthority (line 155) | private void checkInitAuthority(Context context) {
    method queryAuthority (line 176) | private static String queryAuthority(Context context) {
    method getSharedPreferences (line 207) | public static SharedPreferences getSharedPreferences(Context context, ...
    method MultiProcessSharedPreferences (line 211) | public MultiProcessSharedPreferences() {
    method MultiProcessSharedPreferences (line 214) | private MultiProcessSharedPreferences(Context context, String name, in...
    method getAll (line 225) | @SuppressWarnings("unchecked")
    method getString (line 231) | @Override
    method getStringSet (line 238) | public Set<String> getStringSet(String key, Set<String> defValues) {
    method getInt (line 246) | @Override
    method getLong (line 252) | @Override
    method getFloat (line 258) | @Override
    method getBoolean (line 264) | @Override
    method contains (line 270) | @Override
    method edit (line 276) | @Override
    method registerOnSharedPreferenceChangeListener (line 281) | @Override
    method unregisterOnSharedPreferenceChangeListener (line 322) | @Override
    class EditorImpl (line 346) | public final class EditorImpl implements Editor {
      method putString (line 350) | @Override
      method putStringSet (line 359) | public Editor putStringSet(String key, Set<String> values) {
      method putInt (line 366) | @Override
      method putLong (line 374) | @Override
      method putFloat (line 382) | @Override
      method putBoolean (line 390) | @Override
      method remove (line 398) | @Override
      method clear (line 406) | @Override
      method apply (line 414) | @Override
      method commit (line 419) | @Override
      method setValue (line 424) | private boolean setValue(String pathSegment) {
    method getValue (line 442) | private Object getValue(String pathSegment, String key, Object defValu...
    method makeAction (line 467) | private String makeAction(String name) {
    method onCreate (line 471) | @Override
    method query (line 491) | @Override
    method getType (line 552) | @Override
    method insert (line 557) | @Override
    method delete (line 562) | @Override
    method update (line 567) | @SuppressWarnings("unchecked")
    method onLowMemory (line 658) | @Override
    method onTrimMemory (line 666) | @Override
    method checkInitListenersCount (line 674) | private void checkInitListenersCount() {
    method notifyListeners (line 680) | private void notifyListeners(String name, ArrayList<String> keysModifi...
    class BundleCursor (line 691) | private static final class BundleCursor extends MatrixCursor {
      method BundleCursor (line 694) | public BundleCursor(Bundle extras) {
      method getExtras (line 699) | @Override
      method respond (line 704) | @Override

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyApplication.java
  class MyApplication (line 32) | public class MyApplication extends Application implements MMKVHandler {
    method onCreate (line 33) | @Override
    method onTerminate (line 64) | @Override
    method onMMKVCRCCheckFail (line 71) | @Override
    method onMMKVFileLengthError (line 76) | @Override
    method wantLogRedirecting (line 81) | @Override
    method mmkvLog (line 86) | @Override
    method getNativeLogHandler (line 106) | @Override
    method onContentChangedByOuterProcess (line 109) | @Override
    method wantContentChangeNotification (line 114) | @Override
    method onMMKVContentLoadSuccessfully (line 119) | @Override
    method testNameSpace (line 124) | private void testNameSpace() {
    method testNameSpaceInNative (line 138) | private native void testNameSpaceInNative(String nameSpaceRoot, String...

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyService.java
  class MyService (line 27) | public class MyService extends BenchMarkBaseService {
    method onCreate (line 36) | @Override
    method onDestroy (line 42) | @Override
    method onStartCommand (line 48) | @Override
    method testRemove (line 76) | private void testRemove() {
    method testLock (line 82) | private void testLock() {
    method testTrimNonEmpty (line 100) | private void testTrimNonEmpty() {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyService_1.java
  class MyService_1 (line 31) | public class MyService_1 extends BenchMarkBaseService implements Service...
    method onStartCommand (line 35) | @Override
    method onCreate (line 61) | @Override
    method onDestroy (line 67) | @Override
    method onServiceConnected (line 73) | @Override
    method onServiceDisconnected (line 89) | @Override

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/SQLiteKV.java
  class SQLiteKV (line 29) | public final class SQLiteKV {
    class SQLiteKVDBHelper (line 30) | private static class SQLiteKVDBHelper extends SQLiteOpenHelper {
      method SQLiteKVDBHelper (line 36) | public SQLiteKVDBHelper(Context context) {
      method onCreate (line 40) | @Override
      method onUpgrade (line 49) | @Override
    method SQLiteKV (line 62) | public SQLiteKV(Context context) {
    method beginTransaction (line 67) | public void beginTransaction() {
    method endTransaction (line 71) | public void endTransaction() {
    method getWritetableDB (line 81) | private SQLiteDatabase getWritetableDB() {
    method getReadableDatabase (line 88) | private SQLiteDatabase getReadableDatabase() {
    method finalize (line 95) | @Override
    method putInt (line 106) | public boolean putInt(String key, int value) {
    method getInt (line 114) | public int getInt(String key) {
    method putString (line 125) | public boolean putString(String key, String value) {
    method getString (line 133) | public String getString(String key) {

FILE: Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/TestParcelable.java
  class TestParcelable (line 28) | class TestParcelable implements Parcelable {
    method writeToParcel (line 33) | @Override
    method describeContents (line 40) | @Override
    method TestParcelable (line 45) | TestParcelable(int i, String s) {
    method TestParcelable (line 53) | private TestParcelable(Parcel in) {
    method createFromParcel (line 60) | @Override
    method newArray (line 65) | @Override

FILE: Core/CodedInputData.cpp
  type mmkv (line 34) | namespace mmkv {
    function string (line 86) | string CodedInputData::readString() {
    function string (line 118) | string CodedInputData::readString(KeyValueHolder &kvHolder) {
    function MMBuffer (line 139) | MMBuffer CodedInputData::readRealData(mmkv::MMBuffer & data) {
    function MMBuffer (line 144) | MMBuffer CodedInputData::readData(bool copy, bool exactly) {

FILE: Core/CodedInputData.h
  function namespace (line 31) | namespace mmkv {

FILE: Core/CodedInputDataCrypt.cpp
  type mmkv (line 39) | namespace mmkv {
    function string (line 220) | string CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) {

FILE: Core/CodedInputDataCrypt.h
  function namespace (line 34) | namespace mmkv {
  function namespace (line 40) | namespace mmkv {

FILE: Core/CodedInputDataCrypt_OSX.cpp
  type mmkv (line 34) | namespace mmkv {
    function NSString (line 36) | NSString *CodedInputDataCrypt::readNSString(KeyValueHolderCrypt &kvHol...

FILE: Core/CodedInputData_OSX.cpp
  type mmkv (line 34) | namespace mmkv {
    function NSString (line 36) | NSString *CodedInputData::readNSString() {
    function NSString (line 53) | NSString *CodedInputData::readNSString(KeyValueHolder &kvHolder) {
    function NSData (line 74) | NSData *CodedInputData::readNSData() {

FILE: Core/CodedOutputData.cpp
  type mmkv (line 34) | namespace mmkv {

FILE: Core/CodedOutputData.h
  function namespace (line 30) | namespace mmkv {

FILE: Core/InterProcessLock.cpp
  type mmkv (line 28) | namespace mmkv {
    function LockType2FlockType (line 94) | static int32_t LockType2FlockType(LockType lockType) {

FILE: Core/InterProcessLock.h
  function namespace (line 29) | namespace mmkv {

FILE: Core/InterProcessLock_Android.cpp
  type mmkv (line 29) | namespace mmkv {
    function LockType2FlockType (line 41) | static short LockType2FlockType(LockType lockType) {

FILE: Core/InterProcessLock_Win32.cpp
  type mmkv (line 26) | namespace mmkv {
    function DWORD (line 28) | static DWORD LockType2Flag(LockType lockType) {

FILE: Core/KeyValueHolder.cpp
  type mmkv (line 28) | namespace mmkv {
    function MMBuffer (line 36) | MMBuffer KeyValueHolder::toMMBuffer(const void *basePtr) const {
    function KeyValueHolderCrypt (line 95) | KeyValueHolderCrypt &KeyValueHolderCrypt::operator=(KeyValueHolderCryp...
    function MMBuffer (line 133) | static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &input...
    function MMBuffer (line 155) | MMBuffer KeyValueHolderCrypt::toMMBuffer(const void *basePtr, const AE...
  type mmkv (line 182) | namespace mmkv {
    function MMBuffer (line 36) | MMBuffer KeyValueHolder::toMMBuffer(const void *basePtr) const {
    function KeyValueHolderCrypt (line 95) | KeyValueHolderCrypt &KeyValueHolderCrypt::operator=(KeyValueHolderCryp...
    function MMBuffer (line 133) | static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &input...
    function MMBuffer (line 155) | MMBuffer KeyValueHolderCrypt::toMMBuffer(const void *basePtr, const AE...

FILE: Core/KeyValueHolder.h
  type KeyValueHolder (line 32) | struct KeyValueHolder {
  type KeyValueHolderType (line 46) | enum KeyValueHolderType : uint8_t {
  function MediumBufferSize (line 53) | struct KeyValueHolderCrypt {
  function isValueStoredAsOffset (line 85) | static bool isValueStoredAsOffset(size_t valueSize) { return valueSize >...

FILE: Core/MMBuffer.cpp
  type mmkv (line 39) | namespace mmkv {
    function MMBuffer (line 135) | MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept {
    function NSData (line 208) | NSData *MMBuffer::toNSData(bool transferOwnerShip) {

FILE: Core/MMBuffer.h
  function namespace (line 31) | namespace mmkv {

FILE: Core/MMKV.cpp
  function MMKV (line 157) | MMKV *MMKV::defaultMMKV(MMKVMode mode, const string *cryptKey, bool aes2...
  function MMKV (line 165) | MMKV *MMKV::defaultMMKV(const MMKVConfig &config) {
  function initialize (line 169) | static void initialize() {
  function ensureMinimalInitialize (line 207) | static void ensureMinimalInitialize() {
  function MMKVPath_t (line 235) | const MMKVPath_t &MMKV::getRootDir() {
  function MMKV (line 241) | MMKV *MMKV::getMMKVWithID(const std::string &mmapID, const MMKVConfig &c...
  function MMKV (line 272) | MMKV *MMKV::mmkvWithID(const string &mmapID, MMKVMode mode, const string...
  function MMKV (line 285) | MMKV *MMKV::mmkvWithID(const std::string &mmapID, const MMKVConfig &conf...
  function string (line 314) | const string &MMKV::mmapID() const {
  function string (line 382) | string MMKV::cryptKey() const {
  function MMBuffer (line 763) | MMBuffer MMKV::getBytes(MMKVKey_t key) {
  function backupOneToDirectoryByFilePath (line 1246) | static bool backupOneToDirectoryByFilePath(const string &mmapKey, const ...
  function endsWith (line 1348) | bool endsWith(const MMKVPath_t &str, const MMKVPath_t &suffix) {
  function MMKVPath_t (line 1356) | MMKVPath_t filename(const MMKVPath_t &path) {
  function restoreOneFromDirectoryByFilePath (line 1415) | static bool restoreOneFromDirectoryByFilePath(const string &mmapKey, con...
  function mkSpecialCharacterFileDirectory (line 1610) | static void mkSpecialCharacterFileDirectory() {
  function string (line 1616) | static string md5(const basic_string<T> &value) {
  function MMKVPath_t (line 1627) | static MMKVPath_t encodeFilePath(const string &mmapID) {
  function MMKVPath_t (line 1647) | static MMKVPath_t encodeFilePath(const string &mmapID, const MMKVPath_t ...
  function string (line 1668) | string mmapedKVKey(const string &mmapID, const MMKVPath_t *rootPath, boo...
  function string (line 1684) | string legacyMmapedKVKey(const string &mmapID, const MMKVPath_t *rootPat...
  function MMKVPath_t (line 1692) | MMKVPath_t mappedKVPathWithID(const string &mmapID, const MMKVPath_t *ro...
  function MMKVPath_t (line 1705) | MMKVPath_t mappedKVPathWithID(const string &mmapID, const MMKVPath_t *ro...
  function MMKVPath_t (line 1721) | MMKVPath_t crcPathWithPath(const MMKVPath_t &kvPath) {
  function MMKVRecoverStrategic (line 1725) | MMKVRecoverStrategic onMMKVCRCCheckFail(const string &mmapID) {
  function MMKVRecoverStrategic (line 1732) | MMKVRecoverStrategic onMMKVFileLengthError(const string &mmapID) {
  function NameSpace (line 1741) | NameSpace MMKV::nameSpace(const MMKVPath_t &rootDir) {
  function NameSpace (line 1764) | NameSpace MMKV::defaultNameSpace() {
  function MMKV (line 1772) | MMKV *NameSpace::mmkvWithID(const string &mmapID, MMKVMode mode, const s...
  function MMKV (line 1784) | MMKV *NameSpace::mmkvWithID(const string &mmapID, const MMKVConfig &conf...

FILE: Core/MMKV.h
  function namespace (line 43) | namespace mmkv {
  function MMKVMode (line 67) | static inline MMKVMode operator | (MMKVMode one, MMKVMode other) {
  type MMKVConfig (line 72) | struct MMKVConfig {
  function class (line 121) | class MMKV_EXPORT MMKV {
  function MMKV_NAMESPACE_END (line 736) | MMKV_NAMESPACE_END

FILE: Core/MMKVHandler.h
  function namespace (line 28) | namespace mmkv {

FILE: Core/MMKVLog.cpp
  function _MMKVLogWithLevel (line 79) | void _MMKVLogWithLevel(MMKVLogLevel level, const char *filename, const c...
  function WriteUTF8ToStream (line 99) | static void WriteUTF8ToStream(const char* utf8_str) {
  function PrintUTF8 (line 122) | static void PrintUTF8(const char* format, ...) {
  function _MMKVLogWithLevel (line 151) | void _MMKVLogWithLevel(MMKVLogLevel level, const char *filename, const c...

FILE: Core/MMKVLog_Android.cpp
  function LogLevel (line 33) | static LogLevel MMKVLogLevelDesc(MMKVLogLevel level) {
  function _MMKVLogWithLevel (line 48) | void _MMKVLogWithLevel(MMKVLogLevel level, const char *filename, const c...
  function android_LogPriority (line 88) | static android_LogPriority MMKVLogLevelDesc(MMKVLogLevel level) {
  function _MMKVLogWithLevel (line 103) | void _MMKVLogWithLevel(MMKVLogLevel level, const char *filename, const c...

FILE: Core/MMKVMetaInfo.hpp
  type mmkv (line 29) | namespace mmkv {
    type MMKVVersion (line 31) | enum MMKVVersion : uint32_t {
    type MMKVMetaInfo (line 56) | struct MMKVMetaInfo {
      type MMKVMetaInfoFlag (line 72) | enum MMKVMetaInfoFlag : uint64_t {
      method hasFlag (line 75) | bool hasFlag(MMKVMetaInfoFlag flag) { return (m_flags & flag) != 0; }
      method setFlag (line 76) | void setFlag(MMKVMetaInfoFlag flag) { m_flags |= flag; }
      method unsetFlag (line 77) | void unsetFlag(MMKVMetaInfoFlag flag) { m_flags &= ~flag; }
      method write (line 79) | void write(void *ptr) const {
      method writeCRCAndActualSizeOnly (line 84) | void writeCRCAndActualSizeOnly(void *ptr) const {
      method read (line 91) | void read(const void *ptr) {

FILE: Core/MMKVPredef.h
  type MMKVRecoverStrategic (line 156) | enum MMKVRecoverStrategic : int {
  type MMKVErrorType (line 161) | enum MMKVErrorType : int {
  type SyncFlag (line 166) | enum SyncFlag : bool { MMKV_SYNC = true, MMKV_ASYNC = false }
  function MMKV_NAMESPACE_END (line 168) | MMKV_NAMESPACE_END

FILE: Core/MMKV_Android.cpp
  function MigrateStatus (line 185) | MigrateStatus tryMigrateLegacyMMKVFile(const string &mmapID, const strin...
  function MMKV (line 224) | MMKV *MMKV::getMMKVWithID(const string &mmapID, const MMKVConfig &config) {
  function MMKV (line 268) | MMKV *MMKV::mmkvWithAshmemFD(const std::string &mmapID, int fd, int meta...
  function MMKV (line 275) | MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, c...

FILE: Core/MMKV_IO.cpp
  function MMKV_NAMESPACE_BEGIN (line 65) | MMKV_NAMESPACE_BEGIN
  function deleteOrRenameFile (line 204) | static bool deleteOrRenameFile(const MMKVPath_t &src) {
  function prepareEncode (line 420) | static pair<MMBuffer, size_t> prepareEncode(const MMKVMap &dic) {
  function prepareEncode (line 431) | static pair<MMBuffer, size_t> prepareEncode(const MMKVMapCrypt &dic) {
  function prepareEncode (line 460) | static pair<MMBuffer, size_t> prepareEncode(MMKVVector &&vec) {
  function MMBuffer (line 624) | MMBuffer MMKV::getRawDataForKey(MMKVKey_t key) {
  function eraseHelper (line 823) | static void eraseHelper(T& container, std::string_view key) {
  function KVHolderRet_t (line 902) | KVHolderRet_t
  function KVHolderRet_t (line 963) | KVHolderRet_t MMKV::doOverrideDataWithKey(const MMBuffer &data,
  function KVHolderRet_t (line 1057) | KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t ke...
  function KVHolderRet_t (line 1067) | KVHolderRet_t MMKV::overrideDataWithKey(const MMBuffer &data, MMKVKey_t ...
  function KVHolderRet_t (line 1077) | KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, const KeyVal...
  function KVHolderRet_t (line 1103) | KVHolderRet_t MMKV::overrideDataWithKey(const MMBuffer &data, const KeyV...
  function memmoveDictionary (line 1183) | static void
  function memmoveDictionary (line 1240) | static void memmoveDictionary(MMKVMapCrypt &dic,
  function fullWriteBackWholeData (line 1329) | static void fullWriteBackWholeData(MMBuffer allData, size_t totalSize, C...
  function getStorage (line 1618) | static std::pair<MMKVPath_t, MMKVPath_t> getStorage(const std::string &m...

FILE: Core/MMKV_OSX.cpp
  function MMKV_NAMESPACE_BEGIN (line 58) | MMKV_NAMESPACE_BEGIN
  function id (line 352) | static id unSecureUnArchiveObjectWithData(NSData *data) {
  function NSObject (line 371) | NSObject *MMKV::getObject(MMKVKey_t key, Class cls) {
  function NSArray (line 439) | NSArray *MMKV::allKeysObjC(bool filterExpire) {
  function GetAppleMachineInfo (line 559) | void GetAppleMachineInfo(int &device, int &version) {

FILE: Core/MemoryFile.cpp
  type mmkv (line 44) | namespace mmkv {
    function OpenFlag2NativeFlag (line 67) | static int OpenFlag2NativeFlag(OpenFlag flag) {
    function MMKVFileHandle_t (line 154) | MMKVFileHandle_t MemoryFile::getFd() {
    function isFileExist (line 315) | bool isFileExist(const string &nsFilePath) {
    function mkPath (line 324) | extern bool mkPath(const MMKVPath_t &str) {
    function mkPath (line 362) | extern bool mkPath(const MMKVPath_t &str) {
    function MMBuffer (line 374) | MMBuffer *readWholeFile(const MMKVPath_t &path) {
    function zeroFillFile (line 399) | bool zeroFillFile(int fd, size_t startPos, size_t size) {
    function getFileSize (line 428) | bool getFileSize(int fd, size_t &size) {
    function getFileSize (line 437) | bool getFileSize(const char *path, size_t &size) {
    function getFileSize (line 449) | bool getFileSize(int fd, size_t &size) {
    function getFileSize (line 464) | bool getFileSize(const char *path, size_t &size) {
    function getPageSize (line 476) | size_t getPageSize() {
    function MMKVPath_t (line 480) | extern MMKVPath_t absolutePath(const MMKVPath_t &path) {
    function createUniqueTempFile (line 494) | static pair<MMKVPath_t, int> createUniqueTempFile(const char *prefix) {
    function tryAtomicRename (line 513) | bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 521) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD...
    function copyFile (line 582) | bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
    function copyFileContent (line 613) | bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 627) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
    function walkInDir (line 633) | void walkInDir(const MMKVPath_t &dirPath, WalkType type, const functio...
    function deleteFile (line 679) | bool deleteFile(const MMKVPath_t &path) {
    function isDiskOfMMAPFileCorrupted (line 690) | bool isDiskOfMMAPFileCorrupted(MemoryFile *file, bool &needReportReadF...
    function getUniqueFileName (line 715) | std::optional<MMKVPath_t> getUniqueFileName(const MMKVPath_t &folder, ...

FILE: Core/MemoryFile.h
  function namespace (line 35) | namespace mmkv {
  type class (line 45) | enum class
  function OpenFlag (line 55) | static inline OpenFlag operator | (OpenFlag left, OpenFlag right) {
  function operator (line 59) | static inline bool operator & (OpenFlag left, OpenFlag right) {
  function OpenFlag (line 63) | static inline OpenFlag operator & (OpenFlag left, uint32_t right) {
  function class (line 74) | class File {

FILE: Core/MemoryFile_Android.cpp
  type mmkv (line 37) | namespace mmkv {
    function ASharedMemory_create (line 134) | int ASharedMemory_create(const char *name, size_t size) {
    function ASharedMemory_getSize (line 180) | size_t ASharedMemory_getSize(int fd) {
    function string (line 208) | string ASharedMemory_getName(int fd) {
  type mmkv (line 105) | namespace mmkv {
    function ASharedMemory_create (line 134) | int ASharedMemory_create(const char *name, size_t size) {
    function ASharedMemory_getSize (line 180) | size_t ASharedMemory_getSize(int fd) {
    function string (line 208) | string ASharedMemory_getName(int fd) {
  function MMKVPath_t (line 228) | MMKVPath_t ashmemMMKVPathWithID(const MMKVPath_t &mmapID) {
  function timespec_to_ms (line 232) | static long long timespec_to_ms(struct timespec ts) {
  function getFileModifyTimeInMS (line 236) | long long getFileModifyTimeInMS(const char *path) {

FILE: Core/MemoryFile_Linux.cpp
  type mmkv (line 49) | namespace mmkv {
    function tryAtomicRename (line 51) | bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 90) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD...

FILE: Core/MemoryFile_OSX.cpp
  type mmkv (line 28) | namespace mmkv {
    function tryResetFileProtection (line 30) | void tryResetFileProtection(const string &path) {
    function tryAtomicRename (line 60) | bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFile (line 90) | bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
    function copyFileContent (line 112) | bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 125) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
    function copyFileContent (line 144) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD...
    function isDiskOfMMAPFileCorrupted (line 148) | bool isDiskOfMMAPFileCorrupted(MemoryFile *file, bool &needReportReadF...
  type mmkv (line 58) | namespace mmkv {
    function tryResetFileProtection (line 30) | void tryResetFileProtection(const string &path) {
    function tryAtomicRename (line 60) | bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFile (line 90) | bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
    function copyFileContent (line 112) | bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 125) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
    function copyFileContent (line 144) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD...
    function isDiskOfMMAPFileCorrupted (line 148) | bool isDiskOfMMAPFileCorrupted(MemoryFile *file, bool &needReportReadF...

FILE: Core/MemoryFile_Win32.cpp
  type mmkv (line 37) | namespace mmkv {
    function OpenFlag2NativeFlag (line 48) | static pair<int, int> OpenFlag2NativeFlag(OpenFlag flag) {
    function MMKVFileHandle_t (line 290) | MMKVFileHandle_t MemoryFile::getFd() {
    function getPageSize (line 297) | size_t getPageSize() {
    function MMKVPath_t (line 303) | MMKVPath_t absolutePath(const MMKVPath_t& path) {
    function isFileExist (line 316) | bool isFileExist(const MMKVPath_t &nsFilePath) {
    function mkPath (line 324) | bool mkPath(const MMKVPath_t &str) {
    function MMBuffer (line 358) | MMBuffer *readWholeFile(const MMKVPath_t &nsFilePath) {
    function zeroFillFile (line 387) | bool zeroFillFile(MMKVFileHandle_t file, size_t startPos, size_t size) {
    function ftruncate (line 421) | static bool ftruncate(MMKVFileHandle_t file, size_t size) {
    function getFileSize (line 436) | static bool getFileSize(MMKVFileHandle_t fd, size_t &size) {
    function getFileSize (line 445) | bool getFileSize(const wchar_t *filename, size_t &size) {
    function createUniqueTempFile (line 454) | static pair<MMKVPath_t, MMKVFileHandle_t> createUniqueTempFile(const w...
    function tryAtomicRename (line 479) | bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 489) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD...
    function copyFile (line 544) | bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
    function copyFileContent (line 573) | bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstP...
    function copyFileContent (line 588) | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
    function walkInDir (line 592) | void walkInDir(const MMKVPath_t &dirPath,
    function isDiskOfMMAPFileCorrupted (line 626) | bool isDiskOfMMAPFileCorrupted(MemoryFile *file, bool &needReportReadF...
    function deleteFile (line 652) | bool deleteFile(const MMKVPath_t &path) {
    function getUniqueFileName (line 661) | std::optional<MMKVPath_t> getUniqueFileName(const MMKVPath_t &folder, ...
  function string2MMKVPath_t (line 678) | std::wstring string2MMKVPath_t(const std::string &str) {
  function MMKVPath_t2String (line 687) | std::string MMKVPath_t2String(const MMKVPath_t &str) {

FILE: Core/MiniPBCoder.cpp
  type mmkv (line 37) | namespace mmkv {
    function MMBuffer (line 187) | MMBuffer MiniPBCoder::writePreparedItems(size_t index) {
    function MMBuffer (line 207) | MMBuffer MiniPBCoder::encodeDataWithObject(const MMBuffer &obj) {
    function MMBuffer (line 604) | MMBuffer MiniPBCoder::getEncodeData(const std::vector<bool> &value) {
    function MMBuffer (line 617) | MMBuffer MiniPBCoder::getEncodeData(const std::span<const float> &valu...
    function MMBuffer (line 630) | MMBuffer MiniPBCoder::getEncodeData(const std::span<const double> &val...

FILE: Core/MiniPBCoder.h
  function namespace (line 37) | namespace mmkv {

FILE: Core/PBEncodeItem.hpp
  type mmkv (line 31) | namespace mmkv {
    type PBEncodeItemType (line 33) | enum PBEncodeItemType {
    type PBEncodeItem (line 54) | struct PBEncodeItem {
      method PBEncodeItem (line 76) | PBEncodeItem() : type(PBEncodeItemType_None), compiledSize(0), value...
      method PBEncodeItem (line 80) | PBEncodeItem(PBEncodeItem &&other) = default;
      method PBEncodeItem (line 83) | PBEncodeItem(PBEncodeItem &&other)

FILE: Core/PBUtility.cpp
  type mmkv (line 23) | namespace mmkv {
    function pbRawVarint32Size (line 25) | uint32_t pbRawVarint32Size(uint32_t value) {
    function pbUInt64Size (line 38) | uint32_t pbUInt64Size(uint64_t value) {

FILE: Core/PBUtility.h
  function namespace (line 29) | namespace mmkv {

FILE: Core/ScopedLock.hpp
  type mmkv (line 25) | namespace mmkv {
    class ScopedLock (line 28) | class ScopedLock {
      method lock (line 31) | void lock() {
      method unlock (line 37) | void unlock() {
      method ScopedLock (line 44) | explicit ScopedLock(T *oLock) : m_lock(oLock) {
      method ScopedLock (line 55) | explicit ScopedLock(const ScopedLock<T> &other) = delete;
      method ScopedLock (line 56) | ScopedLock &operator=(const ScopedLock<T> &other) = delete;

FILE: Core/ThreadLock.cpp
  type mmkv (line 28) | namespace mmkv {

FILE: Core/ThreadLock.h
  function namespace (line 37) | namespace mmkv {

FILE: Core/ThreadLock_Win32.cpp
  type mmkv (line 29) | namespace mmkv {

FILE: Core/aes/AESCrypt.cpp
  type mmkv (line 30) | namespace mmkv {
    function Rollback_cfb_decrypt (line 123) | static inline void
    function AESCrypt (line 178) | AESCrypt AESCrypt::cloneWithStatus(const AESCryptStatus &status) const {
    function testRandomPlaceHolder (line 184) | void testRandomPlaceHolder() {

FILE: Core/aes/AESCrypt.h
  function namespace (line 31) | namespace mmkv {
  function namespace (line 40) | namespace openssl {
  function namespace (line 44) | namespace mmkv {

FILE: Core/aes/openssl/openssl_aes.h
  function namespace (line 22) | namespace openssl {
  function namespace (line 67) | namespace openssl {
  function namespace (line 85) | namespace openssl {

FILE: Core/aes/openssl/openssl_aes_core.cpp
  function AES_C_set_encrypt_key (line 646) | int AES_C_set_encrypt_key(const uint8_t *userKey, const int bits, void *...
  function AES_C_set_decrypt_key (line 750) | int AES_C_set_decrypt_key(const uint8_t *userKey, const int bits, void *...
  function AES_C_encrypt (line 806) | void AES_C_encrypt(const uint8_t *in, uint8_t *out, const void *k) {
  function AES_decrypt (line 924) | void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {

FILE: Core/aes/openssl/openssl_aes_locl.h
  type u32 (line 30) | typedef unsigned long u32;
  type u32 (line 32) | typedef unsigned int u32;
  type u16 (line 34) | typedef unsigned short u16;
  type u8 (line 35) | typedef unsigned char u8;

FILE: Core/aes/openssl/openssl_cfb128.cpp
  type openssl (line 16) | namespace openssl {
    function AES_cfb128_encrypt (line 23) | void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, c...
    function AES_cfb128_decrypt (line 59) | void AES_cfb128_decrypt(const uint8_t *in, uint8_t *out, size_t len, c...

FILE: Core/aes/openssl/openssl_md32_common.h
  function HASH_UPDATE (line 127) | int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
  function HASH_FINAL (line 190) | int HASH_FINAL(unsigned char *md, HASH_CTX *c)

FILE: Core/aes/openssl/openssl_md5.h
  function namespace (line 19) | namespace openssl {

FILE: Core/aes/openssl/openssl_md5_dgst.cpp
  type openssl (line 13) | namespace openssl {
    function MD5_Init (line 23) | int MD5_Init(MD5_CTX *c)
    function md5_block_data_order (line 37) | void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num)

FILE: Core/aes/openssl/openssl_md5_locl.h
  function namespace (line 15) | namespace openssl {

FILE: Core/aes/openssl/openssl_md5_one.cpp
  type openssl (line 14) | namespace openssl {

FILE: Core/crc32/Checksum.h
  function namespace (line 32) | namespace zlib {
  type z_size_t (line 45) | typedef size_t z_size_t;
  function namespace (line 56) | namespace mmkv {

FILE: Core/crc32/crc32_armv8.cpp
  function _crc32Wrap (line 29) | static inline uint32_t _crc32Wrap(uint32_t crc, const uint8_t *buf, size...
  function _crc32Wrap (line 38) | static inline uint32_t _crc32Wrap(uint32_t crc, const uint8_t *buf, size...
  function TARGET_ARM_CRC (line 57) | TARGET_ARM_CRC static inline uint32_t __crc32b(uint32_t a, uint8_t b) {
  function TARGET_ARM_CRC (line 61) | TARGET_ARM_CRC static inline uint32_t __crc32h(uint32_t a, uint16_t b) {
  function TARGET_ARM_CRC (line 65) | TARGET_ARM_CRC static inline uint32_t __crc32w(uint32_t a, uint32_t b) {
  function TARGET_ARM_CRC (line 69) | TARGET_ARM_CRC static inline uint32_t __crc32d(uint32_t a, uint64_t b) {
  function TARGET_ARM_CRC (line 73) | TARGET_ARM_CRC static inline uint32_t armv8_crc32_small(uint32_t crc, co...
  type mmkv (line 91) | namespace mmkv {
    function TARGET_ARM_CRC (line 93) | TARGET_ARM_CRC uint32_t armv8_crc32(uint32_t crc, const uint8_t *buf, ...

FILE: Core/crc32/zlib/crc32.cpp
  type zlib (line 25) | namespace zlib {
    function crc32_z (line 32) | unsigned long local crc32_z(unsigned long crc, const unsigned char FAR...
    function crc32 (line 49) | unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR...

FILE: Core/crc32/zlib/zconf.h
  type z_size_t (line 87) | typedef unsigned long z_size_t;
  type z_size_t (line 91) | typedef unsigned NO_SIZE_T z_size_t;
  type z_size_t (line 94) | typedef size_t z_size_t;
  type z_size_t (line 96) | typedef unsigned long z_size_t;
  type Byte (line 237) | typedef unsigned char Byte;
  type uInt (line 239) | typedef unsigned int uInt;
  type uLong (line 240) | typedef unsigned long uLong;
  type Byte (line 246) | typedef Byte FAR Bytef;
  type charf (line 248) | typedef char FAR charf;
  type intf (line 249) | typedef int FAR intf;
  type uInt (line 250) | typedef uInt FAR uIntf;
  type uLong (line 251) | typedef uLong FAR uLongf;
  type Byte (line 258) | typedef Byte const *voidpc;
  type Byte (line 259) | typedef Byte FAR *voidpf;
  type Byte (line 260) | typedef Byte *voidp;
  type Z_U4 (line 275) | typedef Z_U4 z_crc_t;
  type z_crc_t (line 277) | typedef unsigned long z_crc_t;

FILE: OpenHarmony/MMKV/src/main/cpp/flutter-bridge.cpp
  type mmkv (line 33) | namespace mmkv {
  class FlutterMMKVHandler (line 44) | class FlutterMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 51) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 57) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 64) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 71) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 77) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function MMKV_EXPORT (line 86) | MMKV_EXPORT void *mmkvInitialize_v2(const char *rootDir, const char *cac...
  function MMKV_EXPORT (line 110) | MMKV_EXPORT void mmkvInitialize_v1(const char *rootDir, const char *cach...
  function MMKV_EXPORT (line 114) | MMKV_EXPORT void mmkvInitialize(const char *rootDir, int32_t logLevel) {
  function MMKV_EXPORT (line 118) | MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const ...
  function MMKV_EXPORT (line 182) | MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey, boo...
  function MMKV_EXPORT (line 215) | MMKV_EXPORT const char *mmapID(void *handle) {
  function MMKV_EXPORT (line 223) | MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) {
  function MMKV_EXPORT (line 232) | MMKV_EXPORT bool encodeBool_v2(void *handle, const char *oKey, bool valu...
  function MMKV_EXPORT (line 241) | MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool default...
  function MMKV_EXPORT (line 250) | MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t val...
  function MMKV_EXPORT (line 259) | MMKV_EXPORT bool encodeInt32_v2(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 268) | MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 277) | MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t val...
  function MMKV_EXPORT (line 286) | MMKV_EXPORT bool encodeInt64_v2(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 295) | MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 304) | MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double val...
  function MMKV_EXPORT (line 313) | MMKV_EXPORT bool encodeDouble_v2(void *handle, const char *oKey, double ...
  function MMKV_EXPORT (line 322) | MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double d...
  function MMKV_EXPORT (line 331) | MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValu...
  function MMKV_EXPORT (line 346) | MMKV_EXPORT bool encodeBytes_v2(void *handle, const char *oKey, void *oV...
  function MMKV_EXPORT (line 361) | MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *...
  function MMKV_EXPORT (line 393) | MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length, bool a...
  function MMKV_EXPORT (line 406) | MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) {
  function MMKV_EXPORT (line 422) | MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t l...
  function MMKV_EXPORT (line 436) | MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) {
  function MMKV_EXPORT (line 446) | MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *point...
  function MMKV_EXPORT (line 455) | MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t...
  function MMKV_EXPORT (line 484) | MMKV_EXPORT bool containsKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 493) | MMKV_EXPORT uint64_t count(void *handle, bool filterExpire) {
  function MMKV_EXPORT (line 501) | MMKV_EXPORT uint64_t totalSize(void *handle) {
  function MMKV_EXPORT (line 509) | MMKV_EXPORT uint64_t actualSize(void *handle) {
  function MMKV_EXPORT (line 517) | MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 525) | MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint...
  function MMKV_EXPORT (line 541) | MMKV_EXPORT void clearAll(void *handle, bool keepSpace) {
  function MMKV_EXPORT (line 548) | MMKV_EXPORT void mmkvSync(void *handle, bool sync) {
  function MMKV_EXPORT (line 555) | MMKV_EXPORT void clearMemoryCache(void *handle) {
  function MMKV_EXPORT (line 562) | MMKV_EXPORT int32_t pageSize() {
  function MMKV_EXPORT (line 566) | MMKV_EXPORT const char *version() {
  function MMKV_EXPORT (line 570) | MMKV_EXPORT void trim(void *handle) {
  function MMKV_EXPORT (line 577) | MMKV_EXPORT void mmkvClose(void *handle) {
  function MMKV_EXPORT (line 584) | MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) {
  function MMKV_EXPORT (line 588) | MMKV_EXPORT bool backupOne(const char *mmapID, const char *dstDir, const...
  function MMKV_EXPORT (line 598) | MMKV_EXPORT bool restoreOne(const char *mmapID, const char *srcDir, cons...
  function MMKV_EXPORT (line 608) | MMKV_EXPORT uint64_t backupAll(const char *dstDir/*, const char *rootPat...
  function MMKV_EXPORT (line 620) | MMKV_EXPORT uint64_t restoreAll(const char *srcDir/*, const char *rootPa...
  function MMKV_EXPORT (line 632) | MMKV_EXPORT bool enableAutoExpire(void *handle, uint32_t expireDuration) {
  function MMKV_EXPORT (line 640) | MMKV_EXPORT bool disableAutoExpire(void *handle) {
  function MMKV_EXPORT (line 648) | MMKV_EXPORT bool enableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 656) | MMKV_EXPORT bool disableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 664) | MMKV_EXPORT bool isFileValid(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 674) | MMKV_EXPORT bool removeStorage(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 684) | MMKV_EXPORT bool isMultiProcess(void *handle) {
  function MMKV_EXPORT (line 692) | MMKV_EXPORT bool isReadOnly(void *handle) {
  function MMKV_EXPORT (line 700) | MMKV_EXPORT void registerErrorHandler(ErrorCallback_t callback) {
  function MMKV_EXPORT (line 707) | MMKV_EXPORT void registerContentChangeNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 714) | MMKV_EXPORT void registerContentLoadedNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 721) | MMKV_EXPORT void checkContentChanged(void *handle) {
  function MMKV_EXPORT (line 728) | MMKV_EXPORT bool getNameSpace(const char *rootPath) {
  function MMKV_EXPORT (line 739) | MMKV_EXPORT bool checkExist(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 749) | MMKV_EXPORT uint64_t importFrom(void *handle, void *srcHandle) {

FILE: OpenHarmony/MMKV/src/main/cpp/native_bridge.cpp
  function IsNValueUndefined (line 53) | bool IsNValueUndefined(napi_env env, napi_value value) {
  function string (line 61) | static string NValueToString(napi_env env, napi_value value, bool maybeU...
  function napi_value (line 73) | static napi_value StringToNValue(napi_env env, const string &value) {
  function NValueToStringArray (line 79) | static vector<string> NValueToStringArray(napi_env env, napi_value value...
  function napi_value (line 101) | static napi_value StringArrayToNValue(napi_env env, const vector<string>...
  function NValueToDoubleArray (line 114) | static vector<double> NValueToDoubleArray(napi_env env, napi_value value...
  function napi_value (line 136) | static napi_value DoubleArrayToNValue(napi_env env, const vector<double>...
  function NValueToBoolArray (line 149) | static vector<bool> NValueToBoolArray(napi_env env, napi_value value, bo...
  function napi_value (line 171) | static napi_value BoolArrayToNValue(napi_env env, const vector<bool> &va...
  function my_finalizer (line 181) | static void my_finalizer(napi_env env, void *finalize_data, void *finali...
  function MMBuffer (line 186) | static MMBuffer NValueToMMBuffer(napi_env env, napi_value value, bool ma...
  function napi_value (line 199) | static napi_value MMBufferToNValue(napi_env env, const MMBuffer &value) {
  function napi_value (line 208) | static napi_value MMBufferToNValue(napi_env env, MMBuffer &&value) {
  function napi_value (line 244) | static napi_value NAPIUndefined(napi_env env) {
  function napi_value (line 250) | static napi_value NAPINull(napi_env env) {
  function napi_value (line 256) | static napi_value BoolToNValue(napi_env env, bool value) {
  function NValueToBool (line 264) | static bool NValueToBool(napi_env env, napi_value value, bool maybeUndef...
  function napi_value (line 275) | static napi_value Int32ToNValue(napi_env env, int32_t value) {
  function NValueToInt32 (line 281) | static int32_t NValueToInt32(napi_env env, napi_value value) {
  function NValueToInt32 (line 287) | static int32_t NValueToInt32(napi_env env, napi_value value, int32_t def...
  function napi_value (line 294) | static napi_value UInt32ToNValue(napi_env env, uint32_t value) {
  function NValueToUInt32 (line 300) | static uint32_t NValueToUInt32(napi_env env, napi_value value) {
  function NValueToUInt32 (line 306) | static uint32_t NValueToUInt32(napi_env env, napi_value value, uint32_t ...
  function napi_value (line 313) | static napi_value DoubleToNValue(napi_env env, double value) {
  function NValueToDouble (line 319) | static double NValueToDouble(napi_env env, napi_value value) {
  function napi_value (line 325) | static napi_value Int64ToNValue(napi_env env, int64_t value) {
  function NValueToInt64 (line 331) | static int64_t NValueToInt64(napi_env env, napi_value value) {
  function napi_value (line 338) | static napi_value UInt64ToNValue(napi_env env, uint64_t value) {
  function NValueToUInt64 (line 344) | static uint64_t NValueToUInt64(napi_env env, napi_value value, bool mayb...
  type CallbackInfo (line 354) | struct CallbackInfo {
  function initCallbacks (line 379) | static std::tuple<bool, bool, bool> initCallbacks(napi_env env, napi_val...
  class NAPIMMKVHandler (line 437) | class NAPIMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 439) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 460) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 480) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 500) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 515) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function napi_value (line 533) | static napi_value initialize(napi_env env, napi_callback_info info) {
  function napi_value (line 562) | static napi_value version(napi_env env, napi_callback_info info) {
  function napi_value (line 568) | static napi_value pageSize(napi_env env, napi_callback_info info) {
  function napi_value (line 574) | static napi_value getDefaultMMKV(napi_env env, napi_callback_info info) {
  function napi_value (line 611) | static napi_value mmkvWithID(napi_env env, napi_callback_info info) {
  function napi_value (line 653) | static napi_value mmkvWithAshmemFD(napi_env env, napi_callback_info info) {
  function napi_value (line 690) | static napi_value mmapID(napi_env env, napi_callback_info info) {
  function napi_value (line 703) | static napi_value encodeBool(napi_env env, napi_callback_info info) {
  function napi_value (line 724) | static napi_value decodeBool(napi_env env, napi_callback_info info) {
  function napi_value (line 743) | static napi_value encodeInt32(napi_env env, napi_callback_info info) {
  function napi_value (line 764) | static napi_value decodeInt32(napi_env env, napi_callback_info info) {
  function napi_value (line 783) | static napi_value encodeUInt32(napi_env env, napi_callback_info info) {
  function napi_value (line 804) | static napi_value decodeUInt32(napi_env env, napi_callback_info info) {
  function napi_value (line 823) | static napi_value encodeInt64(napi_env env, napi_callback_info info) {
  function napi_value (line 844) | static napi_value decodeInt64(napi_env env, napi_callback_info info) {
  function napi_value (line 863) | static napi_value encodeUInt64(napi_env env, napi_callback_info info) {
  function napi_value (line 884) | static napi_value decodeUInt64(napi_env env, napi_callback_info info) {
  function napi_value (line 903) | static napi_value encodeFloat(napi_env env, napi_callback_info info) {
  function napi_value (line 924) | static napi_value decodeFloat(napi_env env, napi_callback_info info) {
  function napi_value (line 943) | static napi_value encodeDouble(napi_env env, napi_callback_info info) {
  function napi_value (line 964) | static napi_value decodeDouble(napi_env env, napi_callback_info info) {
  function napi_value (line 983) | static napi_value encodeString(napi_env env, napi_callback_info info) {
  function napi_value (line 1004) | static napi_value decodeString(napi_env env, napi_callback_info info) {
  function napi_value (line 1021) | static napi_value encodeStringSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1042) | static napi_value decodeStringSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1059) | static napi_value encodeNumberSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1080) | static napi_value decodeNumberSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1097) | static napi_value encodeBoolSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1117) | static napi_value decodeBoolSet(napi_env env, napi_callback_info info) {
  function napi_value (line 1134) | static napi_value encodeBytes(napi_env env, napi_callback_info info) {
  function napi_value (line 1158) | static napi_value decodeBytes(napi_env env, napi_callback_info info) {
  function napi_value (line 1176) | napi_value encodeArray(napi_env env, napi_callback_info info) {
  function napi_value (line 1202) | napi_value decodeArray(napi_env env, napi_callback_info info) {
  function napi_value (line 1220) | static napi_value encodeInt32Array(napi_env env, napi_callback_info info) {
  function napi_value (line 1224) | static napi_value decodeInt32Array(napi_env env, napi_callback_info info) {
  function napi_value (line 1228) | static napi_value encodeUInt32Array(napi_env env, napi_callback_info inf...
  function napi_value (line 1232) | static napi_value decodeUInt32Array(napi_env env, napi_callback_info inf...
  function napi_value (line 1236) | static napi_value encodeInt64Array(napi_env env, napi_callback_info info) {
  function napi_value (line 1240) | static napi_value decodeInt64Array(napi_env env, napi_callback_info info) {
  function napi_value (line 1244) | static napi_value encodeUInt64Array(napi_env env, napi_callback_info inf...
  function napi_value (line 1248) | static napi_value decodeUInt64Array(napi_env env, napi_callback_info inf...
  function napi_value (line 1252) | static napi_value containsKey(napi_env env, napi_callback_info info) {
  function napi_value (line 1266) | static napi_value removeValueForKey(napi_env env, napi_callback_info inf...
  function napi_value (line 1280) | static napi_value removeValuesForKeys(napi_env env, napi_callback_info i...
  function napi_value (line 1298) | static napi_value count(napi_env env, napi_callback_info info) {
  function napi_value (line 1312) | static napi_value allKeys(napi_env env, napi_callback_info info) {
  function napi_value (line 1327) | static napi_value clearAll(napi_env env, napi_callback_info info) {
  function napi_value (line 1341) | static napi_value sync(napi_env env, napi_callback_info info) {
  function napi_value (line 1355) | static napi_value clearMemoryCache(napi_env env, napi_callback_info info) {
  function napi_value (line 1368) | static napi_value totalSize(napi_env env, napi_callback_info info) {
  function napi_value (line 1381) | static napi_value actualSize(napi_env env, napi_callback_info info) {
  function napi_value (line 1394) | static napi_value lock(napi_env env, napi_callback_info info) {
  function napi_value (line 1407) | static napi_value unlock(napi_env env, napi_callback_info info) {
  function napi_value (line 1420) | static napi_value tryLock(napi_env env, napi_callback_info info) {
  function napi_value (line 1433) | static napi_value getValueSize(napi_env env, napi_callback_info info) {
  function napi_value (line 1448) | static napi_value trim(napi_env env, napi_callback_info info) {
  function napi_value (line 1461) | static napi_value importFrom(napi_env env, napi_callback_info info) {
  function napi_value (line 1476) | static napi_value mmkvClose(napi_env env, napi_callback_info info) {
  function napi_value (line 1489) | static napi_value removeStorage(napi_env env, napi_callback_info info) {
  function napi_value (line 1505) | static napi_value isFileValid(napi_env env, napi_callback_info info) {
  function napi_value (line 1523) | static napi_value cryptKey(napi_env env, napi_callback_info info) {
  function napi_value (line 1536) | static napi_value reKey(napi_env env, napi_callback_info info) {
  function napi_value (line 1551) | static napi_value checkReSetCryptKey(napi_env env, napi_callback_info in...
  function napi_value (line 1569) | static napi_value backupOneToDirectory(napi_env env, napi_callback_info ...
  function napi_value (line 1584) | static napi_value restoreOneFromDirectory(napi_env env, napi_callback_in...
  function napi_value (line 1599) | static napi_value backupAllToDirectory(napi_env env, napi_callback_info ...
  function napi_value (line 1611) | static napi_value restoreAllFromDirectory(napi_env env, napi_callback_in...
  function napi_value (line 1623) | static napi_value enableAutoKeyExpire(napi_env env, napi_callback_info i...
  function napi_value (line 1637) | static napi_value disableAutoKeyExpire(napi_env env, napi_callback_info ...
  function napi_value (line 1650) | static napi_value enableCompareBeforeSet(napi_env env, napi_callback_inf...
  function napi_value (line 1663) | static napi_value disableCompareBeforeSet(napi_env env, napi_callback_in...
  function napi_value (line 1676) | static napi_value ashmemFD(napi_env env, napi_callback_info info) {
  function napi_value (line 1689) | static napi_value ashmemMetaFD(napi_env env, napi_callback_info info) {
  function napi_value (line 1702) | static napi_value createNativeBuffer(napi_env env, napi_callback_info in...
  function napi_value (line 1715) | static napi_value destroyNativeBuffer(napi_env env, napi_callback_info i...
  function napi_value (line 1728) | static napi_value writeValueToNativeBuffer(napi_env env, napi_callback_i...
  function napi_value (line 1744) | static napi_value isMultiProcess(napi_env env, napi_callback_info info) {
  function napi_value (line 1757) | static napi_value isReadOnly(napi_env env, napi_callback_info info) {
  function napi_value (line 1770) | static napi_value checkContentChanged(napi_env env, napi_callback_info i...
  function napi_value (line 1783) | static napi_value getNameSpace(napi_env env, napi_callback_info info) {
  function napi_value (line 1796) | static napi_value checkExist(napi_env env, napi_callback_info info) {
  function EXTERN_C_START (line 1812) | EXTERN_C_START
  function RegisterMMKVModule (line 1912) | __attribute__((constructor)) void RegisterMMKVModule(void) {

FILE: OpenHarmony/MMKV/src/main/ets/utils/Util.ts
  function getObjKeys (line 21) | function getObjKeys(obj: Object): string[] {

FILE: OpenHarmony/entry/src/main/cpp/napi_init.cpp
  function IsNValueUndefined (line 30) | bool IsNValueUndefined(napi_env env, napi_value value) {
  function string (line 38) | static string NValueToString(napi_env env, napi_value value, bool maybeU...
  function napi_value (line 50) | static napi_value StringToNValue(napi_env env, const string &value) {
  function napi_value (line 56) | static napi_value BoolToNValue(napi_env env, bool value) {
  function napi_value (line 64) | static napi_value UInt64ToNValue(napi_env env, uint64_t value) {
  function _MMKVLogWithLevel (line 70) | void _MMKVLogWithLevel(const char *filename, const char *func, int line,...
  function string (line 97) | string to_string(const std::string& str) {  return str; }
  function string (line 100) | string to_string(const vector<T> &arr, const char* sp = ", ") {
  function functionalTest (line 112) | void functionalTest(MMKV *mmkv, bool decodeOnly) {
  function napi_value (line 190) | static napi_value TestNativeMMKV(napi_env env, napi_callback_info info)
  function EXTERN_C_START (line 209) | EXTERN_C_START
  function RegisterEntryModule (line 230) | __attribute__((constructor)) void RegisterEntryModule(void)

FILE: POSIX/demo/TestInterProcessLock.cpp
  function threadTest (line 61) | bool threadTest() {
  function main (line 103) | int main() {

FILE: POSIX/demo/UnitTest.cpp
  function testBool (line 36) | void testBool(MMKV *mmkv) {
  function testInt32 (line 52) | void testInt32(MMKV *mmkv) {
  function testUInt32 (line 68) | void testUInt32(MMKV *mmkv) {
  function testInt64 (line 84) | void testInt64(MMKV *mmkv) {
  function testUInt64 (line 100) | void testUInt64(MMKV *mmkv) {
  function EqualWithAccuracy (line 117) | bool EqualWithAccuracy(T value1, T value2, T accuracy) {
  function testFloat (line 121) | void testFloat(MMKV *mmkv) {
  function testDouble (line 137) | void testDouble(MMKV *mmkv) {
  function testString (line 153) | void testString(MMKV *mmkv) {
  function testBytes (line 175) | void testBytes(MMKV *mmkv) {
  function testVector (line 190) | void testVector(MMKV *mmkv) {
  function testRemove (line 202) | void testRemove(MMKV *mmkv) {
  function main (line 249) | int main() {

FILE: POSIX/demo/demo.cpp
  function string (line 47) | string to_string(const std::string& str) {  return str; }
  function string (line 50) | string to_string(const vector<T> &arr, const char* sp = ", ") {
  function functionalTest (line 64) | void functionalTest(MMKV *mmkv, bool decodeOnly) {
  function containerTest (line 142) | void containerTest(MMKV *mmkv, bool decodeOnly) {
  function threadTest (line 255) | void threadTest() {
  function brutleTest (line 268) | void brutleTest() {
  function processTest (line 283) | void processTest() {
  function testInterProcessLock (line 308) | void testInterProcessLock() {
  function cornetSizeTest (line 355) | void cornetSizeTest() {
  function itemSizeHolderTest (line 371) | void itemSizeHolderTest() {
  function fastRemoveCornetSizeTest (line 387) | void fastRemoveCornetSizeTest() {
  function testClearEmptyMMKV (line 411) | void testClearEmptyMMKV() {
  function testClearAllKeepSpace (line 418) | void testClearAllKeepSpace() {
  function testBackup (line 495) | void testBackup() {
  function testRestore (line 523) | void testRestore() {
  function testAutoExpiration (line 554) | void testAutoExpiration() {
  function testExpectedCapacity (line 608) | void testExpectedCapacity() {
  function testOnlyOneKey (line 652) | void testOnlyOneKey() {
  function testOverride (line 755) | void testOverride() {
  function getTimeInMs (line 858) | uint64_t getTimeInMs() {
  function testGetStringSpeed (line 863) | void testGetStringSpeed() {
  function printVector (line 900) | void printVector(vector<string> &v) {
  function testCompareBeforeSet (line 915) | void testCompareBeforeSet() {
  function testFtruncateFail (line 1218) | void testFtruncateFail() {
  function testRemoveStorage (line 1239) | void testRemoveStorage() {
  function setReadOnly (line 1264) | void setReadOnly(const MMKVPath_t& path, bool readOnly) {
  function testReadOnly (line 1280) | void testReadOnly() {
  function testNameSpace (line 1306) | void testNameSpace() {
  function testImport (line 1313) | void testImport() {
  function MMKV (line 1341) | MMKV* testMMKV(const string& mmapID, const string* cryptKey, bool aes256...
  function testReKey (line 1347) | void testReKey() {
  function MyLogHandler (line 1366) | void MyLogHandler(MMKVLogLevel level, const char *file, int line, const ...
  function testReadonlyCrash (line 1385) | void testReadonlyCrash() {
  function main (line 1396) | int main() {

FILE: POSIX/demo/process.cpp
  function brutleTest (line 36) | void brutleTest(int processID) {
  function main (line 58) | int main() {

FILE: POSIX/golang/callback.go
  constant OnErrorDiscard (line 31) | OnErrorDiscard = iota
  constant OnErrorRecover (line 32) | OnErrorRecover
  constant MMKVCRCCheckFail (line 36) | MMKVCRCCheckFail = iota
  constant MMKVFileLength (line 37) | MMKVFileLength
  type Handler (line 41) | type Handler interface
  type DefaultHandler (line 68) | type DefaultHandler struct
    method WantLogRedirect (line 70) | func (d DefaultHandler) WantLogRedirect() bool                     { r...
    method MMKVLog (line 71) | func (d DefaultHandler) MMKVLog(level int, file string, line int, func...
    method OnMMKVCRCCheckFail (line 72) | func (d DefaultHandler) OnMMKVCRCCheckFail(mmapID string) int      { r...
    method OnMMKVFileLengthError (line 73) | func (d DefaultHandler) OnMMKVFileLengthError(mmapID string) int   { r...
    method WantContentChangeNotification (line 74) | func (d DefaultHandler) WantContentChangeNotification() bool       { r...
    method OnContentChangedByOuterProcess (line 75) | func (d DefaultHandler) OnContentChangedByOuterProcess(mmapID string) {}
    method OnMMKVContentLoadSuccessfully (line 76) | func (d DefaultHandler) OnMMKVContentLoadSuccessfully(mmapID string) {}
  function RegisterHandler (line 81) | func RegisterHandler(handler Handler) {
  function UnRegisterHandler (line 90) | func UnRegisterHandler() {
  function myLogHandler (line 97) | func myLogHandler(level int, file string, line int, function string, mes...
  function myErrorHandler (line 104) | func myErrorHandler(mmapID string, error int) int {
  function myContentChangeHandler (line 116) | func myContentChangeHandler(mmapID string) {
  function myContentLoadedHandler (line 123) | func myContentLoadedHandler(mmapID string) {

FILE: POSIX/golang/golang-bridge.cpp
  class GoMMKVHandler (line 42) | class GoMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 47) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 57) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 62) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 67) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 75) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function MMKV_EXPORT (line 83) | MMKV_EXPORT void mmkvInitialize(GoStringWrap rootDir, int32_t logLevel, ...
  function MMKV_EXPORT (line 92) | MMKV_EXPORT void onExit() {
  function MMKV_EXPORT (line 96) | MMKV_EXPORT void *getMMKVWithID(GoStringWrap mmapID, MMKVCreationConfig_...
  function MMKV_EXPORT (line 147) | MMKV_EXPORT void *getDefaultMMKV(MMKVCreationConfig_t cfg) {
  function MMKV_EXPORT (line 179) | MMKV_EXPORT const char *mmapID(void *handle) {
  function MMKV_EXPORT (line 187) | MMKV_EXPORT bool encodeBool(void *handle, GoStringWrap oKey, bool value) {
  function MMKV_EXPORT (line 196) | MMKV_EXPORT bool encodeBool_v2(void *handle, GoStringWrap oKey, bool val...
  function MMKV_EXPORT (line 205) | MMKV_EXPORT bool decodeBool(void *handle, GoStringWrap oKey, bool defaul...
  function MMKV_EXPORT (line 214) | MMKV_EXPORT bool encodeInt32(void *handle, GoStringWrap oKey, int32_t va...
  function MMKV_EXPORT (line 223) | MMKV_EXPORT bool encodeInt32_v2(void *handle, GoStringWrap oKey, int32_t...
  function MMKV_EXPORT (line 232) | MMKV_EXPORT int32_t decodeInt32(void *handle, GoStringWrap oKey, int32_t...
  function MMKV_EXPORT (line 241) | MMKV_EXPORT bool encodeUInt32(void *handle, GoStringWrap oKey, uint32_t ...
  function MMKV_EXPORT (line 250) | MMKV_EXPORT bool encodeUInt32_v2(void *handle, GoStringWrap oKey, uint32...
  function MMKV_EXPORT (line 259) | MMKV_EXPORT uint32_t decodeUInt32(void *handle, GoStringWrap oKey, uint3...
  function MMKV_EXPORT (line 268) | MMKV_EXPORT bool encodeInt64(void *handle, GoStringWrap oKey, int64_t va...
  function MMKV_EXPORT (line 277) | MMKV_EXPORT bool encodeInt64_v2(void *handle, GoStringWrap oKey, int64_t...
  function MMKV_EXPORT (line 286) | MMKV_EXPORT int64_t decodeInt64(void *handle, GoStringWrap oKey, int64_t...
  function MMKV_EXPORT (line 295) | MMKV_EXPORT bool encodeUInt64(void *handle, GoStringWrap oKey, uint64_t ...
  function MMKV_EXPORT (line 304) | MMKV_EXPORT bool encodeUInt64_v2(void *handle, GoStringWrap oKey, uint64...
  function MMKV_EXPORT (line 313) | MMKV_EXPORT uint64_t decodeUInt64(void *handle, GoStringWrap oKey, uint6...
  function MMKV_EXPORT (line 322) | MMKV_EXPORT bool encodeFloat(void *handle, GoStringWrap oKey, float valu...
  function MMKV_EXPORT (line 331) | MMKV_EXPORT bool encodeFloat_v2(void *handle, GoStringWrap oKey, float v...
  function MMKV_EXPORT (line 340) | MMKV_EXPORT float decodeFloat(void *handle, GoStringWrap oKey, float def...
  function MMKV_EXPORT (line 349) | MMKV_EXPORT bool encodeDouble(void *handle, GoStringWrap oKey, double va...
  function MMKV_EXPORT (line 358) | MMKV_EXPORT bool encodeDouble_v2(void *handle, GoStringWrap oKey, double...
  function MMKV_EXPORT (line 367) | MMKV_EXPORT double decodeDouble(void *handle, GoStringWrap oKey, double ...
  function MMKV_EXPORT (line 376) | MMKV_EXPORT bool encodeBytes(void *handle, GoStringWrap oKey, GoStringWr...
  function MMKV_EXPORT (line 391) | MMKV_EXPORT bool encodeBytes_v2(void *handle, GoStringWrap oKey, GoStrin...
  function MMKV_EXPORT (line 406) | MMKV_EXPORT void *decodeBytes(void *handle, GoStringWrap oKey, uint64_t ...
  function MMKV_EXPORT (line 432) | MMKV_EXPORT bool reKey(void *handle, GoStringWrap oKey, bool aes256) {
  function MMKV_EXPORT (line 445) | MMKV_EXPORT void *cryptKey(void *handle, uint32_t *lengthPtr) {
  function MMKV_EXPORT (line 461) | MMKV_EXPORT void checkReSetCryptKey(void *handle, GoStringWrap oKey, boo...
  function MMKV_EXPORT (line 475) | MMKV_EXPORT bool reKey(void *handle, GoStringWrap oKey, bool aes256) {
  function MMKV_EXPORT (line 479) | MMKV_EXPORT void *cryptKey(void *handle, uint32_t *lengthPtr) {
  function MMKV_EXPORT (line 483) | MMKV_EXPORT void checkReSetCryptKey(void *handle, GoStringWrap oKey, boo...
  function MMKV_EXPORT (line 487) | MMKV_EXPORT GoStringWrap *allKeys(void *handle, uint64_t *lengthPtr, boo...
  function MMKV_EXPORT (line 513) | MMKV_EXPORT bool containsKey(void *handle, GoStringWrap oKey) {
  function MMKV_EXPORT (line 522) | MMKV_EXPORT uint64_t count(void *handle, bool filterExpire) {
  function MMKV_EXPORT (line 530) | MMKV_EXPORT uint64_t totalSize(void *handle) {
  function MMKV_EXPORT (line 538) | MMKV_EXPORT uint64_t actualSize(void *handle) {
  function MMKV_EXPORT (line 546) | MMKV_EXPORT void removeValueForKey(void *handle, GoStringWrap oKey) {
  function MMKV_EXPORT (line 554) | MMKV_EXPORT void removeValuesForKeys(void *handle, GoStringWrap *keyArra...
  function MMKV_EXPORT (line 571) | MMKV_EXPORT void clearAll(void *handle, bool keepSpace) {
  function MMKV_EXPORT (line 578) | MMKV_EXPORT void mmkvSync(void *handle, bool sync) {
  function MMKV_EXPORT (line 585) | MMKV_EXPORT void clearMemoryCache(void *handle) {
  function MMKV_EXPORT (line 592) | MMKV_EXPORT int32_t pageSize() {
  function MMKV_EXPORT (line 596) | MMKV_EXPORT const char *version() {
  function MMKV_EXPORT (line 600) | MMKV_EXPORT const char *getRootDir() {
  function MMKV_EXPORT (line 604) | MMKV_EXPORT void trim(void *handle) {
  function MMKV_EXPORT (line 611) | MMKV_EXPORT void mmkvClose(void *handle) {
  function MMKV_EXPORT (line 618) | MMKV_EXPORT bool backupOneToDirectory(GoStringWrap_t mmapID, GoStringWra...
  function MMKV_EXPORT (line 631) | MMKV_EXPORT bool restoreOneFromDirectory(GoStringWrap_t mmapID, GoString...
  function MMKV_EXPORT (line 644) | MMKV_EXPORT uint64_t backupAllToDirectory(GoStringWrap_t dstDir, GoStrin...
  function MMKV_EXPORT (line 657) | MMKV_EXPORT uint64_t restoreAllFromDirectory(GoStringWrap_t srcDir, GoSt...
  function MMKV_EXPORT (line 670) | MMKV_EXPORT bool enableAutoExpire(void *handle, uint32_t expireDuration) {
  function MMKV_EXPORT (line 678) | MMKV_EXPORT bool disableAutoExpire(void *handle) {
  function MMKV_EXPORT (line 686) | MMKV_EXPORT bool enableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 694) | MMKV_EXPORT bool disableCompareBeforeSet(void *handle) {
  function setWantsHandler (line 702) | void setWantsHandler(bool hasHandler, bool wantLog, bool wantContent) {
  function MMKV_EXPORT (line 714) | MMKV_EXPORT bool removeStorage(GoStringWrap_t mmapID, GoStringWrap_t roo...
  function MMKV_EXPORT (line 726) | MMKV_EXPORT bool isMultiProcess(void *handle) {
  function MMKV_EXPORT (line 734) | MMKV_EXPORT bool isReadOnly(void *handle) {
  function MMKV_EXPORT (line 742) | MMKV_EXPORT bool getNameSpace(GoStringWrap_t rootPath) {
  function MMKV_EXPORT (line 751) | MMKV_EXPORT bool checkExist(GoStringWrap_t mmapID, GoStringWrap_t rootPa...
  function MMKV_EXPORT (line 763) | MMKV_EXPORT uint64_t importFrom(void *handle, void *srcHandle) {

FILE: POSIX/golang/golang-bridge.h
  type GoStringWrap (line 29) | struct GoStringWrap {
  type GoStringWrap_t (line 33) | typedef struct GoStringWrap GoStringWrap_t;
  type GoSliceWrap (line 35) | struct GoSliceWrap {
  type GoSliceWrap_t (line 40) | typedef struct GoSliceWrap GoSliceWrap_t;
  type MMKVCreationConfig_t (line 42) | typedef struct {

FILE: POSIX/golang/mmkv.go
  constant MMKVLogDebug (line 60) | MMKVLogDebug = iota
  constant MMKVLogInfo (line 61) | MMKVLogInfo
  constant MMKVLogWarning (line 62) | MMKVLogWarning
  constant MMKVLogError (line 63) | MMKVLogError
  constant MMKVLogNone (line 64) | MMKVLogNone
  constant MMKV_SINGLE_PROCESS (line 68) | MMKV_SINGLE_PROCESS        = 1 << iota
  constant MMKV_MULTI_PROCESS (line 69) | MMKV_MULTI_PROCESS         = 1 << iota
  constant context_MODE_MULTI_PROCESS (line 70) | context_MODE_MULTI_PROCESS = 1 << iota
  constant mmkv_ASHMEM (line 71) | mmkv_ASHMEM                = 1 << iota
  constant mmkv_BACKUP (line 72) | mmkv_BACKUP                = 1 << iota
  constant MMKV_READ_ONLY (line 73) | MMKV_READ_ONLY             = 1 << iota
  constant MMKV_Expire_Never (line 77) | MMKV_Expire_Never  = iota
  constant MMKV_Expire_Minute (line 78) | MMKV_Expire_Minute = 60
  constant MMKV_Expire_Hour (line 79) | MMKV_Expire_Hour   = 60 * 60
  constant MMKV_Expire_Day (line 80) | MMKV_Expire_Day    = 24 * 60 * 60
  constant MMKV_Expire_Month (line 81) | MMKV_Expire_Month  = 30 * 24 * 60 * 60
  constant MMKV_Expire_Year (line 82) | MMKV_Expire_Year   = 365 * 30 * 24 * 60 * 60
  constant MMKV_ON_ERROR_DISCARD (line 86) | MMKV_ON_ERROR_DISCARD = iota
  constant MMKV_ON_ERROR_RECOVER (line 87) | MMKV_ON_ERROR_RECOVER
  type MMBuffer (line 92) | type MMBuffer struct
    method Pointer (line 98) | func (buffer MMBuffer) Pointer() uintptr {
    method Length (line 103) | func (buffer MMBuffer) Length() int {
    method ByteSliceView (line 109) | func (buffer MMBuffer) ByteSliceView() []byte {
    method StringView (line 116) | func (buffer MMBuffer) StringView() string {
    method Destroy (line 121) | func (buffer MMBuffer) Destroy() {
  type Config (line 126) | type Config struct
  type EncryptionConfig (line 137) | type EncryptionConfig struct
  type ExpirationConfig (line 142) | type ExpirationConfig struct
  function configToC (line 147) | func configToC(cfg *Config) C.MMKVCreationConfig_t {
  type MMKV (line 191) | type MMKV interface
  type ctorMMKV (line 313) | type ctorMMKV
    method SetBool (line 482) | func (kv ctorMMKV) SetBool(value bool, key string) bool {
    method SetBoolExpire (line 487) | func (kv ctorMMKV) SetBoolExpire(value bool, key string, expireDuratio...
    method GetBool (line 492) | func (kv ctorMMKV) GetBool(key string) bool {
    method GetBoolWithDefault (line 496) | func (kv ctorMMKV) GetBoolWithDefault(key string, defaultValue bool) b...
    method SetInt32 (line 501) | func (kv ctorMMKV) SetInt32(value int32, key string) bool {
    method SetInt32Expire (line 506) | func (kv ctorMMKV) SetInt32Expire(value int32, key string, expireDurat...
    method GetInt32 (line 511) | func (kv ctorMMKV) GetInt32(key string) int32 {
    method GetInt32WithDefault (line 515) | func (kv ctorMMKV) GetInt32WithDefault(key string, defaultValue int32)...
    method SetUInt32 (line 520) | func (kv ctorMMKV) SetUInt32(value uint32, key string) bool {
    method SetUInt32Expire (line 525) | func (kv ctorMMKV) SetUInt32Expire(value uint32, key string, expireDur...
    method GetUInt32 (line 530) | func (kv ctorMMKV) GetUInt32(key string) uint32 {
    method GetUInt32WithDefault (line 534) | func (kv ctorMMKV) GetUInt32WithDefault(key string, defaultValue uint3...
    method SetInt64 (line 539) | func (kv ctorMMKV) SetInt64(value int64, key string) bool {
    method SetInt64Expire (line 544) | func (kv ctorMMKV) SetInt64Expire(value int64, key string, expireDurat...
    method GetInt64 (line 549) | func (kv ctorMMKV) GetInt64(key string) int64 {
    method GetInt64WithDefault (line 553) | func (kv ctorMMKV) GetInt64WithDefault(key string, defaultValue int64)...
    method SetUInt64 (line 558) | func (kv ctorMMKV) SetUInt64(value uint64, key string) bool {
    method SetUInt64Expire (line 563) | func (kv ctorMMKV) SetUInt64Expire(value uint64, key string, expireDur...
    method GetUInt64 (line 568) | func (kv ctorMMKV) GetUInt64(key string) uint64 {
    method GetUInt64WithDefault (line 572) | func (kv ctorMMKV) GetUInt64WithDefault(key string, defaultValue uint6...
    method SetFloat32 (line 577) | func (kv ctorMMKV) SetFloat32(value float32, key string) bool {
    method SetFloat32Expire (line 582) | func (kv ctorMMKV) SetFloat32Expire(value float32, key string, expireD...
    method GetFloat32 (line 587) | func (kv ctorMMKV) GetFloat32(key string) float32 {
    method GetFloat32WithDefault (line 591) | func (kv ctorMMKV) GetFloat32WithDefault(key string, defaultValue floa...
    method SetFloat64 (line 596) | func (kv ctorMMKV) SetFloat64(value float64, key string) bool {
    method SetFloat64Expire (line 601) | func (kv ctorMMKV) SetFloat64Expire(value float64, key string, expireD...
    method GetFloat64 (line 606) | func (kv ctorMMKV) GetFloat64(key string) float64 {
    method GetFloat64WithDefault (line 610) | func (kv ctorMMKV) GetFloat64WithDefault(key string, defaultValue floa...
    method SetString (line 615) | func (kv ctorMMKV) SetString(value string, key string) bool {
    method SetStringExpire (line 621) | func (kv ctorMMKV) SetStringExpire(value string, key string, expireDur...
    method GetString (line 627) | func (kv ctorMMKV) GetString(key string) string {
    method GetStringBuffer (line 637) | func (kv ctorMMKV) GetStringBuffer(key string) MMBuffer {
    method SetBytes (line 641) | func (kv ctorMMKV) SetBytes(value []byte, key string) bool {
    method SetBytesExpire (line 647) | func (kv ctorMMKV) SetBytesExpire(value []byte, key string, expireDura...
    method GetBytes (line 653) | func (kv ctorMMKV) GetBytes(key string) []byte {
    method GetBytesBuffer (line 663) | func (kv ctorMMKV) GetBytesBuffer(key string) MMBuffer {
    method RemoveKey (line 672) | func (kv ctorMMKV) RemoveKey(key string) {
    method RemoveKeys (line 676) | func (kv ctorMMKV) RemoveKeys(keys []string) {
    method Count (line 681) | func (kv ctorMMKV) Count() uint64 {
    method CountNonExpiredKeys (line 685) | func (kv ctorMMKV) CountNonExpiredKeys() uint64 {
    method allKeys (line 689) | func (kv ctorMMKV) allKeys(filterExpire bool) []string {
    method AllKeys (line 711) | func (kv ctorMMKV) AllKeys() []string {
    method AllNonExpireKeys (line 715) | func (kv ctorMMKV) AllNonExpireKeys() []string {
    method Contains (line 719) | func (kv ctorMMKV) Contains(key string) bool {
    method ClearAll (line 724) | func (kv ctorMMKV) ClearAll() {
    method ClearAllKeepSpace (line 728) | func (kv ctorMMKV) ClearAllKeepSpace() {
    method TotalSize (line 732) | func (kv ctorMMKV) TotalSize() uint64 {
    method ActualSize (line 736) | func (kv ctorMMKV) ActualSize() uint64 {
    method MMAP_ID (line 740) | func (kv ctorMMKV) MMAP_ID() string {
    method Sync (line 745) | func (kv ctorMMKV) Sync(sync bool) {
    method ClearMemoryCache (line 749) | func (kv ctorMMKV) ClearMemoryCache() {
    method Trim (line 753) | func (kv ctorMMKV) Trim() {
    method ImportFrom (line 757) | func (kv ctorMMKV) ImportFrom(src MMKV) uint64 {
    method Close (line 765) | func (kv ctorMMKV) Close() {
    method ReKey (line 769) | func (kv ctorMMKV) ReKey(newKey string, aes256 bool) bool {
    method CheckReSetCryptKey (line 774) | func (kv ctorMMKV) CheckReSetCryptKey(key string, aes256 bool) {
    method CryptKey (line 778) | func (kv ctorMMKV) CryptKey() string {
    method EnableAutoKeyExpire (line 789) | func (kv ctorMMKV) EnableAutoKeyExpire(expireDurationInSecond uint32) ...
    method DisableAutoKeyExpire (line 794) | func (kv ctorMMKV) DisableAutoKeyExpire() bool {
    method EnableCompareBeforeSet (line 799) | func (kv ctorMMKV) EnableCompareBeforeSet() bool {
    method DisableCompareBeforeSet (line 804) | func (kv ctorMMKV) DisableCompareBeforeSet() bool {
    method IsMultiProcess (line 809) | func (kv ctorMMKV) IsMultiProcess() bool {
    method IsReadOnly (line 814) | func (kv ctorMMKV) IsReadOnly() bool {
  function Version (line 316) | func Version() string {
  function InitializeMMKV (line 331) | func InitializeMMKV(rootDir string) {
  function InitializeMMKVWithLogLevel (line 337) | func InitializeMMKVWithLogLevel(rootDir string, logLevel int) {
  function InitializeMMKVWithLogLevelAndHandler (line 342) | func InitializeMMKVWithLogLevelAndHandler(rootDir string, logLevel int, ...
  type logHandlerAdapter (line 350) | type logHandlerAdapter struct
    method WantLogRedirect (line 355) | func (a *logHandlerAdapter) WantLogRedirect() bool { return true }
    method MMKVLog (line 356) | func (a *logHandlerAdapter) MMKVLog(level int, file string, line int, ...
  function OnExit (line 361) | func OnExit() {
  function PageSize (line 366) | func PageSize() int32 {
  function DefaultMMKV (line 371) | func DefaultMMKV() MMKV {
  function DefaultMMKVWithMode (line 376) | func DefaultMMKVWithMode(mode int) MMKV {
  function DefaultMMKVWithModeAndCryptKey (line 381) | func DefaultMMKVWithModeAndCryptKey(mode int, cryptKey string, aes256 bo...
  function DefaultMMKVWithConfig (line 386) | func DefaultMMKVWithConfig(config Config) MMKV {
  function MMKVWithID (line 393) | func MMKVWithID(mmapID string) MMKV {
  function MMKVWithIDAndConfig (line 397) | func MMKVWithIDAndConfig(mmapID string, config Config) MMKV {
  function MMKVWithIDAndExpectedCapacity (line 404) | func MMKVWithIDAndExpectedCapacity(mmapID string, expectedCapacity uint6...
  function MMKVWithIDAndMode (line 409) | func MMKVWithIDAndMode(mmapID string, mode int) MMKV {
  function MMKVWithIDAndModeAndCryptKey (line 414) | func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey stri...
  function BackupOneToDirectory (line 419) | func BackupOneToDirectory(mmapID string, dstDir string) bool {
  function RestoreOneFromDirectory (line 426) | func RestoreOneFromDirectory(mmapID string, srcDir string) bool {
  function BackupAllToDirectory (line 434) | func BackupAllToDirectory(dstDir string) uint64 {
  function RestoreAllFromDirectory (line 442) | func RestoreAllFromDirectory(srcDir string) uint64 {
  function RemoveStorage (line 450) | func RemoveStorage(mmapID string) bool {
  function GetRootDir (line 456) | func GetRootDir() string {
  function CheckExist (line 463) | func CheckExist(mmapID string) bool {
  function GetNameSpace (line 470) | func GetNameSpace(rootDir string) NameSpace {
  function DefaultNameSpace (line 478) | func DefaultNameSpace() NameSpace {
  type NameSpace (line 819) | type NameSpace struct
    method GetRootDir (line 823) | func (ns *NameSpace) GetRootDir() string {
    method MMKVWithID (line 828) | func (ns *NameSpace) MMKVWithID(mmapID string) MMKV {
    method MMKVWithIDAndConfig (line 834) | func (ns *NameSpace) MMKVWithIDAndConfig(mmapID string, config Config)...
    method MMKVWithIDAndExpectedCapacity (line 842) | func (ns *NameSpace) MMKVWithIDAndExpectedCapacity(mmapID string, expe...
    method MMKVWithIDAndMode (line 849) | func (ns *NameSpace) MMKVWithIDAndMode(mmapID string, mode int) MMKV {
    method MMKVWithIDAndModeAndCryptKey (line 856) | func (ns *NameSpace) MMKVWithIDAndModeAndCryptKey(mmapID string, mode ...
    method BackupOneToDirectory (line 863) | func (ns *NameSpace) BackupOneToDirectory(mmapID string, dstDir string...
    method RestoreOneFromDirectory (line 870) | func (ns *NameSpace) RestoreOneFromDirectory(mmapID string, srcDir str...
    method BackupAllToDirectory (line 878) | func (ns *NameSpace) BackupAllToDirectory(dstDir string) uint64 {
    method RestoreAllFromDirectory (line 886) | func (ns *NameSpace) RestoreAllFromDirectory(srcDir string) uint64 {
    method RemoveStorage (line 894) | func (ns *NameSpace) RemoveStorage(mmapID string) bool {
    method CheckExist (line 901) | func (ns *NameSpace) CheckExist(mmapID string) bool {

FILE: POSIX/golang/mmkv_test.go
  function TestVersionEmpty (line 28) | func TestVersionEmpty(t *testing.T) {

FILE: POSIX/golang/test/main.go
  function main (line 13) | func main() {
  function functionalTest (line 43) | func functionalTest() {
  function testMMKV (line 103) | func testMMKV(mmapID string, cryptKey string, decodeOnly bool, aes bool)...
  function testMMKVImp (line 109) | func testMMKVImp(kv mmkv.MMKV, decodeOnly bool) {
  function testReKey (line 163) | func testReKey() {
  function testBackup (line 183) | func testBackup() {
  function testExpectedCapacity (line 193) | func testExpectedCapacity() {
  function testRestore (line 220) | func testRestore() {
  function testAutoExpire (line 248) | func testAutoExpire() {
  function testCompareBeforeSet (line 277) | func testCompareBeforeSet() {
  function testRemoveStorage (line 330) | func testRemoveStorage() {
  function testReadOnly (line 352) | func testReadOnly() {
  function testNameSpace (line 377) | func testNameSpace() {
  function testImport (line 384) | func testImport() {
  type myHandler (line 424) | type myHandler struct
    method WantLogRedirect (line 428) | func (h *myHandler) WantLogRedirect() bool { return true }
    method MMKVLog (line 430) | func (h *myHandler) MMKVLog(level int, file string, line int, function...
    method OnMMKVCRCCheckFail (line 447) | func (h *myHandler) OnMMKVCRCCheckFail(mmapID string) int {
    method OnMMKVFileLengthError (line 452) | func (h *myHandler) OnMMKVFileLengthError(mmapID string) int {
    method WantContentChangeNotification (line 457) | func (h *myHandler) WantContentChangeNotification() bool { return true }
    method OnContentChangedByOuterProcess (line 459) | func (h *myHandler) OnContentChangedByOuterProcess(mmapID string) {
    method OnMMKVContentLoadSuccessfully (line 463) | func (h *myHandler) OnMMKVContentLoadSuccessfully(mmapID string) {

FILE: Python/demo.py
  function functional_test (line 11) | def functional_test(mmap_id, decode_only):
  function functional_test_imp (line 19) | def functional_test_imp(kv, decode_only):
  function test_backup (line 66) | def test_backup():
  function utf8len (line 81) | def utf8len(s):
  function test_expected_capacity (line 85) | def test_expected_capacity():
  function test_restore (line 109) | def test_restore():
  function test_auto_expire (line 133) | def test_auto_expire():
  function test_compare_before_set (line 159) | def test_compare_before_set():
  function test_remove_storage (line 205) | def test_remove_storage():
  function test_read_only (line 229) | def test_read_only():
  function test_import (line 251) | def test_import():
  function test_namespace (line 284) | def test_namespace():
  function test_rekey (line 291) | def test_rekey():
  function logger (line 313) | def logger(log_level, file, line, function, message):
  function error_handler (line 322) | def error_handler(mmap_id, error_type):
  function content_change_handler (line 327) | def content_change_handler(mmap_id):

FILE: Python/libmmkv_python.cpp
  function MMKVConfig (line 35) | static MMKVConfig pyArgsToConfig(MMKVMode mode, const string &cryptKey, ...
  function MMBuffer (line 53) | static MMBuffer pyBytes2MMBuffer(const py::bytes &bytes) {
  class PyMMKVHandler (line 69) | class PyMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 71) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 77) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 84) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 91) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 97) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function PYBIND11_MODULE (line 106) | PYBIND11_MODULE(mmkv, m) {

FILE: Python/setup.py
  class CMakeExtension (line 15) | class CMakeExtension(Extension):
    method __init__ (line 16) | def __init__(self, name, sourcedir=''):
  class CMakeBuild (line 21) | class CMakeBuild(build_ext):
    method run (line 22) | def run(self):
    method build_extension (line 37) | def build_extension(self, ext):

FILE: Python/unit_test.py
  function test_bool (line 11) | def test_bool(kv):
  function test_int (line 27) | def test_int(kv):
  function test_uint (line 51) | def test_uint(kv):
  function test_long_int (line 68) | def test_long_int(kv):
  function test_long_uint (line 92) | def test_long_uint(kv):
  function is_float_equal (line 109) | def is_float_equal(a, b, accuracy=1e-09):
  function test_float (line 113) | def test_float(kv):
  function test_string (line 137) | def test_string(kv):
  function test_bytes (line 157) | def test_bytes(kv):
  function test_equal (line 183) | def test_equal(kv, mmap_id):

FILE: Script/dumpJavaSignature.py
  function get_jni_signature (line 20) | def get_jni_signature(return_type, params):
  function get_ctypes_signature (line 35) | def get_ctypes_signature(return_type, params):
  function parse_method_declaration (line 53) | def parse_method_declaration(declaration):

FILE: Win32/Win32Demo/Win32Demo.cpp
  function wstring (line 30) | wstring getAppDataRoaming(const wstring &company, const wstring &appName) {
  function string (line 44) | string to_string(const vector<string> &arr, const char *sp = ", ") {
  function functionalTest (line 56) | void functionalTest(MMKV *mmkv, bool decodeOnly) {
  function DWORD (line 106) | DWORD WINAPI threadFunction(LPVOID lpParam) {
  function threadTest (line 126) | void threadTest() {
  function brutleTest (line 138) | void brutleTest() {
  function processTest (line 146) | void processTest() {
  function getpagesize (line 180) | size_t getpagesize(void) {
  function cornetSizeTest (line 186) | void cornetSizeTest() {
  function fastRemoveCornetSizeTest (line 202) | void fastRemoveCornetSizeTest() {
  function testBackup (line 226) | void testBackup() {
  function testRestore (line 262) | void testRestore() {
  function testAutoExpire (line 294) | void testAutoExpire() {
  function testExpectedCapacity (line 335) | void testExpectedCapacity() {
  function testRemoveStorage (line 357) | void testRemoveStorage() {
  function setReadOnly (line 386) | void setReadOnly(const MMKVPath_t& path, bool readOnly) {
  function testReadOnly (line 410) | void testReadOnly() {
  function testNameSpace (line 436) | void testNameSpace() {
  function testImport (line 444) | void testImport() {
  function MMKV (line 472) | MMKV* testMMKV(const string& mmapID, const string* cryptKey, bool aes256...
  function testReKey (line 478) | void testReKey() {
  function WriteUTF8ToStream (line 498) | void WriteUTF8ToStream(const char* utf8_str) {
  function PrintUTF8 (line 522) | void PrintUTF8(const char* format, ...) {
  function LogHandler (line 550) | static void
  function main (line 570) | int main() {

FILE: Win32/Win32DemoProcess/Win32DemoProcess.cpp
  function wstring (line 30) | wstring getAppDataRoaming(const wstring &company, const wstring &appName) {
  function brutleTest (line 49) | void brutleTest(DWORD processID) {
  function main (line 70) | int main() {

FILE: flutter/mmkv/example/android/app/src/main/java/com/tencent/mmkv_example/MainActivity.java
  class MainActivity (line 25) | public class MainActivity extends FlutterActivity {}

FILE: flutter/mmkv/example/ios/Flutter/ephemeral/flutter_lldb_helper.py
  function handle_new_rx_page (line 7) | def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_d...
  function __lldb_init_module (line 24) | def __lldb_init_module(debugger: lldb.SBDebugger, _):

FILE: flutter/mmkv/example/lib/main.dart
  function main (line 32) | void main()
  function _testNameSpace (line 55) | Future<void> _testNameSpace()
  function _testMMKVImp (line 63) | void _testMMKVImp(MMKV mmkv, bool decodeOnly)
  class MyMMKVHandler (line 125) | class MyMMKVHandler extends MMKVHandler {
    method wantLogRedirect (line 127) | bool wantLogRedirect()
    method mmkvLog (line 133) | void mmkvLog(MMKVLogLevel level, String file, int line, String functio...
    method onMMKVCRCCheckFail (line 138) | MMKVRecoverStrategic onMMKVCRCCheckFail(String mmapID)
    method onMMKVFileLengthError (line 144) | MMKVRecoverStrategic onMMKVFileLengthError(String mmapID)
    method wantContentChangeNotification (line 150) | bool wantContentChangeNotification()
    method onContentChangedByOuterProcess (line 156) | void onContentChangedByOuterProcess(String mmapID)
  class MyApp (line 161) | class MyApp extends StatefulWidget {
    method createState (line 165) | _MyAppState createState()
  class _MyAppState (line 168) | class _MyAppState extends State<MyApp> {
    method initState (line 170) | void initState()
    method initPlatformState (line 176) | Future<void> initPlatformState()
    method build (line 186) | Widget build(BuildContext context)
    method functionalTest (line 233) | void functionalTest()
    method testMMKV (line 319) | MMKV testMMKV(String mmapID, String? cryptKey, bool aes256, bool decod...
    method testReKey (line 325) | void testReKey()
    method testBackup (line 342) | void testBackup()
    method testRestore (line 358) | void testRestore()
    method testAutoExpire (line 386) | void testAutoExpire()
    method testCompareBeforeSet (line 425) | void testCompareBeforeSet()
    method testRemoveStorageAndCheckExist (line 470) | void testRemoveStorageAndCheckExist()
    method testReadOnly (line 500) | void testReadOnly()
    method testImport (line 528) | void testImport()
  function _isDarwin (line 569) | bool _isDarwin()

FILE: flutter/mmkv/example/linux/flutter/generated_plugin_registrant.cc
  function fl_register_plugins (line 11) | void fl_register_plugins(FlPluginRegistry* registry) {

FILE: flutter/mmkv/example/linux/runner/main.cc
  function main (line 3) | int main(int argc, char** argv) {

FILE: flutter/mmkv/example/linux/runner/my_application.cc
  type _MyApplication (line 10) | struct _MyApplication {
  function my_application_activate (line 18) | static void my_application_activate(GApplication* application) {
  function gboolean (line 66) | static gboolean my_application_local_command_line(GApplication* applicat...
  function my_application_startup (line 85) | static void my_application_startup(GApplication* application) {
  function my_application_shutdown (line 94) | static void my_application_shutdown(GApplication* application) {
  function my_application_dispose (line 103) | static void my_application_dispose(GObject* object) {
  function my_application_class_init (line 109) | static void my_application_class_init(MyApplicationClass* klass) {
  function my_application_init (line 117) | static void my_application_init(MyApplication* self) {}
  function MyApplication (line 119) | MyApplication* my_application_new() {

FILE: flutter/mmkv/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts
  function onAbilityCreateCallback (line 23) | async function onAbilityCreateCallback() {
  function addAbilityMonitorCallback (line 27) | async function addAbilityMonitorCallback(err: any) {
  class OpenHarmonyTestRunner (line 31) | class OpenHarmonyTestRunner implements TestRunner {
    method constructor (line 32) | constructor() {
    method onPrepare (line 35) | onPrepare() {
    method onRun (line 39) | async onRun() {

FILE: flutter/mmkv/example/windows/flutter/generated_plugin_registrant.cc
  function RegisterPlugins (line 11) | void RegisterPlugins(flutter::PluginRegistry* registry) {

FILE: flutter/mmkv/example/windows/runner/flutter_window.cpp
  function LRESULT (line 50) | LRESULT

FILE: flutter/mmkv/example/windows/runner/flutter_window.h
  function class (line 12) | class FlutterWindow : public Win32Window {

FILE: flutter/mmkv/example/windows/runner/main.cpp
  function wWinMain (line 8) | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,

FILE: flutter/mmkv/example/windows/runner/utils.cpp
  function CreateAndAttachConsole (line 10) | void CreateAndAttachConsole() {
  function GetCommandLineArguments (line 24) | std::vector<std::string> GetCommandLineArguments() {
  function Utf8FromUtf16 (line 44) | std::string Utf8FromUtf16(const wchar_t* utf16_string) {

FILE: flutter/mmkv/example/windows/runner/win32_window.cpp
  function Scale (line 36) | int Scale(int source, double scale_factor) {
  function EnableFullDpiSupportIfAvailable (line 42) | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
  class WindowClassRegistrar (line 59) | class WindowClassRegistrar {
    method WindowClassRegistrar (line 64) | static WindowClassRegistrar* GetInstance() {
    method WindowClassRegistrar (line 80) | WindowClassRegistrar() = default;
  function wchar_t (line 89) | const wchar_t* WindowClassRegistrar::GetWindowClass() {
  function LRESULT (line 157) | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
  function LRESULT (line 176) | LRESULT
  function Win32Window (line 236) | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
  function RECT (line 252) | RECT Win32Window::GetClientArea() {
  function HWND (line 258) | HWND Win32Window::GetHandle() {

FILE: flutter/mmkv/example/windows/runner/win32_window.h
  type Size (line 21) | struct Size {

FILE: flutter/mmkv/lib/mmkv.dart
  type MMKVMode (line 35) | enum MMKVMode {
  class MMBuffer (line 43) | class MMBuffer {
    method fromList (line 70) | MMBuffer? fromList(List<int>? list)
    method _fromPointer (line 85) | MMBuffer _fromPointer(Pointer<Uint8> ptr, int length, {bool fromNative...
    method _copyFromPointer (line 95) | MMBuffer _copyFromPointer(Pointer<Uint8> ptr, int length)
    method destroy (line 106) | void destroy()
    method asList (line 121) | Uint8List? asList()
    method takeList (line 130) | Uint8List? takeList()
  class NameSpace (line 141) | class NameSpace {
    method mmkv (line 155) | MMKV mmkv(String mmapID, {MMKVMode mode = MMKVMode.SINGLE_PROCESS_MODE...
    method backupOneToDirectory (line 165) | bool backupOneToDirectory(String mmapID, String dstDir)
    method restoreOneMMKVFromDirectory (line 170) | bool restoreOneMMKVFromDirectory(String mmapID, String srcDir)
    method isFileValid (line 176) | bool isFileValid(String mmapID)
    method removeStorage (line 182) | bool removeStorage(String mmapID)
    method checkExist (line 187) | bool checkExist(String mmapID)
  class MMKV (line 194) | class MMKV {
    method initialize (line 216) | Future<String> initialize({String? rootDir, String? groupDir, MMKVLogL...
    method nameSpace (line 246) | NameSpace nameSpace(String path)
    method defaultNameSpace (line 260) | NameSpace defaultNameSpace()
    method defaultMMKV (line 277) | MMKV defaultMMKV({String? cryptKey, bool aes256 = false, int expectedC...
    method encodeBool (line 342) | bool encodeBool(String key, bool value, [int? expireDurationInSecond])
    method decodeBool (line 351) | bool decodeBool(String key, {bool defaultValue = false})
    method encodeInt32 (line 362) | bool encodeInt32(String key, int value, [int? expireDurationInSecond])
    method decodeInt32 (line 372) | int decodeInt32(String key, {int defaultValue = 0})
    method encodeInt (line 381) | bool encodeInt(String key, int value, [int? expireDurationInSecond])
    method decodeInt (line 389) | int decodeInt(String key, {int defaultValue = 0})
    method encodeDouble (line 398) | bool encodeDouble(String key, double value, [int? expireDurationInSeco...
    method decodeDouble (line 406) | double decodeDouble(String key, {double defaultValue = 0})
    method encodeString (line 416) | bool encodeString(String key, String? value, [int? expireDurationInSec...
    method decodeString (line 435) | String? decodeString(String key)
    method encodeBytes (line 470) | bool encodeBytes(String key, MMBuffer? value, [int? expireDurationInSe...
    method decodeBytes (line 498) | MMBuffer? decodeBytes(String key)
    method reKey (line 524) | bool reKey(String? cryptKey, {bool aes256 = false})
    method checkReSetCryptKey (line 552) | void checkReSetCryptKey(String cryptKey, {bool aes256 = false})
    method valueSize (line 560) | int valueSize(String key, bool actualSize)
    method writeValueToNativeBuffer (line 571) | int writeValueToNativeBuffer(String key, MMBuffer buffer)
    method _allKeysImp (line 588) | List<String> _allKeysImp(bool filterExpire)
    method containsKey (line 618) | bool containsKey(String key)
    method removeValue (line 652) | void removeValue(String key)
    method removeValues (line 659) | void removeValues(List<String> keys)
    method clearAll (line 681) | void clearAll({bool keepSpace = false})
    method sync (line 690) | void sync(bool sync)
    method clearMemoryCache (line 695) | void clearMemoryCache()
    method trim (line 713) | void trim()
    method importFrom (line 720) | int importFrom(MMKV src)
    method close (line 726) | void close()
    method backupOneToDirectory (line 733) | bool backupOneToDirectory(String mmapID, String dstDir, {String? rootD...
    method restoreOneMMKVFromDirectory (line 750) | bool restoreOneMMKVFromDirectory(String mmapID, String srcDir, {String...
    method backupAllToDirectory (line 765) | int backupAllToDirectory(String dstDir)
    method restoreAllFromDirectory (line 776) | int restoreAllFromDirectory(String srcDir)
    method enableAutoKeyExpire (line 789) | bool enableAutoKeyExpire(int expiredInSeconds)
    method disableAutoKeyExpire (line 794) | bool disableAutoKeyExpire()
    method enableCompareBeforeSet (line 799) | bool enableCompareBeforeSet()
    method disableCompareBeforeSet (line 804) | bool disableCompareBeforeSet()
    method isFileValid (line 810) | bool isFileValid(String mmapID, {String? rootDir})
    method removeStorage (line 824) | bool removeStorage(String mmapID, {String? rootDir})
    method checkExist (line 837) | bool checkExist(String mmapID, {String? rootDir})
    method groupPath (line 850) | String? groupPath()
    method checkContentChangedByOuterProcess (line 855) | void checkContentChangedByOuterProcess()
  function _isDarwin (line 860) | bool _isDarwin()
  function _logRedirect (line 864) | void _logRedirect(int logLevel, Pointer<Utf8> file, int line, Pointer<Ut...
  type _MMKVErrorType (line 892) | enum _MMKVErrorType {
  function _errorHandler (line 897) | int _errorHandler(Pointer<Utf8> mmapIDPtr, int errorType)
  function _contentChangeHandler (line 915) | void _contentChangeHandler(Pointer<Utf8> mmapIDPtr)
  function _contentLoadedHandler (line 925) | void _contentLoadedHandler(Pointer<Utf8> mmapIDPtr)
  function _bool2Int (line 932) | int _bool2Int(bool value)
  function _int2Bool (line 936) | bool _int2Bool(int value)
  function _string2Pointer (line 940) | Pointer<Utf8> _string2Pointer(String? str)
  function _pointer2String (line 947) | String? _pointer2String(Pointer<Utf8>? ptr)
  function _buffer2String (line 954) | String? _buffer2String(Pointer<Uint8>? ptr, int length)

FILE: flutter/mmkv/test/mmkv_test.dart
  function main (line 24) | void main()

FILE: flutter/mmkv/tool/fix_mmkv_plugin_name.rb
  function fix_mmkv_plugin_name (line 1) | def fix_mmkv_plugin_name(flutter_application_path)

FILE: flutter/mmkv/tool/mmkvpodhelper.rb
  function mmkv_fix_plugin_name (line 21) | def mmkv_fix_plugin_name(flutter_application_path, is_module)

FILE: flutter/mmkv_android/android/src/main/java/com/tencent/mmkv/MMKVPlugin.java
  class MMKVPlugin (line 32) | public class MMKVPlugin implements FlutterPlugin, MethodCallHandler {
    method onAttachedToEngine (line 40) | @Override
    method onMethodCall (line 49) | @Override
    method onDetachedFromEngine (line 69) | @Override
    method loadLibrary (line 76) | private static void loadLibrary() {

FILE: flutter/mmkv_android/lib/mmkv_android.dart
  class MMKVPlatformAndroid (line 27) | class MMKVPlatformAndroid extends MMKVPluginPlatformFFI {
    method registerWith (line 29) | void registerWith()
    method nativeLib (line 36) | DynamicLibrary nativeLib()
    method initialize (line 49) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
  function _string2Pointer (line 64) | Pointer<Utf8> _string2Pointer(String? str)
  function _pointer2String (line 71) | String? _pointer2String(Pointer<Utf8>? ptr)

FILE: flutter/mmkv_ios/darwin/Classes/flutter-bridge.h
  type MMKVErrorType (line 13) | enum MMKVErrorType : int {

FILE: flutter/mmkv_ios/lib/mmkv_ios.dart
  class MMKVPlatformIOS (line 27) | class MMKVPlatformIOS extends MMKVPluginPlatformFFI {
    method registerWith (line 28) | void registerWith()
    method nativeFuncName (line 33) | String nativeFuncName(String name)
    method nativeLib (line 40) | DynamicLibrary nativeLib()
    method initialize (line 53) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
  function _string2Pointer (line 66) | Pointer<Utf8> _string2Pointer(String? str)
  function _pointer2String (line 73) | String? _pointer2String(Pointer<Utf8>? ptr)

FILE: flutter/mmkv_linux/lib/mmkv_linux.dart
  class MMKVPlatformLinux (line 27) | class MMKVPlatformLinux extends MMKVPluginPlatformFFI {
    method registerWith (line 28) | void registerWith()
    method nativeLib (line 35) | DynamicLibrary nativeLib()
    method initialize (line 46) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
  function _string2Pointer (line 57) | Pointer<Utf8> _string2Pointer(String? str)
  function _pointer2String (line 64) | String? _pointer2String(Pointer<Utf8>? ptr)

FILE: flutter/mmkv_linux/linux/flutter-bridge.cpp
  class FlutterMMKVHandler (line 42) | class FlutterMMKVHandler : public mmkv::MMKVHandler {
    method mmkvLog (line 49) | void mmkvLog(MMKVLogLevel level, const char *file, int line, const cha...
    method MMKVRecoverStrategic (line 55) | MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) ove...
    method MMKVRecoverStrategic (line 62) | MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) ...
    method onContentChangedByOuterProcess (line 69) | void onContentChangedByOuterProcess(const std::string &mmapID) override {
    method onMMKVContentLoadSuccessfully (line 75) | void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
  function MMKV_EXPORT (line 84) | MMKV_EXPORT void *mmkvInitialize(const char *rootDir, int32_t logLevel, ...
  function MMKV_EXPORT (line 99) | MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const ...
  function MMKV_EXPORT (line 163) | MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey, boo...
  function MMKV_EXPORT (line 196) | MMKV_EXPORT const char *mmapID(void *handle) {
  function MMKV_EXPORT (line 204) | MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) {
  function MMKV_EXPORT (line 213) | MMKV_EXPORT bool encodeBool_v2(void *handle, const char *oKey, bool valu...
  function MMKV_EXPORT (line 222) | MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool default...
  function MMKV_EXPORT (line 231) | MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t val...
  function MMKV_EXPORT (line 240) | MMKV_EXPORT bool encodeInt32_v2(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 249) | MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t ...
  function MMKV_EXPORT (line 258) | MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t val...
  function MMKV_EXPORT (line 267) | MMKV_EXPORT bool encodeInt64_v2(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 276) | MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t ...
  function MMKV_EXPORT (line 285) | MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double val...
  function MMKV_EXPORT (line 294) | MMKV_EXPORT bool encodeDouble_v2(void *handle, const char *oKey, double ...
  function MMKV_EXPORT (line 303) | MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double d...
  function MMKV_EXPORT (line 312) | MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValu...
  function MMKV_EXPORT (line 327) | MMKV_EXPORT bool encodeBytes_v2(void *handle, const char *oKey, void *oV...
  function MMKV_EXPORT (line 342) | MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *...
  function MMKV_EXPORT (line 374) | MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length, bool a...
  function MMKV_EXPORT (line 387) | MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) {
  function MMKV_EXPORT (line 403) | MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t l...
  function MMKV_EXPORT (line 417) | MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) {
  function MMKV_EXPORT (line 427) | MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *point...
  function MMKV_EXPORT (line 436) | MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t...
  function MMKV_EXPORT (line 465) | MMKV_EXPORT bool containsKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 474) | MMKV_EXPORT uint64_t count(void *handle, bool filterExpire) {
  function MMKV_EXPORT (line 482) | MMKV_EXPORT uint64_t totalSize(void *handle) {
  function MMKV_EXPORT (line 490) | MMKV_EXPORT uint64_t actualSize(void *handle) {
  function MMKV_EXPORT (line 498) | MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) {
  function MMKV_EXPORT (line 506) | MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint...
  function MMKV_EXPORT (line 522) | MMKV_EXPORT void clearAll(void *handle, bool keepSpace) {
  function MMKV_EXPORT (line 529) | MMKV_EXPORT void mmkvSync(void *handle, bool sync) {
  function MMKV_EXPORT (line 536) | MMKV_EXPORT void clearMemoryCache(void *handle) {
  function MMKV_EXPORT (line 543) | MMKV_EXPORT int32_t pageSize() {
  function MMKV_EXPORT (line 547) | MMKV_EXPORT const char *version() {
  function MMKV_EXPORT (line 551) | MMKV_EXPORT void trim(void *handle) {
  function MMKV_EXPORT (line 558) | MMKV_EXPORT void mmkvClose(void *handle) {
  function MMKV_EXPORT (line 565) | MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) {
  function MMKV_EXPORT (line 569) | MMKV_EXPORT bool backupOne(const char *mmapID, const char *dstDir, const...
  function MMKV_EXPORT (line 580) | MMKV_EXPORT bool restoreOne(const char *mmapID, const char *srcDir, cons...
  function MMKV_EXPORT (line 591) | MMKV_EXPORT uint64_t backupAll(const char *dstDir/*, const char *rootPat...
  function MMKV_EXPORT (line 604) | MMKV_EXPORT uint64_t restoreAll(const char *srcDir/*, const char *rootPa...
  function MMKV_EXPORT (line 617) | MMKV_EXPORT bool enableAutoExpire(void *handle, uint32_t expireDuration) {
  function MMKV_EXPORT (line 625) | MMKV_EXPORT bool disableAutoExpire(void *handle) {
  function MMKV_EXPORT (line 633) | MMKV_EXPORT bool enableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 641) | MMKV_EXPORT bool disableCompareBeforeSet(void *handle) {
  function MMKV_EXPORT (line 649) | MMKV_EXPORT bool isFileValid(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 659) | MMKV_EXPORT bool removeStorage(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 669) | MMKV_EXPORT bool isMultiProcess(void *handle) {
  function MMKV_EXPORT (line 677) | MMKV_EXPORT bool isReadOnly(void *handle) {
  function MMKV_EXPORT (line 685) | MMKV_EXPORT void registerErrorHandler(ErrorCallback_t callback) {
  function MMKV_EXPORT (line 692) | MMKV_EXPORT void registerContentChangeNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 699) | MMKV_EXPORT void registerContentLoadedNotify(ContenctChangeCallback_t ca...
  function MMKV_EXPORT (line 706) | MMKV_EXPORT void checkContentChanged(void *handle) {
  function MMKV_EXPORT (line 713) | MMKV_EXPORT bool getNameSpace(const char *rootPath) {
  function MMKV_EXPORT (line 724) | MMKV_EXPORT bool checkExist(const char *mmapID, const char *rootPath) {
  function MMKV_EXPORT (line 734) | MMKV_EXPORT size_t importFrom(void *handle, void *srcHandle) {
  function MMKV_EXPORT (line 743) | MMKV_EXPORT void freePtr(void *ptr) {

FILE: flutter/mmkv_linux/linux/mmkv_linux_plugin.cc
  function mmkv_linux_plugin_register_with_registrar (line 83) | void mmkv_linux_plugin_register_with_registrar(FlPluginRegistrar* regist...

FILE: flutter/mmkv_ohos/lib/mmkv_ohos.dart
  class MMKVPlatformOHOS (line 28) | class MMKVPlatformOHOS extends MMKVPluginPlatformFFI {
    method registerWith (line 30) | void registerWith()
    method nativeLib (line 37) | DynamicLibrary nativeLib()
    method initialize (line 44) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
    method getApplicationDocumentsPath (line 66) | Future<String> getApplicationDocumentsPath()
    method getTemporaryPath (line 76) | Future<String> getTemporaryPath()

FILE: flutter/mmkv_platform_interface/lib/mmkv_platform_ffi.dart
  class MMKVPluginPlatformFFI (line 27) | class MMKVPluginPlatformFFI extends MMKVPluginPlatform {
    method nativeLib (line 29) | DynamicLibrary nativeLib()
    method nativeFuncName (line 34) | String nativeFuncName(String name)
    method getMMKVWithIDFunc (line 39) | Pointer<Void> Function(Pointer<Utf8> mmapID, int, Pointer<Utf8> cryptK...
    method getDefaultMMKVFunc (line 48) | Pointer<Void> Function(int, Pointer<Utf8> cryptKey, int aes256, int ex...
    method mmapIDFunc (line 54) | Pointer<Utf8> Function(Pointer<Void>) mmapIDFunc()
    method encodeBoolFunc (line 59) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeBoolFunc()
    method encodeBoolV2Func (line 64) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeBoolV2Func()
    method decodeBoolFunc (line 71) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeBoolFunc()
    method encodeInt32Func (line 76) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeInt32Func()
    method encodeInt32V2Func (line 81) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeInt32V2Func()
    method decodeInt32Func (line 88) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeInt32Func()
    method encodeInt64Func (line 93) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeInt64Func()
    method encodeInt64V2Func (line 98) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeInt64V2Func()
    method decodeInt64Func (line 105) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeInt64Func()
    method encodeDoubleFunc (line 110) | int Function(Pointer<Void>, Pointer<Utf8>, double) encodeDoubleFunc()
    method encodeDoubleV2Func (line 115) | int Function(Pointer<Void>, Pointer<Utf8>, double, int) encodeDoubleV2...
    method decodeDoubleFunc (line 122) | double Function(Pointer<Void>, Pointer<Utf8>, double) decodeDoubleFunc()
    method encodeBytesFunc (line 127) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int) encode...
    method encodeBytesV2Func (line 134) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int, int) e...
    method decodeBytesFunc (line 141) | Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint64>)...
    method reKeyFunc (line 148) | int Function(Pointer<Void>, Pointer<Uint8>, int length, int aes256) re...
    method cryptKeyFunc (line 153) | Pointer<Uint8> Function(Pointer<Void>, Pointer<Uint64>) cryptKeyFunc()
    method checkReSetCryptKeyFunc (line 158) | void Function(Pointer<Void>, Pointer<Uint8>, int length, int aes256) c...
    method valueSizeFunc (line 165) | int Function(Pointer<Void>, Pointer<Utf8>, int) valueSizeFunc()
    method writeValueToNBFunc (line 170) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>, int) writeVa...
    method allKeysFunc (line 177) | int Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>, Pointer<P...
    method containsKeyFunc (line 185) | int Function(Pointer<Void>, Pointer<Utf8>) containsKeyFunc()
    method countFunc (line 190) | int Function(Pointer<Void>, int) countFunc()
    method totalSizeFunc (line 195) | int Function(Pointer<Void>) totalSizeFunc()
    method actualSizeFunc (line 200) | int Function(Pointer<Void>) actualSizeFunc()
    method removeValueForKeyFunc (line 205) | void Function(Pointer<Void>, Pointer<Utf8>) removeValueForKeyFunc()
    method removeValuesForKeysFunc (line 210) | void Function(Pointer<Void>, Pointer<Pointer<Utf8>>, Pointer<Uint32>, ...
    method clearAllFunc (line 217) | void Function(Pointer<Void>, int) clearAllFunc()
    method mmkvSyncFunc (line 222) | void Function(Pointer<Void>, int) mmkvSyncFunc()
    method clearMemoryCacheFunc (line 227) | void Function(Pointer<Void>) clearMemoryCacheFunc()
    method pageSizeFunc (line 232) | int Function() pageSizeFunc()
    method versionFunc (line 237) | Pointer<Utf8> Function() versionFunc()
    method trimFunc (line 242) | void Function(Pointer<Void>) trimFunc()
    method mmkvCloseFunc (line 247) | void Function(Pointer<Void>) mmkvCloseFunc()
    method memcpyFunc (line 252) | void Function(Pointer<Void>, Pointer<Void>, int) memcpyFunc()
    method backupOneFunc (line 257) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> dstDir, Pointer<Utf8>...
    method restoreOneFunc (line 262) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> srcDir, Pointer<Utf8>...
    method backupAllFunc (line 267) | int Function(Pointer<Utf8> dstDir) backupAllFunc()
    method restoreAllFunc (line 272) | int Function(Pointer<Utf8> srcDir) restoreAllFunc()
    method enableAutoExpireFunc (line 277) | bool Function(Pointer<Void>, int) enableAutoExpireFunc()
    method disableAutoExpireFunc (line 282) | bool Function(Pointer<Void>) disableAutoExpireFunc()
    method enableCompareBeforeSetFunc (line 287) | bool Function(Pointer<Void>) enableCompareBeforeSetFunc()
    method disableCompareBeforeSetFunc (line 292) | bool Function(Pointer<Void>) disableCompareBeforeSetFunc()
    method removeStorageFunc (line 297) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) removeStora...
    method isMultiProcessFunc (line 302) | bool Function(Pointer<Void>) isMultiProcessFunc()
    method isReadOnlyFunc (line 307) | bool Function(Pointer<Void>) isReadOnlyFunc()
    method registerErrorHandlerFunc (line 312) | ErrorCallbackRegister registerErrorHandlerFunc()
    method registerContentHandlerFunc (line 317) | ContentCallbackRegister registerContentHandlerFunc()
    method registerContentLoadedHandlerFunc (line 322) | ContentCallbackRegister registerContentLoadedHandlerFunc()
    method checkContentChangedFunc (line 327) | void Function(Pointer<Void> p1) checkContentChangedFunc()
    method getNameSpaceFunc (line 332) | bool Function(Pointer<Utf8> rootPath) getNameSpaceFunc()
    method checkExistFunc (line 337) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) checkExistF...
    method isFileValidFunc (line 342) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) isFileValid...
    method groupPathFunc (line 347) | Pointer<Utf8> Function() groupPathFunc()
    method importFromFunc (line 352) | int Function(Pointer<Void> handle, Pointer<Void> srcHandle) importFrom...
    method freePtrFunc (line 357) | void Function(Pointer) freePtrFunc()

FILE: flutter/mmkv_platform_interface/lib/mmkv_platform_interface.dart
  type MMKVLogLevel (line 28) | enum MMKVLogLevel { Debug, Info, Warning, Error, None }
  type MMKVRecoverStrategic (line 31) | enum MMKVRecoverStrategic {
  class MMKVHandler (line 41) | class MMKVHandler {
    method wantLogRedirect (line 43) | bool wantLogRedirect()
    method mmkvLog (line 54) | void mmkvLog(MMKVLogLevel level, String file, int line, String functio...
    method onMMKVCRCCheckFail (line 61) | MMKVRecoverStrategic onMMKVCRCCheckFail(String mmapID)
    method onMMKVFileLengthError (line 68) | MMKVRecoverStrategic onMMKVFileLengthError(String mmapID)
    method wantContentChangeNotification (line 73) | bool wantContentChangeNotification()
    method onContentChangedByOuterProcess (line 81) | void onContentChangedByOuterProcess(String mmapID)
    method onMMKVContentLoadSuccessfully (line 87) | void onMMKVContentLoadSuccessfully(String mmapID)
  class MMKVPluginPlatform (line 94) | class MMKVPluginPlatform {
    method initialize (line 106) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
    method encodeBoolFunc (line 110) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeBoolFunc()
    method getMMKVWithIDFunc (line 114) | Pointer<Void> Function(Pointer<Utf8> mmapID, int, Pointer<Utf8> cryptK...
    method getDefaultMMKVFunc (line 119) | Pointer<Void> Function(int, Pointer<Utf8> cryptKey, int aes256, int ex...
    method mmapIDFunc (line 124) | Pointer<Utf8> Function(Pointer<Void>) mmapIDFunc()
    method encodeBoolV2Func (line 128) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeBoolV2Func()
    method decodeBoolFunc (line 132) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeBoolFunc()
    method encodeInt32Func (line 136) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeInt32Func()
    method encodeInt32V2Func (line 140) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeInt32V2Func()
    method decodeInt32Func (line 144) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeInt32Func()
    method encodeInt64Func (line 148) | int Function(Pointer<Void>, Pointer<Utf8>, int) encodeInt64Func()
    method encodeInt64V2Func (line 152) | int Function(Pointer<Void>, Pointer<Utf8>, int, int) encodeInt64V2Func()
    method decodeInt64Func (line 156) | int Function(Pointer<Void>, Pointer<Utf8>, int) decodeInt64Func()
    method encodeDoubleFunc (line 160) | int Function(Pointer<Void>, Pointer<Utf8>, double) encodeDoubleFunc()
    method encodeDoubleV2Func (line 164) | int Function(Pointer<Void>, Pointer<Utf8>, double, int) encodeDoubleV2...
    method decodeDoubleFunc (line 168) | double Function(Pointer<Void>, Pointer<Utf8>, double) decodeDoubleFunc()
    method encodeBytesFunc (line 172) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int) encode...
    method encodeBytesV2Func (line 176) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int, int) e...
    method decodeBytesFunc (line 180) | Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint64>)...
    method reKeyFunc (line 184) | int Function(Pointer<Void>, Pointer<Uint8>, int length, int aes256) re...
    method cryptKeyFunc (line 188) | Pointer<Uint8> Function(Pointer<Void>, Pointer<Uint64>) cryptKeyFunc()
    method checkReSetCryptKeyFunc (line 192) | void Function(Pointer<Void>, Pointer<Uint8>, int length, int aes256) c...
    method valueSizeFunc (line 196) | int Function(Pointer<Void>, Pointer<Utf8>, int) valueSizeFunc()
    method writeValueToNBFunc (line 200) | int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>, int) writeVa...
    method allKeysFunc (line 204) | int Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>, Pointer<P...
    method containsKeyFunc (line 208) | int Function(Pointer<Void>, Pointer<Utf8>) containsKeyFunc()
    method countFunc (line 212) | int Function(Pointer<Void>, int) countFunc()
    method totalSizeFunc (line 216) | int Function(Pointer<Void>) totalSizeFunc()
    method actualSizeFunc (line 220) | int Function(Pointer<Void>) actualSizeFunc()
    method removeValueForKeyFunc (line 224) | void Function(Pointer<Void>, Pointer<Utf8>) removeValueForKeyFunc()
    method removeValuesForKeysFunc (line 228) | void Function(Pointer<Void>, Pointer<Pointer<Utf8>>, Pointer<Uint32>, ...
    method clearAllFunc (line 232) | void Function(Pointer<Void>, int) clearAllFunc()
    method mmkvSyncFunc (line 236) | void Function(Pointer<Void>, int) mmkvSyncFunc()
    method clearMemoryCacheFunc (line 240) | void Function(Pointer<Void>) clearMemoryCacheFunc()
    method pageSizeFunc (line 244) | int Function() pageSizeFunc()
    method versionFunc (line 248) | Pointer<Utf8> Function() versionFunc()
    method trimFunc (line 252) | void Function(Pointer<Void>) trimFunc()
    method mmkvCloseFunc (line 256) | void Function(Pointer<Void>) mmkvCloseFunc()
    method memcpyFunc (line 260) | void Function(Pointer<Void>, Pointer<Void>, int) memcpyFunc()
    method backupOneFunc (line 264) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> dstDir, Pointer<Utf8>...
    method restoreOneFunc (line 268) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> srcDir, Pointer<Utf8>...
    method backupAllFunc (line 272) | int Function(Pointer<Utf8> dstDir) backupAllFunc()
    method restoreAllFunc (line 276) | int Function(Pointer<Utf8> srcDir) restoreAllFunc()
    method enableAutoExpireFunc (line 280) | bool Function(Pointer<Void>, int) enableAutoExpireFunc()
    method disableAutoExpireFunc (line 284) | bool Function(Pointer<Void>) disableAutoExpireFunc()
    method enableCompareBeforeSetFunc (line 288) | bool Function(Pointer<Void>) enableCompareBeforeSetFunc()
    method disableCompareBeforeSetFunc (line 292) | bool Function(Pointer<Void>) disableCompareBeforeSetFunc()
    method removeStorageFunc (line 296) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) removeStora...
    method isMultiProcessFunc (line 300) | bool Function(Pointer<Void>) isMultiProcessFunc()
    method isReadOnlyFunc (line 304) | bool Function(Pointer<Void>) isReadOnlyFunc()
    method registerErrorHandlerFunc (line 308) | ErrorCallbackRegister registerErrorHandlerFunc()
    method registerContentHandlerFunc (line 312) | ContentCallbackRegister registerContentHandlerFunc()
    method registerContentLoadedHandlerFunc (line 316) | ContentCallbackRegister registerContentLoadedHandlerFunc()
    method checkContentChangedFunc (line 320) | void Function(Pointer<Void>) checkContentChangedFunc()
    method getNameSpaceFunc (line 324) | bool Function(Pointer<Utf8> rootPath) getNameSpaceFunc()
    method freePtrFunc (line 328) | void Function(Pointer) freePtrFunc()
    method getApplicationDocumentsPath (line 334) | Future<String> getApplicationDocumentsPath()
    method getTemporaryPath (line 339) | Future<String> getTemporaryPath()
    method checkExistFunc (line 344) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) checkExistF...
    method isFileValidFunc (line 348) | int Function(Pointer<Utf8> mmapID, Pointer<Utf8> rootPath) isFileValid...
    method groupPathFunc (line 352) | Pointer<Utf8> Function() groupPathFunc()
    method importFromFunc (line 356) | int Function(Pointer<Void> handle, Pointer<Void> srcHandle) importFrom...
  type LogCallbackWrap (line 361) | typedef LogCallbackWrap = Void Function(Uint32, Pointer<Utf8>, Int32, Po...
  type LogCallbackRegisterWrap (line 362) | typedef LogCallbackRegisterWrap = Void Function(Pointer<NativeFunction<L...
  type LogCallbackRegister (line 363) | typedef LogCallbackRegister = void Function(Pointer<NativeFunction<LogCa...
  type ErrorCallbackWrap (line 365) | typedef ErrorCallbackWrap = Int32 Function(Pointer<Utf8>, Int32);
  type ErrorCallbackRegisterWrap (line 366) | typedef ErrorCallbackRegisterWrap = Void Function(Pointer<NativeFunction...
  type ErrorCallbackRegister (line 367) | typedef ErrorCallbackRegister = void Function(Pointer<NativeFunction<Err...
  type ContentCallbackWrap (line 369) | typedef ContentCallbackWrap = Void Function(Pointer<Utf8>);
  type ContentCallbackRegisterWrap (line 370) | typedef ContentCallbackRegisterWrap = Void Function(Pointer<NativeFuncti...
  type ContentCallbackRegister (line 371) | typedef ContentCallbackRegister = void Function(Pointer<NativeFunction<C...

FILE: flutter/mmkv_win32/lib/mmkv_win32.dart
  class MMKVPlatformWin32 (line 27) | class MMKVPlatformWin32 extends MMKVPluginPlatformFFI {
    method registerWith (line 28) | void registerWith()
    method nativeLib (line 35) | DynamicLibrary nativeLib()
    method initialize (line 46) | Future<String> initialize(String rootDir, {String? groupDir, int logLe...
  function _string2Pointer (line 57) | Pointer<Utf8> _string2Pointer(String? str)
  function _pointer2String (line 64) | String? _pointer2String(Pointer<Utf16>? ptr)

FILE: iOS/MMKV/MMKV/AutoCleanInfo.hpp
  type AutoCleanInfo (line 26) | struct AutoCleanInfo {
    method AutoCleanInfo (line 30) | AutoCleanInfo(NSString *key, uint64_t time) {
    method AutoCleanInfo (line 35) | AutoCleanInfo(AutoCleanInfo &&src) {
    method AutoCleanInfo (line 59) | explicit AutoCleanInfo(const AutoCleanInfo &other) = delete;
    method AutoCleanInfo (line 60) | AutoCleanInfo &operator=(const AutoCleanInfo &other) = delete;

FILE: iOS/MMKV/MMKV/MMKV.h
  type MMKVConfig (line 44) | typedef struct {
  function MMKVConfig (line 70) | static inline MMKVConfig MMKVConfigDefault(void) {
  function namespace (line 82) | namespace mmkv {

FILE: iOS/MMKVDemo/MMKVDemo/TestMMKVCpp.cpp
  function string (line 17) | string to_string(const std::string& str) {  return str; }
  function string (line 20) | string to_string(const vector<T> &arr, const char* sp = ", ") {
  function containerTest (line 32) | void containerTest(MMKV* mmkv, bool decodeOnly) {
  function functionalTest (line 119) | void functionalTest(MMKV *mmkv, bool decodeOnly) {
  function functionalTest (line 197) | void functionalTest(bool decodeOnly) {
Condensed preview — 614 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,956K chars).
[
  {
    "path": ".clang-format",
    "chars": 836,
    "preview": "---\nBasedOnStyle: LLVM\nIndentWidth: 4\nTabWidth: 4\nAlwaysBreakTemplateDeclarations: true\nAllowShortFunctionsOnASingleLine"
  },
  {
    "path": ".dockerignore",
    "chars": 17,
    "preview": "# 排除特定文件\noutput/\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 796,
    "preview": "# These are supported funding model platforms\n\ngithub: [lingol]\npatreon: # Replace with a single Patreon username\nopen_c"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 1055,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\n---\n\n## Note:\nAn crash issue will be **ignored & closed**"
  },
  {
    "path": ".gitignore",
    "chars": 601,
    "preview": "## Various settings\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!de"
  },
  {
    "path": ".gitmodules",
    "chars": 100,
    "preview": "[submodule \"Python/pybind11\"]\n\tpath = Python/pybind11\n\turl = https://github.com/pybind/pybind11.git\n"
  },
  {
    "path": "Android/MMKV/.gitignore",
    "chars": 182,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n.DS_Store\n/build\n/captures\n.ext"
  },
  {
    "path": "Android/MMKV/build.gradle",
    "chars": 1372,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    e"
  },
  {
    "path": "Android/MMKV/checkstyle.xml",
    "chars": 5566,
    "preview": "<?xml version=\"1.0\"?>\n<!--\n  Copyright (C) 2016 THL A29 Limited, a Tencent company.\n  Copyright (C) 2014 Square, Inc.\n\n "
  },
  {
    "path": "Android/MMKV/gradle/android-publish-private.gradle",
    "chars": 6632,
    "preview": "// OSS_ANDROID_TEMPLATE_FILE_HEADER\n/**\n * New android-publish gradle script (for private use only, without bintray supp"
  },
  {
    "path": "Android/MMKV/gradle/android-publish.gradle",
    "chars": 9892,
    "preview": "import java.util.regex.Matcher\nimport java.util.regex.Pattern\n\n// OSS_ANDROID_TEMPLATE_FILE_HEADER\n/**\n * New android-pu"
  },
  {
    "path": "Android/MMKV/gradle/build_library.gradle",
    "chars": 1822,
    "preview": "// OSS_ANDROID_TEMPLATE_FILE_HEADER\n/**\n * Optional android libraries gradle file\n *\n * Simply apply from: rootProject.f"
  },
  {
    "path": "Android/MMKV/gradle/check.gradle",
    "chars": 1549,
    "preview": "// OSS_ANDROID_TEMPLATE_FILE_HEADER\n\napply plugin: 'checkstyle'\n\n\ncheckstyle {\n    configFile rootProject.file('checksty"
  },
  {
    "path": "Android/MMKV/gradle/wrapper/gradle-wrapper.properties",
    "chars": 233,
    "preview": "#Fri Oct 16 21:16:39 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "Android/MMKV/gradle.properties",
    "chars": 1178,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "Android/MMKV/gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "Android/MMKV/gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "Android/MMKV/mmkv/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "Android/MMKV/mmkv/CMakeLists.txt",
    "chars": 1906,
    "preview": "# For more information about using CMake with Android Studio, read the\n# documentation: https://d.android.com/studio/pro"
  },
  {
    "path": "Android/MMKV/mmkv/build.gradle",
    "chars": 8794,
    "preview": "plugins {\n    id 'com.android.library'\n    id 'maven-publish'\n    id 'signing'\n//    id 'org.jetbrains.dokka' version '1"
  },
  {
    "path": "Android/MMKV/mmkv/gradle.properties",
    "chars": 40,
    "preview": "POM_ARTIFACT_ID=mmkv\nPRIVATE_ONLY=false\n"
  },
  {
    "path": "Android/MMKV/mmkv/proguard-rules.pro",
    "chars": 460,
    "preview": "# Keep all native methods, their classes and any classes in their descriptors\n-keepclasseswithmembers,includedescriptorc"
  },
  {
    "path": "Android/MMKV/mmkv/src/androidTest/AndroidManifest.xml",
    "chars": 355,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <applic"
  },
  {
    "path": "Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTest.java",
    "chars": 8165,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/androidTest/java/com/tencent/mmkv/MMKVTestService.java",
    "chars": 2276,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/AndroidManifest.xml",
    "chars": 120,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n</manifest>"
  },
  {
    "path": "Android/MMKV/mmkv/src/main/aidl/com/tencent/mmkv/ParcelableMMKV.aidl",
    "chars": 67,
    "preview": "// MMKV.aidl\npackage com.tencent.mmkv;\n\nparcelable ParcelableMMKV;\n"
  },
  {
    "path": "Android/MMKV/mmkv/src/main/cpp/flutter-bridge.cpp",
    "chars": 22984,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2020 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp",
    "chars": 46782,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java",
    "chars": 80741,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVConfig.java",
    "chars": 1467,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVContentChangeNotification.java",
    "chars": 1388,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVContentProvider.java",
    "chars": 6175,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVHandler.java",
    "chars": 3083,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVLogLevel.java",
    "chars": 1286,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVProcessUtil.java",
    "chars": 3308,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKVRecoverStrategic.java",
    "chars": 1094,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/NameSpace.java",
    "chars": 9406,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/NativeBuffer.java",
    "chars": 1163,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/ParcelableMMKV.java",
    "chars": 3530,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/UnsupportedArchitectureException.java",
    "chars": 930,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkvannotation/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "Android/MMKV/mmkvannotation/build.gradle",
    "chars": 827,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    namespace \"com.tencent.mmkv\"\n\n    compileSdk rootProject.ext.compileS"
  },
  {
    "path": "Android/MMKV/mmkvannotation/src/main/AndroidManifest.xml",
    "chars": 120,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n</manifest>"
  },
  {
    "path": "Android/MMKV/mmkvannotation/src/main/java/dalvik/annotation/optimization/FastNative.java",
    "chars": 4952,
    "preview": "/*\n * Copyright (C) 2016 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "Android/MMKV/mmkvdemo/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "Android/MMKV/mmkvdemo/build.gradle",
    "chars": 3632,
    "preview": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\n\nandroid {\n    namespace \"com.tencent.mmkvdemo\"\n "
  },
  {
    "path": "Android/MMKV/mmkvdemo/proguard-rules.pro",
    "chars": 856,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/AndroidManifest.xml",
    "chars": 1877,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <appli"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/aidl/com/tencent/mmkvdemo/IAshmemMMKV.aidl",
    "chars": 154,
    "preview": "// IAshmemMMKV.aidl\npackage com.tencent.mmkvdemo;\n\nimport com.tencent.mmkv.ParcelableMMKV;\n\ninterface IAshmemMMKV {\n    "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/cpp/CMakeLists.txt",
    "chars": 2089,
    "preview": "\n# For more information about using CMake with Android Studio, read the\n# documentation: https://d.android.com/studio/pr"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/cpp/mmkvdemo.cpp",
    "chars": 7943,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Baseline.java",
    "chars": 11500,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/BenchMarkBaseService.java",
    "chars": 14467,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/FakeInfo.java",
    "chars": 1790,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/Info.java",
    "chars": 1808,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java",
    "chars": 40288,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MultiProcessSharedPreferences.java",
    "chars": 29137,
    "preview": "package com.tencent.mmkvdemo;\n\nimport android.content.BroadcastReceiver;\nimport android.content.ContentProvider;\nimport "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyApplication.java",
    "chars": 4439,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyService.java",
    "chars": 3628,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MyService_1.java",
    "chars": 3353,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/SQLiteKV.java",
    "chars": 4921,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/TestParcelable.java",
    "chars": 1980,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2025 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/kotlin/KotlinUsecase.kt",
    "chars": 2447,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1880,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/layout/activity_main.xml",
    "chars": 3077,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/values/strings.xml",
    "chars": 71,
    "preview": "<resources>\n    <string name=\"app_name\">MMKVDemo</string>\n</resources>\n"
  },
  {
    "path": "Android/MMKV/mmkvdemo/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "Android/MMKV/pmd-ruleset.xml",
    "chars": 1783,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n<ruleset name=\"PMD.rul\" xmlns=\"http://pmd.sourceforge.net/rulese"
  },
  {
    "path": "Android/MMKV/proguard-rules/proguard-rules-android-lib.pro",
    "chars": 1690,
    "preview": "# OSS_ANDROID_TEMPLATE_FILE_HEADER\n#\n# Proguard config for publish an private aar module\n# NOTE: It's different from lib"
  },
  {
    "path": "Android/MMKV/proguard-rules/proguard-rules-test.pro",
    "chars": 152,
    "preview": "# OSS_ANDROID_TEMPLATE_FILE_HEADER\n-dontnote junit.**\n-dontnote org.xmlpull.v1.**\n-dontwarn junit.**\n-dontwarn org.junit"
  },
  {
    "path": "Android/MMKV/settings.gradle",
    "chars": 82,
    "preview": "rootProject.name = \"MMKV-Android\"\n\ninclude ':mmkv', ':mmkvdemo', 'mmkvannotation'\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 51250,
    "preview": "# MMKV Change Log\n## v2.4.0 / 2026-03-18\n\nThis release introduces a **unified `MMKVHandler` callback interface** across "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3351,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3132,
    "preview": "# Contributing to MMKV\nWelcome to [report Issues](https://github.com/Tencent/MMKV/issues) or [pull requests](https://git"
  },
  {
    "path": "Core/.gitignore",
    "chars": 9,
    "preview": "include/\n"
  },
  {
    "path": "Core/CMakeLists.txt",
    "chars": 6423,
    "preview": "#\n# Tencent is pleased to support the open source community by making\n# MMKV available.\n#\n# Copyright (C) 2019 THL A29 L"
  },
  {
    "path": "Core/CodedInputData.cpp",
    "chars": 7584,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/CodedInputData.h",
    "chars": 2032,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/CodedInputDataCrypt.cpp",
    "chars": 9902,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/CodedInputDataCrypt.h",
    "chars": 2413,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/CodedInputDataCrypt_OSX.cpp",
    "chars": 1912,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/CodedInputData_OSX.cpp",
    "chars": 2817,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/CodedOutputData.cpp",
    "chars": 5547,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/CodedOutputData.h",
    "chars": 1909,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/Core.xcodeproj/project.pbxproj",
    "chars": 44465,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Core/Core.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 149,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:Core.xcodeproj\""
  },
  {
    "path": "Core/Core.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme",
    "chars": 2369,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1530\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme",
    "chars": 2379,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1530\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Core/InterProcessLock.cpp",
    "chars": 5857,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/InterProcessLock.h",
    "chars": 3619,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/InterProcessLock_Android.cpp",
    "chars": 3585,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/InterProcessLock_Win32.cpp",
    "chars": 3585,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/KeyValueHolder.cpp",
    "chars": 8758,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2020 THL "
  },
  {
    "path": "Core/KeyValueHolder.h",
    "chars": 3574,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2020 THL "
  },
  {
    "path": "Core/MMBuffer.cpp",
    "chars": 6348,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMBuffer.h",
    "chars": 3162,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMKV.cpp",
    "chars": 56625,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMKV.h",
    "chars": 29662,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMKVHandler.h",
    "chars": 2055,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/MMKVLog.cpp",
    "chars": 5468,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MMKVLog.h",
    "chars": 3677,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMKVLog_Android.cpp",
    "chars": 4158,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MMKVMetaInfo.hpp",
    "chars": 2817,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MMKVPredef.h",
    "chars": 7455,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MMKV_Android.cpp",
    "chars": 13763,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MMKV_IO.cpp",
    "chars": 75933,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/MMKV_IO.h",
    "chars": 2861,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/MMKV_OSX.cpp",
    "chars": 19246,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MMKV_OSX.h",
    "chars": 952,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MemoryFile.cpp",
    "chars": 23030,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MemoryFile.h",
    "chars": 6671,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MemoryFile_Android.cpp",
    "chars": 8349,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MemoryFile_Linux.cpp",
    "chars": 4152,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2021 THL "
  },
  {
    "path": "Core/MemoryFile_OSX.cpp",
    "chars": 6004,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MemoryFile_Win32.cpp",
    "chars": 23055,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/MiniPBCoder.cpp",
    "chars": 21275,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MiniPBCoder.h",
    "chars": 5095,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/MiniPBCoder_OSX.cpp",
    "chars": 7611,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/PBEncodeItem.hpp",
    "chars": 2830,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/PBUtility.cpp",
    "chars": 1926,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/PBUtility.h",
    "chars": 3675,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/ScopedLock.hpp",
    "chars": 1831,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/ThreadLock.cpp",
    "chars": 1900,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/ThreadLock.h",
    "chars": 1935,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/ThreadLock_Win32.cpp",
    "chars": 2373,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2019 THL "
  },
  {
    "path": "Core/aes/AESCrypt.cpp",
    "chars": 9540,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/aes/AESCrypt.h",
    "chars": 3230,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/aes/openssl/openssl_aes.h",
    "chars": 3438,
    "preview": "/*\n * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_aes_core.cpp",
    "chars": 45342,
    "preview": "/*\n * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_aes_locl.h",
    "chars": 1243,
    "preview": "/*\n * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_aesv8-armx.S",
    "chars": 5709,
    "preview": "#include \"openssl_arm_arch.h\"\n#include \"../../MMKVPredef.h\"\n\n#if (__ARM_MAX_ARCH__ > 7) && !defined(MMKV_DISABLE_CRYPT)\n"
  },
  {
    "path": "Core/aes/openssl/openssl_arm_arch.h",
    "chars": 2638,
    "preview": "/*\n * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_cfb128.cpp",
    "chars": 2455,
    "preview": "/*\n * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_md32_common.h",
    "chars": 8016,
    "preview": "/*\n * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_md5.h",
    "chars": 1293,
    "preview": "/*\n * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_md5_dgst.cpp",
    "chars": 5469,
    "preview": "/*\n * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_md5_locl.h",
    "chars": 2186,
    "preview": "/*\n * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_md5_one.cpp",
    "chars": 733,
    "preview": "/*\n * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (th"
  },
  {
    "path": "Core/aes/openssl/openssl_opensslconf.h",
    "chars": 7464,
    "preview": "/* opensslconf.h */\n/* WARNING: Generated automatically from opensslconf.h.in by Configure. */\n\n#ifdef  __cplusplus\nexte"
  },
  {
    "path": "Core/core.vcxproj",
    "chars": 15700,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micro"
  },
  {
    "path": "Core/core.vcxproj.filters",
    "chars": 5167,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbu"
  },
  {
    "path": "Core/crc32/CMakeLists.txt",
    "chars": 1757,
    "preview": "#\n# Tencent is pleased to support the open source community by making\n# MMKV available.\n#\n# Copyright (C) 2020 THL A29 L"
  },
  {
    "path": "Core/crc32/Checksum.h",
    "chars": 2043,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/crc32/crc32_armv8.cpp",
    "chars": 3957,
    "preview": "/*\n* Tencent is pleased to support the open source community by making\n* MMKV available.\n*\n* Copyright (C) 2020 THL A29 "
  },
  {
    "path": "Core/crc32/zlib/crc32.cpp",
    "chars": 1679,
    "preview": "/* crc32.c -- compute the CRC-32 of a data stream\n * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler\n * For c"
  },
  {
    "path": "Core/crc32/zlib/crc32.h",
    "chars": 3940,
    "preview": "/* crc32.h -- tables for rapid CRC calculation\n * Generated automatically by crc32.c\n */\n\nlocal const z_crc_t FAR crc_ta"
  },
  {
    "path": "Core/crc32/zlib/zconf.h",
    "chars": 9059,
    "preview": "/* zconf.h -- configuration of the zlib compression library\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\n * F"
  },
  {
    "path": "Core/crc32/zlib/zutil.h",
    "chars": 762,
    "preview": "/* zutil.h -- internal interface and configuration of the compression library\n * Copyright (C) 1995-2016 Jean-loup Gaill"
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MMBuffer.h",
    "chars": 764,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MMKV.h",
    "chars": 760,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MMKVHandler.h",
    "chars": 767,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MMKVLog.h",
    "chars": 763,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MMKVPredef.h",
    "chars": 766,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MemoryFile.h",
    "chars": 766,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/MiniPBCoder.h",
    "chars": 767,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/ScopedLock.hpp",
    "chars": 767,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Core/fakeinclude/MMKVCore/ThreadLock.h",
    "chars": 765,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2018 THL "
  },
  {
    "path": "Dockerfile",
    "chars": 708,
    "preview": "FROM gcc:11.5.0 AS builder\n\nRUN apt-get update && apt-get install cmake -y\n\nWORKDIR /MMKV\n\nCOPY . .\n\n## 设置环境变量\n#ENV CGO_"
  },
  {
    "path": "LICENSE.TXT",
    "chars": 20899,
    "preview": "Tencent is pleased to support the open source community by making MMKV available.  \nCopyright (C) 2018 THL A29 Limited, "
  },
  {
    "path": "MMKV.podspec",
    "chars": 1583,
    "preview": "Pod::Spec.new do |s|\n\n  s.name         = \"MMKV\"\n  s.version      = \"2.4.0\"\n  s.summary      = \"MMKV is a cross-platform "
  },
  {
    "path": "MMKV.xcworkspace/contents.xcworkspacedata",
    "chars": 243,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:iOS/MMKVDemo/M"
  },
  {
    "path": "MMKV.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "MMKVAppExtension.podspec",
    "chars": 1473,
    "preview": "Pod::Spec.new do |s|\n\n  s.name         = \"MMKVAppExtension\"\n  s.version      = \"2.4.0\"\n  s.summary      = \"MMKV is a cro"
  },
  {
    "path": "MMKVCore.podspec",
    "chars": 2275,
    "preview": "Pod::Spec.new do |s|\n\n  s.name         = \"MMKVCore\"\n  s.version      = \"2.4.0\"\n  s.summary      = \"MMKVCore for MMKV. MM"
  },
  {
    "path": "MMKVWatchExtension.podspec",
    "chars": 1534,
    "preview": "Pod::Spec.new do |s|\n\n  s.name         = \"MMKVWatchExtension\"\n  s.version      = \"2.4.0\"\n  s.summary      = \"MMKV is a c"
  },
  {
    "path": "Makefile",
    "chars": 210,
    "preview": "format_code:\n\tpython Script/formatCode.py\n\ngolang:\n\tif [ -z \"$(PLATFORM)\" ]; then \\\n\t\tdocker buildx build --output ./out"
  },
  {
    "path": "OpenHarmony/.gitignore",
    "chars": 179,
    "preview": "/node_modules\n/oh_modules\n/local.properties\n/.idea\n**/build\n/.hvigor\n.cxx\n/.clangd\n/.clang-format\n/.clang-tidy\n**/.test\n"
  },
  {
    "path": "OpenHarmony/AppScope/app.json5",
    "chars": 205,
    "preview": "{\n  \"app\": {\n    \"bundleName\": \"com.tencent.mmkvdemo\",\n    \"vendor\": \"example\",\n    \"versionCode\": 1000000,\n    \"version"
  },
  {
    "path": "OpenHarmony/AppScope/resources/base/element/string.json",
    "chars": 86,
    "preview": "{\n  \"string\": [\n    {\n      \"name\": \"app_name\",\n      \"value\": \"MMKVDemo\"\n    }\n  ]\n}\n"
  },
  {
    "path": "OpenHarmony/MMKV/.gitignore",
    "chars": 55,
    "preview": "/node_modules\n/oh_modules\n/.preview\n/build\n/.cxx\n/.test"
  },
  {
    "path": "OpenHarmony/MMKV/BuildProfile.ets",
    "chars": 522,
    "preview": "/**\n * Use these variables when you tailor your ArkTS code. They must be of the const type.\n */\nexport const HAR_VERSION"
  },
  {
    "path": "OpenHarmony/MMKV/CHANGELOG.md",
    "chars": 5058,
    "preview": "# MMKV for HarmonyOS NEXT Change Log\r\n## v2.4.0 / 2026-03-18\r\n* **Feature:** Refactored the callback system into a unifi"
  },
  {
    "path": "OpenHarmony/MMKV/Index.ets",
    "chars": 330,
    "preview": "export { MMKV } from \"./src/main/ets/utils/MMKV\";\nexport { MMKVLogLevel } from \"./src/main/ets/utils/MMKVLogLevel\";\nexpo"
  },
  {
    "path": "OpenHarmony/MMKV/LICENSE",
    "chars": 20899,
    "preview": "Tencent is pleased to support the open source community by making MMKV available.  \nCopyright (C) 2018 THL A29 Limited, "
  },
  {
    "path": "OpenHarmony/MMKV/README.md",
    "chars": 8387,
    "preview": "[![license](https://img.shields.io/badge/license-BSD_3-brightgreen.svg?style=flat)](https://github.com/Tencent/MMKV/blob"
  },
  {
    "path": "OpenHarmony/MMKV/build-profile.json5",
    "chars": 862,
    "preview": "{\n  \"apiType\": \"stageMode\",\n  \"buildOption\": {\n    \"externalNativeOptions\": {\n      \"path\": \"./src/main/cpp/CMakeLists.t"
  },
  {
    "path": "OpenHarmony/MMKV/consumer-rules.txt",
    "chars": 1677,
    "preview": "# Define project specific obfuscation rules here.\n# You can include the obfuscation configuration files in the current m"
  },
  {
    "path": "OpenHarmony/MMKV/example/Index.ets",
    "chars": 27493,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/example/Util.ets",
    "chars": 1034,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/hvigorfile.ts",
    "chars": 234,
    "preview": "import { harTasks } from '@ohos/hvigor-ohos-plugin';\n\nexport default {\n    system: harTasks,  /* Built-in plugin of Hvig"
  },
  {
    "path": "OpenHarmony/MMKV/obfuscation-rules.txt",
    "chars": 893,
    "preview": "# Define project specific obfuscation rules here.\n# You can include the obfuscation configuration files in the current m"
  },
  {
    "path": "OpenHarmony/MMKV/oh-package.json5",
    "chars": 752,
    "preview": "{\n  \"name\": \"@tencent/mmkv\",\n  \"version\": \"2.4.0\",\n  \"description\": \"The official OpenHarmony package of MMKV. An effici"
  },
  {
    "path": "OpenHarmony/MMKV/src/main/cpp/CMakeLists.txt",
    "chars": 1126,
    "preview": "# the minimum version of CMake.\ncmake_minimum_required(VERSION 3.4.1)\nproject(mmkv)\n\nset(NATIVERENDER_ROOT_PATH ${CMAKE_"
  },
  {
    "path": "OpenHarmony/MMKV/src/main/cpp/flutter-bridge.cpp",
    "chars": 22922,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2020 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/cpp/native_bridge.cpp",
    "chars": 71884,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/cpp/types/libmmkv/index.d.ts",
    "chars": 7147,
    "preview": "export const initialize: (rootDir: string, cacheDir: string, logLevel: number, handler?: MMKVHandler) => string;\nexport "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/cpp/types/libmmkv/oh-package.json5",
    "chars": 129,
    "preview": "{\n  \"name\": \"libmmkv.so\",\n  \"types\": \"./index.d.ts\",\n  \"version\": \"\",\n  \"description\": \"Please describe the basic inform"
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/MMKV.ets",
    "chars": 46466,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/MMKVConfig.ets",
    "chars": 1370,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2026 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/MMKVHandler.ets",
    "chars": 4001,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/MMKVLogLevel.ets",
    "chars": 1223,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/NativeBuffer.ets",
    "chars": 1134,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/ets/utils/Util.ts",
    "chars": 836,
    "preview": "/*\n * Tencent is pleased to support the open source community by making\n * MMKV available.\n *\n * Copyright (C) 2024 THL "
  },
  {
    "path": "OpenHarmony/MMKV/src/main/module.json5",
    "chars": 174,
    "preview": "{\n  \"module\": {\n    \"name\": \"MMKV\",\n    \"type\": \"har\",\n    \"description\": \"$string:shared_desc\",\n    \"deviceTypes\": [\n  "
  }
]

// ... and 414 more files (download for full content)

About this extraction

This page contains the full source code of the Tencent/MMKV GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 614 files (16.0 MB), approximately 732.2k tokens, and a symbol index with 1947 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!