MMKV.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. /*
  2. * Tencent is pleased to support the open source community by making
  3. * MMKV available.
  4. *
  5. * Copyright (C) 2018 THL A29 Limited, a Tencent company.
  6. * All rights reserved.
  7. *
  8. * Licensed under the BSD 3-Clause License (the "License"); you may not use
  9. * this file except in compliance with the License. You may obtain a copy of
  10. * the License at
  11. *
  12. * https://opensource.org/licenses/BSD-3-Clause
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. #ifndef MMKV_MMKV_H
  21. #define MMKV_MMKV_H
  22. #ifdef __cplusplus
  23. #include "MMKVPredef.h"
  24. #ifdef MMKV_APPLE
  25. # include "MMBuffer.h"
  26. # ifdef MMKV_HAS_CPP20
  27. # include <span>
  28. # endif
  29. #endif
  30. #include "MiniPBCoder.h"
  31. #include <cstdint>
  32. #include <type_traits>
  33. #include <cstring>
  34. namespace mmkv {
  35. class CodedOutputData;
  36. class MemoryFile;
  37. class AESCrypt;
  38. struct MMKVMetaInfo;
  39. class FileLock;
  40. class InterProcessLock;
  41. class ThreadLock;
  42. class NameSpace;
  43. } // namespace mmkv
  44. MMKV_NAMESPACE_BEGIN
  45. enum MMKVMode : uint32_t {
  46. MMKV_SINGLE_PROCESS = 1 << 0,
  47. MMKV_MULTI_PROCESS = 1 << 1,
  48. #ifdef MMKV_ANDROID
  49. CONTEXT_MODE_MULTI_PROCESS = 1 << 2, // in case someone mistakenly pass Context.MODE_MULTI_PROCESS
  50. MMKV_ASHMEM = 1 << 3,
  51. MMKV_BACKUP = 1 << 4,
  52. #endif
  53. MMKV_READ_ONLY = 1 << 5,
  54. };
  55. static inline MMKVMode operator | (MMKVMode one, MMKVMode other) {
  56. return static_cast<MMKVMode>(static_cast<uint32_t>(one) | static_cast<uint32_t>(other));
  57. }
  58. #define MMKV_OUT
  59. #ifdef MMKV_HAS_CPP20
  60. template <class T>
  61. struct mmkv_is_vector { static constexpr bool value = false; };
  62. template <class T, class A>
  63. struct mmkv_is_vector<std::vector<T, A>> { static constexpr bool value = true; };
  64. template <class T, size_t S>
  65. struct mmkv_is_vector<std::span<T, S>> { static constexpr bool value = true; };
  66. template <class T>
  67. inline constexpr bool mmkv_is_vector_v = mmkv_is_vector<T>::value;
  68. template <class T>
  69. concept MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE = std::is_integral_v<T> || std::is_floating_point_v<T>;
  70. template <class T>
  71. concept MMKV_SUPPORTED_POD_VALUE_TYPE = std::is_same_v<T, const char*> || std::is_same_v<T, std::string> ||
  72. std::is_same_v<T, mmkv::MMBuffer>;
  73. template <class T>
  74. concept MMKV_SUPPORTED_VECTOR_VALUE_TYPE = mmkv_is_vector_v<T> &&
  75. (MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE<typename T::value_type> || MMKV_SUPPORTED_POD_VALUE_TYPE<typename T::value_type>);
  76. template <class T>
  77. concept MMKV_SUPPORTED_VALUE_TYPE = MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE<T> || MMKV_SUPPORTED_POD_VALUE_TYPE<T> ||
  78. MMKV_SUPPORTED_VECTOR_VALUE_TYPE<T>;
  79. #endif // MMKV_HAS_CPP20
  80. class MMKV_EXPORT MMKV {
  81. #ifndef MMKV_ANDROID
  82. MMKV(const std::string &mmapID, MMKVMode mode, const std::string *cryptKey, const MMKVPath_t *rootPath, size_t expectedCapacity = 0);
  83. #else // defined(MMKV_ANDROID)
  84. #ifndef MMKV_OHOS
  85. mmkv::FileLock *m_fileModeLock;
  86. mmkv::InterProcessLock *m_sharedProcessModeLock;
  87. mmkv::InterProcessLock *m_exclusiveProcessModeLock;
  88. #endif // !MMKV_OHOS
  89. mmkv::FileLock *m_fileMigrationLock;
  90. mmkv::InterProcessLock *m_sharedMigrationLock;
  91. MMKV(const std::string &mmapID, int size, MMKVMode mode, const std::string *cryptKey, const MMKVPath_t *rootPath, size_t expectedCapacity = 0);
  92. MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, const std::string *cryptKey = nullptr);
  93. #endif // MMKV_ANDROID
  94. ~MMKV();
  95. std::string m_mmapKey;
  96. std::string m_mmapID;
  97. const MMKVMode m_mode;
  98. MMKVPath_t m_path;
  99. MMKVPath_t m_crcPath;
  100. mmkv::MMKVMap *m_dic;
  101. mmkv::MMKVMapCrypt *m_dicCrypt;
  102. size_t m_expectedCapacity;
  103. mmkv::MemoryFile *m_file;
  104. size_t m_actualSize;
  105. mmkv::CodedOutputData *m_output;
  106. bool m_needLoadFromFile;
  107. bool m_hasFullWriteback;
  108. uint32_t m_crcDigest;
  109. mmkv::MemoryFile *m_metaFile;
  110. mmkv::MMKVMetaInfo *m_metaInfo;
  111. mmkv::AESCrypt *m_crypter;
  112. mmkv::ThreadLock *m_lock;
  113. mmkv::FileLock *m_fileLock;
  114. mmkv::InterProcessLock *m_sharedProcessLock;
  115. mmkv::InterProcessLock *m_exclusiveProcessLock;
  116. bool m_enableKeyExpire = false;
  117. uint32_t m_expiredInSeconds = ExpireNever;
  118. bool m_enableCompareBeforeSet = false;
  119. #ifdef MMKV_APPLE
  120. #ifdef __OBJC__
  121. using MMKVKey_t = NSString *__unsafe_unretained;
  122. static bool isKeyEmpty(MMKVKey_t key) { return key.length <= 0; }
  123. # define mmkv_key_length(key) key.length
  124. # define mmkv_retain_key(key) [key retain]
  125. # define mmkv_release_key(key) [key release]
  126. #else
  127. using MMKVKey_t = std::string_view;
  128. static bool isKeyEmpty(MMKVKey_t key) { return key.empty(); }
  129. #endif // __OBJC__
  130. #else
  131. using MMKVKey_t = std::string_view;
  132. static bool isKeyEmpty(MMKVKey_t key) { return key.empty(); }
  133. # define mmkv_key_length(key) key.length()
  134. # define mmkv_retain_key(key) ((void) 0)
  135. # define mmkv_release_key(key) ((void) 0)
  136. #endif // !MMKV_APPLE
  137. void loadFromFile();
  138. void partialLoadFromFile();
  139. //#if defined(MMKV_APPLE) || defined(MMKV_WIN32)
  140. // the disk corruption detection is tested in iOS/Win32, but not Android
  141. // let's assume what works for iOS also works on Android for they are all POSIX
  142. bool m_isSecondLoad = false;
  143. bool checkFileHasDiskError();
  144. //#else
  145. // bool checkFileHasDiskError() { return false; }
  146. //#endif
  147. void loadMetaInfoAndCheck();
  148. void checkDataValid(bool &loadFromFile, bool &needFullWriteback);
  149. void checkLoadData();
  150. bool isFileValid();
  151. bool checkFileCRCValid(size_t actualSize, uint32_t crcDigest);
  152. void recalculateCRCDigestWithIV(const void *iv);
  153. void recalculateCRCDigestOnly();
  154. void updateCRCDigest(const uint8_t *ptr, size_t length);
  155. size_t readActualSize();
  156. void oldStyleWriteActualSize(size_t actualSize);
  157. bool writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool increaseSequence);
  158. bool ensureMemorySize(size_t newSize);
  159. bool expandAndWriteBack(size_t newSize, std::pair<mmkv::MMBuffer, size_t> preparedData, bool needSync = true);
  160. bool fullWriteback(mmkv::AESCrypt *newCrypter = nullptr, bool onlyWhileExpire = false);
  161. bool doFullWriteBack(std::pair<mmkv::MMBuffer, size_t> preparedData, mmkv::AESCrypt *newCrypter, bool needSync = true);
  162. bool doFullWriteBack(mmkv::MMKVVector &&vec);
  163. mmkv::MMBuffer getRawDataForKey(MMKVKey_t key);
  164. mmkv::MMBuffer getDataForKey(MMKVKey_t key);
  165. // isDataHolder: avoid memory copying
  166. bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, bool isDataHolder = false);
  167. bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, uint32_t expireDuration);
  168. bool removeDataForKey(MMKVKey_t key);
  169. using KVHolderRet_t = std::pair<bool, mmkv::KeyValueHolder>;
  170. // isDataHolder: avoid memory copying
  171. KVHolderRet_t doAppendDataWithKey(const mmkv::MMBuffer &data, const mmkv::MMBuffer &key, bool isDataHolder, uint32_t keyLength);
  172. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, MMKVKey_t key, bool isDataHolder = false);
  173. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, const mmkv::KeyValueHolder &kvHolder, bool isDataHolder = false);
  174. KVHolderRet_t doOverrideDataWithKey(const mmkv::MMBuffer &data, const mmkv::MMBuffer &key, bool isDataHolder, uint32_t keyLength);
  175. KVHolderRet_t overrideDataWithKey(const mmkv::MMBuffer &data, const mmkv::KeyValueHolder &kvHolder, bool isDataHolder = false);
  176. KVHolderRet_t overrideDataWithKey(const mmkv::MMBuffer &data, MMKVKey_t key, bool isDataHolder = false);
  177. bool checkSizeForOverride(size_t size);
  178. #ifdef MMKV_APPLE
  179. #ifdef __OBJC__
  180. mmkv::MMBuffer getDataForKey(std::string_view key);
  181. bool setDataForKey(mmkv::MMBuffer &&data, std::string_view key, bool isDataHolder = false);
  182. #endif
  183. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data,
  184. MMKVKey_t key,
  185. const mmkv::KeyValueHolderCrypt &kvHolder,
  186. bool isDataHolder = false);
  187. KVHolderRet_t overrideDataWithKey(const mmkv::MMBuffer &data,
  188. MMKVKey_t key,
  189. const mmkv::KeyValueHolderCrypt &kvHolder,
  190. bool isDataHolder = false);
  191. #endif
  192. void notifyContentChanged();
  193. #if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT)
  194. void checkReSetCryptKey(int fd, int metaFD, const std::string *cryptKey);
  195. #endif
  196. static bool backupOneToDirectory(const std::string &mmapKey, const MMKVPath_t &dstPath, const MMKVPath_t &srcPath, bool compareFullPath);
  197. static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &srcDir, bool isInSpecialDir);
  198. static bool restoreOneFromDirectory(const std::string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath, bool compareFullPath);
  199. static size_t restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t &dstDir, bool isInSpecialDir);
  200. static uint32_t getCurrentTimeInSecond();
  201. uint32_t getExpireTimeForKey(MMKVKey_t key);
  202. mmkv::MMBuffer getDataWithoutMTimeForKey(MMKVKey_t key);
  203. size_t filterExpiredKeys();
  204. static constexpr uint32_t ConstFixed32Size = 4;
  205. void shared_lock();
  206. void shared_unlock();
  207. public:
  208. // call this before getting any MMKV instance
  209. static void initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel = MMKVLogInfo, mmkv::LogHandler handler = nullptr);
  210. // a generic purpose instance
  211. static MMKV *defaultMMKV(MMKVMode mode = MMKV_SINGLE_PROCESS, const std::string *cryptKey = nullptr);
  212. #ifndef MMKV_ANDROID
  213. // mmapID: any unique ID (com.tencent.xin.pay, etc.)
  214. // if you want a per-user mmkv, you could merge user-id within mmapID
  215. // cryptKey: 16 bytes at most
  216. static MMKV *mmkvWithID(const std::string &mmapID,
  217. MMKVMode mode = MMKV_SINGLE_PROCESS,
  218. const std::string *cryptKey = nullptr,
  219. const MMKVPath_t *rootPath = nullptr,
  220. size_t expectedCapacity = 0);
  221. #else // defined(MMKV_ANDROID)
  222. // mmapID: any unique ID (com.tencent.xin.pay, etc.)
  223. // if you want a per-user mmkv, you could merge user-id within mmapID
  224. // cryptKey: 16 bytes at most
  225. static MMKV *mmkvWithID(const std::string &mmapID,
  226. int size = mmkv::DEFAULT_MMAP_SIZE,
  227. MMKVMode mode = MMKV_SINGLE_PROCESS,
  228. const std::string *cryptKey = nullptr,
  229. const MMKVPath_t *rootPath = nullptr,
  230. size_t expectedCapacity = 0);
  231. static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, const std::string *cryptKey = nullptr);
  232. int ashmemFD();
  233. int ashmemMetaFD();
  234. #ifndef MMKV_OHOS
  235. bool checkProcessMode();
  236. static void enableDisableProcessMode(bool enable);
  237. #endif // !MMKV_OHOS
  238. #endif // MMKV_ANDROID
  239. // get a namespace with custom root dir
  240. static mmkv::NameSpace nameSpace(const MMKVPath_t &rootDir);
  241. // identical with the original MMKV with the global root dir
  242. static mmkv::NameSpace defaultNameSpace();
  243. // you can call this on application termination, it's totally fine if you don't call
  244. static void onExit();
  245. const std::string &mmapID() const;
  246. #ifndef MMKV_ANDROID
  247. bool isMultiProcess() const { return (m_mode & MMKV_MULTI_PROCESS) != 0; }
  248. #else
  249. bool isMultiProcess() const {
  250. return (m_mode & MMKV_MULTI_PROCESS) != 0
  251. || (m_mode & CONTEXT_MODE_MULTI_PROCESS) != 0
  252. || (m_mode & MMKV_ASHMEM) != 0; // ashmem is always multi-process
  253. }
  254. bool isAshmem() const {
  255. return (m_mode & MMKV_ASHMEM) != 0;
  256. }
  257. #endif
  258. bool isReadOnly() const { return (m_mode & MMKV_READ_ONLY) != 0; }
  259. #ifndef MMKV_DISABLE_CRYPT
  260. std::string cryptKey() const;
  261. // transform plain text into encrypted text, or vice versa with empty cryptKey
  262. // you can change existing crypt key with different cryptKey
  263. bool reKey(const std::string &cryptKey);
  264. // just reset cryptKey (will not encrypt or decrypt anything)
  265. // usually you should call this method after other process reKey() the multi-process mmkv
  266. void checkReSetCryptKey(const std::string *cryptKey);
  267. #endif
  268. bool set(bool value, MMKVKey_t key);
  269. bool set(bool value, MMKVKey_t key, uint32_t expireDuration);
  270. bool set(int32_t value, MMKVKey_t key);
  271. bool set(int32_t value, MMKVKey_t key, uint32_t expireDuration);
  272. bool set(uint32_t value, MMKVKey_t key);
  273. bool set(uint32_t value, MMKVKey_t key, uint32_t expireDuration);
  274. bool set(int64_t value, MMKVKey_t key);
  275. bool set(int64_t value, MMKVKey_t key, uint32_t expireDuration);
  276. bool set(uint64_t value, MMKVKey_t key);
  277. bool set(uint64_t value, MMKVKey_t key, uint32_t expireDuration);
  278. bool set(float value, MMKVKey_t key);
  279. bool set(float value, MMKVKey_t key, uint32_t expireDuration);
  280. bool set(double value, MMKVKey_t key);
  281. bool set(double value, MMKVKey_t key, uint32_t expireDuration);
  282. #ifdef MMKV_HAS_CPP20
  283. // avoid unexpected type conversion (pointer to bool, etc.)
  284. template <typename T>
  285. requires(!MMKV_SUPPORTED_VALUE_TYPE<T>)
  286. bool set(T value, MMKVKey_t key) = delete;
  287. // avoid unexpected type conversion (pointer to bool, etc.)
  288. template <typename T>
  289. requires(!MMKV_SUPPORTED_VALUE_TYPE<T>)
  290. bool set(T value, MMKVKey_t key, uint32_t expireDuration) = delete;
  291. #else
  292. // avoid unexpected type conversion (pointer to bool, etc.)
  293. template <typename T>
  294. bool set(T value, MMKVKey_t key, uint32_t expireDuration) = delete;
  295. #endif
  296. #ifdef MMKV_APPLE
  297. #ifdef __OBJC__
  298. bool set(bool value, std::string_view key);
  299. bool set(bool value, std::string_view key, uint32_t expireDuration);
  300. bool set(int32_t value, std::string_view key);
  301. bool set(int32_t value, std::string_view key, uint32_t expireDuration);
  302. bool set(uint32_t value, std::string_view key);
  303. bool set(uint32_t value, std::string_view key, uint32_t expireDuration);
  304. bool set(int64_t value, std::string_view key);
  305. bool set(int64_t value, std::string_view key, uint32_t expireDuration);
  306. bool set(uint64_t value, std::string_view key);
  307. bool set(uint64_t value, std::string_view key, uint32_t expireDuration);
  308. bool set(float value, std::string_view key);
  309. bool set(float value, std::string_view key, uint32_t expireDuration);
  310. bool set(double value, std::string_view key);
  311. bool set(double value, std::string_view key, uint32_t expireDuration);
  312. bool set(const char *value, std::string_view key);
  313. bool set(const char *value, std::string_view key, uint32_t expireDuration);
  314. bool set(const std::string &value, std::string_view key);
  315. bool set(const std::string &value, std::string_view key, uint32_t expireDuration);
  316. bool set(std::string_view value, std::string_view key);
  317. bool set(std::string_view value, std::string_view key, uint32_t expireDuration);
  318. bool set(const mmkv::MMBuffer &value, std::string_view key);
  319. bool set(const mmkv::MMBuffer &value, std::string_view key, uint32_t expireDuration);
  320. bool set(const std::vector<std::string> &vector, std::string_view key);
  321. bool set(const std::vector<std::string> &vector, std::string_view key, uint32_t expireDuration);
  322. bool containsKey(std::string_view key);
  323. bool removeValueForKey(std::string_view key);
  324. bool getBool(std::string_view key, bool defaultValue = false, MMKV_OUT bool *hasValue = nullptr);
  325. int32_t getInt32(std::string_view key, int32_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  326. uint32_t getUInt32(std::string_view key, uint32_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  327. int64_t getInt64(std::string_view key, int64_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  328. uint64_t getUInt64(std::string_view key, uint64_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  329. float getFloat(std::string_view key, float defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  330. double getDouble(std::string_view key, double defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  331. bool getString(std::string_view key, std::string &result, bool inplaceModification = true);
  332. #ifdef MMKV_HAS_CPP20
  333. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  334. bool getVector(std::string_view key, T &result);
  335. bool getVector(std::string_view key, std::vector<std::string> &result);
  336. #endif
  337. bool set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key);
  338. bool set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key, uint32_t expireDuration);
  339. NSObject *getObject(MMKVKey_t key, Class cls);
  340. #endif // __OBJC__
  341. #endif // MMKV_APPLE
  342. bool set(const char *value, MMKVKey_t key);
  343. bool set(const char *value, MMKVKey_t key, uint32_t expireDuration);
  344. bool set(const std::string &value, MMKVKey_t key);
  345. bool set(const std::string &value, MMKVKey_t key, uint32_t expireDuration);
  346. bool set(std::string_view value, MMKVKey_t key);
  347. bool set(std::string_view value, MMKVKey_t key, uint32_t expireDuration);
  348. bool set(const mmkv::MMBuffer &value, MMKVKey_t key);
  349. bool set(const mmkv::MMBuffer &value, MMKVKey_t key, uint32_t expireDuration);
  350. bool set(const std::vector<std::string> &vector, MMKVKey_t key);
  351. bool set(const std::vector<std::string> &vector, MMKVKey_t key, uint32_t expireDuration);
  352. #ifdef MMKV_HAS_CPP20
  353. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  354. bool set(const T& value, MMKVKey_t key) {
  355. return set<T>(value, key, m_expiredInSeconds);
  356. }
  357. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  358. bool set(const T& value, MMKVKey_t key, uint32_t expireDuration);
  359. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  360. bool getVector(MMKVKey_t key, T &result);
  361. #endif // MMKV_HAS_CPP20
  362. // inplaceModification is recommended for faster speed
  363. bool getString(MMKVKey_t key, std::string &result, bool inplaceModification = true);
  364. mmkv::MMBuffer getBytes(MMKVKey_t key);
  365. bool getBytes(MMKVKey_t key, mmkv::MMBuffer &result);
  366. bool getVector(MMKVKey_t key, std::vector<std::string> &result);
  367. bool getBool(MMKVKey_t key, bool defaultValue = false, MMKV_OUT bool *hasValue = nullptr);
  368. int32_t getInt32(MMKVKey_t key, int32_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  369. uint32_t getUInt32(MMKVKey_t key, uint32_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  370. int64_t getInt64(MMKVKey_t key, int64_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  371. uint64_t getUInt64(MMKVKey_t key, uint64_t defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  372. float getFloat(MMKVKey_t key, float defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  373. double getDouble(MMKVKey_t key, double defaultValue = 0, MMKV_OUT bool *hasValue = nullptr);
  374. // return the actual size consumption of the key's value
  375. // pass actualSize = true to get value's length
  376. size_t getValueSize(MMKVKey_t key, bool actualSize);
  377. // return size written into buffer
  378. // return -1 on any error
  379. int32_t writeValueToBuffer(MMKVKey_t key, void *ptr, int32_t size);
  380. bool containsKey(MMKVKey_t key);
  381. // filterExpire: return count of all non-expired keys, keep in mind it comes with cost
  382. size_t count(bool filterExpire = false);
  383. size_t totalSize();
  384. size_t actualSize();
  385. static constexpr uint32_t ExpireNever = 0;
  386. // all keys created (or last modified) longer than expiredInSeconds will be deleted on next full-write-back
  387. // expiredInSeconds = MMKV::ExpireNever (0) means no common expiration duration for all keys, aka each key will have it's own expiration duration
  388. bool enableAutoKeyExpire(uint32_t expiredInSeconds = 0);
  389. bool disableAutoKeyExpire();
  390. // compare value for key before set, to reduce the possibility of file expanding
  391. bool enableCompareBeforeSet();
  392. bool disableCompareBeforeSet();
  393. bool isExpirationEnabled() const { return m_enableKeyExpire; }
  394. bool isEncryptionEnabled() const { return m_dicCrypt; }
  395. bool isCompareBeforeSetEnabled() const { return m_enableCompareBeforeSet && !m_enableKeyExpire && !m_dicCrypt; }
  396. #ifdef MMKV_APPLE
  397. #ifdef __OBJC__
  398. // filterExpire: return all non-expired keys, keep in mind it comes with cost
  399. NSArray *allKeysObjC(bool filterExpire = false);
  400. bool removeValuesForKeys(NSArray *arrKeys);
  401. typedef void (^EnumerateBlock)(NSString *key, BOOL *stop);
  402. void enumerateKeys(EnumerateBlock block);
  403. #endif // __OBJC__
  404. // filterExpire: return all non-expired keys, keep in mind it comes with cost
  405. std::vector<std::string> allKeys(bool filterExpire = false);
  406. bool removeValuesForKeys(const std::vector<std::string> &arrKeys);
  407. # ifdef MMKV_IOS
  408. static void setIsInBackground(bool isInBackground);
  409. static bool isInBackground();
  410. # endif
  411. #else // !defined(MMKV_APPLE)
  412. // filterExpire: return all non-expired keys, keep in mind it comes with cost
  413. std::vector<std::string> allKeys(bool filterExpire = false);
  414. bool removeValuesForKeys(const std::vector<std::string> &arrKeys);
  415. #endif // MMKV_APPLE
  416. bool removeValueForKey(MMKVKey_t key);
  417. // keepSpace: remove all keys but keep the file size not changed, running faster
  418. void clearAll(bool keepSpace = false);
  419. // MMKV's size won't reduce after deleting key-values
  420. // call this method after lots of deleting if you care about disk usage
  421. // note that `clearAll` has the similar effect of `trim`
  422. void trim();
  423. // import all key-value items from source
  424. // return count of items imported
  425. size_t importFrom(MMKV *src);
  426. // call this method if the instance is no longer needed in the near future
  427. // any subsequent call to the instance is undefined behavior
  428. void close();
  429. // call this method if you are facing memory-warning
  430. // any subsequent call to the instance will load all key-values from file again
  431. // keepSpace: remove all keys but keep the file size not changed, running faster
  432. void clearMemoryCache(bool keepSpace = false);
  433. // you don't need to call this, really, I mean it
  434. // unless you worry about running out of battery
  435. void sync(SyncFlag flag = MMKV_SYNC);
  436. // get exclusive access
  437. void lock();
  438. void unlock();
  439. bool try_lock();
  440. // get thread lock
  441. #ifndef MMKV_WIN32
  442. void lock_thread();
  443. void unlock_thread();
  444. bool try_lock_thread();
  445. #endif
  446. static const MMKVPath_t &getRootDir();
  447. // backup one MMKV instance from srcDir to dstDir
  448. // if srcDir is null, then backup from the root dir of MMKV
  449. static bool backupOneToDirectory(const std::string &mmapID, const MMKVPath_t &dstDir, const MMKVPath_t *srcDir = nullptr);
  450. // restore one MMKV instance from srcDir to dstDir
  451. // if dstDir is null, then restore to the root dir of MMKV
  452. static bool restoreOneFromDirectory(const std::string &mmapID, const MMKVPath_t &srcDir, const MMKVPath_t *dstDir = nullptr);
  453. // backup all MMKV instance from srcDir to dstDir
  454. // if srcDir is null, then backup from the root dir of MMKV
  455. // return count of MMKV successfully backuped
  456. static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t *srcDir = nullptr);
  457. // restore all MMKV instance from srcDir to dstDir
  458. // if dstDir is null, then restore to the root dir of MMKV
  459. // return count of MMKV successfully restored
  460. static size_t restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t *dstDir = nullptr);
  461. // check if content been changed by other process
  462. void checkContentChanged();
  463. // called when content is changed by other process
  464. // doesn't guarantee real-time notification
  465. static void registerContentChangeHandler(mmkv::ContentChangeHandler handler);
  466. static void unRegisterContentChangeHandler();
  467. // by default MMKV will discard all datas on failure
  468. // return `OnErrorRecover` to recover any data from file
  469. static void registerErrorHandler(mmkv::ErrorHandler handler);
  470. static void unRegisterErrorHandler();
  471. // MMKVLogInfo by default
  472. // pass MMKVLogNone to disable all logging
  473. static void setLogLevel(MMKVLogLevel level);
  474. // by default MMKV will print log to the console
  475. // implement this method to redirect MMKV's log
  476. static void registerLogHandler(mmkv::LogHandler handler);
  477. static void unRegisterLogHandler();
  478. // detect if the MMKV file is valid or not
  479. // Note: Don't use this to check the existence of the instance, the return value is undefined if the file was never created.
  480. static bool isFileValid(const std::string &mmapID, const MMKVPath_t *relatePath = nullptr);
  481. // remove the storage of the MMKV, including the data file & meta file (.crc)
  482. // Note: the existing instance (if any) will be closed & destroyed
  483. static bool removeStorage(const std::string &mmapID, const MMKVPath_t *relatePath = nullptr);
  484. // check the existence of the MMKV file
  485. static bool checkExist(const std::string &mmapID, const MMKVPath_t *relatePath = nullptr);
  486. // just forbid it for possibly misuse
  487. explicit MMKV(const MMKV &other) = delete;
  488. MMKV &operator=(const MMKV &other) = delete;
  489. };
  490. #if defined(MMKV_HAS_CPP20)
  491. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  492. bool MMKV::set(const T& value, MMKVKey_t key, uint32_t expireDuration) {
  493. if (isKeyEmpty(key)) {
  494. return false;
  495. }
  496. mmkv::MMBuffer data;
  497. if constexpr (std::is_same_v<T, std::vector<bool>>) {
  498. data = mmkv::MiniPBCoder::encodeDataWithObject(value);
  499. } else {
  500. data = mmkv::MiniPBCoder::encodeDataWithObject(std::span(value));
  501. }
  502. if (mmkv_unlikely(m_enableKeyExpire) && data.length() > 0) {
  503. auto tmp = mmkv::MMBuffer(data.length() + ConstFixed32Size);
  504. auto ptr = (uint8_t *) tmp.getPtr();
  505. memcpy(ptr, data.getPtr(), data.length());
  506. auto time = (expireDuration != ExpireNever) ? getCurrentTimeInSecond() + expireDuration : ExpireNever;
  507. memcpy(ptr + data.length(), &time, ConstFixed32Size);
  508. data = std::move(tmp);
  509. }
  510. return setDataForKey(std::move(data), key);
  511. }
  512. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  513. bool MMKV::getVector(MMKVKey_t key, T &result) {
  514. if (isKeyEmpty(key)) {
  515. return false;
  516. }
  517. shared_lock();
  518. bool ret = false;
  519. auto data = getDataForKey(key);
  520. if (data.length() > 0) {
  521. ret = mmkv::MiniPBCoder::decodeVector(data, result);
  522. }
  523. shared_unlock();
  524. return ret;
  525. }
  526. #ifdef __OBJC__
  527. template<MMKV_SUPPORTED_VECTOR_VALUE_TYPE T>
  528. bool getVector(std::string_view key, T &result) {
  529. HybridString hybridKey(key);
  530. return getVector(hybridKey.str, result);
  531. }
  532. #endif // __OBJC__
  533. #endif // MMKV_HAS_CPP20
  534. MMKV_NAMESPACE_END
  535. namespace mmkv {
  536. // a POD-like facade what wraps custom root directory
  537. class MMKV_EXPORT NameSpace {
  538. const MMKVPath_t &m_rootDir;
  539. NameSpace(const MMKVPath_t &rootDir) : m_rootDir(rootDir) {}
  540. public:
  541. // return the absolute root dir of NameSpace
  542. const MMKVPath_t &getRootDir() { return m_rootDir; }
  543. #ifndef MMKV_ANDROID
  544. // mmapID: any unique ID (com.tencent.xin.pay, etc.)
  545. // if you want a per-user mmkv, you could merge user-id within mmapID
  546. // cryptKey: 16 bytes at most
  547. MMKV *mmkvWithID(const std::string &mmapID,
  548. MMKVMode mode = MMKV_SINGLE_PROCESS,
  549. const std::string *cryptKey = nullptr,
  550. size_t expectedCapacity = 0);
  551. #else // defined(MMKV_ANDROID)
  552. // mmapID: any unique ID (com.tencent.xin.pay, etc.)
  553. // if you want a per-user mmkv, you could merge user-id within mmapID
  554. // cryptKey: 16 bytes at most
  555. MMKV *mmkvWithID(const std::string &mmapID,
  556. int size = mmkv::DEFAULT_MMAP_SIZE,
  557. MMKVMode mode = MMKV_SINGLE_PROCESS,
  558. const std::string *cryptKey = nullptr,
  559. size_t expectedCapacity = 0);
  560. #endif // MMKV_ANDROID
  561. // backup one MMKV instance to dstDir
  562. bool backupOneToDirectory(const std::string &mmapID, const MMKVPath_t &dstDir);
  563. // restore one MMKV instance from srcDir
  564. bool restoreOneFromDirectory(const std::string &mmapID, const MMKVPath_t &srcDir);
  565. // backup all MMKV instance to dstDir
  566. // return count of MMKV successfully backuped
  567. size_t backupAllToDirectory(const MMKVPath_t &dstDir);
  568. // restore all MMKV instance from srcDir
  569. // return count of MMKV successfully restored
  570. size_t restoreAllFromDirectory(const MMKVPath_t &srcDir);
  571. // detect if the MMKV file is valid or not
  572. // Note: Don't use this to check the existence of the instance, the return value is undefined if the file was never created.
  573. bool isFileValid(const std::string &mmapID);
  574. // remove the storage of the MMKV, including the data file & meta file (.crc)
  575. // Note: the existing instance (if any) will be closed & destroyed
  576. bool removeStorage(const std::string &mmapID);
  577. // check the existence of the MMKV file
  578. bool checkExist(const std::string &mmapID);
  579. friend class MMKV_NAMESPACE_PREFIX::MMKV;
  580. };
  581. }
  582. #endif // __cplusplus
  583. #endif // MMKV_MMKV_H