MMKV.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 "MMBuffer.h"
  24. #include <cstdint>
  25. namespace mmkv {
  26. class CodedOutputData;
  27. class MemoryFile;
  28. class AESCrypt;
  29. struct MMKVMetaInfo;
  30. class FileLock;
  31. class InterProcessLock;
  32. class ThreadLock;
  33. } // namespace mmkv
  34. MMKV_NAMESPACE_BEGIN
  35. enum MMKVMode : uint32_t {
  36. MMKV_SINGLE_PROCESS = 0x1,
  37. MMKV_MULTI_PROCESS = 0x2,
  38. #ifdef MMKV_ANDROID
  39. CONTEXT_MODE_MULTI_PROCESS = 0x4, // in case someone mistakenly pass Context.MODE_MULTI_PROCESS
  40. MMKV_ASHMEM = 0x8,
  41. #endif
  42. };
  43. class MMKV {
  44. #ifndef MMKV_ANDROID
  45. std::string m_mmapKey;
  46. MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath);
  47. #else // defined(MMKV_ANDROID)
  48. mmkv::FileLock *m_fileModeLock;
  49. mmkv::InterProcessLock *m_sharedProcessModeLock;
  50. mmkv::InterProcessLock *m_exclusiveProcessModeLock;
  51. MMKV(const std::string &mmapID, int size, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath);
  52. MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, std::string *cryptKey = nullptr);
  53. #endif
  54. ~MMKV();
  55. std::string m_mmapID;
  56. MMKVPath_t m_path;
  57. MMKVPath_t m_crcPath;
  58. mmkv::MMKVMap *m_dic;
  59. mmkv::MMKVMapCrypt *m_dicCrypt;
  60. mmkv::MemoryFile *m_file;
  61. size_t m_actualSize;
  62. mmkv::CodedOutputData *m_output;
  63. bool m_needLoadFromFile;
  64. bool m_hasFullWriteback;
  65. uint32_t m_crcDigest;
  66. mmkv::MemoryFile *m_metaFile;
  67. mmkv::MMKVMetaInfo *m_metaInfo;
  68. mmkv::AESCrypt *m_crypter;
  69. mmkv::ThreadLock *m_lock;
  70. mmkv::FileLock *m_fileLock;
  71. mmkv::InterProcessLock *m_sharedProcessLock;
  72. mmkv::InterProcessLock *m_exclusiveProcessLock;
  73. #ifdef MMKV_APPLE
  74. using MMKVKey_t = NSString *__unsafe_unretained;
  75. static bool isKeyEmpty(MMKVKey_t key) { return key.length <= 0; }
  76. #else
  77. using MMKVKey_t = const std::string &;
  78. static bool isKeyEmpty(MMKVKey_t key) { return key.empty(); }
  79. #endif
  80. void loadFromFile();
  81. void partialLoadFromFile();
  82. void checkDataValid(bool &loadFromFile, bool &needFullWriteback);
  83. void checkLoadData();
  84. bool isFileValid();
  85. bool checkFileCRCValid(size_t actualSize, uint32_t crcDigest);
  86. void recaculateCRCDigestWithIV(const void *iv);
  87. void updateCRCDigest(const uint8_t *ptr, size_t length);
  88. size_t readActualSize();
  89. void oldStyleWriteActualSize(size_t actualSize);
  90. bool writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool increaseSequence);
  91. bool ensureMemorySize(size_t newSize);
  92. bool fullWriteback(mmkv::AESCrypt *newCrypter = nullptr);
  93. bool doFullWriteBack(std::pair<mmkv::MMBuffer, size_t> preparedData, mmkv::AESCrypt *newCrypter);
  94. mmkv::MMBuffer getDataForKey(MMKVKey_t key);
  95. // isDataHolder: avoid memory copying
  96. bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, bool isDataHolder = false);
  97. bool removeDataForKey(MMKVKey_t key);
  98. using KVHolderRet_t = std::pair<bool, mmkv::KeyValueHolder>;
  99. // isDataHolder: avoid memory copying
  100. KVHolderRet_t doAppendDataWithKey(const mmkv::MMBuffer &data, const mmkv::MMBuffer &key, bool isDataHolder, uint32_t keyLength);
  101. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, MMKVKey_t key, bool isDataHolder = false);
  102. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, const mmkv::KeyValueHolder &kvHolder, bool isDataHolder = false);
  103. #ifdef MMKV_APPLE
  104. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data,
  105. MMKVKey_t key,
  106. const mmkv::KeyValueHolderCrypt &kvHolder,
  107. bool isDataHolder = false);
  108. #endif
  109. void notifyContentChanged();
  110. #if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT)
  111. void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey);
  112. #endif
  113. public:
  114. // call this before getting any MMKV instance
  115. static void initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel = MMKVLogInfo);
  116. #ifdef MMKV_APPLE
  117. // protect from some old code that don't call initializeMMKV()
  118. static void minimalInit(MMKVPath_t defaultRootDir);
  119. #endif
  120. // a generic purpose instance
  121. static MMKV *defaultMMKV(MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr);
  122. #ifndef MMKV_ANDROID
  123. // mmapID: any unique ID (com.tencent.xin.pay, etc)
  124. // if you want a per-user mmkv, you could merge user-id within mmapID
  125. // cryptKey: 16 bytes at most
  126. static MMKV *mmkvWithID(const std::string &mmapID,
  127. MMKVMode mode = MMKV_SINGLE_PROCESS,
  128. std::string *cryptKey = nullptr,
  129. MMKVPath_t *rootPath = nullptr);
  130. #else // defined(MMKV_ANDROID)
  131. // mmapID: any unique ID (com.tencent.xin.pay, etc)
  132. // if you want a per-user mmkv, you could merge user-id within mmapID
  133. // cryptKey: 16 bytes at most
  134. static MMKV *mmkvWithID(const std::string &mmapID,
  135. int size = mmkv::DEFAULT_MMAP_SIZE,
  136. MMKVMode mode = MMKV_SINGLE_PROCESS,
  137. std::string *cryptKey = nullptr,
  138. MMKVPath_t *rootPath = nullptr);
  139. static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, std::string *cryptKey = nullptr);
  140. int ashmemFD();
  141. int ashmemMetaFD();
  142. bool checkProcessMode();
  143. #endif // MMKV_ANDROID
  144. // you can call this on application termination, it's totally fine if you don't call
  145. static void onExit();
  146. const std::string &mmapID() const;
  147. const bool m_isInterProcess;
  148. #ifndef MMKV_DISABLE_CRYPT
  149. std::string cryptKey() const;
  150. // transform plain text into encrypted text, or vice versa with empty cryptKey
  151. // you can change existing crypt key with different cryptKey
  152. bool reKey(const std::string &cryptKey);
  153. // just reset cryptKey (will not encrypt or decrypt anything)
  154. // usually you should call this method after other process reKey() the multi-process mmkv
  155. void checkReSetCryptKey(const std::string *cryptKey);
  156. #endif
  157. bool set(bool value, MMKVKey_t key);
  158. bool set(int32_t value, MMKVKey_t key);
  159. bool set(uint32_t value, MMKVKey_t key);
  160. bool set(int64_t value, MMKVKey_t key);
  161. bool set(uint64_t value, MMKVKey_t key);
  162. bool set(float value, MMKVKey_t key);
  163. bool set(double value, MMKVKey_t key);
  164. // avoid unexpected type conversion (pointer to bool, etc)
  165. template <typename T>
  166. bool set(T value, MMKVKey_t key) = delete;
  167. #ifdef MMKV_APPLE
  168. bool set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key);
  169. NSObject *getObject(MMKVKey_t key, Class cls);
  170. #else // !defined(MMKV_APPLE)
  171. bool set(const char *value, MMKVKey_t key);
  172. bool set(const std::string &value, MMKVKey_t key);
  173. bool set(const mmkv::MMBuffer &value, MMKVKey_t key);
  174. bool set(const std::vector<std::string> &vector, MMKVKey_t key);
  175. bool getString(MMKVKey_t key, std::string &result);
  176. mmkv::MMBuffer getBytes(MMKVKey_t key);
  177. bool getVector(MMKVKey_t key, std::vector<std::string> &result);
  178. #endif // MMKV_APPLE
  179. bool getBool(MMKVKey_t key, bool defaultValue = false);
  180. int32_t getInt32(MMKVKey_t key, int32_t defaultValue = 0);
  181. uint32_t getUInt32(MMKVKey_t key, uint32_t defaultValue = 0);
  182. int64_t getInt64(MMKVKey_t key, int64_t defaultValue = 0);
  183. uint64_t getUInt64(MMKVKey_t key, uint64_t defaultValue = 0);
  184. float getFloat(MMKVKey_t key, float defaultValue = 0);
  185. double getDouble(MMKVKey_t key, double defaultValue = 0);
  186. // return the actual size consumption of the key's value
  187. // pass actualSize = true to get value's length
  188. size_t getValueSize(MMKVKey_t key, bool actualSize);
  189. // return size written into buffer
  190. // return -1 on any error
  191. int32_t writeValueToBuffer(MMKVKey_t key, void *ptr, int32_t size);
  192. bool containsKey(MMKVKey_t key);
  193. size_t count();
  194. size_t totalSize();
  195. size_t actualSize();
  196. #ifdef MMKV_APPLE
  197. NSArray *allKeys();
  198. void removeValuesForKeys(NSArray *arrKeys);
  199. typedef void (^EnumerateBlock)(NSString *key, BOOL *stop);
  200. void enumerateKeys(EnumerateBlock block);
  201. # ifdef MMKV_IOS
  202. static void setIsInBackground(bool isInBackground);
  203. static bool isInBackground();
  204. # endif
  205. #else // !defined(MMKV_APPLE)
  206. std::vector<std::string> allKeys();
  207. void removeValuesForKeys(const std::vector<std::string> &arrKeys);
  208. #endif // MMKV_APPLE
  209. void removeValueForKey(MMKVKey_t key);
  210. void clearAll();
  211. // MMKV's size won't reduce after deleting key-values
  212. // call this method after lots of deleting if you care about disk usage
  213. // note that `clearAll` has the similar effect of `trim`
  214. void trim();
  215. // call this method if the instance is no longer needed in the near future
  216. // any subsequent call to the instance is undefined behavior
  217. void close();
  218. // call this method if you are facing memory-warning
  219. // any subsequent call to the instance will load all key-values from file again
  220. void clearMemoryCache();
  221. // you don't need to call this, really, I mean it
  222. // unless you worry about running out of battery
  223. void sync(SyncFlag flag = MMKV_SYNC);
  224. // get exclusive access
  225. void lock();
  226. void unlock();
  227. bool try_lock();
  228. // check if content been changed by other process
  229. void checkContentChanged();
  230. // called when content is changed by other process
  231. // doesn't guarantee real-time notification
  232. static void registerContentChangeHandler(mmkv::ContentChangeHandler handler);
  233. static void unRegisterContentChangeHandler();
  234. // by default MMKV will discard all datas on failure
  235. // return `OnErrorRecover` to recover any data from file
  236. static void registerErrorHandler(mmkv::ErrorHandler handler);
  237. static void unRegisterErrorHandler();
  238. // MMKVLogInfo by default
  239. // pass MMKVLogNone to disable all logging
  240. static void setLogLevel(MMKVLogLevel level);
  241. // by default MMKV will print log to the console
  242. // implement this method to redirect MMKV's log
  243. static void registerLogHandler(mmkv::LogHandler handler);
  244. static void unRegisterLogHandler();
  245. static bool isFileValid(const std::string &mmapID, MMKVPath_t *relatePath = nullptr);
  246. // just forbid it for possibly misuse
  247. explicit MMKV(const MMKV &other) = delete;
  248. MMKV &operator=(const MMKV &other) = delete;
  249. };
  250. MMKV_NAMESPACE_END
  251. #endif
  252. #endif // MMKV_MMKV_H