react-native-mmkv-dz 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +219 -0
- package/MMKV/CHANGELOG.md +553 -0
- package/MMKV/Core/CMakeLists.txt +153 -0
- package/MMKV/Core/CodedInputData.cpp +228 -0
- package/MMKV/Core/CodedInputData.h +83 -0
- package/MMKV/Core/CodedInputDataCrypt.cpp +280 -0
- package/MMKV/Core/CodedInputDataCrypt.h +87 -0
- package/MMKV/Core/CodedInputDataCrypt_OSX.cpp +62 -0
- package/MMKV/Core/CodedInputData_OSX.cpp +92 -0
- package/MMKV/Core/CodedOutputData.cpp +174 -0
- package/MMKV/Core/CodedOutputData.h +82 -0
- package/MMKV/Core/Core.xcodeproj/project.pbxproj +702 -0
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +67 -0
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +67 -0
- package/MMKV/Core/InterProcessLock.cpp +186 -0
- package/MMKV/Core/InterProcessLock.h +119 -0
- package/MMKV/Core/InterProcessLock_Android.cpp +103 -0
- package/MMKV/Core/InterProcessLock_Win32.cpp +108 -0
- package/MMKV/Core/KeyValueHolder.cpp +236 -0
- package/MMKV/Core/KeyValueHolder.h +118 -0
- package/MMKV/Core/MMBuffer.cpp +185 -0
- package/MMKV/Core/MMBuffer.h +107 -0
- package/MMKV/Core/MMKV.cpp +1418 -0
- package/MMKV/Core/MMKV.h +386 -0
- package/MMKV/Core/MMKVLog.cpp +127 -0
- package/MMKV/Core/MMKVLog.h +86 -0
- package/MMKV/Core/MMKVLog_Android.cpp +79 -0
- package/MMKV/Core/MMKVMetaInfo.hpp +81 -0
- package/MMKV/Core/MMKVPredef.h +245 -0
- package/MMKV/Core/MMKV_Android.cpp +259 -0
- package/MMKV/Core/MMKV_IO.cpp +1119 -0
- package/MMKV/Core/MMKV_IO.h +57 -0
- package/MMKV/Core/MMKV_OSX.cpp +347 -0
- package/MMKV/Core/MMKV_OSX.h +51 -0
- package/MMKV/Core/MemoryFile.cpp +537 -0
- package/MMKV/Core/MemoryFile.h +182 -0
- package/MMKV/Core/MemoryFile_Android.cpp +211 -0
- package/MMKV/Core/MemoryFile_Linux.cpp +120 -0
- package/MMKV/Core/MemoryFile_OSX.cpp +142 -0
- package/MMKV/Core/MemoryFile_Win32.cpp +536 -0
- package/MMKV/Core/MiniPBCoder.cpp +366 -0
- package/MMKV/Core/MiniPBCoder.h +129 -0
- package/MMKV/Core/MiniPBCoder_OSX.cpp +228 -0
- package/MMKV/Core/PBEncodeItem.hpp +86 -0
- package/MMKV/Core/PBUtility.cpp +61 -0
- package/MMKV/Core/PBUtility.h +153 -0
- package/MMKV/Core/ScopedLock.hpp +69 -0
- package/MMKV/Core/ThreadLock.cpp +68 -0
- package/MMKV/Core/ThreadLock.h +78 -0
- package/MMKV/Core/ThreadLock_Win32.cpp +89 -0
- package/MMKV/Core/aes/AESCrypt.cpp +256 -0
- package/MMKV/Core/aes/AESCrypt.h +107 -0
- package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +1231 -0
- package/MMKV/Core/aes/openssl/openssl_aes.h +118 -0
- package/MMKV/Core/aes/openssl/openssl_aes_core.cpp +1044 -0
- package/MMKV/Core/aes/openssl/openssl_aes_locl.h +38 -0
- package/MMKV/Core/aes/openssl/openssl_aesv8-armx.S +308 -0
- package/MMKV/Core/aes/openssl/openssl_arm_arch.h +84 -0
- package/MMKV/Core/aes/openssl/openssl_cfb128.cpp +97 -0
- package/MMKV/Core/aes/openssl/openssl_md32_common.h +254 -0
- package/MMKV/Core/aes/openssl/openssl_md5.h +49 -0
- package/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp +166 -0
- package/MMKV/Core/aes/openssl/openssl_md5_locl.h +75 -0
- package/MMKV/Core/aes/openssl/openssl_md5_one.cpp +30 -0
- package/MMKV/Core/aes/openssl/openssl_opensslconf.h +271 -0
- package/MMKV/Core/core.vcxproj +186 -0
- package/MMKV/Core/core.vcxproj.filters +150 -0
- package/MMKV/Core/crc32/Checksum.h +67 -0
- package/MMKV/Core/crc32/crc32_armv8.cpp +132 -0
- package/MMKV/Core/crc32/zlib/crc32.cpp +55 -0
- package/MMKV/Core/crc32/zlib/crc32.h +48 -0
- package/MMKV/Core/crc32/zlib/zconf.h +380 -0
- package/MMKV/Core/crc32/zlib/zutil.h +25 -0
- package/MMKV/LICENSE.TXT +193 -0
- package/MMKV/README.md +288 -0
- package/README.md +221 -0
- package/android/CMakeLists.txt +71 -0
- package/android/build.gradle +371 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/MmkvHostObject.cpp +302 -0
- package/android/src/main/cpp/MmkvHostObject.h +26 -0
- package/android/src/main/cpp/cpp-adapter.cpp +65 -0
- package/android/src/main/java/com/reactnativemmkv/MmkvModule.java +49 -0
- package/android/src/main/java/com/reactnativemmkv/MmkvPackage.java +26 -0
- package/cpp/TypedArray.cpp +341 -0
- package/cpp/TypedArray.h +175 -0
- package/ios/JSIUtils.h +50 -0
- package/ios/JSIUtils.mm +194 -0
- package/ios/Mmkv.xcodeproj/project.pbxproj +291 -0
- package/ios/MmkvHostObject.h +27 -0
- package/ios/MmkvHostObject.mm +299 -0
- package/ios/MmkvModule.h +5 -0
- package/ios/MmkvModule.mm +73 -0
- package/lib/commonjs/MMKV.js +146 -0
- package/lib/commonjs/MMKV.js.map +1 -0
- package/lib/commonjs/PlatformChecker.js +16 -0
- package/lib/commonjs/PlatformChecker.js.map +1 -0
- package/lib/commonjs/createMMKV.js +66 -0
- package/lib/commonjs/createMMKV.js.map +1 -0
- package/lib/commonjs/createMMKV.mock.js +40 -0
- package/lib/commonjs/createMMKV.mock.js.map +1 -0
- package/lib/commonjs/createMMKV.web.js +77 -0
- package/lib/commonjs/createMMKV.web.js.map +1 -0
- package/lib/commonjs/createTextEncoder.js +24 -0
- package/lib/commonjs/createTextEncoder.js.map +1 -0
- package/lib/commonjs/hooks.js +200 -0
- package/lib/commonjs/hooks.js.map +1 -0
- package/lib/commonjs/index.js +32 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/MMKV.js +134 -0
- package/lib/module/MMKV.js.map +1 -0
- package/lib/module/PlatformChecker.js +9 -0
- package/lib/module/PlatformChecker.js.map +1 -0
- package/lib/module/createMMKV.js +55 -0
- package/lib/module/createMMKV.js.map +1 -0
- package/lib/module/createMMKV.mock.js +31 -0
- package/lib/module/createMMKV.mock.js.map +1 -0
- package/lib/module/createMMKV.web.js +67 -0
- package/lib/module/createMMKV.web.js.map +1 -0
- package/lib/module/createTextEncoder.js +17 -0
- package/lib/module/createTextEncoder.js.map +1 -0
- package/lib/module/hooks.js +181 -0
- package/lib/module/hooks.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/MMKV.d.ts +137 -0
- package/lib/typescript/PlatformChecker.d.ts +1 -0
- package/lib/typescript/createMMKV.d.ts +6 -0
- package/lib/typescript/createMMKV.mock.d.ts +2 -0
- package/lib/typescript/createMMKV.web.d.ts +2 -0
- package/lib/typescript/createTextEncoder.d.ts +1 -0
- package/lib/typescript/hooks.d.ts +81 -0
- package/lib/typescript/index.d.ts +2 -0
- package/package.json +168 -0
- package/react-native-mmkv.podspec +32 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making
|
|
3
|
+
* MMKV available.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2019 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
|
+
|
|
21
|
+
#include "MemoryFile.h"
|
|
22
|
+
|
|
23
|
+
#ifdef MMKV_WIN32
|
|
24
|
+
|
|
25
|
+
# include "InterProcessLock.h"
|
|
26
|
+
# include "MMBuffer.h"
|
|
27
|
+
# include "MMKVLog.h"
|
|
28
|
+
# include "ScopedLock.hpp"
|
|
29
|
+
# include "ThreadLock.h"
|
|
30
|
+
# include <cassert>
|
|
31
|
+
# include <strsafe.h>
|
|
32
|
+
|
|
33
|
+
using namespace std;
|
|
34
|
+
|
|
35
|
+
namespace mmkv {
|
|
36
|
+
|
|
37
|
+
static bool getFileSize(MMKVFileHandle_t fd, size_t &size);
|
|
38
|
+
static bool ftruncate(MMKVFileHandle_t file, size_t size);
|
|
39
|
+
|
|
40
|
+
File::File(MMKVPath_t path, OpenFlag flag) : m_path(std::move(path)), m_fd(INVALID_HANDLE_VALUE), m_flag(flag) {
|
|
41
|
+
open();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static pair<int, int> OpenFlag2NativeFlag(OpenFlag flag) {
|
|
45
|
+
int access = 0, create = OPEN_EXISTING;
|
|
46
|
+
if (flag & OpenFlag::ReadWrite) {
|
|
47
|
+
access = (GENERIC_READ | GENERIC_WRITE);
|
|
48
|
+
} else if (flag & OpenFlag::ReadOnly) {
|
|
49
|
+
access |= GENERIC_READ;
|
|
50
|
+
} else if (flag & OpenFlag::WriteOnly) {
|
|
51
|
+
access |= GENERIC_WRITE;
|
|
52
|
+
}
|
|
53
|
+
if (flag & OpenFlag::Create) {
|
|
54
|
+
create = OPEN_ALWAYS;
|
|
55
|
+
}
|
|
56
|
+
if (flag & OpenFlag::Excel) {
|
|
57
|
+
access = CREATE_NEW;
|
|
58
|
+
}
|
|
59
|
+
if (flag & OpenFlag::Truncate) {
|
|
60
|
+
access = CREATE_ALWAYS;
|
|
61
|
+
}
|
|
62
|
+
return {access, create};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
bool File::open() {
|
|
66
|
+
if (isFileValid()) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
auto pair = OpenFlag2NativeFlag(m_flag);
|
|
70
|
+
m_fd = CreateFile(m_path.c_str(), pair.first, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
|
71
|
+
pair.second, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
72
|
+
if (!isFileValid()) {
|
|
73
|
+
MMKVError("fail to open:[%ws], %d", m_path.c_str(), GetLastError());
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
MMKVInfo("open fd[%p], %ws", m_fd, m_path.c_str());
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void File::close() {
|
|
81
|
+
if (isFileValid()) {
|
|
82
|
+
MMKVInfo("closing fd[%p], %ws", m_fd, m_path.c_str());
|
|
83
|
+
if (CloseHandle(m_fd)) {
|
|
84
|
+
m_fd = INVALID_HANDLE_VALUE;
|
|
85
|
+
} else {
|
|
86
|
+
MMKVError("fail to close [%ws], %d", m_path.c_str(), GetLastError());
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
size_t File::getActualFileSize() const {
|
|
92
|
+
size_t size = 0;
|
|
93
|
+
mmkv::getFileSize(m_fd, size);
|
|
94
|
+
return size;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
MemoryFile::MemoryFile(MMKVPath_t path)
|
|
98
|
+
: m_diskFile(std::move(path), OpenFlag::ReadWrite | OpenFlag::Create)
|
|
99
|
+
, m_fileMapping(nullptr)
|
|
100
|
+
, m_ptr(nullptr)
|
|
101
|
+
, m_size(0) {
|
|
102
|
+
reloadFromFile();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
bool MemoryFile::truncate(size_t size) {
|
|
106
|
+
if (!m_diskFile.isFileValid()) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if (size == m_size) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
auto oldSize = m_size;
|
|
114
|
+
m_size = size;
|
|
115
|
+
// round up to (n * pagesize)
|
|
116
|
+
if (m_size < DEFAULT_MMAP_SIZE || (m_size % DEFAULT_MMAP_SIZE != 0)) {
|
|
117
|
+
m_size = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!ftruncate(m_diskFile.getFd(), m_size)) {
|
|
121
|
+
MMKVError("fail to truncate [%ws] to size %zu", m_diskFile.m_path.c_str(), m_size);
|
|
122
|
+
m_size = oldSize;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
if (m_size > oldSize) {
|
|
126
|
+
if (!zeroFillFile(m_diskFile.getFd(), oldSize, m_size - oldSize)) {
|
|
127
|
+
MMKVError("fail to zeroFile [%ws] to size %zu", m_diskFile.m_path.c_str(), m_size);
|
|
128
|
+
m_size = oldSize;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (m_ptr) {
|
|
134
|
+
if (!UnmapViewOfFile(m_ptr)) {
|
|
135
|
+
MMKVError("fail to munmap [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
136
|
+
}
|
|
137
|
+
m_ptr = nullptr;
|
|
138
|
+
}
|
|
139
|
+
if (m_fileMapping) {
|
|
140
|
+
CloseHandle(m_fileMapping);
|
|
141
|
+
m_fileMapping = nullptr;
|
|
142
|
+
}
|
|
143
|
+
auto ret = mmap();
|
|
144
|
+
if (!ret) {
|
|
145
|
+
doCleanMemoryCache(true);
|
|
146
|
+
}
|
|
147
|
+
return ret;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
bool MemoryFile::msync(SyncFlag syncFlag) {
|
|
151
|
+
if (m_ptr) {
|
|
152
|
+
if (FlushViewOfFile(m_ptr, m_size)) {
|
|
153
|
+
if (syncFlag == MMKV_SYNC) {
|
|
154
|
+
if (!FlushFileBuffers(m_diskFile.getFd())) {
|
|
155
|
+
MMKVError("fail to FlushFileBuffers [%ws]:%d", m_diskFile.m_path.c_str(), GetLastError());
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
MMKVError("fail to FlushViewOfFile [%ws]:%d", m_diskFile.m_path.c_str(), GetLastError());
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
bool MemoryFile::mmap() {
|
|
168
|
+
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, PAGE_READWRITE, 0, 0, nullptr);
|
|
169
|
+
if (!m_fileMapping) {
|
|
170
|
+
MMKVError("fail to CreateFileMapping [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
171
|
+
return false;
|
|
172
|
+
} else {
|
|
173
|
+
m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
|
174
|
+
if (!m_ptr) {
|
|
175
|
+
MMKVError("fail to mmap [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void MemoryFile::reloadFromFile() {
|
|
184
|
+
if (isFileValid()) {
|
|
185
|
+
MMKVWarning("calling reloadFromFile while the cache [%ws] is still valid", m_diskFile.m_path.c_str());
|
|
186
|
+
assert(0);
|
|
187
|
+
clearMemoryCache();
|
|
188
|
+
}
|
|
189
|
+
m_diskFile.open();
|
|
190
|
+
if (m_diskFile.isFileValid()) {
|
|
191
|
+
FileLock fileLock(m_diskFile.getFd());
|
|
192
|
+
InterProcessLock lock(&fileLock, ExclusiveLockType);
|
|
193
|
+
SCOPED_LOCK(&lock);
|
|
194
|
+
|
|
195
|
+
mmkv::getFileSize(m_diskFile.getFd(), m_size);
|
|
196
|
+
// round up to (n * pagesize)
|
|
197
|
+
if (m_size < DEFAULT_MMAP_SIZE || (m_size % DEFAULT_MMAP_SIZE != 0)) {
|
|
198
|
+
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
|
|
199
|
+
truncate(roundSize);
|
|
200
|
+
} else {
|
|
201
|
+
auto ret = mmap();
|
|
202
|
+
if (!ret) {
|
|
203
|
+
doCleanMemoryCache(true);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
void MemoryFile::doCleanMemoryCache(bool forceClean) {
|
|
210
|
+
if (m_ptr) {
|
|
211
|
+
UnmapViewOfFile(m_ptr);
|
|
212
|
+
m_ptr = nullptr;
|
|
213
|
+
}
|
|
214
|
+
if (m_fileMapping) {
|
|
215
|
+
CloseHandle(m_fileMapping);
|
|
216
|
+
m_fileMapping = nullptr;
|
|
217
|
+
}
|
|
218
|
+
m_diskFile.close();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
size_t getPageSize() {
|
|
222
|
+
SYSTEM_INFO system_info;
|
|
223
|
+
GetSystemInfo(&system_info);
|
|
224
|
+
return system_info.dwPageSize;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
bool isFileExist(const MMKVPath_t &nsFilePath) {
|
|
228
|
+
if (nsFilePath.empty()) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
auto attribute = GetFileAttributes(nsFilePath.c_str());
|
|
232
|
+
return (attribute != INVALID_FILE_ATTRIBUTES);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
bool mkPath(const MMKVPath_t &str) {
|
|
236
|
+
wchar_t *path = _wcsdup(str.c_str());
|
|
237
|
+
|
|
238
|
+
bool done = false;
|
|
239
|
+
wchar_t *slash = path;
|
|
240
|
+
|
|
241
|
+
while (!done) {
|
|
242
|
+
slash += wcsspn(slash, L"\\");
|
|
243
|
+
slash += wcscspn(slash, L"\\");
|
|
244
|
+
|
|
245
|
+
done = (*slash == L'\0');
|
|
246
|
+
*slash = L'\0';
|
|
247
|
+
|
|
248
|
+
auto attribute = GetFileAttributes(path);
|
|
249
|
+
if (attribute == INVALID_FILE_ATTRIBUTES) {
|
|
250
|
+
if (!CreateDirectory(path, nullptr)) {
|
|
251
|
+
MMKVError("fail to create dir:%ws, %d", str.c_str(), GetLastError());
|
|
252
|
+
free(path);
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
} else if (!(attribute & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
256
|
+
MMKVError("%ws attribute:%d not a directry", str.c_str(), attribute);
|
|
257
|
+
free(path);
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
*slash = L'\\';
|
|
262
|
+
}
|
|
263
|
+
free(path);
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
MMBuffer *readWholeFile(const MMKVPath_t &nsFilePath) {
|
|
268
|
+
MMBuffer *buffer = nullptr;
|
|
269
|
+
auto fd = CreateFile(nsFilePath.c_str(), GENERIC_READ | GENERIC_WRITE,
|
|
270
|
+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING,
|
|
271
|
+
FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
272
|
+
if (fd != INVALID_HANDLE_VALUE) {
|
|
273
|
+
size_t fileLength = 0;
|
|
274
|
+
getFileSize(fd, fileLength);
|
|
275
|
+
if (fileLength > 0) {
|
|
276
|
+
buffer = new MMBuffer(static_cast<size_t>(fileLength));
|
|
277
|
+
SetFilePointer(fd, 0, 0, FILE_BEGIN);
|
|
278
|
+
DWORD readSize = 0;
|
|
279
|
+
if (ReadFile(fd, buffer->getPtr(), fileLength, &readSize, nullptr)) {
|
|
280
|
+
//fileSize = readSize;
|
|
281
|
+
} else {
|
|
282
|
+
MMKVWarning("fail to read %ws: %d", nsFilePath.c_str(), GetLastError());
|
|
283
|
+
delete buffer;
|
|
284
|
+
buffer = nullptr;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
CloseHandle(fd);
|
|
288
|
+
} else {
|
|
289
|
+
MMKVWarning("fail to open %ws: %d", nsFilePath.c_str(), GetLastError());
|
|
290
|
+
}
|
|
291
|
+
return buffer;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
bool zeroFillFile(MMKVFileHandle_t file, size_t startPos, size_t size) {
|
|
295
|
+
if (file == INVALID_HANDLE_VALUE) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
if (size == 0) {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
LARGE_INTEGER position;
|
|
303
|
+
position.QuadPart = startPos;
|
|
304
|
+
if (!SetFilePointerEx(file, position, nullptr, FILE_BEGIN)) {
|
|
305
|
+
MMKVError("fail to lseek fd[%p], error:%d", file, GetLastError());
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static const char zeros[4096] = {0};
|
|
310
|
+
while (size >= sizeof(zeros)) {
|
|
311
|
+
DWORD bytesWritten = 0;
|
|
312
|
+
if (!WriteFile(file, zeros, sizeof(zeros), &bytesWritten, nullptr)) {
|
|
313
|
+
MMKVError("fail to write fd[%p], error:%d", file, GetLastError());
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
size -= bytesWritten;
|
|
317
|
+
}
|
|
318
|
+
if (size > 0) {
|
|
319
|
+
DWORD bytesWritten = 0;
|
|
320
|
+
if (!WriteFile(file, zeros, size, &bytesWritten, nullptr)) {
|
|
321
|
+
MMKVError("fail to write fd[%p], error:%d", file, GetLastError());
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
static bool ftruncate(MMKVFileHandle_t file, size_t size) {
|
|
329
|
+
LARGE_INTEGER large;
|
|
330
|
+
large.QuadPart = size;
|
|
331
|
+
if (SetFilePointerEx(file, large, 0, FILE_BEGIN)) {
|
|
332
|
+
if (SetEndOfFile(file)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
MMKVError("fail to SetEndOfFile:%d", GetLastError());
|
|
336
|
+
return false;
|
|
337
|
+
} else {
|
|
338
|
+
MMKVError("fail to SetFilePointer:%d", GetLastError());
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static bool getFileSize(MMKVFileHandle_t fd, size_t &size) {
|
|
344
|
+
LARGE_INTEGER filesize = {0};
|
|
345
|
+
if (GetFileSizeEx(fd, &filesize)) {
|
|
346
|
+
size = static_cast<size_t>(filesize.QuadPart);
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static pair<MMKVPath_t, MMKVFileHandle_t> createUniqueTempFile(const wchar_t *prefix) {
|
|
353
|
+
wchar_t lpTempPathBuffer[MAX_PATH];
|
|
354
|
+
// Gets the temp path env string (no guarantee it's a valid path).
|
|
355
|
+
auto dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
|
|
356
|
+
if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
|
|
357
|
+
MMKVError("GetTempPath failed %d", GetLastError());
|
|
358
|
+
return {L"", INVALID_HANDLE_VALUE};
|
|
359
|
+
}
|
|
360
|
+
// Generates a temporary file name.
|
|
361
|
+
wchar_t szTempFileName[MAX_PATH];
|
|
362
|
+
if (!GetTempFileName(lpTempPathBuffer, prefix, 0, szTempFileName)) {
|
|
363
|
+
MMKVError("GetTempFileName failed %d", GetLastError());
|
|
364
|
+
return {L"", INVALID_HANDLE_VALUE};
|
|
365
|
+
}
|
|
366
|
+
auto hTempFile = CreateFile(szTempFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
367
|
+
if (hTempFile == INVALID_HANDLE_VALUE) {
|
|
368
|
+
MMKVError("fail to create unique temp file [%ws], %d", szTempFileName, GetLastError());
|
|
369
|
+
return {L"", INVALID_HANDLE_VALUE};
|
|
370
|
+
}
|
|
371
|
+
MMKVDebug("create unique temp file [%ws] with fd[%p]", szTempFileName, hTempFile);
|
|
372
|
+
return {MMKVPath_t(szTempFileName), hTempFile};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
376
|
+
if (MoveFileEx(srcPath.c_str(), dstPath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0) {
|
|
377
|
+
MMKVError("MoveFileEx [%ws] to [%ws] failed %d", srcPath.c_str(), dstPath.c_str(), GetLastError());
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
|
|
384
|
+
if (dstFD == INVALID_HANDLE_VALUE) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
bool ret = false;
|
|
388
|
+
File srcFile(srcPath, OpenFlag::ReadOnly);
|
|
389
|
+
if (!srcFile.isFileValid()) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
auto bufferSize = getPageSize();
|
|
393
|
+
auto buffer = (char *) malloc(bufferSize);
|
|
394
|
+
if (!buffer) {
|
|
395
|
+
MMKVError("fail to malloc size %zu, %d(%s)", bufferSize, errno, strerror(errno));
|
|
396
|
+
goto errorOut;
|
|
397
|
+
}
|
|
398
|
+
SetFilePointer(dstFD, 0, 0, FILE_BEGIN);
|
|
399
|
+
|
|
400
|
+
// the Win32 platform don't have sendfile()/fcopyfile() equivalent, do it the hard way
|
|
401
|
+
while (true) {
|
|
402
|
+
DWORD sizeRead = 0;
|
|
403
|
+
if (!ReadFile(srcFile.getFd(), buffer, bufferSize, &sizeRead, nullptr)) {
|
|
404
|
+
MMKVError("fail to read %ws: %d", srcPath.c_str(), GetLastError());
|
|
405
|
+
goto errorOut;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
DWORD sizeWrite = 0;
|
|
409
|
+
if (!WriteFile(dstFD, buffer, sizeRead, &sizeWrite, nullptr)) {
|
|
410
|
+
MMKVError("fail to write fd [%d], %d", dstFD, GetLastError());
|
|
411
|
+
goto errorOut;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (sizeRead < bufferSize) {
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (needTruncate) {
|
|
419
|
+
size_t dstFileSize = 0;
|
|
420
|
+
getFileSize(dstFD, dstFileSize);
|
|
421
|
+
auto srcFileSize = srcFile.getActualFileSize();
|
|
422
|
+
if ((dstFileSize != srcFileSize) && !ftruncate(dstFD, static_cast<off_t>(srcFileSize))) {
|
|
423
|
+
MMKVError("fail to truncate [%d] to size [%zu]", dstFD, srcFileSize);
|
|
424
|
+
goto errorOut;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
ret = true;
|
|
429
|
+
MMKVInfo("copy content from %ws to fd[%d] finish", srcPath.c_str(), dstFD);
|
|
430
|
+
|
|
431
|
+
errorOut:
|
|
432
|
+
free(buffer);
|
|
433
|
+
return ret;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// copy to a temp file then rename it
|
|
437
|
+
// this is the best we can do on Win32
|
|
438
|
+
bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
439
|
+
auto pair = createUniqueTempFile(L"MMKV");
|
|
440
|
+
auto tmpFD = pair.second;
|
|
441
|
+
auto &tmpPath = pair.first;
|
|
442
|
+
if (tmpFD == INVALID_HANDLE_VALUE) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
bool renamed = false;
|
|
447
|
+
if (copyFileContent(srcPath, tmpFD, false)) {
|
|
448
|
+
MMKVInfo("copyed file [%ws] to [%ws]", srcPath.c_str(), tmpPath.c_str());
|
|
449
|
+
CloseHandle(tmpFD);
|
|
450
|
+
renamed = tryAtomicRename(tmpPath.c_str(), dstPath.c_str());
|
|
451
|
+
if (renamed) {
|
|
452
|
+
MMKVInfo("copyfile [%ws] to [%ws] finish.", srcPath.c_str(), dstPath.c_str());
|
|
453
|
+
}
|
|
454
|
+
} else {
|
|
455
|
+
CloseHandle(tmpFD);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (!renamed) {
|
|
459
|
+
DeleteFile(tmpPath.c_str());
|
|
460
|
+
}
|
|
461
|
+
return renamed;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
465
|
+
File dstFile(dstPath, OpenFlag::WriteOnly | OpenFlag::Create | OpenFlag::Truncate);
|
|
466
|
+
if (!dstFile.isFileValid()) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
auto ret = copyFileContent(srcPath, dstFile.getFd(), false);
|
|
470
|
+
if (!ret) {
|
|
471
|
+
MMKVError("fail to copyfile(): target file %ws", dstPath.c_str());
|
|
472
|
+
} else {
|
|
473
|
+
MMKVInfo("copy content from %ws to [%ws] finish", srcPath.c_str(), dstPath.c_str());
|
|
474
|
+
}
|
|
475
|
+
return ret;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
|
|
479
|
+
return copyFileContent(srcPath, dstFD, true);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
void walkInDir(const MMKVPath_t &dirPath,
|
|
483
|
+
WalkType type,
|
|
484
|
+
const std::function<void(const MMKVPath_t &, WalkType)> &walker) {
|
|
485
|
+
wchar_t szDir[MAX_PATH];
|
|
486
|
+
StringCchCopy(szDir, MAX_PATH, dirPath.c_str());
|
|
487
|
+
StringCchCat(szDir, MAX_PATH, L"\\*");
|
|
488
|
+
|
|
489
|
+
WIN32_FIND_DATA ffd;
|
|
490
|
+
auto hFind = FindFirstFile(szDir, &ffd);
|
|
491
|
+
if (hFind == INVALID_HANDLE_VALUE) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
do {
|
|
496
|
+
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
497
|
+
if (type & WalkFolder) {
|
|
498
|
+
if (wcscmp(ffd.cFileName, L".") == 0 || wcscmp(ffd.cFileName, L"..") == 0) {
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
walker(dirPath + L"\\" + ffd.cFileName, WalkFolder);
|
|
502
|
+
}
|
|
503
|
+
} else if (type & WalkFile) {
|
|
504
|
+
walker(dirPath + L"\\" + ffd.cFileName, WalkFile);
|
|
505
|
+
}
|
|
506
|
+
} while (FindNextFile(hFind, &ffd) != 0);
|
|
507
|
+
|
|
508
|
+
auto dwError = GetLastError();
|
|
509
|
+
if (dwError != ERROR_NO_MORE_FILES) {
|
|
510
|
+
MMKVError("WalkInDir fail %d", dwError);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
FindClose(hFind);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
} // namespace mmkv
|
|
517
|
+
|
|
518
|
+
std::wstring string2MMKVPath_t(const std::string &str) {
|
|
519
|
+
auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
|
|
520
|
+
auto buffer = new wchar_t[length];
|
|
521
|
+
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, length);
|
|
522
|
+
wstring result(buffer);
|
|
523
|
+
delete[] buffer;
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
std::string MMKVPath_t2String(const MMKVPath_t &str) {
|
|
528
|
+
auto length = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, nullptr, 0, 0, 0);
|
|
529
|
+
auto buffer = new char[length];
|
|
530
|
+
WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, buffer, length, 0, 0);
|
|
531
|
+
string result(buffer);
|
|
532
|
+
delete[] buffer;
|
|
533
|
+
return result;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
#endif // MMKV_WIN32
|