From 9854ba0f82feba4c5a65a86372c7e360294a6a55 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 7 Dec 2018 16:28:47 +0800 Subject: [PATCH 01/57] init for Win32 --- .gitignore | 9 +- Win32/.clang-format | 34 ++++ Win32/MMKV/MMKV.cpp | 39 +++++ Win32/MMKV/MMKV.h | 11 ++ Win32/MMKV/MMKV.vcxproj | 161 +++++++++++++++++++ Win32/MMKV/MMKV.vcxproj.filters | 36 +++++ Win32/MMKV/MMKVDef.h | 13 ++ Win32/MMKV/dllmain.cpp | 19 +++ Win32/MMKV/targetver.h | 10 ++ Win32/Win32.sln | 44 ++++++ Win32/Win32Demo/Win32Demo.cpp | 24 +++ Win32/Win32Demo/Win32Demo.vcxproj | 180 ++++++++++++++++++++++ Win32/Win32Demo/Win32Demo.vcxproj.filters | 30 ++++ Win32/Win32Demo/pch.cpp | 5 + Win32/Win32Demo/pch.h | 14 ++ 15 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 Win32/.clang-format create mode 100644 Win32/MMKV/MMKV.cpp create mode 100644 Win32/MMKV/MMKV.h create mode 100644 Win32/MMKV/MMKV.vcxproj create mode 100644 Win32/MMKV/MMKV.vcxproj.filters create mode 100644 Win32/MMKV/MMKVDef.h create mode 100644 Win32/MMKV/dllmain.cpp create mode 100644 Win32/MMKV/targetver.h create mode 100644 Win32/Win32.sln create mode 100644 Win32/Win32Demo/Win32Demo.cpp create mode 100644 Win32/Win32Demo/Win32Demo.vcxproj create mode 100644 Win32/Win32Demo/Win32Demo.vcxproj.filters create mode 100644 Win32/Win32Demo/pch.cpp create mode 100644 Win32/Win32Demo/pch.h diff --git a/.gitignore b/.gitignore index cb2e9819..76393348 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,11 @@ xcuserdata *.xcscheme ## Xcode -DerivedData \ No newline at end of file +DerivedData + +## Visual Studio +.vs +[Dd]ebug/ +[Rr]elease/ +*.user + diff --git a/Win32/.clang-format b/Win32/.clang-format new file mode 100644 index 00000000..38cca093 --- /dev/null +++ b/Win32/.clang-format @@ -0,0 +1,34 @@ +--- +BasedOnStyle: LLVM +IndentWidth: 4 +TabWidth: 4 +AlwaysBreakTemplateDeclarations: true +AllowShortFunctionsOnASingleLine: 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 +--- +Language: Cpp +ColumnLimit: 100 +--- +Language: ObjC +ColumnLimit: 0 +UseTab: ForIndentation +ObjCBlockIndentWidth: 4 +--- +Language: Java +ColumnLimit: 100 +AllowShortFunctionsOnASingleLine: None +BreakBeforeBinaryOperators: NonAssignment diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp new file mode 100644 index 00000000..6f050c03 --- /dev/null +++ b/Win32/MMKV/MMKV.cpp @@ -0,0 +1,39 @@ +// MMKV.cpp : Defines the exported functions for the DLL application. +// + +#include "MMKV.h" + +static int getpagesize(void) { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwPageSize; +} + +MMKV::MMKV() {} + +MMKV::~MMKV() {} + +int MMKV::foo() { + OFSTRUCT of; + HANDLE file = (HANDLE) CreateFile(L"testmm", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == (HANDLE) HFILE_ERROR) { + return -1; + } + SetFilePointer(file, getpagesize(), 0, FILE_BEGIN); + SetEndOfFile(file); + + auto mmFile = CreateFileMapping(file, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!mmFile) { + return -2; + } + auto ptr = MapViewOfFile(mmFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!ptr) { + return -3; + } + int value = 1024; + //memcpy(ptr, &value, sizeof(value)); + memcpy(&value, ptr, sizeof(value)); + return value; +} diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h new file mode 100644 index 00000000..b54a72c1 --- /dev/null +++ b/Win32/MMKV/MMKV.h @@ -0,0 +1,11 @@ +#pragma once + +#include "MMKVDef.h" + +class MMKV_API MMKV { +public: + MMKV(); + ~MMKV(); + int foo(); +private: +}; diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj new file mode 100644 index 00000000..91cfb51c --- /dev/null +++ b/Win32/MMKV/MMKV.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {9D4250EF-E8D6-4652-B738-3D4B2E982126} + Win32Proj + MMKV + 10.0.17763.0 + + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + true + _DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters new file mode 100644 index 00000000..c96fb243 --- /dev/null +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Win32/MMKV/MMKVDef.h b/Win32/MMKV/MMKVDef.h new file mode 100644 index 00000000..b356b803 --- /dev/null +++ b/Win32/MMKV/MMKVDef.h @@ -0,0 +1,13 @@ +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include + +#ifdef MMKV_EXPORTS +#define MMKV_API __declspec(dllexport) +#else +#define MMKV_API __declspec(dllimport) +#endif diff --git a/Win32/MMKV/dllmain.cpp b/Win32/MMKV/dllmain.cpp new file mode 100644 index 00000000..fe91032b --- /dev/null +++ b/Win32/MMKV/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "MMKVDef.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/Win32/MMKV/targetver.h b/Win32/MMKV/targetver.h new file mode 100644 index 00000000..a2c3bc00 --- /dev/null +++ b/Win32/MMKV/targetver.h @@ -0,0 +1,10 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#define _WIN32_WINNT _WIN32_WINNT_WINXP + +#include diff --git a/Win32/Win32.sln b/Win32/Win32.sln new file mode 100644 index 00000000..6ea80da7 --- /dev/null +++ b/Win32/Win32.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.136 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win32Demo", "Win32Demo\Win32Demo.vcxproj", "{532303C4-38D9-45D3-B925-18056C66CD01}" + ProjectSection(ProjectDependencies) = postProject + {9D4250EF-E8D6-4652-B738-3D4B2E982126} = {9D4250EF-E8D6-4652-B738-3D4B2E982126} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMKV", "MMKV\MMKV.vcxproj", "{9D4250EF-E8D6-4652-B738-3D4B2E982126}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {532303C4-38D9-45D3-B925-18056C66CD01}.Debug|x64.ActiveCfg = Debug|x64 + {532303C4-38D9-45D3-B925-18056C66CD01}.Debug|x64.Build.0 = Debug|x64 + {532303C4-38D9-45D3-B925-18056C66CD01}.Debug|x86.ActiveCfg = Debug|Win32 + {532303C4-38D9-45D3-B925-18056C66CD01}.Debug|x86.Build.0 = Debug|Win32 + {532303C4-38D9-45D3-B925-18056C66CD01}.Release|x64.ActiveCfg = Release|x64 + {532303C4-38D9-45D3-B925-18056C66CD01}.Release|x64.Build.0 = Release|x64 + {532303C4-38D9-45D3-B925-18056C66CD01}.Release|x86.ActiveCfg = Release|Win32 + {532303C4-38D9-45D3-B925-18056C66CD01}.Release|x86.Build.0 = Release|Win32 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Debug|x64.ActiveCfg = Debug|x64 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Debug|x64.Build.0 = Debug|x64 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Debug|x86.ActiveCfg = Debug|Win32 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Debug|x86.Build.0 = Debug|Win32 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x64.ActiveCfg = Release|x64 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x64.Build.0 = Release|x64 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x86.ActiveCfg = Release|Win32 + {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EAE99F5F-91EC-4631-A8DA-E8223A366552} + EndGlobalSection +EndGlobal diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp new file mode 100644 index 00000000..56f1b115 --- /dev/null +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -0,0 +1,24 @@ +// Win32Demo.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include "pch.h" +#include +#include "MMKV.h" + +using namespace std; + +int main() { + cout << MMKV().foo() << endl; + cout << "Hello World!\n"; +} + +// Run program: Ctrl + F5 or Debug > Start Without Debugging menu +// Debug program: F5 or Debug > Start Debugging menu + +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj new file mode 100644 index 00000000..9383a204 --- /dev/null +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {532303C4-38D9-45D3-B925-18056C66CD01} + Win32Proj + Win32Demo + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\MMKV;%(AdditionalIncludeDirectories) + + + Console + true + ..\$(IntDir);%(AdditionalLibraryDirectories) + MMKV.lib;%(AdditionalDependencies) + + + xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\MMKV;%(AdditionalIncludeDirectories) + + + Console + true + true + true + ..\$(IntDir);%(AdditionalLibraryDirectories) + MMKV.lib;%(AdditionalDependencies) + + + xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/Win32/Win32Demo/Win32Demo.vcxproj.filters b/Win32/Win32Demo/Win32Demo.vcxproj.filters new file mode 100644 index 00000000..bc4d88c3 --- /dev/null +++ b/Win32/Win32Demo/Win32Demo.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Win32/Win32Demo/pch.cpp b/Win32/Win32Demo/pch.cpp new file mode 100644 index 00000000..3a3d12b5 --- /dev/null +++ b/Win32/Win32Demo/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed + +#include "pch.h" + +// In general, ignore this file, but keep it around if you are using pre-compiled headers. diff --git a/Win32/Win32Demo/pch.h b/Win32/Win32Demo/pch.h new file mode 100644 index 00000000..b04e71e0 --- /dev/null +++ b/Win32/Win32Demo/pch.h @@ -0,0 +1,14 @@ +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file + +#ifndef PCH_H +#define PCH_H + +// TODO: add headers that you want to pre-compile here + +#endif //PCH_H From 0770b4d012dd264b489036b7034500955f6dc7e7 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 7 Dec 2018 21:32:47 +0800 Subject: [PATCH 02/57] compile --- Win32/MMKV/MMKV.cpp | 1366 ++++++++++++++++++++++++++++++- Win32/MMKV/MMKV.h | 238 +++++- Win32/MMKV/MMKV.vcxproj | 38 +- Win32/MMKV/MMKV.vcxproj.filters | 102 +++ Win32/Win32Demo/Win32Demo.cpp | 2 +- 5 files changed, 1733 insertions(+), 13 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 6f050c03..d3f8444d 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -1,7 +1,46 @@ // MMKV.cpp : Defines the exported functions for the DLL application. // +/* + * 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.h" +#include "CodedInputData.h" +#include "CodedOutputData.h" +#include "InterProcessLock.h" +#include "MMBuffer.h" +#include "MMKVLog.h" +#include "MiniPBCoder.h" +#include "MmapedFile.h" +#include "PBUtility.h" +#include "ScopedLock.hpp" +#include "aes/AESCrypt.h" +#include "aes/openssl/md5.h" +#include +#include +#include +#include +#include +#include + +using namespace std; static int getpagesize(void) { SYSTEM_INFO system_info; @@ -9,11 +48,7 @@ static int getpagesize(void) { return system_info.dwPageSize; } -MMKV::MMKV() {} - -MMKV::~MMKV() {} - -int MMKV::foo() { +static int foo() { OFSTRUCT of; HANDLE file = (HANDLE) CreateFile(L"testmm", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -33,7 +68,1326 @@ int MMKV::foo() { return -3; } int value = 1024; - //memcpy(ptr, &value, sizeof(value)); + //memcpy(ptr, &value, sizeof(value)); memcpy(&value, ptr, sizeof(value)); return value; } + +static unordered_map *g_instanceDic; +static ThreadLock g_instanceLock; +static std::string g_rootDir; + +#define DEFAULT_MMAP_ID "mmkv.default" +#define SPECIAL_CHARACTER_DIRECTORY_NAME "specialCharacter" +constexpr uint32_t Fixed32Size = pbFixed32Size(0); + +static string mappedKVPathWithID(const string &mmapID, MMKVMode mode); +static string crcPathWithID(const string &mmapID, MMKVMode mode); +static void mkSpecialCharacterFileDirectory(); +static string md5(const string &value); +static string encodeFilePath(const string &mmapID); + +enum : bool { + KeepSequence = false, + IncreaseSequence = true, +}; + +MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) + : m_mmapID(mmapID) + , m_path(mappedKVPathWithID(m_mmapID, mode)) + , m_crcPath(crcPathWithID(m_mmapID, mode)) + , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE, (mode & MMKV_ASHMEM) ? MMAP_ASHMEM : MMAP_FILE) + , m_crypter(nullptr) + , m_fileLock(m_metaFile.getFd()) + , m_sharedProcessLock(&m_fileLock, SharedLockType) + , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) + , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) + , m_isAshmem((mode & MMKV_ASHMEM) != 0) { + m_fd = -1; + m_ptr = nullptr; + m_size = 0; + m_actualSize = 0; + m_output = nullptr; + + if (m_isAshmem) { + m_ashmemFile = new MmapedFile(m_mmapID, static_cast(size), MMAP_ASHMEM); + m_fd = m_ashmemFile->getFd(); + } else { + m_ashmemFile = nullptr; + } + + if (cryptKey && cryptKey->length() > 0) { + m_crypter = new AESCrypt((const unsigned char *) cryptKey->data(), cryptKey->length()); + } + + m_needLoadFromFile = true; + m_hasFullWriteback = false; + + m_crcDigest = 0; + + m_sharedProcessLock.m_enable = m_isInterProcess; + m_exclusiveProcessLock.m_enable = m_isInterProcess; + + // sensitive zone + { + SCOPEDLOCK(m_sharedProcessLock); + loadFromFile(); + } +} + +MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKey) + : m_mmapID(mmapID) + , m_path("") + , m_crcPath("") + , m_metaFile(ashmemMetaFD) + , m_crypter(nullptr) + , m_fileLock(m_metaFile.getFd()) + , m_sharedProcessLock(&m_fileLock, SharedLockType) + , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) + , m_isInterProcess(true) + , m_isAshmem(true) { + + // check mmapID with ashmemID + { + auto ashmemID = m_metaFile.getName(); + size_t pos = ashmemID.find_last_of('.'); + if (pos != string::npos) { + ashmemID.erase(pos, string::npos); + } + if (mmapID != ashmemID) { + MMKVWarning("mmapID[%s] != ashmem[%s]", mmapID.c_str(), ashmemID.c_str()); + } + } + m_path = string(ASHMEM_NAME_DEF) + "/" + m_mmapID; + m_crcPath = string(ASHMEM_NAME_DEF) + "/" + m_metaFile.getName(); + m_fd = ashmemFD; + m_ptr = nullptr; + m_size = 0; + m_actualSize = 0; + m_output = nullptr; + + if (m_isAshmem) { + m_ashmemFile = new MmapedFile(m_fd); + } else { + m_ashmemFile = nullptr; + } + + if (cryptKey && cryptKey->length() > 0) { + m_crypter = new AESCrypt((const unsigned char *) cryptKey->data(), cryptKey->length()); + } + + m_needLoadFromFile = true; + m_hasFullWriteback = false; + + m_crcDigest = 0; + + m_sharedProcessLock.m_enable = m_isInterProcess; + m_exclusiveProcessLock.m_enable = m_isInterProcess; + + // sensitive zone + { + SCOPEDLOCK(m_sharedProcessLock); + loadFromFile(); + } +} + +MMKV::~MMKV() { + clearMemoryState(); + + if (m_ashmemFile) { + delete m_ashmemFile; + m_ashmemFile = nullptr; + } + if (m_crypter) { + delete m_crypter; + m_crypter = nullptr; + } +} + +MMKV *MMKV::defaultMMKV(MMKVMode mode, string *cryptKey) { + return mmkvWithID(DEFAULT_MMAP_ID, DEFAULT_MMAP_SIZE, mode, cryptKey); +} + +void initialize() { + g_instanceDic = new unordered_map; + g_instanceLock = ThreadLock(); + + //testAESCrypt(); + + MMKVInfo("page size:%d", DEFAULT_MMAP_SIZE); +} + +void MMKV::initializeMMKV(const std::string &rootDir) { + // TODO: do_once + //static pthread_once_t once_control = PTHREAD_ONCE_INIT; + //pthread_once(&once_control, initialize); + + g_rootDir = rootDir; + char *path = _strdup(g_rootDir.c_str()); + mkPath(path); + free(path); + + MMKVInfo("root dir: %s", g_rootDir.c_str()); +} + +MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) { + + if (mmapID.empty()) { + return nullptr; + } + SCOPEDLOCK(g_instanceLock); + + auto itr = g_instanceDic->find(mmapID); + if (itr != g_instanceDic->end()) { + MMKV *kv = itr->second; + return kv; + } + auto kv = new MMKV(mmapID, size, mode, cryptKey); + (*g_instanceDic)[mmapID] = kv; + return kv; +} + +MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, string *cryptKey) { + + if (fd < 0) { + return nullptr; + } + SCOPEDLOCK(g_instanceLock); + + auto itr = g_instanceDic->find(mmapID); + if (itr != g_instanceDic->end()) { + MMKV *kv = itr->second; + kv->checkReSetCryptKey(fd, metaFD, cryptKey); + return kv; + } + auto kv = new MMKV(mmapID, fd, metaFD, cryptKey); + (*g_instanceDic)[mmapID] = kv; + return kv; +} + +void MMKV::onExit() { + SCOPEDLOCK(g_instanceLock); + + for (auto &itr : *g_instanceDic) { + MMKV *kv = itr.second; + kv->sync(); + kv->clearMemoryState(); + } +} + +const std::string &MMKV::mmapID() { + return m_mmapID; +} + +std::string MMKV::cryptKey() { + SCOPEDLOCK(m_lock); + + if (m_crypter) { + char key[AES_KEY_LEN]; + m_crypter->getKey(key); + return string(key, strnlen(key, AES_KEY_LEN)); + } + return ""; +} + +#pragma mark - really dirty work + +void decryptBuffer(AESCrypt &crypter, MMBuffer &inputBuffer) { + size_t length = inputBuffer.length(); + MMBuffer tmp(length); + + auto input = (unsigned char *) inputBuffer.getPtr(); + auto output = (unsigned char *) tmp.getPtr(); + crypter.decrypt(input, output, length); + + inputBuffer = std::move(tmp); +} + +void MMKV::loadFromFile() { + if (m_isAshmem) { + loadFromAshmem(); + return; + } + + m_metaInfo.read(m_metaFile.getMemory()); + + //m_fd = open(m_path.c_str(), O_RDWR | O_CREAT, S_IRWXU); + if (m_fd < 0) { + MMKVError("fail to open:%s, %s", m_path.c_str(), strerror(errno)); + } else { + m_size = 0; + struct stat st = {0}; + if (fstat(m_fd, &st) != -1) { + m_size = static_cast(st.st_size); + } + // round up to (n * pagesize) + if (m_size < DEFAULT_MMAP_SIZE || (m_size % DEFAULT_MMAP_SIZE != 0)) { + size_t oldSize = m_size; + m_size = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE; + /*if (ftruncate(m_fd, m_size) != 0) { + MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, + strerror(errno)); + m_size = static_cast(st.st_size); + }*/ + zeroFillFile(m_fd, oldSize, m_size - oldSize); + } + /*m_ptr = (char *) mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); + if (m_ptr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + } else*/ + { + memcpy(&m_actualSize, m_ptr, Fixed32Size); + MMKVInfo("loading [%s] with %zu size in total, file size is %zu", m_mmapID.c_str(), + m_actualSize, m_size); + bool loadFromFile = false, needFullWriteback = false; + if (m_actualSize > 0) { + if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { + if (checkFileCRCValid()) { + loadFromFile = true; + } else { + auto strategic = onMMKVCRCCheckFail(m_mmapID); + if (strategic == OnErrorRecover) { + loadFromFile = true; + needFullWriteback = true; + } + } + } else { + auto strategic = onMMKVFileLengthError(m_mmapID); + if (strategic == OnErrorRecover) { + loadFromFile = true; + needFullWriteback = true; + } + } + } + if (loadFromFile) { + MMKVInfo("loading [%s] with crc %u sequence %u", m_mmapID.c_str(), + m_metaInfo.m_crcDigest, m_metaInfo.m_sequence); + MMBuffer inputBuffer(m_ptr + Fixed32Size, m_actualSize, MMBufferNoCopy); + if (m_crypter) { + decryptBuffer(*m_crypter, inputBuffer); + } + m_dic.clear(); + MiniPBCoder::decodeMap(m_dic, inputBuffer); + m_output = new CodedOutputData(m_ptr + Fixed32Size + m_actualSize, + m_size - Fixed32Size - m_actualSize); + if (needFullWriteback) { + fullWriteback(); + } + } else { + SCOPEDLOCK(m_exclusiveProcessLock); + + if (m_actualSize > 0) { + writeAcutalSize(0); + } + m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); + recaculateCRCDigest(); + } + MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); + } + } + + if (!isFileValid()) { + MMKVWarning("[%s] file not valid", m_mmapID.c_str()); + } + + m_needLoadFromFile = false; +} + +void MMKV::loadFromAshmem() { + m_metaInfo.read(m_metaFile.getMemory()); + + if (m_fd < 0 || !m_ashmemFile) { + MMKVError("ashmem file invalid %s, fd:%d", m_path.c_str(), m_fd); + } else { + m_size = m_ashmemFile->getFileSize(); + m_ptr = (char *) m_ashmemFile->getMemory(); + /*if (m_ptr != MAP_FAILED)*/ { + memcpy(&m_actualSize, m_ptr, Fixed32Size); + MMKVInfo("loading [%s] with %zu size in total, file size is %zu", m_mmapID.c_str(), + m_actualSize, m_size); + bool loaded = false; + if (m_actualSize > 0) { + if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { + if (checkFileCRCValid()) { + MMKVInfo("loading [%s] with crc %u sequence %u", m_mmapID.c_str(), + m_metaInfo.m_crcDigest, m_metaInfo.m_sequence); + MMBuffer inputBuffer(m_ptr + Fixed32Size, m_actualSize, MMBufferNoCopy); + if (m_crypter) { + decryptBuffer(*m_crypter, inputBuffer); + } + m_dic.clear(); + MiniPBCoder::decodeMap(m_dic, inputBuffer); + m_output = new CodedOutputData(m_ptr + Fixed32Size + m_actualSize, + m_size - Fixed32Size - m_actualSize); + loaded = true; + } + } + } + if (!loaded) { + SCOPEDLOCK(m_exclusiveProcessLock); + + if (m_actualSize > 0) { + writeAcutalSize(0); + } + m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); + recaculateCRCDigest(); + } + MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); + } + } + + if (!isFileValid()) { + MMKVWarning("[%s] ashmem not valid", m_mmapID.c_str()); + } + + m_needLoadFromFile = false; +} + +// read from last m_position +void MMKV::partialLoadFromFile() { + m_metaInfo.read(m_metaFile.getMemory()); + + size_t oldActualSize = m_actualSize; + memcpy(&m_actualSize, m_ptr, Fixed32Size); + MMKVDebug("loading [%s] with file size %zu, oldActualSize %zu, newActualSize %zu", + m_mmapID.c_str(), m_size, oldActualSize, m_actualSize); + + if (m_actualSize > 0) { + if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { + if (m_actualSize > oldActualSize) { + size_t bufferSize = m_actualSize - oldActualSize; + MMBuffer inputBuffer(m_ptr + Fixed32Size + oldActualSize, bufferSize, + MMBufferNoCopy); + // incremental update crc digest + // TODO: crc32 + /*m_crcDigest = (uint32_t) crc32(m_crcDigest, (const uint8_t *) inputBuffer.getPtr(), + static_cast(inputBuffer.length()));*/ + if (m_crcDigest == m_metaInfo.m_crcDigest) { + if (m_crypter) { + decryptBuffer(*m_crypter, inputBuffer); + } + MiniPBCoder::decodeMap(m_dic, inputBuffer, bufferSize); + m_output->seek(bufferSize); + m_hasFullWriteback = false; + + MMKVDebug("partial loaded [%s] with %zu values", m_mmapID.c_str(), + m_dic.size()); + return; + } else { + MMKVError("m_crcDigest[%u] != m_metaInfo.m_crcDigest[%u]", m_crcDigest, + m_metaInfo.m_crcDigest); + } + } + } + } + // something is wrong, do a full load + clearMemoryState(); + loadFromFile(); +} + +void MMKV::checkLoadData() { + if (m_needLoadFromFile) { + SCOPEDLOCK(m_sharedProcessLock); + + m_needLoadFromFile = false; + loadFromFile(); + return; + } + if (!m_isInterProcess) { + return; + } + + // TODO: atomic lock m_metaFile? + MMKVMetaInfo metaInfo; + metaInfo.read(m_metaFile.getMemory()); + if (m_metaInfo.m_sequence != metaInfo.m_sequence) { + MMKVInfo("[%s] oldSeq %u, newSeq %u", m_mmapID.c_str(), m_metaInfo.m_sequence, + metaInfo.m_sequence); + SCOPEDLOCK(m_sharedProcessLock); + + clearMemoryState(); + loadFromFile(); + } else if (m_metaInfo.m_crcDigest != metaInfo.m_crcDigest) { + MMKVDebug("[%s] oldCrc %u, newCrc %u", m_mmapID.c_str(), m_metaInfo.m_crcDigest, + metaInfo.m_crcDigest); + SCOPEDLOCK(m_sharedProcessLock); + + size_t fileSize = 0; + if (m_isAshmem) { + fileSize = m_size; + } else { + struct stat st = {0}; + if (fstat(m_fd, &st) != -1) { + fileSize = (size_t) st.st_size; + } + } + if (m_size != fileSize) { + MMKVInfo("file size has changed [%s] from %zu to %zu", m_mmapID.c_str(), m_size, + fileSize); + clearMemoryState(); + loadFromFile(); + } else { + partialLoadFromFile(); + } + } +} + +void MMKV::clearAll() { + MMKVInfo("cleaning all key-values from [%s]", m_mmapID.c_str()); + SCOPEDLOCK(m_lock); + SCOPEDLOCK(m_exclusiveProcessLock); + + if (m_needLoadFromFile && !m_isAshmem) { + removeFile(m_path.c_str()); + loadFromFile(); + return; + } + + /*if (m_ptr && m_ptr != MAP_FAILED) { + // for truncate + size_t size = std::min(static_cast(DEFAULT_MMAP_SIZE), m_size); + memset(m_ptr, 0, size); + if (msync(m_ptr, size, MS_SYNC) != 0) { + MMKVError("fail to msync [%s]:%s", m_mmapID.c_str(), strerror(errno)); + } + } + if (!m_isAshmem) { + if (m_fd >= 0) { + if (m_size != DEFAULT_MMAP_SIZE) { + MMKVInfo("truncating [%s] from %zu to %d", m_mmapID.c_str(), m_size, + DEFAULT_MMAP_SIZE); + if (ftruncate(m_fd, DEFAULT_MMAP_SIZE) != 0) { + MMKVError("fail to truncate [%s] to size %d, %s", m_mmapID.c_str(), + DEFAULT_MMAP_SIZE, strerror(errno)); + } + } + } + }*/ + + clearMemoryState(); + loadFromFile(); +} + +void MMKV::clearMemoryState() { + MMKVInfo("clearMemoryState [%s]", m_mmapID.c_str()); + SCOPEDLOCK(m_lock); + if (m_needLoadFromFile) { + return; + } + m_needLoadFromFile = true; + + m_dic.clear(); + m_hasFullWriteback = false; + + if (m_crypter) { + m_crypter->reset(); + } + + if (m_output) { + delete m_output; + } + m_output = nullptr; + + if (!m_isAshmem) { + /*if (m_ptr && m_ptr != MAP_FAILED) { + if (munmap(m_ptr, m_size) != 0) { + MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + } + } + m_ptr = nullptr; + + if (m_fd >= 0) { + if (::close(m_fd) != 0) { + MMKVError("fail to close [%s], %s", m_mmapID.c_str(), strerror(errno)); + } + }*/ + m_fd = -1; + } + m_size = 0; + m_actualSize = 0; +} + +void MMKV::close() { + MMKVInfo("close [%s]", m_mmapID.c_str()); + SCOPEDLOCK(g_instanceLock); + SCOPEDLOCK(m_lock); + + auto itr = g_instanceDic->find(m_mmapID); + if (itr != g_instanceDic->end()) { + g_instanceDic->erase(itr); + } + delete this; +} + +void MMKV::trim() { + if (m_isAshmem) { + MMKVInfo("there's no way to trim ashmem MMKV:%s", m_mmapID.c_str()); + return; + } + SCOPEDLOCK(m_lock); + MMKVInfo("prepare to trim %s", m_mmapID.c_str()); + + checkLoadData(); + + if (m_actualSize == 0) { + clearAll(); + return; + } else if (m_size <= DEFAULT_MMAP_SIZE) { + return; + } + SCOPEDLOCK(m_exclusiveProcessLock); + + fullWriteback(); + auto oldSize = m_size; + while (m_size > (m_actualSize * 2)) { + m_size /= 2; + } + if (oldSize == m_size) { + MMKVInfo("there's no need to trim %s with size %zu, actualSize %zu", m_mmapID.c_str(), + m_size, m_actualSize); + return; + } + + MMKVInfo("trimming %s from %zu to %zu", m_mmapID.c_str(), oldSize, m_size); + + /*if (ftruncate(m_fd, m_size) != 0) { + MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, + strerror(errno)); + m_size = oldSize; + return; + } + if (munmap(m_ptr, oldSize) != 0) { + MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + } + m_ptr = (char *) mmap(m_ptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); + if (m_ptr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + }*/ + + delete m_output; + m_output = new CodedOutputData(m_ptr + pbFixed32Size(0), m_size - pbFixed32Size(0)); + m_output->seek(m_actualSize); + + MMKVInfo("finish trim %s from to %zu", m_mmapID.c_str(), m_size); +} + +// since we use append mode, when -[setData: forKey:] many times, space may not be enough +// try a full rewrite to make space +bool MMKV::ensureMemorySize(size_t newSize) { + if (!isFileValid()) { + MMKVWarning("[%s] file not valid", m_mmapID.c_str()); + return false; + } + + if (newSize >= m_output->spaceLeft()) { + // try a full rewrite to make space + static const int offset = pbFixed32Size(0); + MMBuffer data = MiniPBCoder::encodeDataWithObject(m_dic); + size_t lenNeeded = data.length() + offset + newSize; + if (m_isAshmem) { + if (lenNeeded > m_size) { + MMKVWarning("ashmem %s reach size limit:%zu, consider configure with larger size", + m_mmapID.c_str(), m_size); + return false; + } + } else { + size_t avgItemSize = lenNeeded / std::max(1, m_dic.size()); + size_t futureUsage = avgItemSize * std::max(8, (m_dic.size() + 1) / 2); + // 1. no space for a full rewrite, double it + // 2. or space is not large enough for future usage, double it to avoid frequently full rewrite + if (lenNeeded >= m_size || (lenNeeded + futureUsage) >= m_size) { + size_t oldSize = m_size; + do { + m_size *= 2; + } while (lenNeeded + futureUsage >= m_size); + MMKVInfo( + "extending [%s] file size from %zu to %zu, incoming size:%zu, futrue usage:%zu", + m_mmapID.c_str(), oldSize, m_size, newSize, futureUsage); + + // if we can't extend size, rollback to old state + /*if (ftruncate(m_fd, m_size) != 0) { + MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, + strerror(errno)); + m_size = oldSize; + return false; + } + if (!zeroFillFile(m_fd, oldSize, m_size - oldSize)) { + MMKVError("fail to zeroFile [%s] to size %zu, %s", m_mmapID.c_str(), m_size, + strerror(errno)); + m_size = oldSize; + return false; + } + + if (munmap(m_ptr, oldSize) != 0) { + MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + } + m_ptr = (char *) mmap(m_ptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); + if (m_ptr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + }*/ + + // check if we fail to make more space + if (!isFileValid()) { + MMKVWarning("[%s] file not valid", m_mmapID.c_str()); + return false; + } + } + } + + if (m_crypter) { + m_crypter->reset(); + auto ptr = (unsigned char *) data.getPtr(); + m_crypter->encrypt(ptr, ptr, data.length()); + } + + writeAcutalSize(data.length()); + + delete m_output; + m_output = new CodedOutputData(m_ptr + offset, m_size - offset); + m_output->writeRawData(data); + recaculateCRCDigest(); + m_hasFullWriteback = true; + } + return true; +} + +void MMKV::writeAcutalSize(size_t actualSize) { + assert(m_ptr != 0); + //assert(m_ptr != MAP_FAILED); + + memcpy(m_ptr, &actualSize, Fixed32Size); + m_actualSize = actualSize; +} + +const MMBuffer &MMKV::getDataForKey(const std::string &key) { + checkLoadData(); + auto itr = m_dic.find(key); + if (itr != m_dic.end()) { + return itr->second; + } + static MMBuffer nan(0); + return nan; +} + +bool MMKV::setDataForKey(MMBuffer &&data, const std::string &key) { + if (data.length() == 0 || key.empty()) { + return false; + } + SCOPEDLOCK(m_lock); + SCOPEDLOCK(m_exclusiveProcessLock); + checkLoadData(); + + // m_dic[key] = std::move(data); + auto itr = m_dic.find(key); + if (itr == m_dic.end()) { + itr = m_dic.emplace(key, std::move(data)).first; + } else { + itr->second = std::move(data); + } + m_hasFullWriteback = false; + + return appendDataWithKey(itr->second, key); +} + +bool MMKV::removeDataForKey(const std::string &key) { + if (key.empty()) { + return false; + } + + auto deleteCount = m_dic.erase(key); + if (deleteCount > 0) { + m_hasFullWriteback = false; + static MMBuffer nan(0); + return appendDataWithKey(nan, key); + } + + return false; +} + +bool MMKV::appendDataWithKey(const MMBuffer &data, const std::string &key) { + size_t keyLength = key.length(); + // size needed to encode the key + size_t size = keyLength + pbRawVarint32Size((int32_t) keyLength); + // size needed to encode the value + size += data.length() + pbRawVarint32Size((int32_t) data.length()); + + SCOPEDLOCK(m_exclusiveProcessLock); + + bool hasEnoughSize = ensureMemorySize(size); + + if (!hasEnoughSize || !isFileValid()) { + return false; + } + if (m_actualSize == 0) { + auto allData = MiniPBCoder::encodeDataWithObject(m_dic); + if (allData.length() > 0) { + if (m_crypter) { + m_crypter->reset(); + auto ptr = (unsigned char *) allData.getPtr(); + m_crypter->encrypt(ptr, ptr, allData.length()); + } + writeAcutalSize(allData.length()); + m_output->writeRawData(allData); // note: don't write size of data + recaculateCRCDigest(); + return true; + } + return false; + } else { + writeAcutalSize(m_actualSize + size); + m_output->writeString(key); + m_output->writeData(data); // note: write size of data + + auto ptr = (uint8_t *) m_ptr + Fixed32Size + m_actualSize - size; + if (m_crypter) { + m_crypter->encrypt(ptr, ptr, size); + } + updateCRCDigest(ptr, size, KeepSequence); + + return true; + } +} + +bool MMKV::fullWriteback() { + if (m_hasFullWriteback) { + return true; + } + if (m_needLoadFromFile) { + return true; + } + if (!isFileValid()) { + MMKVWarning("[%s] file not valid", m_mmapID.c_str()); + return false; + } + + if (m_dic.empty()) { + clearAll(); + return true; + } + + auto allData = MiniPBCoder::encodeDataWithObject(m_dic); + SCOPEDLOCK(m_exclusiveProcessLock); + if (allData.length() > 0) { + if (allData.length() + Fixed32Size <= m_size) { + if (m_crypter) { + m_crypter->reset(); + auto ptr = (unsigned char *) allData.getPtr(); + m_crypter->encrypt(ptr, ptr, allData.length()); + } + writeAcutalSize(allData.length()); + delete m_output; + m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); + m_output->writeRawData(allData); // note: don't write size of data + recaculateCRCDigest(); + m_hasFullWriteback = true; + return true; + } else { + // ensureMemorySize will extend file & full rewrite, no need to write back again + return ensureMemorySize(allData.length() + Fixed32Size - m_size); + } + } + return false; +} + +bool MMKV::reKey(const std::string &cryptKey) { + SCOPEDLOCK(m_lock); + checkLoadData(); + + if (m_crypter) { + if (cryptKey.length() > 0) { + string oldKey = this->cryptKey(); + if (cryptKey == oldKey) { + return true; + } else { + // change encryption key + MMKVInfo("reKey with new aes key"); + delete m_crypter; + auto ptr = (const unsigned char *) cryptKey.data(); + m_crypter = new AESCrypt(ptr, cryptKey.length()); + return fullWriteback(); + } + } else { + // decryption to plain text + MMKVInfo("reKey with no aes key"); + delete m_crypter; + m_crypter = nullptr; + return fullWriteback(); + } + } else { + if (cryptKey.length() > 0) { + // transform plain text to encrypted text + MMKVInfo("reKey with aes key"); + auto ptr = (const unsigned char *) cryptKey.data(); + m_crypter = new AESCrypt(ptr, cryptKey.length()); + return fullWriteback(); + } else { + return true; + } + } + return false; +} + +void MMKV::checkReSetCryptKey(const std::string *cryptKey) { + SCOPEDLOCK(m_lock); + + if (m_crypter) { + if (cryptKey) { + string oldKey = this->cryptKey(); + if (oldKey != *cryptKey) { + MMKVInfo("setting new aes key"); + delete m_crypter; + auto ptr = (const unsigned char *) cryptKey->data(); + m_crypter = new AESCrypt(ptr, cryptKey->length()); + + checkLoadData(); + } else { + // nothing to do + } + } else { + MMKVInfo("reset aes key"); + delete m_crypter; + m_crypter = nullptr; + + checkLoadData(); + } + } else { + if (cryptKey) { + MMKVInfo("setting new aes key"); + auto ptr = (const unsigned char *) cryptKey->data(); + m_crypter = new AESCrypt(ptr, cryptKey->length()); + + checkLoadData(); + } else { + // nothing to do + } + } +} + +void MMKV::checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey) { + SCOPEDLOCK(m_lock); + + checkReSetCryptKey(cryptKey); + + /*if (m_isAshmem) { + if (m_fd != fd) { + ::close(fd); + } + if (m_metaFile.getFd() != metaFD) { + ::close(metaFD); + } + }*/ +} + +bool MMKV::isFileValid() { + /* if (m_fd >= 0 && m_size > 0 && m_output && m_ptr && m_ptr != MAP_FAILED) { + return true; + }*/ + return false; +} + +#pragma mark - crc + +// assuming m_ptr & m_size is set +bool MMKV::checkFileCRCValid() { + /*if (m_ptr && m_ptr != MAP_FAILED) { + constexpr int offset = pbFixed32Size(0); + m_crcDigest = + (uint32_t) crc32(0, (const uint8_t *) m_ptr + offset, (uint32_t) m_actualSize); + m_metaInfo.read(m_metaFile.getMemory()); + if (m_crcDigest == m_metaInfo.m_crcDigest) { + return true; + } + MMKVError("check crc [%s] fail, crc32:%u, m_crcDigest:%u", m_mmapID.c_str(), + m_metaInfo.m_crcDigest, m_crcDigest); + }*/ + return false; +} + +void MMKV::recaculateCRCDigest() { + /*if (m_ptr && m_ptr != MAP_FAILED) { + m_crcDigest = 0; + constexpr int offset = pbFixed32Size(0); + updateCRCDigest((const uint8_t *) m_ptr + offset, m_actualSize, IncreaseSequence); + }*/ +} + +void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSequence) { + if (!ptr) { + return; + } + //m_crcDigest = (uint32_t) crc32(m_crcDigest, ptr, (uint32_t) length); + + void *crcPtr = m_metaFile.getMemory(); + /*if (crcPtr == nullptr || crcPtr == MAP_FAILED) { + return; + }*/ + + m_metaInfo.m_crcDigest = m_crcDigest; + if (increaseSequence) { + m_metaInfo.m_sequence++; + } + if (m_metaInfo.m_version == 0) { + m_metaInfo.m_version = 1; + } + m_metaInfo.write(crcPtr); +} + +#pragma mark - set & get + +bool MMKV::setStringForKey(const std::string &value, const std::string &key) { + if (key.empty()) { + return false; + } + auto data = MiniPBCoder::encodeDataWithObject(value); + return setDataForKey(std::move(data), key); +} + +bool MMKV::setBytesForKey(const MMBuffer &value, const std::string &key) { + if (key.empty()) { + return false; + } + auto data = MiniPBCoder::encodeDataWithObject(value); + return setDataForKey(std::move(data), key); +} + +bool MMKV::setBool(bool value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbBoolSize(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeBool(value); + + return setDataForKey(std::move(data), key); +} + +bool MMKV::setInt32(int32_t value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbInt32Size(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeInt32(value); + + return setDataForKey(std::move(data), key); +} + +bool MMKV::setInt64(int64_t value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbInt64Size(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeInt64(value); + + return setDataForKey(std::move(data), key); +} + +bool MMKV::setFloat(float value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbFloatSize(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeFloat(value); + + return setDataForKey(std::move(data), key); +} + +bool MMKV::setDouble(double value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbDoubleSize(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeDouble(value); + + return setDataForKey(std::move(data), key); +} + +bool MMKV::setVectorForKey(const std::vector &v, const std::string &key) { + if (key.empty()) { + return false; + } + auto data = MiniPBCoder::encodeDataWithObject(v); + return setDataForKey(std::move(data), key); +} + +bool MMKV::getStringForKey(const std::string &key, std::string &result) { + if (key.empty()) { + return false; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + result = MiniPBCoder::decodeString(data); + return true; + } + return false; +} + +MMBuffer MMKV::getBytesForKey(const std::string &key) { + if (key.empty()) { + return MMBuffer(0); + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + return MiniPBCoder::decodeBytes(data); + } + return MMBuffer(0); +} + +bool MMKV::getBoolForKey(const std::string &key, bool defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readBool(); + } + return defaultValue; +} + +int32_t MMKV::getInt32ForKey(const std::string &key, int32_t defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readInt32(); + } + return defaultValue; +} + +int64_t MMKV::getInt64ForKey(const std::string &key, int64_t defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readInt64(); + } + return defaultValue; +} + +float MMKV::getFloatForKey(const std::string &key, float defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readFloat(); + } + return defaultValue; +} + +double MMKV::getDoubleForKey(const std::string &key, double defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readDouble(); + } + return defaultValue; +} + +bool MMKV::getVectorForKey(const std::string &key, std::vector &result) { + if (key.empty()) { + return false; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + result = MiniPBCoder::decodeSet(data); + return true; + } + return false; +} + +#pragma mark - enumerate + +bool MMKV::containsKey(const std::string &key) { + SCOPEDLOCK(m_lock); + checkLoadData(); + return m_dic.find(key) != m_dic.end(); +} + +size_t MMKV::count() { + SCOPEDLOCK(m_lock); + checkLoadData(); + return m_dic.size(); +} + +size_t MMKV::totalSize() { + SCOPEDLOCK(m_lock); + checkLoadData(); + return m_size; +} + +std::vector MMKV::allKeys() { + SCOPEDLOCK(m_lock); + checkLoadData(); + + vector keys; + for (const auto &itr : m_dic) { + keys.push_back(itr.first); + }; + return keys; +} + +void MMKV::removeValueForKey(const std::string &key) { + if (key.empty()) { + return; + } + SCOPEDLOCK(m_lock); + SCOPEDLOCK(m_exclusiveProcessLock); + checkLoadData(); + + removeDataForKey(key); +} + +void MMKV::removeValuesForKeys(const std::vector &arrKeys) { + if (arrKeys.empty()) { + return; + } + if (arrKeys.size() == 1) { + return removeValueForKey(arrKeys[0]); + } + + SCOPEDLOCK(m_lock); + SCOPEDLOCK(m_exclusiveProcessLock); + checkLoadData(); + for (const auto &key : arrKeys) { + m_dic.erase(key); + } + m_hasFullWriteback = false; + + fullWriteback(); +} + +#pragma mark - file + +void MMKV::sync() { + SCOPEDLOCK(m_lock); + if (m_needLoadFromFile || !isFileValid()) { + return; + } + SCOPEDLOCK(m_exclusiveProcessLock); + /*if (msync(m_ptr, m_size, MS_SYNC) != 0) { + MMKVError("fail to msync [%s]:%s", m_mmapID.c_str(), strerror(errno)); + }*/ +} + +bool MMKV::isFileValid(const std::string &mmapID) { + string kvPath = mappedKVPathWithID(mmapID, MMKV_SINGLE_PROCESS); + if (!isFileExist(kvPath)) { + return true; + } + + string crcPath = crcPathWithID(mmapID, MMKV_SINGLE_PROCESS); + if (!isFileExist(crcPath.c_str())) { + return false; + } + + uint32_t crcFile = 0; + MMBuffer *data = readWholeFile(crcPath.c_str()); + if (data) { + MMKVMetaInfo metaInfo; + metaInfo.read(data->getPtr()); + crcFile = metaInfo.m_crcDigest; + delete data; + } else { + return false; + } + + const int offset = pbFixed32Size(0); + size_t actualSize = 0; + MMBuffer *fileData = readWholeFile(kvPath.c_str()); + if (fileData) { + actualSize = CodedInputData(fileData->getPtr(), fileData->length()).readFixed32(); + if (actualSize > fileData->length() - offset) { + delete fileData; + return false; + } + + /*uint32_t crcDigest = (uint32_t) crc32(0, (const uint8_t *) fileData->getPtr() + offset, + (uint32_t) actualSize); + + delete fileData; + return crcFile == crcDigest;*/ + } else { + return false; + } +} + +static void mkSpecialCharacterFileDirectory() { + char *path = _strdup((g_rootDir + "/" + SPECIAL_CHARACTER_DIRECTORY_NAME).c_str()); + mkPath(path); + free(path); +} + +static string md5(const string &value) { + unsigned char md[MD5_DIGEST_LENGTH] = {0}; + char tmp[3] = {0}, buf[33] = {0}; + MD5((const unsigned char *) value.c_str(), value.size(), md); + for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { + sprintf(tmp, "%2.2x", md[i]); + strcat(buf, tmp); + } + return buf; +} + +static string encodeFilePath(const string &mmapID) { + const char *specialCharacters = "\\/:*?\"<>|"; + string encodedID; + bool hasSpecialCharacter = false; + for (int i = 0; i < mmapID.size(); i++) { + if (strchr(specialCharacters, mmapID[i]) != NULL) { + encodedID = md5(mmapID); + hasSpecialCharacter = true; + break; + } + } + if (hasSpecialCharacter) { + // TODO: do_once + /*static pthread_once_t once_control = PTHREAD_ONCE_INIT; + pthread_once(&once_control, mkSpecialCharacterFileDirectory);*/ + return string(SPECIAL_CHARACTER_DIRECTORY_NAME) + "/" + encodedID; + } else { + return mmapID; + } +} + +static string mappedKVPathWithID(const string &mmapID, MMKVMode mode) { + return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) + : string(ASHMEM_NAME_DEF) + "/" + encodeFilePath(mmapID); +} + +static string crcPathWithID(const string &mmapID, MMKVMode mode) { + return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) + ".crc" + : encodeFilePath(mmapID) + ".crc"; +} + +MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { + return OnErrorDiscard; +} + +MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) { + return OnErrorDiscard; +} diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index b54a72c1..ad0381fd 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -1,11 +1,241 @@ -#pragma once +/* + * 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. + */ +#ifndef MMKV_MMKV_H +#define MMKV_MMKV_H + +#include "InterProcessLock.h" #include "MMKVDef.h" +#include "MMKVMetaInfo.hpp" +#include "MmapedFile.h" +#include "ThreadLock.h" +#include "MMBuffer.h" +#include +#include +#include +#include +#include + +class CodedOutputData; +class AESCrypt; + +enum MMKVMode : uint32_t { + MMKV_SINGLE_PROCESS = 0x1, + MMKV_MULTI_PROCESS = 0x2, + MMKV_ASHMEM = 0x4, +}; class MMKV_API MMKV { + // TODO: avoid warning "needs to have dll-interface to be used by clients of class" + std::unordered_map m_dic; + std::string m_mmapID; + std::string m_path; + std::string m_crcPath; + int m_fd; + char *m_ptr; + size_t m_size; + size_t m_actualSize; + CodedOutputData *m_output; + MmapedFile *m_ashmemFile; + + bool m_needLoadFromFile; + bool m_hasFullWriteback; + + uint32_t m_crcDigest; + MmapedFile m_metaFile; + MMKVMetaInfo m_metaInfo; + + AESCrypt *m_crypter; + + ThreadLock m_lock; + FileLock m_fileLock; + InterProcessLock m_sharedProcessLock; + InterProcessLock m_exclusiveProcessLock; + + void loadFromFile(); + + void partialLoadFromFile(); + + void loadFromAshmem(); + + void checkLoadData(); + + bool isFileValid(); + + bool checkFileCRCValid(); + + void recaculateCRCDigest(); + + void updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSequence = false); + + void writeAcutalSize(size_t actualSize); + + bool ensureMemorySize(size_t newSize); + + bool fullWriteback(); + + const MMBuffer &getDataForKey(const std::string &key); + + bool setDataForKey(MMBuffer &&data, const std::string &key); + + bool removeDataForKey(const std::string &key); + + bool appendDataWithKey(const MMBuffer &data, const std::string &key); + + void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey); + + // just forbid it for possibly misuse + MMKV(const MMKV &other) = delete; + + MMKV &operator=(const MMKV &other) = delete; + public: - MMKV(); + MMKV(const std::string &mmapID, + int size = DEFAULT_MMAP_SIZE, + MMKVMode mode = MMKV_SINGLE_PROCESS, + std::string *cryptKey = nullptr); + + MMKV(const std::string &mmapID, + int ashmemFD, + int ashmemMetaFd, + std::string *cryptKey = nullptr); + ~MMKV(); - int foo(); -private: + + static void initializeMMKV(const std::string &rootDir); + + // a generic purpose instance + static MMKV *defaultMMKV(MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr); + + // mmapID: any unique ID (com.tencent.xin.pay, etc) + // if you want a per-user mmkv, you could merge user-id within mmapID + static MMKV *mmkvWithID(const std::string &mmapID, + int size = DEFAULT_MMAP_SIZE, + MMKVMode mode = MMKV_SINGLE_PROCESS, + std::string *cryptKey = nullptr); + + static MMKV *mmkvWithAshmemFD(const std::string &mmapID, + int fd, + int metaFD, + std::string *cryptKey = nullptr); + + static void onExit(); + + const std::string &mmapID(); + + const bool m_isInterProcess; + + const bool m_isAshmem; + + int ashmemFD() { return m_isAshmem ? m_fd : -1; } + + int ashmemMetaFD() { return m_isAshmem ? m_metaFile.getFd() : -1; } + + std::string cryptKey(); + + // transform plain text into encrypted text + // or vice versa by passing cryptKey = null + // or change existing crypt key + bool reKey(const std::string &cryptKey); + + // just reset cryptKey (will not encrypt or decrypt anything) + // usually you should call this method after other process reKey() the inter-process mmkv + void checkReSetCryptKey(const std::string *cryptKey); + + bool setStringForKey(const std::string &value, const std::string &key); + + bool setBytesForKey(const MMBuffer &value, const std::string &key); + + bool setBool(bool value, const std::string &key); + + bool setInt32(int32_t value, const std::string &key); + + bool setInt64(int64_t value, const std::string &key); + + bool setFloat(float value, const std::string &key); + + bool setDouble(double value, const std::string &key); + + bool setVectorForKey(const std::vector &vector, const std::string &key); + + bool getStringForKey(const std::string &key, std::string &result); + + MMBuffer getBytesForKey(const std::string &key); + + bool getBoolForKey(const std::string &key, bool defaultValue = false); + + int32_t getInt32ForKey(const std::string &key, int32_t defaultValue = 0); + + int64_t getInt64ForKey(const std::string &key, int64_t defaultValue = 0); + + float getFloatForKey(const std::string &key, float defaultValue = 0); + + double getDoubleForKey(const std::string &key, double defaultValue = 0); + + bool getVectorForKey(const std::string &key, std::vector &result); + + bool containsKey(const std::string &key); + + size_t count(); + + size_t totalSize(); + + std::vector allKeys(); + + void removeValueForKey(const std::string &key); + + void removeValuesForKeys(const std::vector &arrKeys); + + void clearAll(); + + // MMKV's size won't reduce after deleting key-values + // call this method after lots of deleting f you care about disk usage + // note that `clearAll` has the similar effect of `trim` + void trim(); + + // call this method if the instance is no longer needed in the near future + // any subsequent call to the instance is undefined behavior + void close(); + + // call this method if you are facing memory-warning + // any subsequent call to the instance will load all key-values from file again + void clearMemoryState(); + + // you don't need to call this, really, I mean it + // unless you care about out of battery + void sync(); + + static bool isFileValid(const std::string &mmapID); + + void lock() { m_exclusiveProcessLock.lock(); } + void unlock() { m_exclusiveProcessLock.unlock(); } + bool try_lock() { return m_exclusiveProcessLock.try_lock(); } }; + +enum MMKVRecoverStrategic : int { + OnErrorDiscard = 0, + OnErrorRecover, +}; + +MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID); + +MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID); + +#endif // MMKV_MMKV_H diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 91cfb51c..c8c8eebc 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -88,7 +88,7 @@ Level3 Disabled true - WIN32;_DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true @@ -118,7 +118,7 @@ true true true - WIN32;NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true @@ -147,13 +147,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index c96fb243..7742137d 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -24,6 +24,66 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -32,5 +92,47 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 56f1b115..b1fd118f 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -8,7 +8,7 @@ using namespace std; int main() { - cout << MMKV().foo() << endl; + MMKV::initializeMMKV(""); cout << "Hello World!\n"; } From 4fb0b0239cc57d9374c1d31a6c2aa16a37e24e84 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 7 Dec 2018 21:33:03 +0800 Subject: [PATCH 03/57] compile --- Win32/MMKV/CodedInputData.cpp | 170 +++++ Win32/MMKV/CodedInputData.h | 65 ++ Win32/MMKV/CodedOutputData.cpp | 141 ++++ Win32/MMKV/CodedOutputData.h | 69 ++ Win32/MMKV/InterProcessLock.cpp | 136 ++++ Win32/MMKV/InterProcessLock.h | 89 +++ Win32/MMKV/MMBuffer.cpp | 60 ++ Win32/MMKV/MMBuffer.h | 57 ++ Win32/MMKV/MMKVLog.h | 62 ++ Win32/MMKV/MMKVMetaInfo.hpp | 44 ++ Win32/MMKV/MiniPBCoder.cpp | 290 +++++++++ Win32/MMKV/MiniPBCoder.h | 79 +++ Win32/MMKV/MmapedFile.cpp | 232 +++++++ Win32/MMKV/MmapedFile.h | 76 +++ Win32/MMKV/PBEncodeItem.hpp | 50 ++ Win32/MMKV/PBUtility.cpp | 57 ++ Win32/MMKV/PBUtility.h | 121 ++++ Win32/MMKV/ScopedLock.hpp | 73 +++ Win32/MMKV/ThreadLock.cpp | 59 ++ Win32/MMKV/ThreadLock.h | 39 ++ Win32/MMKV/aes/AESCrypt.cpp | 117 ++++ Win32/MMKV/aes/AESCrypt.h | 57 ++ Win32/MMKV/aes/openssl/aes.h | 55 ++ Win32/MMKV/aes/openssl/aes_cfb.c | 26 + Win32/MMKV/aes/openssl/aes_core.c | 918 +++++++++++++++++++++++++++ Win32/MMKV/aes/openssl/aes_locl.h | 40 ++ Win32/MMKV/aes/openssl/cfb128.c | 131 ++++ Win32/MMKV/aes/openssl/md32_common.h | 254 ++++++++ Win32/MMKV/aes/openssl/md5.h | 49 ++ Win32/MMKV/aes/openssl/md5_dgst.c | 163 +++++ Win32/MMKV/aes/openssl/md5_locl.h | 68 ++ Win32/MMKV/aes/openssl/md5_one.c | 26 + Win32/MMKV/aes/openssl/modes.h | 27 + Win32/MMKV/aes/openssl/opensslconf.h | 271 ++++++++ 34 files changed, 4171 insertions(+) create mode 100644 Win32/MMKV/CodedInputData.cpp create mode 100644 Win32/MMKV/CodedInputData.h create mode 100644 Win32/MMKV/CodedOutputData.cpp create mode 100644 Win32/MMKV/CodedOutputData.h create mode 100644 Win32/MMKV/InterProcessLock.cpp create mode 100644 Win32/MMKV/InterProcessLock.h create mode 100644 Win32/MMKV/MMBuffer.cpp create mode 100644 Win32/MMKV/MMBuffer.h create mode 100644 Win32/MMKV/MMKVLog.h create mode 100644 Win32/MMKV/MMKVMetaInfo.hpp create mode 100644 Win32/MMKV/MiniPBCoder.cpp create mode 100644 Win32/MMKV/MiniPBCoder.h create mode 100644 Win32/MMKV/MmapedFile.cpp create mode 100644 Win32/MMKV/MmapedFile.h create mode 100644 Win32/MMKV/PBEncodeItem.hpp create mode 100644 Win32/MMKV/PBUtility.cpp create mode 100644 Win32/MMKV/PBUtility.h create mode 100644 Win32/MMKV/ScopedLock.hpp create mode 100644 Win32/MMKV/ThreadLock.cpp create mode 100644 Win32/MMKV/ThreadLock.h create mode 100644 Win32/MMKV/aes/AESCrypt.cpp create mode 100644 Win32/MMKV/aes/AESCrypt.h create mode 100644 Win32/MMKV/aes/openssl/aes.h create mode 100644 Win32/MMKV/aes/openssl/aes_cfb.c create mode 100644 Win32/MMKV/aes/openssl/aes_core.c create mode 100644 Win32/MMKV/aes/openssl/aes_locl.h create mode 100644 Win32/MMKV/aes/openssl/cfb128.c create mode 100644 Win32/MMKV/aes/openssl/md32_common.h create mode 100644 Win32/MMKV/aes/openssl/md5.h create mode 100644 Win32/MMKV/aes/openssl/md5_dgst.c create mode 100644 Win32/MMKV/aes/openssl/md5_locl.h create mode 100644 Win32/MMKV/aes/openssl/md5_one.c create mode 100644 Win32/MMKV/aes/openssl/modes.h create mode 100644 Win32/MMKV/aes/openssl/opensslconf.h diff --git a/Win32/MMKV/CodedInputData.cpp b/Win32/MMKV/CodedInputData.cpp new file mode 100644 index 00000000..a066f6d3 --- /dev/null +++ b/Win32/MMKV/CodedInputData.cpp @@ -0,0 +1,170 @@ +/* + * 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 "CodedInputData.h" +#include "MMKVLog.h" +#include "PBUtility.h" +#include +#include + +using namespace std; + +CodedInputData::CodedInputData(const void *oData, int32_t length) + : m_ptr((uint8_t *) oData), m_size(length), m_position(0) { + assert(m_ptr); +} + +CodedInputData::~CodedInputData() { + m_ptr = nullptr; + m_size = 0; +} + +double CodedInputData::readDouble() { + return Int64ToFloat64(this->readRawLittleEndian64()); +} + +float CodedInputData::readFloat() { + return Int32ToFloat32(this->readRawLittleEndian32()); +} + +int64_t CodedInputData::readInt64() { + int32_t shift = 0; + int64_t result = 0; + while (shift < 64) { + int8_t b = this->readRawByte(); + result |= (int64_t)(b & 0x7f) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + MMKVError("InvalidProtocolBuffer malformedInt64"); + return 0; +} + +int32_t CodedInputData::readInt32() { + return this->readRawVarint32(); +} + +int32_t CodedInputData::readFixed32() { + return this->readRawLittleEndian32(); +} + +bool CodedInputData::readBool() { + return this->readRawVarint32() != 0; +} + +string CodedInputData::readString() { + int32_t size = this->readRawVarint32(); + if (size <= (m_size - m_position) && size > 0) { + string result((char *) (m_ptr + m_position), size); + m_position += size; + return result; + } else if (size == 0) { + return ""; + } else { + MMKVError("Invalid Size: %d", size); + return ""; + } +} + +MMBuffer CodedInputData::readData() { + int32_t size = this->readRawVarint32(); + if (size < 0) { + MMKVError("InvalidProtocolBuffer negativeSize"); + return MMBuffer(0); + } + + if (size <= m_size - m_position) { + MMBuffer data(((int8_t *) m_ptr) + m_position, size); + m_position += size; + return data; + } else { + MMKVError("InvalidProtocolBuffer truncatedMessage"); + return MMBuffer(0); + } +} + +int32_t CodedInputData::readRawVarint32() { + int8_t tmp = this->readRawByte(); + if (tmp >= 0) { + return tmp; + } + int32_t result = tmp & 0x7f; + if ((tmp = this->readRawByte()) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = this->readRawByte()) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = this->readRawByte()) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = this->readRawByte()) << 28; + if (tmp < 0) { + // discard upper 32 bits + for (int i = 0; i < 5; i++) { + if (this->readRawByte() >= 0) { + return result; + } + } + MMKVError("InvalidProtocolBuffer malformed varint32"); + } + } + } + } + return result; +} + +int32_t CodedInputData::readRawLittleEndian32() { + int8_t b1 = this->readRawByte(); + int8_t b2 = this->readRawByte(); + int8_t b3 = this->readRawByte(); + int8_t b4 = this->readRawByte(); + return (((int32_t) b1 & 0xff)) | (((int32_t) b2 & 0xff) << 8) | (((int32_t) b3 & 0xff) << 16) | + (((int32_t) b4 & 0xff) << 24); +} + +int64_t CodedInputData::readRawLittleEndian64() { + int8_t b1 = this->readRawByte(); + int8_t b2 = this->readRawByte(); + int8_t b3 = this->readRawByte(); + int8_t b4 = this->readRawByte(); + int8_t b5 = this->readRawByte(); + int8_t b6 = this->readRawByte(); + int8_t b7 = this->readRawByte(); + int8_t b8 = this->readRawByte(); + return (((int64_t) b1 & 0xff)) | (((int64_t) b2 & 0xff) << 8) | (((int64_t) b3 & 0xff) << 16) | + (((int64_t) b4 & 0xff) << 24) | (((int64_t) b5 & 0xff) << 32) | + (((int64_t) b6 & 0xff) << 40) | (((int64_t) b7 & 0xff) << 48) | + (((int64_t) b8 & 0xff) << 56); +} + +int8_t CodedInputData::readRawByte() { + if (m_position == m_size) { + MMKVError("reach end, m_position: %d, m_size: %d", m_position, m_size); + return 0; + } + int8_t *bytes = (int8_t *) m_ptr; + return bytes[m_position++]; +} diff --git a/Win32/MMKV/CodedInputData.h b/Win32/MMKV/CodedInputData.h new file mode 100644 index 00000000..bc7c7a6e --- /dev/null +++ b/Win32/MMKV/CodedInputData.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef MMKV_CODEDINPUTDATA_H +#define MMKV_CODEDINPUTDATA_H + +#include "MMBuffer.h" +#include +#include + +class CodedInputData { + uint8_t *m_ptr; + int32_t m_size; + int32_t m_position; + + int8_t readRawByte(); + + int32_t readRawVarint32(); + + int32_t readRawLittleEndian32(); + + int64_t readRawLittleEndian64(); + +public: + CodedInputData(const void *oData, int32_t length); + + ~CodedInputData(); + + bool isAtEnd() { return m_position == m_size; }; + + bool readBool(); + + double readDouble(); + + float readFloat(); + + int64_t readInt64(); + + int32_t readInt32(); + + int32_t readFixed32(); + + std::string readString(); + + MMBuffer readData(); +}; + +#endif //MMKV_CODEDINPUTDATA_H diff --git a/Win32/MMKV/CodedOutputData.cpp b/Win32/MMKV/CodedOutputData.cpp new file mode 100644 index 00000000..94e3e6f3 --- /dev/null +++ b/Win32/MMKV/CodedOutputData.cpp @@ -0,0 +1,141 @@ +/* + * 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 "CodedOutputData.h" +#include "MMKVLog.h" +#include "PBUtility.h" +#include + +using namespace std; + +CodedOutputData::CodedOutputData(void *ptr, size_t len) + : m_ptr((uint8_t *) ptr), m_size(len), m_position(0) { + assert(m_ptr); +} + +CodedOutputData::~CodedOutputData() { + m_ptr = nullptr; + m_position = 0; +} + +void CodedOutputData::writeDouble(double value) { + this->writeRawLittleEndian64(Float64ToInt64(value)); +} + +void CodedOutputData::writeFloat(float value) { + this->writeRawLittleEndian32(Float32ToInt32(value)); +} + +void CodedOutputData::writeInt64(int64_t value) { + this->writeRawVarint64(value); +} + +void CodedOutputData::writeInt32(int32_t value) { + if (value >= 0) { + this->writeRawVarint32(value); + } else { + this->writeRawVarint64(value); + } +} + +void CodedOutputData::writeBool(bool value) { + this->writeRawByte(static_cast(value ? 1 : 0)); +} + +void CodedOutputData::writeString(const string &value) { + size_t numberOfBytes = value.size(); + this->writeRawVarint32((int32_t) numberOfBytes); + memcpy(m_ptr + m_position, ((uint8_t *) value.data()), numberOfBytes); + m_position += numberOfBytes; +} + +void CodedOutputData::writeData(const MMBuffer &value) { + this->writeRawVarint32((int32_t) value.length()); + this->writeRawData(value); +} + +int32_t CodedOutputData::spaceLeft() { + return int32_t(m_size - m_position); +} + +void CodedOutputData::seek(size_t addedSize) { + m_position += addedSize; + + if (m_position > m_size) { + MMKVError("OutOfSpace"); + } +} + +void CodedOutputData::writeRawByte(uint8_t value) { + if (m_position == m_size) { + MMKVError("m_position: %d, m_size: %zd", m_position, m_size); + return; + } + + m_ptr[m_position++] = value; +} + +void CodedOutputData::writeRawData(const MMBuffer &data) { + size_t numberOfBytes = data.length(); + memcpy(m_ptr + m_position, data.getPtr(), numberOfBytes); + m_position += numberOfBytes; +} + +void CodedOutputData::writeRawVarint32(int32_t value) { + while (true) { + if ((value & ~0x7f) == 0) { + this->writeRawByte(static_cast(value)); + return; + } else { + this->writeRawByte(static_cast((value & 0x7F) | 0x80)); + value = logicalRightShift32(value, 7); + } + } +} + +void CodedOutputData::writeRawVarint64(int64_t value) { + while (true) { + if ((value & ~0x7f) == 0) { + this->writeRawByte(static_cast(value)); + return; + } else { + this->writeRawByte(static_cast((value & 0x7f) | 0x80)); + value = logicalRightShift64(value, 7); + } + } +} + +void CodedOutputData::writeRawLittleEndian32(int32_t value) { + this->writeRawByte(static_cast((value) &0xff)); + this->writeRawByte(static_cast((value >> 8) & 0xff)); + this->writeRawByte(static_cast((value >> 16) & 0xff)); + this->writeRawByte(static_cast((value >> 24) & 0xff)); +} + +void CodedOutputData::writeRawLittleEndian64(int64_t value) { + this->writeRawByte(static_cast((value) &0xff)); + this->writeRawByte(static_cast((value >> 8) & 0xff)); + this->writeRawByte(static_cast((value >> 16) & 0xff)); + this->writeRawByte(static_cast((value >> 24) & 0xff)); + this->writeRawByte(static_cast((value >> 32) & 0xff)); + this->writeRawByte(static_cast((value >> 40) & 0xff)); + this->writeRawByte(static_cast((value >> 48) & 0xff)); + this->writeRawByte(static_cast((value >> 56) & 0xff)); +} diff --git a/Win32/MMKV/CodedOutputData.h b/Win32/MMKV/CodedOutputData.h new file mode 100644 index 00000000..c6a1a854 --- /dev/null +++ b/Win32/MMKV/CodedOutputData.h @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#ifndef MMKV_CODEDOUTPUTDATA_H +#define MMKV_CODEDOUTPUTDATA_H + +#include "MMBuffer.h" +#include +#include + +class CodedOutputData { + uint8_t *m_ptr; + size_t m_size; + int32_t m_position; + +public: + CodedOutputData(void *ptr, size_t len); + + ~CodedOutputData(); + + int32_t spaceLeft(); + + void seek(size_t addedSize); + + void writeRawByte(uint8_t value); + + void writeRawLittleEndian32(int32_t value); + + void writeRawLittleEndian64(int64_t value); + + void writeRawVarint32(int32_t value); + + void writeRawVarint64(int64_t value); + + void writeRawData(const MMBuffer &data); + + void writeDouble(double value); + + void writeFloat(float value); + + void writeInt64(int64_t value); + + void writeInt32(int32_t value); + + void writeBool(bool value); + + void writeString(const std::string &value); + + void writeData(const MMBuffer &value); +}; + +#endif //MMKV_CODEDOUTPUTDATA_H diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp new file mode 100644 index 00000000..35e8eae5 --- /dev/null +++ b/Win32/MMKV/InterProcessLock.cpp @@ -0,0 +1,136 @@ +/* + * 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 "InterProcessLock.h" +#include "MMKVLog.h" +/*#include + +static short LockType2FlockType(LockType lockType) { + switch (lockType) { + case SharedLockType: + return F_RDLCK; + case ExclusiveLockType: + return F_WRLCK; + } +} +*/ +FileLock::FileLock(int fd) : m_fd(fd), m_sharedLockCount(0), m_exclusiveLockCount(0) { +/* m_lockInfo.l_type = F_WRLCK; + m_lockInfo.l_start = 0; + m_lockInfo.l_whence = SEEK_SET; + m_lockInfo.l_len = 0; + m_lockInfo.l_pid = 0;*/ +} + +bool FileLock::doLock(LockType lockType, int cmd) { +/* bool unLockFirstIfNeeded = false; + + if (lockType == SharedLockType) { + m_sharedLockCount++; + // don't want shared-lock to break any existing locks + if (m_sharedLockCount > 1 || m_exclusiveLockCount > 0) { + return true; + } + } else { + m_exclusiveLockCount++; + // don't want exclusive-lock to break existing exclusive-locks + if (m_exclusiveLockCount > 1) { + return true; + } + // prevent deadlock + if (m_sharedLockCount > 0) { + unLockFirstIfNeeded = true; + } + } + + m_lockInfo.l_type = LockType2FlockType(lockType); + if (unLockFirstIfNeeded) { + // try lock + auto ret = fcntl(m_fd, F_SETLK, &m_lockInfo); + if (ret == 0) { + return true; + } + // lets be gentleman: unlock my shared-lock to prevent deadlock + auto type = m_lockInfo.l_type; + m_lockInfo.l_type = F_UNLCK; + ret = fcntl(m_fd, F_SETLK, &m_lockInfo); + if (ret != 0) { + MMKVError("fail to try unlock first fd=%d, ret=%d, error:%s", m_fd, ret, + strerror(errno)); + } + m_lockInfo.l_type = type; + } + + auto ret = fcntl(m_fd, cmd, &m_lockInfo); + if (ret != 0) { + MMKVError("fail to lock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + return false; + } else { + return true; + }*/ + return false; +} + +bool FileLock::lock(LockType lockType) { + //return doLock(lockType, F_SETLKW); + return false; +} + +bool FileLock::try_lock(LockType lockType) { + //return doLock(lockType, F_SETLK); + return false; +} + +bool FileLock::unlock(LockType lockType) { +/* bool unlockToSharedLock = false; + + if (lockType == SharedLockType) { + if (m_sharedLockCount == 0) { + return false; + } + m_sharedLockCount--; + // don't want shared-lock to break any existing locks + if (m_sharedLockCount > 0 || m_exclusiveLockCount > 0) { + return true; + } + } else { + if (m_exclusiveLockCount == 0) { + return false; + } + m_exclusiveLockCount--; + if (m_exclusiveLockCount > 0) { + return true; + } + // restore shared-lock when all exclusive-locks are done + if (m_sharedLockCount > 0) { + unlockToSharedLock = true; + } + } + + m_lockInfo.l_type = static_cast(unlockToSharedLock ? F_RDLCK : F_UNLCK); + auto ret = fcntl(m_fd, F_SETLK, &m_lockInfo); + if (ret != 0) { + MMKVError("fail to unlock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + return false; + } else { + return true; + }*/ + return false; +} diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h new file mode 100644 index 00000000..0383e614 --- /dev/null +++ b/Win32/MMKV/InterProcessLock.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#ifndef MMKV_INTERPROCESSLOCK_H +#define MMKV_INTERPROCESSLOCK_H + +#include +#include + +enum LockType { + SharedLockType, + ExclusiveLockType, +}; + +// a recursive POSIX file-lock wrapper +// handles lock upgrade & downgrade correctly +class FileLock { + int m_fd; + //struct flock m_lockInfo; + size_t m_sharedLockCount; + size_t m_exclusiveLockCount; + + bool doLock(LockType lockType, int cmd); + + // just forbid it for possibly misuse + FileLock(const FileLock &other) = delete; + + FileLock &operator=(const FileLock &other) = delete; + +public: + FileLock(int fd); + + bool lock(LockType lockType); + + bool try_lock(LockType lockType); + + bool unlock(LockType lockType); +}; + +class InterProcessLock { + FileLock *m_fileLock; + LockType m_lockType; + +public: + InterProcessLock(FileLock *fileLock, LockType lockType) + : m_fileLock(fileLock), m_lockType(lockType), m_enable(true) { + assert(m_fileLock); + } + + bool m_enable; + + void lock() { + if (m_enable) { + m_fileLock->lock(m_lockType); + } + } + + bool try_lock() { + if (m_enable) { + return m_fileLock->try_lock(m_lockType); + } + return false; + } + + void unlock() { + if (m_enable) { + m_fileLock->unlock(m_lockType); + } + } +}; + +#endif //MMKV_INTERPROCESSLOCK_H diff --git a/Win32/MMKV/MMBuffer.cpp b/Win32/MMKV/MMBuffer.cpp new file mode 100644 index 00000000..a8d0e156 --- /dev/null +++ b/Win32/MMKV/MMBuffer.cpp @@ -0,0 +1,60 @@ +/* + * 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 "MMBuffer.h" +#include +#include +#include + +MMBuffer::MMBuffer(size_t length) : ptr(nullptr), size(length), isNoCopy(MMBufferCopy) { + if (size > 0) { + ptr = malloc(size); + } +} + +MMBuffer::MMBuffer(void *source, size_t length, MMBufferCopyFlag noCopy) + : ptr(source), size(length), isNoCopy(noCopy) { + if (isNoCopy == MMBufferCopy) { + ptr = malloc(size); + memcpy(ptr, source, size); + } +} + +MMBuffer::MMBuffer(MMBuffer &&other) noexcept + : ptr(other.ptr), size(other.size), isNoCopy(other.isNoCopy) { + other.ptr = nullptr; + other.size = 0; + other.isNoCopy = MMBufferCopy; +} + +MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept { + std::swap(ptr, other.ptr); + std::swap(size, other.size); + std::swap(isNoCopy, other.isNoCopy); + + return *this; +} + +MMBuffer::~MMBuffer() { + if (isNoCopy == MMBufferCopy && ptr) { + free(ptr); + } + ptr = nullptr; +} diff --git a/Win32/MMKV/MMBuffer.h b/Win32/MMKV/MMBuffer.h new file mode 100644 index 00000000..acc23e68 --- /dev/null +++ b/Win32/MMKV/MMBuffer.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef MMKV_MMBUFFER_H +#define MMKV_MMBUFFER_H + +#include +#include "MMKVDef.h" + +enum MMBufferCopyFlag : bool { + MMBufferCopy = false, + MMBufferNoCopy = true, +}; + +class MMKV_API MMBuffer { +private: + void *ptr; + size_t size; + MMBufferCopyFlag isNoCopy; + +public: + void *getPtr() const { return ptr; } + + size_t length() const { return size; } + + MMBuffer(size_t length = 0); + MMBuffer(void *source, size_t length, MMBufferCopyFlag noCopy = MMBufferCopy); + + MMBuffer(MMBuffer &&other) noexcept; + MMBuffer &operator=(MMBuffer &&other) noexcept; + + ~MMBuffer(); + +private: + // those are expensive, just forbid it for possibly misuse + MMBuffer(const MMBuffer &other) = delete; + MMBuffer &operator=(const MMBuffer &other) = delete; +}; + +#endif //MMKV_MMBUFFER_H diff --git a/Win32/MMKV/MMKVLog.h b/Win32/MMKV/MMKVLog.h new file mode 100644 index 00000000..073c6ccd --- /dev/null +++ b/Win32/MMKV/MMKVLog.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef MMKV_MMKVLOG_H +#define MMKV_MMKVLOG_H + +#include +#include +#include + +// enable logging +#define ENABLE_MMKV_LOG + +#ifdef ENABLE_MMKV_LOG + +#define APPNAME "MMKV" + +#define MMKVError(format, ...) \ + ::printf(format, ##__VA_ARGS__) +#define MMKVWarning(format, ...) \ + ::printf(format, ##__VA_ARGS__) +#define MMKVInfo(format, ...) ::printf(format, ##__VA_ARGS__) + +#ifndef NDEBUG +#define MMKVDebug(format, ...) \ + ::printf(format, ##__VA_ARGS__) +#else +#define MMKVDebug(format, ...) \ + {} +#endif + +#else + +#define MMKVError(format, ...) \ + {} +#define MMKVWarning(format, ...) \ + {} +#define MMKVInfo(format, ...) \ + {} +#define MMKVDebug(format, ...) \ + {} + +#endif + +#endif //MMKV_MMKVLOG_H diff --git a/Win32/MMKV/MMKVMetaInfo.hpp b/Win32/MMKV/MMKVMetaInfo.hpp new file mode 100644 index 00000000..157bf832 --- /dev/null +++ b/Win32/MMKV/MMKVMetaInfo.hpp @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef MMKV_MMKVMETAINFO_H +#define MMKV_MMKVMETAINFO_H + +#include +#include +#include + +struct MMKVMetaInfo { + uint32_t m_crcDigest = 0; + uint32_t m_version = 1; + uint32_t m_sequence = 0; // full write-back count + + void write(void *ptr) { + assert(ptr); + memcpy(ptr, this, sizeof(MMKVMetaInfo)); + } + + void read(const void *ptr) { + assert(ptr); + memcpy(this, ptr, sizeof(MMKVMetaInfo)); + } +}; + +#endif //MMKV_MMKVMETAINFO_H diff --git a/Win32/MMKV/MiniPBCoder.cpp b/Win32/MMKV/MiniPBCoder.cpp new file mode 100644 index 00000000..d1544b41 --- /dev/null +++ b/Win32/MMKV/MiniPBCoder.cpp @@ -0,0 +1,290 @@ +/* + * 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 "MiniPBCoder.h" +#include "CodedInputData.h" +#include "CodedOutputData.h" +#include "MMBuffer.h" +#include "PBEncodeItem.hpp" +#include "PBUtility.h" +#include +#include +#include + +using namespace std; + +MiniPBCoder::MiniPBCoder() { + m_inputBuffer = nullptr; + m_inputData = nullptr; + + m_outputBuffer = nullptr; + m_outputData = nullptr; + m_encodeItems = nullptr; +} + +MiniPBCoder::~MiniPBCoder() { + if (m_inputData) { + delete m_inputData; + } + if (m_outputBuffer) { + delete m_outputBuffer; + } + if (m_outputData) { + delete m_outputData; + } + if (m_encodeItems) { + delete m_encodeItems; + } +} + +MiniPBCoder::MiniPBCoder(const MMBuffer *inputBuffer) : MiniPBCoder() { + m_inputBuffer = inputBuffer; + m_inputData = + new CodedInputData(m_inputBuffer->getPtr(), static_cast(m_inputBuffer->length())); +} + +#pragma mark - encode + +// write object using prepared m_encodeItems[] +void MiniPBCoder::writeRootObject() { + for (size_t index = 0, total = m_encodeItems->size(); index < total; index++) { + PBEncodeItem *encodeItem = &(*m_encodeItems)[index]; + switch (encodeItem->type) { + case PBEncodeItemType_String: { + m_outputData->writeString(*(encodeItem->value.strValue)); + break; + } + case PBEncodeItemType_Data: { + m_outputData->writeData(*(encodeItem->value.bufferValue)); + break; + } + case PBEncodeItemType_Container: { + m_outputData->writeRawVarint32(encodeItem->valueSize); + break; + } + case PBEncodeItemType_None: { + MMKVError("%d", encodeItem->type); + break; + } + } + } +} + +size_t MiniPBCoder::prepareObjectForEncode(const string &str) { + m_encodeItems->push_back(PBEncodeItem()); + PBEncodeItem *encodeItem = &(m_encodeItems->back()); + size_t index = m_encodeItems->size() - 1; + { + encodeItem->type = PBEncodeItemType_String; + encodeItem->value.strValue = &str; + encodeItem->valueSize = static_cast(str.size()); + } + encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize; + + return index; +} + +size_t MiniPBCoder::prepareObjectForEncode(const MMBuffer &buffer) { + m_encodeItems->push_back(PBEncodeItem()); + PBEncodeItem *encodeItem = &(m_encodeItems->back()); + size_t index = m_encodeItems->size() - 1; + { + encodeItem->type = PBEncodeItemType_Data; + encodeItem->value.bufferValue = &buffer; + encodeItem->valueSize = buffer.length(); + } + encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize; + + return index; +} + +size_t MiniPBCoder::prepareObjectForEncode(const vector &v) { + m_encodeItems->push_back(PBEncodeItem()); + PBEncodeItem *encodeItem = &(m_encodeItems->back()); + size_t index = m_encodeItems->size() - 1; + { + encodeItem->type = PBEncodeItemType_Container; + encodeItem->value.strValue = nullptr; + + for (const auto &str : v) { + size_t itemIndex = prepareObjectForEncode(str); + if (itemIndex < m_encodeItems->size()) { + (*m_encodeItems)[index].valueSize += (*m_encodeItems)[itemIndex].compiledSize; + } + } + + encodeItem = &(*m_encodeItems)[index]; + } + encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize; + + return index; +} + +size_t MiniPBCoder::prepareObjectForEncode(const unordered_map &map) { + m_encodeItems->push_back(PBEncodeItem()); + PBEncodeItem *encodeItem = &(m_encodeItems->back()); + size_t index = m_encodeItems->size() - 1; + { + encodeItem->type = PBEncodeItemType_Container; + encodeItem->value.strValue = nullptr; + + for (const auto &itr : map) { + const auto &key = itr.first; + const auto &value = itr.second; + if (key.length() <= 0) { + continue; + } + + size_t keyIndex = prepareObjectForEncode(key); + if (keyIndex < m_encodeItems->size()) { + size_t valueIndex = prepareObjectForEncode(value); + if (valueIndex < m_encodeItems->size()) { + (*m_encodeItems)[index].valueSize += (*m_encodeItems)[keyIndex].compiledSize; + (*m_encodeItems)[index].valueSize += (*m_encodeItems)[valueIndex].compiledSize; + } else { + m_encodeItems->pop_back(); // pop key + } + } + } + + encodeItem = &(*m_encodeItems)[index]; + } + encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize; + + return index; +} + +MMBuffer MiniPBCoder::getEncodeData(const string &str) { + m_encodeItems = new vector(); + size_t index = prepareObjectForEncode(str); + PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr; + if (oItem && oItem->compiledSize > 0) { + m_outputBuffer = new MMBuffer(oItem->compiledSize); + m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length()); + + writeRootObject(); + } + + return move(*m_outputBuffer); +} + +MMBuffer MiniPBCoder::getEncodeData(const MMBuffer &buffer) { + m_encodeItems = new vector(); + size_t index = prepareObjectForEncode(buffer); + PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr; + if (oItem && oItem->compiledSize > 0) { + m_outputBuffer = new MMBuffer(oItem->compiledSize); + m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length()); + + writeRootObject(); + } + + return move(*m_outputBuffer); +} + +MMBuffer MiniPBCoder::getEncodeData(const vector &v) { + m_encodeItems = new vector(); + size_t index = prepareObjectForEncode(v); + PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr; + if (oItem && oItem->compiledSize > 0) { + m_outputBuffer = new MMBuffer(oItem->compiledSize); + m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length()); + + writeRootObject(); + } + + return move(*m_outputBuffer); +} + +MMBuffer MiniPBCoder::getEncodeData(const unordered_map &map) { + m_encodeItems = new vector(); + size_t index = prepareObjectForEncode(map); + PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr; + if (oItem && oItem->compiledSize > 0) { + m_outputBuffer = new MMBuffer(oItem->compiledSize); + m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length()); + + writeRootObject(); + } + + return std::move(*m_outputBuffer); +} + +#pragma mark - decode + +string MiniPBCoder::decodeOneString() { + return m_inputData->readString(); +} + +MMBuffer MiniPBCoder::decodeOneBytes() { + return m_inputData->readData(); +} + +vector MiniPBCoder::decodeOneSet() { + vector v; + + auto length = m_inputData->readInt32(); + + while (!m_inputData->isAtEnd()) { + const auto &value = m_inputData->readString(); + v.push_back(move(value)); + } + + return v; +} + +void MiniPBCoder::decodeOneMap(unordered_map &dic, size_t size) { + if (size == 0) { + auto length = m_inputData->readInt32(); + } + while (!m_inputData->isAtEnd()) { + const auto &key = m_inputData->readString(); + if (key.length() > 0) { + auto value = m_inputData->readData(); + if (value.length() > 0) { + dic[key] = move(value); + } else { + dic.erase(key); + } + } + } +} + +string MiniPBCoder::decodeString(const MMBuffer &oData) { + MiniPBCoder oCoder(&oData); + return oCoder.decodeOneString(); +} + +MMBuffer MiniPBCoder::decodeBytes(const MMBuffer &oData) { + MiniPBCoder oCoder(&oData); + return oCoder.decodeOneBytes(); +} + +void MiniPBCoder::decodeMap(unordered_map &dic, + const MMBuffer &oData, + size_t size) { + MiniPBCoder oCoder(&oData); + oCoder.decodeOneMap(dic, size); +} + +vector MiniPBCoder::decodeSet(const MMBuffer &oData) { + MiniPBCoder oCoder(&oData); + return oCoder.decodeOneSet(); +} diff --git a/Win32/MMKV/MiniPBCoder.h b/Win32/MMKV/MiniPBCoder.h new file mode 100644 index 00000000..d7706346 --- /dev/null +++ b/Win32/MMKV/MiniPBCoder.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#ifndef MMKV_MINIPBCODER_H +#define MMKV_MINIPBCODER_H + +#include "MMBuffer.h" +#include "MMKVLog.h" +#include "PBEncodeItem.hpp" +#include +#include +#include +#include + +class CodedInputData; +class CodedOutputData; + +class MiniPBCoder { + const MMBuffer *m_inputBuffer; + CodedInputData *m_inputData; + + MMBuffer *m_outputBuffer; + CodedOutputData *m_outputData; + std::vector *m_encodeItems; + +private: + MiniPBCoder(); + MiniPBCoder(const MMBuffer *inputBuffer); + ~MiniPBCoder(); + + void writeRootObject(); + size_t prepareObjectForEncode(const std::string &str); + size_t prepareObjectForEncode(const MMBuffer &buffer); + size_t prepareObjectForEncode(const std::vector &vector); + size_t prepareObjectForEncode(const std::unordered_map &map); + + MMBuffer getEncodeData(const std::string &str); + MMBuffer getEncodeData(const MMBuffer &buffer); + MMBuffer getEncodeData(const std::vector &vector); + MMBuffer getEncodeData(const std::unordered_map &map); + + std::string decodeOneString(); + MMBuffer decodeOneBytes(); + std::vector decodeOneSet(); + void decodeOneMap(std::unordered_map &dic, size_t size = 0); + +public: + template + static MMBuffer encodeDataWithObject(const T &obj) { + MiniPBCoder pbcoder; + return pbcoder.getEncodeData(obj); + } + + static std::string decodeString(const MMBuffer &oData); + static MMBuffer decodeBytes(const MMBuffer &oData); + static std::vector decodeSet(const MMBuffer &oData); + static void decodeMap(std::unordered_map &dic, + const MMBuffer &oData, + size_t size = 0); +}; + +#endif //MMKV_MINIPBCODER_H diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp new file mode 100644 index 00000000..08aa9276 --- /dev/null +++ b/Win32/MMKV/MmapedFile.cpp @@ -0,0 +1,232 @@ +/* + * 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 "MmapedFile.h" +#include "MMBuffer.h" +#include "MMKVLog.h" +#include +#include +//#include +//#include +#include +#include +//#include + +using namespace std; + +const int DEFAULT_MMAP_SIZE = 4096; +//getpagesize(); + +MmapedFile::MmapedFile(const std::string &path, size_t size, bool fileType) + : m_name(path), m_fd(-1), m_segmentPtr(nullptr), m_segmentSize(0), m_fileType(fileType) { +/* if (m_fileType == MMAP_FILE) { + m_fd = open(m_name.c_str(), O_RDWR | O_CREAT, S_IRWXU); + if (m_fd < 0) { + MMKVError("fail to open:%s, %s", m_name.c_str(), strerror(errno)); + } else { + struct stat st = {}; + if (fstat(m_fd, &st) != -1) { + m_segmentSize = static_cast(st.st_size); + } + if (m_segmentSize < DEFAULT_MMAP_SIZE) { + m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); + if (ftruncate(m_fd, m_segmentSize) != 0 || !zeroFillFile(m_fd, 0, m_segmentSize)) { + MMKVError("fail to truncate [%s] to size %zu, %s", m_name.c_str(), + m_segmentSize, strerror(errno)); + close(m_fd); + m_fd = -1; + removeFile(m_name); + return; + } + } + m_segmentPtr = + (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); + if (m_segmentPtr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); + close(m_fd); + m_fd = -1; + m_segmentPtr = nullptr; + } + } + } else { + m_fd = open(ASHMEM_NAME_DEF, O_RDWR); + if (m_fd < 0) { + MMKVError("fail to open ashmem:%s, %s", m_name.c_str(), strerror(errno)); + } else { + if (ioctl(m_fd, ASHMEM_SET_NAME, m_name.c_str()) != 0) { + MMKVError("fail to set ashmem name:%s, %s", m_name.c_str(), strerror(errno)); + } else if (ioctl(m_fd, ASHMEM_SET_SIZE, size) != 0) { + MMKVError("fail to set ashmem:%s, size %d, %s", m_name.c_str(), size, + strerror(errno)); + } else { + m_segmentSize = static_cast(size); + m_segmentPtr = (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, + MAP_SHARED, m_fd, 0); + if (m_segmentPtr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); + m_segmentPtr = nullptr; + } else { + return; + } + } + close(m_fd); + m_fd = -1; + } + }*/ +} + +MmapedFile::MmapedFile(int ashmemFD) + : m_name(""), m_fd(ashmemFD), m_segmentPtr(nullptr), m_segmentSize(0), m_fileType(MMAP_ASHMEM) { +/* if (m_fd < 0) { + MMKVError("fd %d invalid", m_fd); + } else { + char name[ASHMEM_NAME_LEN] = {0}; + if (ioctl(m_fd, ASHMEM_GET_NAME, name) != 0) { + MMKVError("fail to get ashmem name:%d, %s", m_fd, strerror(errno)); + } else { + m_name = string(name); + int size = ioctl(m_fd, ASHMEM_GET_SIZE, nullptr); + if (size < 0) { + MMKVError("fail to get ashmem size:%s, %s", m_name.c_str(), strerror(errno)); + } else { + m_segmentSize = static_cast(size); + MMKVInfo("ashmem verified, name:%s, size:%zu", m_name.c_str(), m_segmentSize); + m_segmentPtr = (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, + MAP_SHARED, m_fd, 0); + if (m_segmentPtr == MAP_FAILED) { + MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); + m_segmentPtr = nullptr; + } + } + } + }*/ +} + +MmapedFile::~MmapedFile() { +/* if (m_segmentPtr != MAP_FAILED && m_segmentPtr != nullptr) { + munmap(m_segmentPtr, m_segmentSize); + m_segmentPtr = nullptr; + } + if (m_fd >= 0) { + close(m_fd); + m_fd = -1; + }*/ +} + +#pragma mark - file + +bool isFileExist(const string &nsFilePath) { + if (nsFilePath.empty()) { + return false; + } + + struct stat temp; + //return lstat(nsFilePath.c_str(), &temp) == 0; + return false; +} + +bool mkPath(char *path) { + struct stat sb = {}; + bool done = false; + char *slash = path; + + while (!done) { + slash += strspn(slash, "/"); + slash += strcspn(slash, "/"); + + done = (*slash == '\0'); + *slash = '\0'; + + if (stat(path, &sb) != 0) { + //if (errno != ENOENT || mkdir(path, 0777) != 0) { + MMKVWarning("%s", path); + return false; + //} + //} else if (!S_ISDIR(sb.st_mode)) { + MMKVWarning("%s: %s", path, strerror(ENOTDIR)); + return false; + } + + *slash = '/'; + } + + return true; +} + +bool removeFile(const string &nsFilePath) { + int ret = _unlink(nsFilePath.c_str()); + if (ret != 0) { + MMKVError("remove file failed. filePath=%s, err=%s", nsFilePath.c_str(), strerror(errno)); + return false; + } + return true; +} + +MMBuffer *readWholeFile(const char *path) { + MMBuffer *buffer = nullptr; +/* int fd = open(path, O_RDONLY); + if (fd >= 0) { + auto fileLength = lseek(fd, 0, SEEK_END); + if (fileLength > 0) { + buffer = new MMBuffer(static_cast(fileLength)); + lseek(fd, 0, SEEK_SET); + auto readSize = read(fd, buffer->getPtr(), static_cast(fileLength)); + if (readSize != -1) { + //fileSize = readSize; + } else { + MMKVWarning("fail to read %s: %s", path, strerror(errno)); + + delete buffer; + buffer = nullptr; + } + } + close(fd); + } else { + MMKVWarning("fail to open %s: %s", path, strerror(errno)); + }*/ + return buffer; +} + +bool zeroFillFile(int fd, size_t startPos, size_t size) { + if (fd < 0) { + return false; + } + /* + if (lseek(fd, startPos, SEEK_SET) < 0) { + MMKVError("fail to lseek fd[%d], error:%s", fd, strerror(errno)); + return false; + } + + static const char zeros[4096] = {0}; + while (size >= sizeof(zeros)) { + if (write(fd, zeros, sizeof(zeros)) < 0) { + MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno)); + return false; + } + size -= sizeof(zeros); + } + if (size > 0) { + if (write(fd, zeros, size) < 0) { + MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno)); + return false; + } + }*/ + return true; +} diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h new file mode 100644 index 00000000..3fa93cf8 --- /dev/null +++ b/Win32/MMKV/MmapedFile.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#ifndef MMKV_MMAPEDFILE_H +#define MMKV_MMAPEDFILE_H + +#include +//#include + +#define ASHMEM_NAME_LEN 256 +#define ASHMEM_NAME_DEF "/dev/ashmem" + +#define __ASHMEMIOC 0x77 +#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) +#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) +#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) +#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) + +enum : bool { MMAP_FILE = false, MMAP_ASHMEM = true }; + +extern const int DEFAULT_MMAP_SIZE; + +class MmapedFile { + std::string m_name; + int m_fd; + void *m_segmentPtr; + size_t m_segmentSize; + + // just forbid it for possibly misuse + MmapedFile(const MmapedFile &other) = delete; + MmapedFile &operator=(const MmapedFile &other) = delete; + +public: + MmapedFile(const std::string &path, + size_t size = static_cast(DEFAULT_MMAP_SIZE), + bool fileType = MMAP_FILE); + MmapedFile(int ashmemFD); + ~MmapedFile(); + + const bool m_fileType; + + size_t getFileSize() { return m_segmentSize; } + + void *getMemory() { return m_segmentPtr; } + + std::string &getName() { return m_name; } + + int getFd() { return m_fd; } +}; + +class MMBuffer; + +extern bool mkPath(char *path); +extern bool isFileExist(const std::string &nsFilePath); +extern bool removeFile(const std::string &nsFilePath); +extern MMBuffer *readWholeFile(const char *path); +extern bool zeroFillFile(int fd, size_t startPos, size_t size); + +#endif //MMKV_MMAPEDFILE_H diff --git a/Win32/MMKV/PBEncodeItem.hpp b/Win32/MMKV/PBEncodeItem.hpp new file mode 100644 index 00000000..47a8cb1f --- /dev/null +++ b/Win32/MMKV/PBEncodeItem.hpp @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef MMKV_PBENCODEITEM_HPP +#define MMKV_PBENCODEITEM_HPP + +#include "MMBuffer.h" +#include +#include +#include + +enum PBEncodeItemType { + PBEncodeItemType_None, + PBEncodeItemType_String, + PBEncodeItemType_Data, + PBEncodeItemType_Container, +}; + +struct PBEncodeItem { + PBEncodeItemType type; + uint32_t compiledSize; + uint32_t valueSize; + union { + const std::string *strValue; + const MMBuffer *bufferValue; + } value; + + PBEncodeItem() : type(PBEncodeItemType_None), compiledSize(0), valueSize(0) { + memset(&value, 0, sizeof(value)); + } +}; + +#endif //MMKV_PBENCODEITEM_HPP diff --git a/Win32/MMKV/PBUtility.cpp b/Win32/MMKV/PBUtility.cpp new file mode 100644 index 00000000..5fdcb119 --- /dev/null +++ b/Win32/MMKV/PBUtility.cpp @@ -0,0 +1,57 @@ +/* + * 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 "PBUtility.h" + +uint32_t pbRawVarint32Size(int32_t value) { + if ((value & (0xffffffff << 7)) == 0) { + return 1; + } else if ((value & (0xffffffff << 14)) == 0) { + return 2; + } else if ((value & (0xffffffff << 21)) == 0) { + return 3; + } else if ((value & (0xffffffff << 28)) == 0) { + return 4; + } + return 5; +} + +uint32_t pbInt64Size(int64_t value) { + if ((value & (0xffffffffffffffffL << 7)) == 0) { + return 1; + } else if ((value & (0xffffffffffffffffL << 14)) == 0) { + return 2; + } else if ((value & (0xffffffffffffffffL << 21)) == 0) { + return 3; + } else if ((value & (0xffffffffffffffffL << 28)) == 0) { + return 4; + } else if ((value & (0xffffffffffffffffL << 35)) == 0) { + return 5; + } else if ((value & (0xffffffffffffffffL << 42)) == 0) { + return 6; + } else if ((value & (0xffffffffffffffffL << 49)) == 0) { + return 7; + } else if ((value & (0xffffffffffffffffL << 56)) == 0) { + return 8; + } else if ((value & (0xffffffffffffffffL << 63)) == 0) { + return 9; + } + return 10; +} diff --git a/Win32/MMKV/PBUtility.h b/Win32/MMKV/PBUtility.h new file mode 100644 index 00000000..96910a98 --- /dev/null +++ b/Win32/MMKV/PBUtility.h @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#ifndef MMKV_PBUTILITY_H +#define MMKV_PBUTILITY_H + +#include + +template +union Converter { + static_assert(sizeof(T) == sizeof(P), "size not match"); + T first; + P second; +}; + +static inline int64_t Float64ToInt64(double v) { + Converter converter; + converter.first = v; + return converter.second; +} + +static inline int32_t Float32ToInt32(float v) { + Converter converter; + converter.first = v; + return converter.second; +} + +static inline double Int64ToFloat64(int64_t v) { + Converter converter; + converter.second = v; + return converter.first; +} + +static inline float Int32ToFloat32(int32_t v) { + Converter converter; + converter.second = v; + return converter.first; +} + +static inline uint64_t Int64ToUInt64(int64_t v) { + Converter converter; + converter.first = v; + return converter.second; +} + +static inline int64_t UInt64ToInt64(uint64_t v) { + Converter converter; + converter.second = v; + return converter.first; +} + +static inline uint32_t Int32ToUInt32(int32_t v) { + Converter converter; + converter.first = v; + return converter.second; +} + +static inline int32_t UInt32ToInt32(uint32_t v) { + Converter converter; + converter.second = v; + return converter.first; +} + +static inline int32_t logicalRightShift32(int32_t value, int32_t spaces) { + return UInt32ToInt32((Int32ToUInt32(value) >> spaces)); +} + +static inline int64_t logicalRightShift64(int64_t value, int32_t spaces) { + return UInt64ToInt64((Int64ToUInt64(value) >> spaces)); +} + +constexpr uint32_t littleEdian32Size = 4; + +constexpr uint32_t pbFloatSize(float value) { + return littleEdian32Size; +} + +constexpr uint32_t pbFixed32Size(int32_t value) { + return littleEdian32Size; +} + +constexpr uint32_t littleEdian64Size = 8; + +constexpr uint32_t pbDoubleSize(double value) { + return littleEdian64Size; +} + +constexpr uint32_t pbBoolSize(bool value) { + return 1; +} + +extern uint32_t pbRawVarint32Size(int32_t value); + +extern uint32_t pbInt64Size(int64_t value); + +static inline uint32_t pbInt32Size(int32_t value) { + if (value >= 0) { + return pbRawVarint32Size(value); + } else { + return 10; + } +} + +#endif //MMKV_PBUTILITY_H diff --git a/Win32/MMKV/ScopedLock.hpp b/Win32/MMKV/ScopedLock.hpp new file mode 100644 index 00000000..33f9c3a0 --- /dev/null +++ b/Win32/MMKV/ScopedLock.hpp @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef MMKV_SCOPEDLOCK_HPP +#define MMKV_SCOPEDLOCK_HPP + +#include "MMKVLog.h" + +template +class ScopedLock { + T *m_lock; + + // just forbid it for possibly misuse + ScopedLock(const ScopedLock &other) = delete; + + ScopedLock &operator=(const ScopedLock &other) = delete; + +public: + ScopedLock(T *oLock) : m_lock(oLock) { + assert(m_lock); + lock(); + } + + ~ScopedLock() { + unlock(); + m_lock = nullptr; + } + + void lock() { + if (m_lock) { + m_lock->lock(); + } + } + + bool try_lock() { + if (m_lock) { + return m_lock->try_lock(); + } + return false; + } + + void unlock() { + if (m_lock) { + m_lock->unlock(); + } + } +}; + +#define SCOPEDLOCK(lock) _SCOPEDLOCK(lock, __COUNTER__) +#define _SCOPEDLOCK(lock, counter) __SCOPEDLOCK(lock, counter) +#define __SCOPEDLOCK(lock, counter) ScopedLock __scopedLock##counter(&lock) + +//#include +//#define __SCOPEDLOCK(lock, counter) ScopedLock::type> __scopedLock##counter(lock) + +#endif //MMKV_SCOPEDLOCK_HPP diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp new file mode 100644 index 00000000..9d659ae4 --- /dev/null +++ b/Win32/MMKV/ThreadLock.cpp @@ -0,0 +1,59 @@ +/* + * 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 "ThreadLock.h" +#include "MMKVLog.h" + +ThreadLock::ThreadLock() { +/* pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&m_lock, &attr); + + pthread_mutexattr_destroy(&attr);*/ +} + +ThreadLock::~ThreadLock() { + //pthread_mutex_destroy(&m_lock); +} + +void ThreadLock::lock() { +/* auto ret = pthread_mutex_lock(&m_lock); + if (ret != 0) { + MMKVError("fail to lock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); + }*/ +} + +bool ThreadLock::try_lock() { +/* auto ret = pthread_mutex_trylock(&m_lock); + if (ret != 0) { + MMKVError("fail to try lock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); + } + return (ret == 0);*/ + return false; +} + +void ThreadLock::unlock() { +/* auto ret = pthread_mutex_unlock(&m_lock); + if (ret != 0) { + MMKVError("fail to unlock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); + }*/ +} diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h new file mode 100644 index 00000000..f003db1e --- /dev/null +++ b/Win32/MMKV/ThreadLock.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef MMKV_THREADLOCK_H +#define MMKV_THREADLOCK_H + +//#include + +class ThreadLock { +private: + //pthread_mutex_t m_lock; + +public: + ThreadLock(); + ~ThreadLock(); + + void lock(); + bool try_lock(); + void unlock(); +}; + +#endif //MMKV_THREADLOCK_H diff --git a/Win32/MMKV/aes/AESCrypt.cpp b/Win32/MMKV/aes/AESCrypt.cpp new file mode 100644 index 00000000..78a4b133 --- /dev/null +++ b/Win32/MMKV/aes/AESCrypt.cpp @@ -0,0 +1,117 @@ +/* + * 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 "AESCrypt.h" +#include "openssl/aes.h" +#include +#include + +AESCrypt::AESCrypt(const unsigned char *key, size_t keyLength) { + if (key && keyLength > 0) { + memcpy(m_key, key, (keyLength > AES_KEY_LEN) ? AES_KEY_LEN : keyLength); + memcpy(m_vector, m_key, AES_KEY_LEN); + + int ret = AES_set_encrypt_key(m_key, AES_KEY_BITSET_LEN, &m_aesKey); + assert(ret == 0); + } +} + +void AESCrypt::reset() { + m_number = 0; + memcpy(m_vector, m_key, AES_KEY_LEN); +} + +void AESCrypt::getKey(void *output) const { + if (output) { + memcpy(output, m_key, AES_KEY_LEN); + } +} + +void AESCrypt::encrypt(const unsigned char *input, unsigned char *output, size_t length) { + if (!input || !output || length == 0) { + return; + } + AES_cfb128_encrypt(input, output, length, &m_aesKey, m_vector, &m_number, AES_ENCRYPT); +} + +void AESCrypt::decrypt(const unsigned char *input, unsigned char *output, size_t length) { + if (!input || !output || length == 0) { + return; + } + AES_cfb128_encrypt(input, output, length, &m_aesKey, m_vector, &m_number, AES_DECRYPT); +} + +#ifndef NDEBUG + +#include "../MMKVLog.h" +#include "../MmapedFile.h" + +// check if AESCrypt is encrypt-decrypt full-duplex +void testAESCrypt() { + const unsigned char plainText[] = "Hello, OpenSSL with AES CFB 128."; + constexpr size_t textLength = sizeof(plainText) - 1; + + const unsigned char key[] = "TheAESKey"; + constexpr size_t keyLength = sizeof(key) - 1; + AESCrypt crypt1(key, keyLength); + AESCrypt crypt2(key, keyLength); + + auto encryptText = new unsigned char[DEFAULT_MMAP_SIZE]; + auto decryptText = new unsigned char[DEFAULT_MMAP_SIZE]; + memset(encryptText, 0, DEFAULT_MMAP_SIZE); + memset(decryptText, 0, DEFAULT_MMAP_SIZE); + + /* in-place encryption & decryption, this is crazy + memcpy(encryptText, plainText, textLength); + crypt1.encrypt(encryptText, encryptText, textLength); + crypt2.decrypt(encryptText, encryptText, textLength); + return; + */ + + size_t actualSize = 0; + bool flip = false; + for (const unsigned char *ptr = plainText; ptr < plainText + textLength;) { + auto tokenPtr = (const unsigned char *) strchr((const char *) ptr, ' '); + size_t size = 0; + if (!tokenPtr) { + size = plainText + textLength - ptr; + } else { + size = tokenPtr - ptr + 1; + } + + flip = !flip; + if (flip) { + crypt1.encrypt(plainText + actualSize, encryptText + actualSize, size); + crypt2.decrypt(encryptText + actualSize, decryptText + actualSize, size); + } else { + crypt2.encrypt(plainText + actualSize, encryptText + actualSize, size); + crypt1.decrypt(encryptText + actualSize, decryptText + actualSize, size); + } + + actualSize += size; + ptr += size; + } + MMKVDebug("AES CFB decode: %s", decryptText); + + delete[] encryptText; + delete[] decryptText; +} + +#endif \ No newline at end of file diff --git a/Win32/MMKV/aes/AESCrypt.h b/Win32/MMKV/aes/AESCrypt.h new file mode 100644 index 00000000..0196bd9e --- /dev/null +++ b/Win32/MMKV/aes/AESCrypt.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef AES_CRYPT_H_ +#define AES_CRYPT_H_ + +#include "openssl/aes.h" +#include + +constexpr size_t AES_KEY_LEN = 16; +constexpr size_t AES_KEY_BITSET_LEN = 128; + +// a AES CFB-128 encrypt-decrypt full-duplex wrapper +class AESCrypt { + unsigned char m_vector[AES_KEY_LEN] = {0}; + unsigned char m_key[AES_KEY_LEN] = {0}; + AES_KEY m_aesKey = {0}; + int m_number = 0; + +public: + AESCrypt(const unsigned char *key, size_t keyLength); + + void encrypt(const unsigned char *input, unsigned char *output, size_t length); + + void decrypt(const unsigned char *input, unsigned char *output, size_t length); + + void reset(); + + // output must have [AES_KEY_LEN] space + void getKey(void *output) const; +}; + +#ifndef NDEBUG + +// check if AESCrypt is encrypt-decrypt full-duplex +void testAESCrypt(); + +#endif + +#endif /* AES_CRYPT_H_ */ diff --git a/Win32/MMKV/aes/openssl/aes.h b/Win32/MMKV/aes/openssl/aes.h new file mode 100644 index 00000000..33da448c --- /dev/null +++ b/Win32/MMKV/aes/openssl/aes.h @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AES_H +# define HEADER_AES_H + +# include "opensslconf.h" + +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define AES_ENCRYPT 1 +# define AES_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ +# define AES_MAXNR 14 +# define AES_BLOCK_SIZE 16 + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { +# ifdef AES_LONG + unsigned long rd_key[4 * (AES_MAXNR + 1)]; +# else + unsigned int rd_key[4 * (AES_MAXNR + 1)]; +# endif + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/Win32/MMKV/aes/openssl/aes_cfb.c b/Win32/MMKV/aes/openssl/aes_cfb.c new file mode 100644 index 00000000..ffe6438b --- /dev/null +++ b/Win32/MMKV/aes/openssl/aes_cfb.c @@ -0,0 +1,26 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "aes.h" +#include "modes.h" + +/* + * The input and output encrypted as though 128bit cfb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ + +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) AES_encrypt); +} diff --git a/Win32/MMKV/aes/openssl/aes_core.c b/Win32/MMKV/aes/openssl/aes_core.c new file mode 100644 index 00000000..74ac4193 --- /dev/null +++ b/Win32/MMKV/aes/openssl/aes_core.c @@ -0,0 +1,918 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Note: rewritten a little bit to provide error control and an OpenSSL- + compatible API */ + +#include + +#include +#include "aes.h" +#include "aes_locl.h" + +/*- +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; + +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u8 Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits == 128) + key->rounds = 10; + else if (bits == 192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te2[(temp >> 24) ] & 0xff000000) ^ + (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te2[(t0 >> 24) ] & 0xff000000) ^ + (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Te2[(t1 >> 24) ] & 0xff000000) ^ + (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Te2[(t2 >> 24) ] & 0xff000000) ^ + (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Te2[(t3 >> 24) ] & 0xff000000) ^ + (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} diff --git a/Win32/MMKV/aes/openssl/aes_locl.h b/Win32/MMKV/aes/openssl/aes_locl.h new file mode 100644 index 00000000..38b98ed7 --- /dev/null +++ b/Win32/MMKV/aes/openssl/aes_locl.h @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AES_LOCL_H +# define HEADER_AES_LOCL_H + +# include "opensslconf.h" +# include +# include +# include +# include + +# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +# else +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +# endif + +# ifdef AES_LONG +typedef unsigned long u32; +# else +typedef unsigned int u32; +# endif +typedef unsigned short u16; +typedef unsigned char u8; + + +/* This controls loop-unrolling in aes_core.c */ +# undef FULL_UNROLL + +#endif /* !HEADER_AES_LOCL_H */ diff --git a/Win32/MMKV/aes/openssl/cfb128.c b/Win32/MMKV/aes/openssl/cfb128.c new file mode 100644 index 00000000..3f5a809b --- /dev/null +++ b/Win32/MMKV/aes/openssl/cfb128.c @@ -0,0 +1,131 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "aes.h" +#include "modes.h" +#include + +/* + * The input and output encrypted as though 128bit cfb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + unsigned int n; + size_t l = 0; + + n = *num; + + if (enc) { +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + *(out++) = ivec[n] ^= *(in++); + --len; + n = (n + 1) % 16; + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % + sizeof(size_t) != 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = + *(size_t *)(ivec + n) ^= *(size_t *)(in + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ivec, key); + while (len--) { + out[n] = ivec[n] ^= in[n]; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + if (n == 0) { + (*block) (ivec, ivec, key); + } + out[l] = ivec[n] ^= in[l]; + ++l; + n = (n + 1) % 16; + } + *num = n; + } else { +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + unsigned char c; + *(out++) = ivec[n] ^ (c = *(in++)); + ivec[n] = c; + --len; + n = (n + 1) % 16; + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % + sizeof(size_t) != 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + size_t t = *(size_t *)(in + n); + *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t; + *(size_t *)(ivec + n) = t; + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ivec, key); + while (len--) { + unsigned char c; + out[n] = ivec[n] ^ (c = in[n]); + ivec[n] = c; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + unsigned char c; + if (n == 0) { + (*block) (ivec, ivec, key); + } + out[l] = ivec[n] ^ (c = in[l]); + ivec[n] = c; + ++l; + n = (n + 1) % 16; + } + *num = n; + } +} diff --git a/Win32/MMKV/aes/openssl/md32_common.h b/Win32/MMKV/aes/openssl/md32_common.h new file mode 100644 index 00000000..ae397e84 --- /dev/null +++ b/Win32/MMKV/aes/openssl/md32_common.h @@ -0,0 +1,254 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at least 32 bit wide. + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * either { + * HASH_LONG data[HASH_LBLOCK]; + * unsigned char data[HASH_CBLOCK]; + * }; + * unsigned int num; + * ... + * } HASH_CTX; + * data[] vector is expected to be zeroed upon first call to + * HASH_UPDATE. + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_DATA_ORDER + * name of "block" function capable of treating *unaligned* input + * message in original (data) byte order, implemented externally. + * HASH_MAKE_STRING + * macro converting context variables to an ASCII hash string. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + */ + + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +# error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +# error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +# error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +# error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +# error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +# error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_DATA_ORDER +# error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif + +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) + +#endif + +/* + * Time for some action :-) + */ + +int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) +{ + const unsigned char *data = data_; + unsigned char *p; + HASH_LONG l; + size_t n; + + if (len == 0) + return 1; + + l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on + * 16-bit */ + c->Nl = l; + + n = c->num; + if (n != 0) { + p = (unsigned char *)c->data; + + if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { + memcpy(p + n, data, HASH_CBLOCK - n); + HASH_BLOCK_DATA_ORDER(c, p, 1); + n = HASH_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + /* + * We use memset rather than OPENSSL_cleanse() here deliberately. + * Using OPENSSL_cleanse() here could be a performance issue. It + * will get properly cleansed on finalisation so this isn't a + * security problem. + */ + memset(p, 0, HASH_CBLOCK); /* keep it zeroed */ + } else { + memcpy(p + n, data, len); + c->num += (unsigned int)len; + return 1; + } + } + + n = len / HASH_CBLOCK; + if (n > 0) { + HASH_BLOCK_DATA_ORDER(c, data, n); + n *= HASH_CBLOCK; + data += n; + len -= n; + } + + if (len != 0) { + p = (unsigned char *)c->data; + c->num = (unsigned int)len; + memcpy(p, data, len); + } + return 1; +} + +void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data) +{ + HASH_BLOCK_DATA_ORDER(c, data, 1); +} + +int HASH_FINAL(unsigned char *md, HASH_CTX *c) +{ + unsigned char *p = (unsigned char *)c->data; + size_t n = c->num; + + p[n] = 0x80; /* there is always room for one */ + n++; + + if (n > (HASH_CBLOCK - 8)) { + memset(p + n, 0, HASH_CBLOCK - n); + n = 0; + HASH_BLOCK_DATA_ORDER(c, p, 1); + } + memset(p + n, 0, HASH_CBLOCK - 8 - n); + + p += HASH_CBLOCK - 8; +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + (void)HOST_l2c(c->Nh, p); + (void)HOST_l2c(c->Nl, p); +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + (void)HOST_l2c(c->Nl, p); + (void)HOST_l2c(c->Nh, p); +#endif + p -= HASH_CBLOCK; + HASH_BLOCK_DATA_ORDER(c, p, 1); + c->num = 0; + +#ifndef HASH_MAKE_STRING +# error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c, md); +#endif + + return 1; +} + +#ifndef MD32_REG_T +# if defined(__alpha) || defined(__sparcv9) || defined(__mips) +# define MD32_REG_T long +/* + * This comment was originally written for MD5, which is why it + * discusses A-D. But it basically applies to all 32-bit digests, + * which is why it was moved to common header file. + * + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + */ +# else +/* + * Above is not absolute and there are LP64 compilers that + * generate better code if MD32_REG_T is defined int. The above + * pre-processor condition reflects the circumstances under which + * the conclusion was made and is subject to further extension. + */ +# define MD32_REG_T int +# endif +#endif diff --git a/Win32/MMKV/aes/openssl/md5.h b/Win32/MMKV/aes/openssl/md5.h new file mode 100644 index 00000000..18fac685 --- /dev/null +++ b/Win32/MMKV/aes/openssl/md5.h @@ -0,0 +1,49 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD5_H +# define HEADER_MD5_H + +# include "opensslconf.h" + +# ifndef OPENSSL_NO_MD5 +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define MD5_LONG unsigned int + +# define MD5_CBLOCK 64 +# define MD5_LBLOCK (MD5_CBLOCK/4) +# define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st { + MD5_LONG A, B, C, D; + MD5_LONG Nl, Nh; + MD5_LONG data[MD5_LBLOCK]; + unsigned int num; +} MD5_CTX; + +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, size_t len); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/Win32/MMKV/aes/openssl/md5_dgst.c b/Win32/MMKV/aes/openssl/md5_dgst.c new file mode 100644 index 00000000..d3b89ff0 --- /dev/null +++ b/Win32/MMKV/aes/openssl/md5_dgst.c @@ -0,0 +1,163 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "md5_locl.h" + +/* + * Implemented from RFC1321 The MD5 Message-Digest Algorithm + */ + +#define INIT_DATA_A (unsigned long)0x67452301L +#define INIT_DATA_B (unsigned long)0xefcdab89L +#define INIT_DATA_C (unsigned long)0x98badcfeL +#define INIT_DATA_D (unsigned long)0x10325476L + +int MD5_Init(MD5_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->A = INIT_DATA_A; + c->B = INIT_DATA_B; + c->C = INIT_DATA_C; + c->D = INIT_DATA_D; + return 1; +} + +#ifndef md5_block_data_order +# ifdef X +# undef X +# endif +void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num) +{ + const unsigned char *data = data_; + register unsigned MD32_REG_T A, B, C, D, l; +# ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; +# define X(i) XX##i +# else + MD5_LONG XX[MD5_LBLOCK]; +# define X(i) XX[i] +# endif + + A = c->A; + B = c->B; + C = c->C; + D = c->D; + + for (; num--;) { + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + /* Round 0 */ + R0(A, B, C, D, X(0), 7, 0xd76aa478L); + (void)HOST_c2l(data, l); + X(2) = l; + R0(D, A, B, C, X(1), 12, 0xe8c7b756L); + (void)HOST_c2l(data, l); + X(3) = l; + R0(C, D, A, B, X(2), 17, 0x242070dbL); + (void)HOST_c2l(data, l); + X(4) = l; + R0(B, C, D, A, X(3), 22, 0xc1bdceeeL); + (void)HOST_c2l(data, l); + X(5) = l; + R0(A, B, C, D, X(4), 7, 0xf57c0fafL); + (void)HOST_c2l(data, l); + X(6) = l; + R0(D, A, B, C, X(5), 12, 0x4787c62aL); + (void)HOST_c2l(data, l); + X(7) = l; + R0(C, D, A, B, X(6), 17, 0xa8304613L); + (void)HOST_c2l(data, l); + X(8) = l; + R0(B, C, D, A, X(7), 22, 0xfd469501L); + (void)HOST_c2l(data, l); + X(9) = l; + R0(A, B, C, D, X(8), 7, 0x698098d8L); + (void)HOST_c2l(data, l); + X(10) = l; + R0(D, A, B, C, X(9), 12, 0x8b44f7afL); + (void)HOST_c2l(data, l); + X(11) = l; + R0(C, D, A, B, X(10), 17, 0xffff5bb1L); + (void)HOST_c2l(data, l); + X(12) = l; + R0(B, C, D, A, X(11), 22, 0x895cd7beL); + (void)HOST_c2l(data, l); + X(13) = l; + R0(A, B, C, D, X(12), 7, 0x6b901122L); + (void)HOST_c2l(data, l); + X(14) = l; + R0(D, A, B, C, X(13), 12, 0xfd987193L); + (void)HOST_c2l(data, l); + X(15) = l; + R0(C, D, A, B, X(14), 17, 0xa679438eL); + R0(B, C, D, A, X(15), 22, 0x49b40821L); + /* Round 1 */ + R1(A, B, C, D, X(1), 5, 0xf61e2562L); + R1(D, A, B, C, X(6), 9, 0xc040b340L); + R1(C, D, A, B, X(11), 14, 0x265e5a51L); + R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL); + R1(A, B, C, D, X(5), 5, 0xd62f105dL); + R1(D, A, B, C, X(10), 9, 0x02441453L); + R1(C, D, A, B, X(15), 14, 0xd8a1e681L); + R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L); + R1(A, B, C, D, X(9), 5, 0x21e1cde6L); + R1(D, A, B, C, X(14), 9, 0xc33707d6L); + R1(C, D, A, B, X(3), 14, 0xf4d50d87L); + R1(B, C, D, A, X(8), 20, 0x455a14edL); + R1(A, B, C, D, X(13), 5, 0xa9e3e905L); + R1(D, A, B, C, X(2), 9, 0xfcefa3f8L); + R1(C, D, A, B, X(7), 14, 0x676f02d9L); + R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL); + /* Round 2 */ + R2(A, B, C, D, X(5), 4, 0xfffa3942L); + R2(D, A, B, C, X(8), 11, 0x8771f681L); + R2(C, D, A, B, X(11), 16, 0x6d9d6122L); + R2(B, C, D, A, X(14), 23, 0xfde5380cL); + R2(A, B, C, D, X(1), 4, 0xa4beea44L); + R2(D, A, B, C, X(4), 11, 0x4bdecfa9L); + R2(C, D, A, B, X(7), 16, 0xf6bb4b60L); + R2(B, C, D, A, X(10), 23, 0xbebfbc70L); + R2(A, B, C, D, X(13), 4, 0x289b7ec6L); + R2(D, A, B, C, X(0), 11, 0xeaa127faL); + R2(C, D, A, B, X(3), 16, 0xd4ef3085L); + R2(B, C, D, A, X(6), 23, 0x04881d05L); + R2(A, B, C, D, X(9), 4, 0xd9d4d039L); + R2(D, A, B, C, X(12), 11, 0xe6db99e5L); + R2(C, D, A, B, X(15), 16, 0x1fa27cf8L); + R2(B, C, D, A, X(2), 23, 0xc4ac5665L); + /* Round 3 */ + R3(A, B, C, D, X(0), 6, 0xf4292244L); + R3(D, A, B, C, X(7), 10, 0x432aff97L); + R3(C, D, A, B, X(14), 15, 0xab9423a7L); + R3(B, C, D, A, X(5), 21, 0xfc93a039L); + R3(A, B, C, D, X(12), 6, 0x655b59c3L); + R3(D, A, B, C, X(3), 10, 0x8f0ccc92L); + R3(C, D, A, B, X(10), 15, 0xffeff47dL); + R3(B, C, D, A, X(1), 21, 0x85845dd1L); + R3(A, B, C, D, X(8), 6, 0x6fa87e4fL); + R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L); + R3(C, D, A, B, X(6), 15, 0xa3014314L); + R3(B, C, D, A, X(13), 21, 0x4e0811a1L); + R3(A, B, C, D, X(4), 6, 0xf7537e82L); + R3(D, A, B, C, X(11), 10, 0xbd3af235L); + R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL); + R3(B, C, D, A, X(9), 21, 0xeb86d391L); + + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } +} +#endif diff --git a/Win32/MMKV/aes/openssl/md5_locl.h b/Win32/MMKV/aes/openssl/md5_locl.h new file mode 100644 index 00000000..03e68d44 --- /dev/null +++ b/Win32/MMKV/aes/openssl/md5_locl.h @@ -0,0 +1,68 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "md5.h" + +void md5_block_data_order(MD5_CTX *c, const void *p, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG MD5_LONG +#define HASH_CTX MD5_CTX +#define HASH_CBLOCK MD5_CBLOCK +#define HASH_UPDATE MD5_Update +#define HASH_TRANSFORM MD5_Transform +#define HASH_FINAL MD5_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER md5_block_data_order + +#include "md32_common.h" + +/*- +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) +*/ + +/* + * As pointed out by Wei Dai, the above can be simplified to the code + * below. Wei attributes these optimizations to Peter Gutmann's + * SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c)) +#define H(b,c,d) ((b) ^ (c) ^ (d)) +#define I(b,c,d) (((~(d)) | (b)) ^ (c)) + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; };\ + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R3(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+I((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; diff --git a/Win32/MMKV/aes/openssl/md5_one.c b/Win32/MMKV/aes/openssl/md5_one.c new file mode 100644 index 00000000..30d56c0d --- /dev/null +++ b/Win32/MMKV/aes/openssl/md5_one.c @@ -0,0 +1,26 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "md5.h" + +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md) +{ + MD5_CTX c; + static unsigned char m[MD5_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!MD5_Init(&c)) + return NULL; + MD5_Update(&c, d, n); + MD5_Final(md, &c); + return md; +} diff --git a/Win32/MMKV/aes/openssl/modes.h b/Win32/MMKV/aes/openssl/modes.h new file mode 100644 index 00000000..6fab3d6f --- /dev/null +++ b/Win32/MMKV/aes/openssl/modes.h @@ -0,0 +1,27 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef void (*block128_f) (const unsigned char in[16], + unsigned char out[16], const void *key); + +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +#ifdef __cplusplus +} + +#define STRICT_ALIGNMENT 1 + +#endif diff --git a/Win32/MMKV/aes/openssl/opensslconf.h b/Win32/MMKV/aes/openssl/opensslconf.h new file mode 100644 index 00000000..55b37d3c --- /dev/null +++ b/Win32/MMKV/aes/openssl/opensslconf.h @@ -0,0 +1,271 @@ +/* opensslconf.h */ +/* WARNING: Generated automatically from opensslconf.h.in by Configure. */ + +#ifdef __cplusplus +extern "C" { +#endif +/* OpenSSL was configured with the following options: */ +#ifndef OPENSSL_SYSNAME_iOS +# define OPENSSL_SYSNAME_iOS +#endif +#ifndef OPENSSL_DOING_MAKEDEPEND + + +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# define OPENSSL_NO_EC_NISTP_64_GCC_128 +#endif +#ifndef OPENSSL_NO_GMP +# define OPENSSL_NO_GMP +#endif +#ifndef OPENSSL_NO_JPAKE +# define OPENSSL_NO_JPAKE +#endif +#ifndef OPENSSL_NO_KRB5 +# define OPENSSL_NO_KRB5 +#endif +#ifndef OPENSSL_NO_LIBUNBOUND +# define OPENSSL_NO_LIBUNBOUND +#endif +#ifndef OPENSSL_NO_MD2 +# define OPENSSL_NO_MD2 +#endif +#ifndef OPENSSL_NO_RC5 +# define OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_NO_RFC3779 +# define OPENSSL_NO_RFC3779 +#endif +#ifndef OPENSSL_NO_SCTP +# define OPENSSL_NO_SCTP +#endif +#ifndef OPENSSL_NO_SSL_TRACE +# define OPENSSL_NO_SSL_TRACE +#endif +#ifndef OPENSSL_NO_SSL2 +# define OPENSSL_NO_SSL2 +#endif +#ifndef OPENSSL_NO_STORE +# define OPENSSL_NO_STORE +#endif +#ifndef OPENSSL_NO_UNIT_TEST +# define OPENSSL_NO_UNIT_TEST +#endif +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS +# define OPENSSL_NO_WEAK_SSL_CIPHERS +#endif + +#endif /* OPENSSL_DOING_MAKEDEPEND */ + +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif +#ifndef OPENSSL_NO_DYNAMIC_ENGINE +# define OPENSSL_NO_DYNAMIC_ENGINE +#endif + +/* The OPENSSL_NO_* macros are also defined as NO_* if the application + asks for it. This is a transient feature that is provided for those + who haven't had the time to do the appropriate changes in their + applications. */ +#ifdef OPENSSL_ALGORITHM_DEFINES +# if defined(OPENSSL_NO_EC_NISTP_64_GCC_128) && !defined(NO_EC_NISTP_64_GCC_128) +# define NO_EC_NISTP_64_GCC_128 +# endif +# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP) +# define NO_GMP +# endif +# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE) +# define NO_JPAKE +# endif +# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5) +# define NO_KRB5 +# endif +# if defined(OPENSSL_NO_LIBUNBOUND) && !defined(NO_LIBUNBOUND) +# define NO_LIBUNBOUND +# endif +# if defined(OPENSSL_NO_MD2) && !defined(NO_MD2) +# define NO_MD2 +# endif +# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5) +# define NO_RC5 +# endif +# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779) +# define NO_RFC3779 +# endif +# if defined(OPENSSL_NO_SCTP) && !defined(NO_SCTP) +# define NO_SCTP +# endif +# if defined(OPENSSL_NO_SSL_TRACE) && !defined(NO_SSL_TRACE) +# define NO_SSL_TRACE +# endif +# if defined(OPENSSL_NO_SSL2) && !defined(NO_SSL2) +# define NO_SSL2 +# endif +# if defined(OPENSSL_NO_STORE) && !defined(NO_STORE) +# define NO_STORE +# endif +# if defined(OPENSSL_NO_UNIT_TEST) && !defined(NO_UNIT_TEST) +# define NO_UNIT_TEST +# endif +# if defined(OPENSSL_NO_WEAK_SSL_CIPHERS) && !defined(NO_WEAK_SSL_CIPHERS) +# define NO_WEAK_SSL_CIPHERS +# endif +#endif + +/* crypto/opensslconf.h.in */ + +/* Generate 80386 code? */ +#undef I386_ONLY + +#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define ENGINESDIR "/Users/elviswu/Desktop/compile/openssl-ios-build-shell-script-master/openssl-1.0.2k-build/armv7/lib/engines" +#define OPENSSLDIR "/Users/elviswu/Desktop/compile/openssl-ios-build-shell-script-master/openssl-1.0.2k-build/armv7/ssl" +#endif +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned char +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned long +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependancies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +#error YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very mucy CPU dependant */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( __sun ) || defined ( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ +#ifdef __cplusplus +} +#endif From bf007efadf2b82e61614ee0ea877f024f429e8f6 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 11 Dec 2018 21:52:48 +0800 Subject: [PATCH 04/57] thread lock & process lock --- Win32/MMKV/InterProcessLock.cpp | 99 +++++++++++++++++++-------------- Win32/MMKV/InterProcessLock.h | 14 ++--- Win32/MMKV/MMKV.cpp | 4 +- Win32/MMKV/ThreadLock.cpp | 34 ++++------- Win32/MMKV/ThreadLock.h | 4 +- 5 files changed, 81 insertions(+), 74 deletions(-) diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index 35e8eae5..8026e8e1 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -20,27 +20,29 @@ #include "InterProcessLock.h" #include "MMKVLog.h" -/*#include -static short LockType2FlockType(LockType lockType) { +static DWORD LockType2Flag(LockType lockType, bool tryLock) { + DWORD flag = 0; switch (lockType) { case SharedLockType: - return F_RDLCK; + flag = 0; + break; case ExclusiveLockType: - return F_WRLCK; + flag = LOCKFILE_EXCLUSIVE_LOCK; + break; } + if (tryLock) { + flag |= LOCKFILE_FAIL_IMMEDIATELY; + } + return flag; } -*/ -FileLock::FileLock(int fd) : m_fd(fd), m_sharedLockCount(0), m_exclusiveLockCount(0) { -/* m_lockInfo.l_type = F_WRLCK; - m_lockInfo.l_start = 0; - m_lockInfo.l_whence = SEEK_SET; - m_lockInfo.l_len = 0; - m_lockInfo.l_pid = 0;*/ + +FileLock::FileLock(HANDLE fd) + : m_fd(fd), m_overLapped{0}, m_sharedLockCount(0), m_exclusiveLockCount(0) { } -bool FileLock::doLock(LockType lockType, int cmd) { -/* bool unLockFirstIfNeeded = false; +bool FileLock::doLock(LockType lockType, bool tryLock) { + bool unLockFirstIfNeeded = false; if (lockType == SharedLockType) { m_sharedLockCount++; @@ -60,46 +62,50 @@ bool FileLock::doLock(LockType lockType, int cmd) { } } - m_lockInfo.l_type = LockType2FlockType(lockType); + auto flag = LockType2Flag(lockType, tryLock); if (unLockFirstIfNeeded) { - // try lock - auto ret = fcntl(m_fd, F_SETLK, &m_lockInfo); - if (ret == 0) { + /* try exclusive-lock above shared-lock will always fail in Win32 + auto ret = LockFileEx(m_fd, flag | LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &m_overLapped); + if (ret) { return true; - } + }*/ // lets be gentleman: unlock my shared-lock to prevent deadlock - auto type = m_lockInfo.l_type; - m_lockInfo.l_type = F_UNLCK; - ret = fcntl(m_fd, F_SETLK, &m_lockInfo); - if (ret != 0) { - MMKVError("fail to try unlock first fd=%d, ret=%d, error:%s", m_fd, ret, - strerror(errno)); + auto ret = UnlockFileEx(m_fd, 0, 1, 0, &m_overLapped); + if (!ret) { + MMKVError("fail to try unlock first fd=%d, error:%d", m_fd, GetLastError()); } - m_lockInfo.l_type = type; } - auto ret = fcntl(m_fd, cmd, &m_lockInfo); - if (ret != 0) { - MMKVError("fail to lock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + auto ret = LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped); + if (!ret) { + MMKVError("fail to lock fd=%d, error:%d", m_fd, ret, GetLastError()); + if (lockType == SharedLockType) { + m_sharedLockCount--; + } else { + m_exclusiveLockCount--; + if (unLockFirstIfNeeded) { + flag = LockType2Flag(SharedLockType, false); + if (!LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped)) { + MMKVError("fail to roll back, error:%d", GetLastError()); + } + } + } return false; } else { return true; - }*/ - return false; + } } bool FileLock::lock(LockType lockType) { - //return doLock(lockType, F_SETLKW); - return false; + return doLock(lockType, false); } bool FileLock::try_lock(LockType lockType) { - //return doLock(lockType, F_SETLK); - return false; + return doLock(lockType, true); } bool FileLock::unlock(LockType lockType) { -/* bool unlockToSharedLock = false; + bool unlockToSharedLock = false; if (lockType == SharedLockType) { if (m_sharedLockCount == 0) { @@ -124,13 +130,24 @@ bool FileLock::unlock(LockType lockType) { } } - m_lockInfo.l_type = static_cast(unlockToSharedLock ? F_RDLCK : F_UNLCK); - auto ret = fcntl(m_fd, F_SETLK, &m_lockInfo); - if (ret != 0) { - MMKVError("fail to unlock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + /* quote from MSDN: + * If the same range is locked with an exclusive and a shared lock, + * two unlock operations are necessary to unlock the region; + * the first unlock operation unlocks the exclusive lock, + * the second unlock operation unlocks the shared lock. + */ + if (unlockToSharedLock) { + auto flag = LockType2Flag(SharedLockType, false); + if (!LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped)) { + MMKVError("fail to roll back to shared-lock, error:%d", GetLastError()); + } + } + auto flag = LockType2Flag(lockType, false); + auto ret = UnlockFileEx(m_fd, 0, 1, 0, &m_overLapped); + if (!ret) { + MMKVError("fail to unlock fd=%d, error:%d", m_fd, GetLastError()); return false; } else { return true; - }*/ - return false; + } } diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h index 0383e614..888e64db 100644 --- a/Win32/MMKV/InterProcessLock.h +++ b/Win32/MMKV/InterProcessLock.h @@ -22,22 +22,22 @@ #define MMKV_INTERPROCESSLOCK_H #include -#include +#include "MMKVDef.h" enum LockType { SharedLockType, ExclusiveLockType, }; -// a recursive POSIX file-lock wrapper +// a recursive Win32 file-lock wrapper // handles lock upgrade & downgrade correctly class FileLock { - int m_fd; - //struct flock m_lockInfo; + HANDLE m_fd; + OVERLAPPED m_overLapped; size_t m_sharedLockCount; size_t m_exclusiveLockCount; - bool doLock(LockType lockType, int cmd); + bool doLock(LockType lockType, bool tryLock); // just forbid it for possibly misuse FileLock(const FileLock &other) = delete; @@ -45,7 +45,7 @@ class FileLock { FileLock &operator=(const FileLock &other) = delete; public: - FileLock(int fd); + FileLock(HANDLE fd); bool lock(LockType lockType); @@ -71,7 +71,7 @@ class InterProcessLock { m_fileLock->lock(m_lockType); } } - + // TODO: remove try_lock() bool try_lock() { if (m_enable) { return m_fileLock->try_lock(m_lockType); diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index d3f8444d..74c9635c 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -98,7 +98,7 @@ MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) , m_crcPath(crcPathWithID(m_mmapID, mode)) , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE, (mode & MMKV_ASHMEM) ? MMAP_ASHMEM : MMAP_FILE) , m_crypter(nullptr) - , m_fileLock(m_metaFile.getFd()) + , m_fileLock(nullptr)// TODO:, m_fileLock(m_metaFile.getFd()) , m_sharedProcessLock(&m_fileLock, SharedLockType) , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) @@ -141,7 +141,7 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe , m_crcPath("") , m_metaFile(ashmemMetaFD) , m_crypter(nullptr) - , m_fileLock(m_metaFile.getFd()) + , m_fileLock(nullptr)// TODO:, m_fileLock(m_metaFile.getFd()) , m_sharedProcessLock(&m_fileLock, SharedLockType) , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) , m_isInterProcess(true) diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index 9d659ae4..043a2ffb 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -21,39 +21,29 @@ #include "ThreadLock.h" #include "MMKVLog.h" -ThreadLock::ThreadLock() { -/* pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_lock, &attr); - - pthread_mutexattr_destroy(&attr);*/ +ThreadLock::ThreadLock() : m_lock {0} { + // TODO: a better spin count? + if (!InitializeCriticalSectionAndSpinCount(&m_lock, 1024)) { + MMKVError("fail to init critical section:%d", GetLastError()); + } } ThreadLock::~ThreadLock() { - //pthread_mutex_destroy(&m_lock); + DeleteCriticalSection(&m_lock); } void ThreadLock::lock() { -/* auto ret = pthread_mutex_lock(&m_lock); - if (ret != 0) { - MMKVError("fail to lock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); - }*/ + EnterCriticalSection(&m_lock); } bool ThreadLock::try_lock() { -/* auto ret = pthread_mutex_trylock(&m_lock); - if (ret != 0) { - MMKVError("fail to try lock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); + auto ret = TryEnterCriticalSection(&m_lock); + if (!ret) { + MMKVError("fail to try lock %p, ret=%d", &m_lock, ret); } - return (ret == 0);*/ - return false; + return ret; } void ThreadLock::unlock() { -/* auto ret = pthread_mutex_unlock(&m_lock); - if (ret != 0) { - MMKVError("fail to unlock %p, ret=%d, errno=%s", &m_lock, ret, strerror(errno)); - }*/ + LeaveCriticalSection(&m_lock); } diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h index f003db1e..8c017b27 100644 --- a/Win32/MMKV/ThreadLock.h +++ b/Win32/MMKV/ThreadLock.h @@ -21,11 +21,11 @@ #ifndef MMKV_THREADLOCK_H #define MMKV_THREADLOCK_H -//#include +#include "MMKVDef.h" class ThreadLock { private: - //pthread_mutex_t m_lock; + CRITICAL_SECTION m_lock; public: ThreadLock(); From 493ecbda9a4ab415c29cb2435b2e47130126f378 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 12 Dec 2018 21:50:15 +0800 Subject: [PATCH 05/57] mmap --- Win32/MMKV/CodedInputData.cpp | 2 +- Win32/MMKV/InterProcessLock.cpp | 3 +- Win32/MMKV/InterProcessLock.h | 2 +- Win32/MMKV/MMBuffer.h | 2 +- Win32/MMKV/MMKV.cpp | 265 ++++---------------------------- Win32/MMKV/MMKV.h | 22 +-- Win32/MMKV/MMKVLog.h | 11 +- Win32/MMKV/MmapedFile.cpp | 207 ++++++++++++------------- Win32/MMKV/MmapedFile.h | 30 ++-- Win32/MMKV/ThreadLock.cpp | 2 +- Win32/MMKV/dllmain.cpp | 20 +-- Win32/Win32Demo/Win32Demo.cpp | 2 +- Win32/Win32Demo/pch.h | 2 +- 13 files changed, 158 insertions(+), 412 deletions(-) diff --git a/Win32/MMKV/CodedInputData.cpp b/Win32/MMKV/CodedInputData.cpp index a066f6d3..ef407fff 100644 --- a/Win32/MMKV/CodedInputData.cpp +++ b/Win32/MMKV/CodedInputData.cpp @@ -21,8 +21,8 @@ #include "CodedInputData.h" #include "MMKVLog.h" #include "PBUtility.h" -#include #include +#include using namespace std; diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index 8026e8e1..0425dc1f 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -38,8 +38,7 @@ static DWORD LockType2Flag(LockType lockType, bool tryLock) { } FileLock::FileLock(HANDLE fd) - : m_fd(fd), m_overLapped{0}, m_sharedLockCount(0), m_exclusiveLockCount(0) { -} + : m_fd(fd), m_overLapped{0}, m_sharedLockCount(0), m_exclusiveLockCount(0) {} bool FileLock::doLock(LockType lockType, bool tryLock) { bool unLockFirstIfNeeded = false; diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h index 888e64db..c69d6deb 100644 --- a/Win32/MMKV/InterProcessLock.h +++ b/Win32/MMKV/InterProcessLock.h @@ -21,8 +21,8 @@ #ifndef MMKV_INTERPROCESSLOCK_H #define MMKV_INTERPROCESSLOCK_H -#include #include "MMKVDef.h" +#include enum LockType { SharedLockType, diff --git a/Win32/MMKV/MMBuffer.h b/Win32/MMKV/MMBuffer.h index acc23e68..ab3c604d 100644 --- a/Win32/MMKV/MMBuffer.h +++ b/Win32/MMKV/MMBuffer.h @@ -21,8 +21,8 @@ #ifndef MMKV_MMBUFFER_H #define MMKV_MMBUFFER_H -#include #include "MMKVDef.h" +#include enum MMBufferCopyFlag : bool { MMBufferCopy = false, diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 74c9635c..ced54a48 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -42,37 +42,6 @@ using namespace std; -static int getpagesize(void) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - return system_info.dwPageSize; -} - -static int foo() { - OFSTRUCT of; - HANDLE file = (HANDLE) CreateFile(L"testmm", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file == (HANDLE) HFILE_ERROR) { - return -1; - } - SetFilePointer(file, getpagesize(), 0, FILE_BEGIN); - SetEndOfFile(file); - - auto mmFile = CreateFileMapping(file, nullptr, PAGE_READWRITE, 0, 0, nullptr); - if (!mmFile) { - return -2; - } - auto ptr = MapViewOfFile(mmFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (!ptr) { - return -3; - } - int value = 1024; - //memcpy(ptr, &value, sizeof(value)); - memcpy(&value, ptr, sizeof(value)); - return value; -} - static unordered_map *g_instanceDic; static ThreadLock g_instanceLock; static std::string g_rootDir; @@ -96,82 +65,18 @@ MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) : m_mmapID(mmapID) , m_path(mappedKVPathWithID(m_mmapID, mode)) , m_crcPath(crcPathWithID(m_mmapID, mode)) - , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE, (mode & MMKV_ASHMEM) ? MMAP_ASHMEM : MMAP_FILE) + , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE) , m_crypter(nullptr) - , m_fileLock(nullptr)// TODO:, m_fileLock(m_metaFile.getFd()) + , m_fileLock(nullptr) // TODO:, m_fileLock(m_metaFile.getFd()) , m_sharedProcessLock(&m_fileLock, SharedLockType) , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) - , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) - , m_isAshmem((mode & MMKV_ASHMEM) != 0) { + , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) { m_fd = -1; m_ptr = nullptr; m_size = 0; m_actualSize = 0; m_output = nullptr; - if (m_isAshmem) { - m_ashmemFile = new MmapedFile(m_mmapID, static_cast(size), MMAP_ASHMEM); - m_fd = m_ashmemFile->getFd(); - } else { - m_ashmemFile = nullptr; - } - - if (cryptKey && cryptKey->length() > 0) { - m_crypter = new AESCrypt((const unsigned char *) cryptKey->data(), cryptKey->length()); - } - - m_needLoadFromFile = true; - m_hasFullWriteback = false; - - m_crcDigest = 0; - - m_sharedProcessLock.m_enable = m_isInterProcess; - m_exclusiveProcessLock.m_enable = m_isInterProcess; - - // sensitive zone - { - SCOPEDLOCK(m_sharedProcessLock); - loadFromFile(); - } -} - -MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKey) - : m_mmapID(mmapID) - , m_path("") - , m_crcPath("") - , m_metaFile(ashmemMetaFD) - , m_crypter(nullptr) - , m_fileLock(nullptr)// TODO:, m_fileLock(m_metaFile.getFd()) - , m_sharedProcessLock(&m_fileLock, SharedLockType) - , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) - , m_isInterProcess(true) - , m_isAshmem(true) { - - // check mmapID with ashmemID - { - auto ashmemID = m_metaFile.getName(); - size_t pos = ashmemID.find_last_of('.'); - if (pos != string::npos) { - ashmemID.erase(pos, string::npos); - } - if (mmapID != ashmemID) { - MMKVWarning("mmapID[%s] != ashmem[%s]", mmapID.c_str(), ashmemID.c_str()); - } - } - m_path = string(ASHMEM_NAME_DEF) + "/" + m_mmapID; - m_crcPath = string(ASHMEM_NAME_DEF) + "/" + m_metaFile.getName(); - m_fd = ashmemFD; - m_ptr = nullptr; - m_size = 0; - m_actualSize = 0; - m_output = nullptr; - - if (m_isAshmem) { - m_ashmemFile = new MmapedFile(m_fd); - } else { - m_ashmemFile = nullptr; - } - if (cryptKey && cryptKey->length() > 0) { m_crypter = new AESCrypt((const unsigned char *) cryptKey->data(), cryptKey->length()); } @@ -194,10 +99,6 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe MMKV::~MMKV() { clearMemoryState(); - if (m_ashmemFile) { - delete m_ashmemFile; - m_ashmemFile = nullptr; - } if (m_crypter) { delete m_crypter; m_crypter = nullptr; @@ -247,24 +148,6 @@ MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, strin return kv; } -MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, string *cryptKey) { - - if (fd < 0) { - return nullptr; - } - SCOPEDLOCK(g_instanceLock); - - auto itr = g_instanceDic->find(mmapID); - if (itr != g_instanceDic->end()) { - MMKV *kv = itr->second; - kv->checkReSetCryptKey(fd, metaFD, cryptKey); - return kv; - } - auto kv = new MMKV(mmapID, fd, metaFD, cryptKey); - (*g_instanceDic)[mmapID] = kv; - return kv; -} - void MMKV::onExit() { SCOPEDLOCK(g_instanceLock); @@ -304,11 +187,6 @@ void decryptBuffer(AESCrypt &crypter, MMBuffer &inputBuffer) { } void MMKV::loadFromFile() { - if (m_isAshmem) { - loadFromAshmem(); - return; - } - m_metaInfo.read(m_metaFile.getMemory()); //m_fd = open(m_path.c_str(), O_RDWR | O_CREAT, S_IRWXU); @@ -328,8 +206,8 @@ void MMKV::loadFromFile() { MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, strerror(errno)); m_size = static_cast(st.st_size); - }*/ - zeroFillFile(m_fd, oldSize, m_size - oldSize); + } + zeroFillFile(m_fd, oldSize, m_size - oldSize);*/ } /*m_ptr = (char *) mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); if (m_ptr == MAP_FAILED) { @@ -393,56 +271,6 @@ void MMKV::loadFromFile() { m_needLoadFromFile = false; } -void MMKV::loadFromAshmem() { - m_metaInfo.read(m_metaFile.getMemory()); - - if (m_fd < 0 || !m_ashmemFile) { - MMKVError("ashmem file invalid %s, fd:%d", m_path.c_str(), m_fd); - } else { - m_size = m_ashmemFile->getFileSize(); - m_ptr = (char *) m_ashmemFile->getMemory(); - /*if (m_ptr != MAP_FAILED)*/ { - memcpy(&m_actualSize, m_ptr, Fixed32Size); - MMKVInfo("loading [%s] with %zu size in total, file size is %zu", m_mmapID.c_str(), - m_actualSize, m_size); - bool loaded = false; - if (m_actualSize > 0) { - if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { - if (checkFileCRCValid()) { - MMKVInfo("loading [%s] with crc %u sequence %u", m_mmapID.c_str(), - m_metaInfo.m_crcDigest, m_metaInfo.m_sequence); - MMBuffer inputBuffer(m_ptr + Fixed32Size, m_actualSize, MMBufferNoCopy); - if (m_crypter) { - decryptBuffer(*m_crypter, inputBuffer); - } - m_dic.clear(); - MiniPBCoder::decodeMap(m_dic, inputBuffer); - m_output = new CodedOutputData(m_ptr + Fixed32Size + m_actualSize, - m_size - Fixed32Size - m_actualSize); - loaded = true; - } - } - } - if (!loaded) { - SCOPEDLOCK(m_exclusiveProcessLock); - - if (m_actualSize > 0) { - writeAcutalSize(0); - } - m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); - recaculateCRCDigest(); - } - MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); - } - } - - if (!isFileValid()) { - MMKVWarning("[%s] ashmem not valid", m_mmapID.c_str()); - } - - m_needLoadFromFile = false; -} - // read from last m_position void MMKV::partialLoadFromFile() { m_metaInfo.read(m_metaFile.getMemory()); @@ -513,13 +341,9 @@ void MMKV::checkLoadData() { SCOPEDLOCK(m_sharedProcessLock); size_t fileSize = 0; - if (m_isAshmem) { - fileSize = m_size; - } else { - struct stat st = {0}; - if (fstat(m_fd, &st) != -1) { - fileSize = (size_t) st.st_size; - } + struct stat st = {0}; + if (fstat(m_fd, &st) != -1) { + fileSize = (size_t) st.st_size; } if (m_size != fileSize) { MMKVInfo("file size has changed [%s] from %zu to %zu", m_mmapID.c_str(), m_size, @@ -537,7 +361,7 @@ void MMKV::clearAll() { SCOPEDLOCK(m_lock); SCOPEDLOCK(m_exclusiveProcessLock); - if (m_needLoadFromFile && !m_isAshmem) { + if (m_needLoadFromFile) { removeFile(m_path.c_str()); loadFromFile(); return; @@ -588,8 +412,7 @@ void MMKV::clearMemoryState() { } m_output = nullptr; - if (!m_isAshmem) { - /*if (m_ptr && m_ptr != MAP_FAILED) { + /*if (m_ptr && m_ptr != MAP_FAILED) { if (munmap(m_ptr, m_size) != 0) { MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); } @@ -601,8 +424,7 @@ void MMKV::clearMemoryState() { MMKVError("fail to close [%s], %s", m_mmapID.c_str(), strerror(errno)); } }*/ - m_fd = -1; - } + m_fd = -1; m_size = 0; m_actualSize = 0; } @@ -620,10 +442,6 @@ void MMKV::close() { } void MMKV::trim() { - if (m_isAshmem) { - MMKVInfo("there's no way to trim ashmem MMKV:%s", m_mmapID.c_str()); - return; - } SCOPEDLOCK(m_lock); MMKVInfo("prepare to trim %s", m_mmapID.c_str()); @@ -684,28 +502,21 @@ bool MMKV::ensureMemorySize(size_t newSize) { static const int offset = pbFixed32Size(0); MMBuffer data = MiniPBCoder::encodeDataWithObject(m_dic); size_t lenNeeded = data.length() + offset + newSize; - if (m_isAshmem) { - if (lenNeeded > m_size) { - MMKVWarning("ashmem %s reach size limit:%zu, consider configure with larger size", - m_mmapID.c_str(), m_size); - return false; - } - } else { - size_t avgItemSize = lenNeeded / std::max(1, m_dic.size()); - size_t futureUsage = avgItemSize * std::max(8, (m_dic.size() + 1) / 2); - // 1. no space for a full rewrite, double it - // 2. or space is not large enough for future usage, double it to avoid frequently full rewrite - if (lenNeeded >= m_size || (lenNeeded + futureUsage) >= m_size) { - size_t oldSize = m_size; - do { - m_size *= 2; - } while (lenNeeded + futureUsage >= m_size); - MMKVInfo( - "extending [%s] file size from %zu to %zu, incoming size:%zu, futrue usage:%zu", - m_mmapID.c_str(), oldSize, m_size, newSize, futureUsage); - - // if we can't extend size, rollback to old state - /*if (ftruncate(m_fd, m_size) != 0) { + size_t avgItemSize = lenNeeded / std::max(1, m_dic.size()); + size_t futureUsage = avgItemSize * std::max(8, (m_dic.size() + 1) / 2); + // 1. no space for a full rewrite, double it + // 2. or space is not large enough for future usage, double it to avoid frequently full rewrite + if (lenNeeded >= m_size || (lenNeeded + futureUsage) >= m_size) { + size_t oldSize = m_size; + do { + m_size *= 2; + } while (lenNeeded + futureUsage >= m_size); + MMKVInfo( + "extending [%s] file size from %zu to %zu, incoming size:%zu, futrue usage:%zu", + m_mmapID.c_str(), oldSize, m_size, newSize, futureUsage); + + // if we can't extend size, rollback to old state + /*if (ftruncate(m_fd, m_size) != 0) { MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, strerror(errno)); m_size = oldSize; @@ -726,11 +537,10 @@ bool MMKV::ensureMemorySize(size_t newSize) { MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); }*/ - // check if we fail to make more space - if (!isFileValid()) { - MMKVWarning("[%s] file not valid", m_mmapID.c_str()); - return false; - } + // check if we fail to make more space + if (!isFileValid()) { + MMKVWarning("[%s] file not valid", m_mmapID.c_str()); + return false; } } @@ -966,15 +776,6 @@ void MMKV::checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey) { SCOPEDLOCK(m_lock); checkReSetCryptKey(cryptKey); - - /*if (m_isAshmem) { - if (m_fd != fd) { - ::close(fd); - } - if (m_metaFile.getFd() != metaFD) { - ::close(metaFD); - } - }*/ } bool MMKV::isFileValid() { @@ -1375,13 +1176,11 @@ static string encodeFilePath(const string &mmapID) { } static string mappedKVPathWithID(const string &mmapID, MMKVMode mode) { - return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) - : string(ASHMEM_NAME_DEF) + "/" + encodeFilePath(mmapID); + return g_rootDir + "/" + encodeFilePath(mmapID); } static string crcPathWithID(const string &mmapID, MMKVMode mode) { - return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) + ".crc" - : encodeFilePath(mmapID) + ".crc"; + return g_rootDir + "/" + encodeFilePath(mmapID) + ".crc"; } MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index ad0381fd..e43ee2ec 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -22,11 +22,11 @@ #define MMKV_MMKV_H #include "InterProcessLock.h" +#include "MMBuffer.h" #include "MMKVDef.h" #include "MMKVMetaInfo.hpp" #include "MmapedFile.h" #include "ThreadLock.h" -#include "MMBuffer.h" #include #include #include @@ -39,7 +39,6 @@ class AESCrypt; enum MMKVMode : uint32_t { MMKV_SINGLE_PROCESS = 0x1, MMKV_MULTI_PROCESS = 0x2, - MMKV_ASHMEM = 0x4, }; class MMKV_API MMKV { @@ -53,7 +52,6 @@ class MMKV_API MMKV { size_t m_size; size_t m_actualSize; CodedOutputData *m_output; - MmapedFile *m_ashmemFile; bool m_needLoadFromFile; bool m_hasFullWriteback; @@ -73,8 +71,6 @@ class MMKV_API MMKV { void partialLoadFromFile(); - void loadFromAshmem(); - void checkLoadData(); bool isFileValid(); @@ -112,11 +108,6 @@ class MMKV_API MMKV { MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr); - MMKV(const std::string &mmapID, - int ashmemFD, - int ashmemMetaFd, - std::string *cryptKey = nullptr); - ~MMKV(); static void initializeMMKV(const std::string &rootDir); @@ -131,23 +122,12 @@ class MMKV_API MMKV { MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr); - static MMKV *mmkvWithAshmemFD(const std::string &mmapID, - int fd, - int metaFD, - std::string *cryptKey = nullptr); - static void onExit(); const std::string &mmapID(); const bool m_isInterProcess; - const bool m_isAshmem; - - int ashmemFD() { return m_isAshmem ? m_fd : -1; } - - int ashmemMetaFD() { return m_isAshmem ? m_metaFile.getFd() : -1; } - std::string cryptKey(); // transform plain text into encrypted text diff --git a/Win32/MMKV/MMKVLog.h b/Win32/MMKV/MMKVLog.h index 073c6ccd..31c26920 100644 --- a/Win32/MMKV/MMKVLog.h +++ b/Win32/MMKV/MMKVLog.h @@ -21,9 +21,9 @@ #ifndef MMKV_MMKVLOG_H #define MMKV_MMKVLOG_H +#include #include #include -#include // enable logging #define ENABLE_MMKV_LOG @@ -32,15 +32,12 @@ #define APPNAME "MMKV" -#define MMKVError(format, ...) \ - ::printf(format, ##__VA_ARGS__) -#define MMKVWarning(format, ...) \ - ::printf(format, ##__VA_ARGS__) +#define MMKVError(format, ...) ::printf(format, ##__VA_ARGS__) +#define MMKVWarning(format, ...) ::printf(format, ##__VA_ARGS__) #define MMKVInfo(format, ...) ::printf(format, ##__VA_ARGS__) #ifndef NDEBUG -#define MMKVDebug(format, ...) \ - ::printf(format, ##__VA_ARGS__) +#define MMKVDebug(format, ...) ::printf(format, ##__VA_ARGS__) #else #define MMKVDebug(format, ...) \ {} diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index 08aa9276..a0449dc9 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -21,117 +21,87 @@ #include "MmapedFile.h" #include "MMBuffer.h" #include "MMKVLog.h" -#include -#include -//#include -//#include -#include -#include -//#include using namespace std; -const int DEFAULT_MMAP_SIZE = 4096; -//getpagesize(); - -MmapedFile::MmapedFile(const std::string &path, size_t size, bool fileType) - : m_name(path), m_fd(-1), m_segmentPtr(nullptr), m_segmentSize(0), m_fileType(fileType) { -/* if (m_fileType == MMAP_FILE) { - m_fd = open(m_name.c_str(), O_RDWR | O_CREAT, S_IRWXU); - if (m_fd < 0) { - MMKVError("fail to open:%s, %s", m_name.c_str(), strerror(errno)); - } else { - struct stat st = {}; - if (fstat(m_fd, &st) != -1) { - m_segmentSize = static_cast(st.st_size); - } - if (m_segmentSize < DEFAULT_MMAP_SIZE) { - m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); - if (ftruncate(m_fd, m_segmentSize) != 0 || !zeroFillFile(m_fd, 0, m_segmentSize)) { - MMKVError("fail to truncate [%s] to size %zu, %s", m_name.c_str(), - m_segmentSize, strerror(errno)); - close(m_fd); - m_fd = -1; - removeFile(m_name); - return; - } - } - m_segmentPtr = - (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); - if (m_segmentPtr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); - close(m_fd); - m_fd = -1; - m_segmentPtr = nullptr; - } - } - } else { - m_fd = open(ASHMEM_NAME_DEF, O_RDWR); - if (m_fd < 0) { - MMKVError("fail to open ashmem:%s, %s", m_name.c_str(), strerror(errno)); - } else { - if (ioctl(m_fd, ASHMEM_SET_NAME, m_name.c_str()) != 0) { - MMKVError("fail to set ashmem name:%s, %s", m_name.c_str(), strerror(errno)); - } else if (ioctl(m_fd, ASHMEM_SET_SIZE, size) != 0) { - MMKVError("fail to set ashmem:%s, size %d, %s", m_name.c_str(), size, - strerror(errno)); - } else { - m_segmentSize = static_cast(size); - m_segmentPtr = (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, - MAP_SHARED, m_fd, 0); - if (m_segmentPtr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); - m_segmentPtr = nullptr; - } else { - return; - } - } - close(m_fd); - m_fd = -1; - } - }*/ +const int DEFAULT_MMAP_SIZE = getpagesize(); + +std::wstring string2wstring(const std::string &str) { + auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); + wstring result; + result.resize(length); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], length); + return result; } -MmapedFile::MmapedFile(int ashmemFD) - : m_name(""), m_fd(ashmemFD), m_segmentPtr(nullptr), m_segmentSize(0), m_fileType(MMAP_ASHMEM) { -/* if (m_fd < 0) { - MMKVError("fd %d invalid", m_fd); +MmapedFile::MmapedFile(const std::string &path, size_t size) + : m_name(path), m_file(INVALID_HANDLE_VALUE), m_segmentPtr(nullptr), m_segmentSize(0) { + auto filename = string2wstring(m_name); + m_file = (HANDLE) CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (m_file == INVALID_HANDLE_VALUE) { + MMKVError("fail to open:%s, %d", m_name.c_str(), GetLastError()); } else { - char name[ASHMEM_NAME_LEN] = {0}; - if (ioctl(m_fd, ASHMEM_GET_NAME, name) != 0) { - MMKVError("fail to get ashmem name:%d, %s", m_fd, strerror(errno)); - } else { - m_name = string(name); - int size = ioctl(m_fd, ASHMEM_GET_SIZE, nullptr); - if (size < 0) { - MMKVError("fail to get ashmem size:%s, %s", m_name.c_str(), strerror(errno)); - } else { - m_segmentSize = static_cast(size); - MMKVInfo("ashmem verified, name:%s, size:%zu", m_name.c_str(), m_segmentSize); - m_segmentPtr = (char *) mmap(nullptr, m_segmentSize, PROT_READ | PROT_WRITE, - MAP_SHARED, m_fd, 0); - if (m_segmentPtr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_name.c_str(), strerror(errno)); - m_segmentPtr = nullptr; - } + LARGE_INTEGER filesize = {0}; + if (GetFileSizeEx(m_file, &filesize)) { + m_segmentSize = static_cast(filesize.QuadPart); + } + if (m_segmentSize < DEFAULT_MMAP_SIZE) { + m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); + if (ftruncate(m_file, m_segmentSize) != 0 || !zeroFillFile(m_file, 0, m_segmentSize)) { + MMKVError("fail to truncate [%s] to size %zu, %d", m_name.c_str(), m_segmentSize, + GetLastError()); + CloseHandle(m_file); + m_file = INVALID_HANDLE_VALUE; + removeFile(m_name); + return; } } - }*/ + m_fileMapping = CreateFileMapping(m_file, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!m_fileMapping) { + MMKVError("fail to CreateFileMapping [%s], %d", m_name.c_str(), GetLastError()); + CloseHandle(m_file); + m_file = INVALID_HANDLE_VALUE; + removeFile(m_name); + return; + } + m_segmentPtr = MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_segmentPtr) { + MMKVError("fail to MapViewOfFile [%s], %d", m_name.c_str(), GetLastError()); + CloseHandle(m_fileMapping); + m_fileMapping = NULL; + CloseHandle(m_file); + m_file = INVALID_HANDLE_VALUE; + removeFile(m_name); + return; + } + } } MmapedFile::~MmapedFile() { -/* if (m_segmentPtr != MAP_FAILED && m_segmentPtr != nullptr) { - munmap(m_segmentPtr, m_segmentSize); + if (m_segmentPtr) { + UnmapViewOfFile(m_segmentPtr); m_segmentPtr = nullptr; } - if (m_fd >= 0) { - close(m_fd); - m_fd = -1; - }*/ + if (m_fileMapping) { + CloseHandle(m_fileMapping); + m_fileMapping = NULL; + } + if (m_file != INVALID_HANDLE_VALUE) { + CloseHandle(m_file); + m_file = INVALID_HANDLE_VALUE; + } } #pragma mark - file +int getpagesize(void) { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwPageSize; +} + bool isFileExist(const string &nsFilePath) { if (nsFilePath.empty()) { return false; @@ -156,10 +126,10 @@ bool mkPath(char *path) { if (stat(path, &sb) != 0) { //if (errno != ENOENT || mkdir(path, 0777) != 0) { - MMKVWarning("%s", path); - return false; + MMKVWarning("%s", path); + return false; //} - //} else if (!S_ISDIR(sb.st_mode)) { + //} else if (!S_ISDIR(sb.st_mode)) { MMKVWarning("%s: %s", path, strerror(ENOTDIR)); return false; } @@ -181,7 +151,7 @@ bool removeFile(const string &nsFilePath) { MMBuffer *readWholeFile(const char *path) { MMBuffer *buffer = nullptr; -/* int fd = open(path, O_RDONLY); + /* int fd = open(path, O_RDONLY); if (fd >= 0) { auto fileLength = lseek(fd, 0, SEEK_END); if (fileLength > 0) { @@ -204,29 +174,48 @@ MMBuffer *readWholeFile(const char *path) { return buffer; } -bool zeroFillFile(int fd, size_t startPos, size_t size) { - if (fd < 0) { +bool zeroFillFile(HANDLE file, size_t startPos, size_t size) { + if (file == INVALID_HANDLE_VALUE) { return false; } - /* - if (lseek(fd, startPos, SEEK_SET) < 0) { - MMKVError("fail to lseek fd[%d], error:%s", fd, strerror(errno)); + + LARGE_INTEGER position; + position.QuadPart = startPos; + if (!SetFilePointerEx(file, position, nullptr, FILE_BEGIN) < 0) { + MMKVError("fail to lseek fd[%p], error:%d", file, GetLastError()); return false; } static const char zeros[4096] = {0}; while (size >= sizeof(zeros)) { - if (write(fd, zeros, sizeof(zeros)) < 0) { - MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno)); + DWORD bytesWritten = 0; + if (!WriteFile(file, zeros, sizeof(zeros), &bytesWritten, nullptr)) { + MMKVError("fail to write fd[%p], error:%d", file, GetLastError()); return false; } - size -= sizeof(zeros); + size -= bytesWritten; } if (size > 0) { - if (write(fd, zeros, size) < 0) { - MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno)); + DWORD bytesWritten = 0; + if (!WriteFile(file, zeros, size, &bytesWritten, nullptr)) { + MMKVError("fail to write fd[%p], error:%d", file, GetLastError()); return false; } - }*/ + } return true; } + +bool ftruncate(HANDLE file, size_t size) { + LARGE_INTEGER large; + large.QuadPart = size; + if (SetFilePointerEx(file, large, 0, FILE_BEGIN)) { + if (SetEndOfFile(file)) { + return true; + } + MMKVError("fail to SetEndOfFile:%d", GetLastError()); + return false; + } else { + MMKVError("fail to SetFilePointer:%d", GetLastError()); + return false; + } +} diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 3fa93cf8..2381be89 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -21,25 +21,15 @@ #ifndef MMKV_MMAPEDFILE_H #define MMKV_MMAPEDFILE_H +#include "MMKVDef.h" #include -//#include - -#define ASHMEM_NAME_LEN 256 -#define ASHMEM_NAME_DEF "/dev/ashmem" - -#define __ASHMEMIOC 0x77 -#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) -#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) -#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) -#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) - -enum : bool { MMAP_FILE = false, MMAP_ASHMEM = true }; extern const int DEFAULT_MMAP_SIZE; class MmapedFile { std::string m_name; - int m_fd; + HANDLE m_file; + HANDLE m_fileMapping; void *m_segmentPtr; size_t m_segmentSize; @@ -48,29 +38,27 @@ class MmapedFile { MmapedFile &operator=(const MmapedFile &other) = delete; public: - MmapedFile(const std::string &path, - size_t size = static_cast(DEFAULT_MMAP_SIZE), - bool fileType = MMAP_FILE); - MmapedFile(int ashmemFD); + MmapedFile(const std::string &path, size_t size = static_cast(DEFAULT_MMAP_SIZE)); ~MmapedFile(); - const bool m_fileType; - size_t getFileSize() { return m_segmentSize; } void *getMemory() { return m_segmentPtr; } std::string &getName() { return m_name; } - int getFd() { return m_fd; } + HANDLE getFd() { return m_file; } }; class MMBuffer; +extern int getpagesize(); +extern std::wstring string2wstring(const std::string &str); extern bool mkPath(char *path); extern bool isFileExist(const std::string &nsFilePath); extern bool removeFile(const std::string &nsFilePath); extern MMBuffer *readWholeFile(const char *path); -extern bool zeroFillFile(int fd, size_t startPos, size_t size); +extern bool zeroFillFile(HANDLE file, size_t startPos, size_t size); +extern bool ftruncate(HANDLE file, size_t size); #endif //MMKV_MMAPEDFILE_H diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index 043a2ffb..c359a7b6 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -21,7 +21,7 @@ #include "ThreadLock.h" #include "MMKVLog.h" -ThreadLock::ThreadLock() : m_lock {0} { +ThreadLock::ThreadLock() : m_lock{0} { // TODO: a better spin count? if (!InitializeCriticalSectionAndSpinCount(&m_lock, 1024)) { MMKVError("fail to init critical section:%d", GetLastError()); diff --git a/Win32/MMKV/dllmain.cpp b/Win32/MMKV/dllmain.cpp index fe91032b..cdf28879 100644 --- a/Win32/MMKV/dllmain.cpp +++ b/Win32/MMKV/dllmain.cpp @@ -1,19 +1,13 @@ // dllmain.cpp : Defines the entry point for the DLL application. #include "MMKVDef.h" -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; } return TRUE; } - diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index b1fd118f..2e99d7a8 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -1,9 +1,9 @@ // Win32Demo.cpp : This file contains the 'main' function. Program execution begins and ends there. // +#include "MMKV.h" #include "pch.h" #include -#include "MMKV.h" using namespace std; diff --git a/Win32/Win32Demo/pch.h b/Win32/Win32Demo/pch.h index b04e71e0..0ddf6ec2 100644 --- a/Win32/Win32Demo/pch.h +++ b/Win32/Win32Demo/pch.h @@ -1,4 +1,4 @@ -// Tips for Getting Started: +// Tips for Getting Started: // 1. Use the Solution Explorer window to add/manage files // 2. Use the Team Explorer window to connect to source control // 3. Use the Output window to see build output and other messages From acaddf3691fe703abf2fb166cf3db14cbfd2a84c Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 13 Dec 2018 16:10:55 +0800 Subject: [PATCH 06/57] file operation --- Win32/MMKV/MMKV.cpp | 4 +- Win32/MMKV/MmapedFile.cpp | 85 ++++++++++++++++++++++----------------- Win32/MMKV/MmapedFile.h | 4 +- 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index ced54a48..41903b57 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -1107,7 +1107,7 @@ bool MMKV::isFileValid(const std::string &mmapID) { } uint32_t crcFile = 0; - MMBuffer *data = readWholeFile(crcPath.c_str()); + MMBuffer *data = readWholeFile(crcPath); if (data) { MMKVMetaInfo metaInfo; metaInfo.read(data->getPtr()); @@ -1119,7 +1119,7 @@ bool MMKV::isFileValid(const std::string &mmapID) { const int offset = pbFixed32Size(0); size_t actualSize = 0; - MMBuffer *fileData = readWholeFile(kvPath.c_str()); + MMBuffer *fileData = readWholeFile(kvPath); if (fileData) { actualSize = CodedInputData(fileData->getPtr(), fileData->length()).readFixed32(); if (actualSize > fileData->length() - offset) { diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index a0449dc9..575726cf 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -106,71 +106,82 @@ bool isFileExist(const string &nsFilePath) { if (nsFilePath.empty()) { return false; } - - struct stat temp; - //return lstat(nsFilePath.c_str(), &temp) == 0; - return false; + auto path = string2wstring(nsFilePath); + auto attribute = GetFileAttributes(path.c_str()); + return (attribute != INVALID_FILE_ATTRIBUTES); } -bool mkPath(char *path) { - struct stat sb = {}; +bool mkPath(const std::string &str) { + auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); + wchar_t *path = new wchar_t[length]; + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, path, length); + bool done = false; - char *slash = path; + wchar_t *slash = path; while (!done) { - slash += strspn(slash, "/"); - slash += strcspn(slash, "/"); - - done = (*slash == '\0'); - *slash = '\0'; - - if (stat(path, &sb) != 0) { - //if (errno != ENOENT || mkdir(path, 0777) != 0) { - MMKVWarning("%s", path); - return false; - //} - //} else if (!S_ISDIR(sb.st_mode)) { - MMKVWarning("%s: %s", path, strerror(ENOTDIR)); + slash += wcsspn(slash, L"\\"); + slash += wcscspn(slash, L"\\"); + + done = (*slash == L'\0'); + *slash = L'\0'; + + auto attribute = GetFileAttributes(path); + if (attribute == INVALID_FILE_ATTRIBUTES) { + if (!CreateDirectory(path, nullptr)) { + MMKVError("fail to create dir:%s, %d", path, GetLastError()); + delete[] path; + return false; + } + } else if (!(attribute & FILE_ATTRIBUTE_DIRECTORY)) { + MMKVError("%s attribute:%d not a directry", path, attribute); + delete[] path; return false; } - *slash = '/'; + *slash = L'\\'; } - + delete[] path; return true; } bool removeFile(const string &nsFilePath) { - int ret = _unlink(nsFilePath.c_str()); - if (ret != 0) { - MMKVError("remove file failed. filePath=%s, err=%s", nsFilePath.c_str(), strerror(errno)); + auto path = string2wstring(nsFilePath); + if (!DeleteFile(path.c_str())) { + MMKVError("remove file failed. filePath=%s, %d", nsFilePath.c_str(), GetLastError()); return false; } return true; } -MMBuffer *readWholeFile(const char *path) { +MMBuffer *readWholeFile(const std::string &nsFilePath) { MMBuffer *buffer = nullptr; - /* int fd = open(path, O_RDONLY); - if (fd >= 0) { - auto fileLength = lseek(fd, 0, SEEK_END); + auto path = string2wstring(nsFilePath); + auto fd = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (fd != INVALID_HANDLE_VALUE) { + size_t fileLength = 0; + LARGE_INTEGER filesize = {0}; + if (!GetFileSizeEx(fd, &filesize)) { + fileLength = static_cast(filesize.QuadPart); + } if (fileLength > 0) { buffer = new MMBuffer(static_cast(fileLength)); - lseek(fd, 0, SEEK_SET); - auto readSize = read(fd, buffer->getPtr(), static_cast(fileLength)); - if (readSize != -1) { + SetFilePointer(fd, 0, 0, FILE_BEGIN); + DWORD readSize = 0; + if (ReadFile(fd, buffer->getPtr(), fileLength, &readSize, nullptr)) { //fileSize = readSize; } else { - MMKVWarning("fail to read %s: %s", path, strerror(errno)); - + MMKVWarning("fail to read %s: %d", path.c_str(), GetLastError()); delete buffer; buffer = nullptr; } } - close(fd); + CloseHandle(fd); } else { - MMKVWarning("fail to open %s: %s", path, strerror(errno)); - }*/ + MMKVWarning("fail to open %s: %d", path, GetLastError()); + } return buffer; } diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 2381be89..5138887c 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -54,10 +54,10 @@ class MMBuffer; extern int getpagesize(); extern std::wstring string2wstring(const std::string &str); -extern bool mkPath(char *path); +extern bool mkPath(const std::string &str); extern bool isFileExist(const std::string &nsFilePath); extern bool removeFile(const std::string &nsFilePath); -extern MMBuffer *readWholeFile(const char *path); +extern MMBuffer *readWholeFile(const std::string &nsFilePath); extern bool zeroFillFile(HANDLE file, size_t startPos, size_t size); extern bool ftruncate(HANDLE file, size_t size); From 33c87cc8228280c49d6ff611884c53ca01a394d0 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 13 Dec 2018 21:32:23 +0800 Subject: [PATCH 07/57] ThreadOnce --- Win32/MMKV/MMKV.cpp | 16 +++++----------- Win32/MMKV/ThreadLock.cpp | 25 +++++++++++++++++++++++++ Win32/MMKV/ThreadLock.h | 8 ++++++++ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 41903b57..e84b6f74 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -37,8 +37,6 @@ #include #include #include -#include -#include using namespace std; @@ -67,7 +65,7 @@ MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) , m_crcPath(crcPathWithID(m_mmapID, mode)) , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE) , m_crypter(nullptr) - , m_fileLock(nullptr) // TODO:, m_fileLock(m_metaFile.getFd()) + , m_fileLock(m_metaFile.getFd()) , m_sharedProcessLock(&m_fileLock, SharedLockType) , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) { @@ -113,15 +111,12 @@ void initialize() { g_instanceDic = new unordered_map; g_instanceLock = ThreadLock(); - //testAESCrypt(); - MMKVInfo("page size:%d", DEFAULT_MMAP_SIZE); } void MMKV::initializeMMKV(const std::string &rootDir) { - // TODO: do_once - //static pthread_once_t once_control = PTHREAD_ONCE_INIT; - //pthread_once(&once_control, initialize); + static volatile ThreadOnceToken onceToken = ThreadOnceUninitialized; + ThreadLock::ThreadOnce(onceToken, initialize); g_rootDir = rootDir; char *path = _strdup(g_rootDir.c_str()); @@ -1166,9 +1161,8 @@ static string encodeFilePath(const string &mmapID) { } } if (hasSpecialCharacter) { - // TODO: do_once - /*static pthread_once_t once_control = PTHREAD_ONCE_INIT; - pthread_once(&once_control, mkSpecialCharacterFileDirectory);*/ + static volatile ThreadOnceToken onceToken = ThreadOnceUninitialized; + ThreadLock::ThreadOnce(onceToken, mkSpecialCharacterFileDirectory); return string(SPECIAL_CHARACTER_DIRECTORY_NAME) + "/" + encodedID; } else { return mmapID; diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index c359a7b6..da6a9d91 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -47,3 +47,28 @@ bool ThreadLock::try_lock() { void ThreadLock::unlock() { LeaveCriticalSection(&m_lock); } + +void ThreadLock::ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback)(void)) { + if (!callback) { + return; + } + while (true) { + auto pre = (ThreadOnceToken) InterlockedCompareExchange( + (volatile LONG *) &onceToken, ThreadOnceInitializing, ThreadOnceUninitialized); + switch (pre) { + case ThreadOnceUninitialized: + callback(); + InterlockedExchange((volatile LONG *) &onceToken, ThreadOnceInitialized); + return; + case ThreadOnceInitializing: + // another thread is initializing, must wait. + Sleep(1); + break; + case ThreadOnceInitialized: + return; + default: + MMKVError("never happen:%ld", pre); + return; + } + } +} diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h index 8c017b27..0fff08ea 100644 --- a/Win32/MMKV/ThreadLock.h +++ b/Win32/MMKV/ThreadLock.h @@ -23,6 +23,12 @@ #include "MMKVDef.h" +enum ThreadOnceToken : LONG { + ThreadOnceUninitialized = 0, + ThreadOnceInitializing, + ThreadOnceInitialized +}; + class ThreadLock { private: CRITICAL_SECTION m_lock; @@ -34,6 +40,8 @@ class ThreadLock { void lock(); bool try_lock(); void unlock(); + + static void ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback)(void)); }; #endif //MMKV_THREADLOCK_H From a12ac92d3f42aa6ec1f7c1029fe3086ce9c7f3a6 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 17 Dec 2018 22:55:04 +0800 Subject: [PATCH 08/57] most mmap --- Win32/MMKV/MMKV.cpp | 243 +++++++++++++++++++------------------- Win32/MMKV/MMKV.h | 3 +- Win32/MMKV/MmapedFile.cpp | 30 +++-- Win32/MMKV/MmapedFile.h | 1 + Win32/MMKV/ThreadLock.cpp | 2 +- 5 files changed, 142 insertions(+), 137 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index e84b6f74..1f610398 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -69,7 +69,7 @@ MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) , m_sharedProcessLock(&m_fileLock, SharedLockType) , m_exclusiveProcessLock(&m_fileLock, ExclusiveLockType) , m_isInterProcess((mode & MMKV_MULTI_PROCESS) != 0) { - m_fd = -1; + m_fd = INVALID_HANDLE_VALUE; m_ptr = nullptr; m_size = 0; m_actualSize = 0; @@ -119,9 +119,7 @@ void MMKV::initializeMMKV(const std::string &rootDir) { ThreadLock::ThreadOnce(onceToken, initialize); g_rootDir = rootDir; - char *path = _strdup(g_rootDir.c_str()); - mkPath(path); - free(path); + mkPath(g_rootDir); MMKVInfo("root dir: %s", g_rootDir.c_str()); } @@ -184,78 +182,83 @@ void decryptBuffer(AESCrypt &crypter, MMBuffer &inputBuffer) { void MMKV::loadFromFile() { m_metaInfo.read(m_metaFile.getMemory()); - //m_fd = open(m_path.c_str(), O_RDWR | O_CREAT, S_IRWXU); - if (m_fd < 0) { - MMKVError("fail to open:%s, %s", m_path.c_str(), strerror(errno)); + auto filename = string2wstring(m_path); + m_fd = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, nullptr); + + if (m_fd == INVALID_HANDLE_VALUE) { + MMKVError("fail to open:%s, %d", m_path.c_str(), GetLastError()); } else { m_size = 0; - struct stat st = {0}; - if (fstat(m_fd, &st) != -1) { - m_size = static_cast(st.st_size); - } + getfilesize(m_fd, m_size); // round up to (n * pagesize) if (m_size < DEFAULT_MMAP_SIZE || (m_size % DEFAULT_MMAP_SIZE != 0)) { size_t oldSize = m_size; m_size = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE; - /*if (ftruncate(m_fd, m_size) != 0) { - MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, - strerror(errno)); - m_size = static_cast(st.st_size); + if (!ftruncate(m_fd, m_size)) { + MMKVError("fail to truncate [%s] to size %zu, %d", m_mmapID.c_str(), m_size, + GetLastError()); + m_size = oldSize; } - zeroFillFile(m_fd, oldSize, m_size - oldSize);*/ + zeroFillFile(m_fd, oldSize, m_size - oldSize); } - /*m_ptr = (char *) mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); - if (m_ptr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); - } else*/ - { - memcpy(&m_actualSize, m_ptr, Fixed32Size); - MMKVInfo("loading [%s] with %zu size in total, file size is %zu", m_mmapID.c_str(), - m_actualSize, m_size); - bool loadFromFile = false, needFullWriteback = false; - if (m_actualSize > 0) { - if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { - if (checkFileCRCValid()) { - loadFromFile = true; + m_fileMapping = CreateFileMapping(m_fd, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!m_fileMapping) { + MMKVError("fail to CreateFileMapping [%s], %d", m_mmapID.c_str(), GetLastError()); + } else { + m_ptr = static_cast(MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0)); + if (!m_ptr) { + MMKVError("fail to MapViewOfFile [%s], %d", m_mmapID.c_str(), GetLastError()); + } else { + memcpy(&m_actualSize, m_ptr, Fixed32Size); + MMKVInfo("loading [%s] with %zu size in total, file size is %zu", m_mmapID.c_str(), + m_actualSize, m_size); + bool loadFromFile = false, needFullWriteback = false; + if (m_actualSize > 0) { + if (m_actualSize < m_size && m_actualSize + Fixed32Size <= m_size) { + if (checkFileCRCValid()) { + loadFromFile = true; + } else { + auto strategic = onMMKVCRCCheckFail(m_mmapID); + if (strategic == OnErrorRecover) { + loadFromFile = true; + needFullWriteback = true; + } + } } else { - auto strategic = onMMKVCRCCheckFail(m_mmapID); + auto strategic = onMMKVFileLengthError(m_mmapID); if (strategic == OnErrorRecover) { loadFromFile = true; needFullWriteback = true; } } - } else { - auto strategic = onMMKVFileLengthError(m_mmapID); - if (strategic == OnErrorRecover) { - loadFromFile = true; - needFullWriteback = true; - } - } - } - if (loadFromFile) { - MMKVInfo("loading [%s] with crc %u sequence %u", m_mmapID.c_str(), - m_metaInfo.m_crcDigest, m_metaInfo.m_sequence); - MMBuffer inputBuffer(m_ptr + Fixed32Size, m_actualSize, MMBufferNoCopy); - if (m_crypter) { - decryptBuffer(*m_crypter, inputBuffer); - } - m_dic.clear(); - MiniPBCoder::decodeMap(m_dic, inputBuffer); - m_output = new CodedOutputData(m_ptr + Fixed32Size + m_actualSize, - m_size - Fixed32Size - m_actualSize); - if (needFullWriteback) { - fullWriteback(); } - } else { - SCOPEDLOCK(m_exclusiveProcessLock); + if (loadFromFile) { + MMKVInfo("loading [%s] with crc %u sequence %u", m_mmapID.c_str(), + m_metaInfo.m_crcDigest, m_metaInfo.m_sequence); + MMBuffer inputBuffer(m_ptr + Fixed32Size, m_actualSize, MMBufferNoCopy); + if (m_crypter) { + decryptBuffer(*m_crypter, inputBuffer); + } + m_dic.clear(); + MiniPBCoder::decodeMap(m_dic, inputBuffer); + m_output = new CodedOutputData(m_ptr + Fixed32Size + m_actualSize, + m_size - Fixed32Size - m_actualSize); + if (needFullWriteback) { + fullWriteback(); + } + } else { + SCOPEDLOCK(m_exclusiveProcessLock); - if (m_actualSize > 0) { - writeAcutalSize(0); + if (m_actualSize > 0) { + writeAcutalSize(0); + } + m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); + recaculateCRCDigest(); } - m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); - recaculateCRCDigest(); + MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); } - MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); } } @@ -336,10 +339,7 @@ void MMKV::checkLoadData() { SCOPEDLOCK(m_sharedProcessLock); size_t fileSize = 0; - struct stat st = {0}; - if (fstat(m_fd, &st) != -1) { - fileSize = (size_t) st.st_size; - } + getfilesize(m_fd, fileSize); if (m_size != fileSize) { MMKVInfo("file size has changed [%s] from %zu to %zu", m_mmapID.c_str(), m_size, fileSize); @@ -362,26 +362,22 @@ void MMKV::clearAll() { return; } - /*if (m_ptr && m_ptr != MAP_FAILED) { + if (m_ptr) { // for truncate size_t size = std::min(static_cast(DEFAULT_MMAP_SIZE), m_size); memset(m_ptr, 0, size); - if (msync(m_ptr, size, MS_SYNC) != 0) { - MMKVError("fail to msync [%s]:%s", m_mmapID.c_str(), strerror(errno)); + if (!FlushViewOfFile(m_ptr, size)) { + MMKVError("fail to FlushViewOfFile [%s]:%d", m_mmapID.c_str(), GetLastError()); } } - if (!m_isAshmem) { - if (m_fd >= 0) { - if (m_size != DEFAULT_MMAP_SIZE) { - MMKVInfo("truncating [%s] from %zu to %d", m_mmapID.c_str(), m_size, - DEFAULT_MMAP_SIZE); - if (ftruncate(m_fd, DEFAULT_MMAP_SIZE) != 0) { - MMKVError("fail to truncate [%s] to size %d, %s", m_mmapID.c_str(), - DEFAULT_MMAP_SIZE, strerror(errno)); - } + if (m_fd >= 0) { + if (m_size != DEFAULT_MMAP_SIZE) { + MMKVInfo("truncating [%s] from %zu to %d", m_mmapID.c_str(), m_size, DEFAULT_MMAP_SIZE); + if (!ftruncate(m_fd, DEFAULT_MMAP_SIZE)) { + MMKVError("fail to truncate [%s] to size %d", m_mmapID.c_str(), DEFAULT_MMAP_SIZE); } } - }*/ + } clearMemoryState(); loadFromFile(); @@ -407,19 +403,26 @@ void MMKV::clearMemoryState() { } m_output = nullptr; - /*if (m_ptr && m_ptr != MAP_FAILED) { - if (munmap(m_ptr, m_size) != 0) { - MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); - } + if (m_ptr) { + if (!UnmapViewOfFile(m_ptr)) { + MMKVError("fail to munmap [%s], %d", m_mmapID.c_str(), GetLastError()); } m_ptr = nullptr; + } - if (m_fd >= 0) { - if (::close(m_fd) != 0) { - MMKVError("fail to close [%s], %s", m_mmapID.c_str(), strerror(errno)); - } - }*/ - m_fd = -1; + if (m_fileMapping) { + if (!CloseHandle(m_fileMapping)) { + MMKVError("fail to CloseHandle [%s], %d", m_mmapID.c_str(), GetLastError()); + } + m_fileMapping = nullptr; + } + + if (m_fd != INVALID_HANDLE_VALUE) { + if (!CloseHandle(m_fd)) { + MMKVError("fail to close [%s], %d", m_mmapID.c_str(), GetLastError()); + } + m_fd = INVALID_HANDLE_VALUE; + } m_size = 0; m_actualSize = 0; } @@ -463,19 +466,18 @@ void MMKV::trim() { MMKVInfo("trimming %s from %zu to %zu", m_mmapID.c_str(), oldSize, m_size); - /*if (ftruncate(m_fd, m_size) != 0) { - MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, - strerror(errno)); + if (!ftruncate(m_fd, m_size)) { + MMKVError("fail to truncate [%s] to size %zu", m_mmapID.c_str(), m_size); m_size = oldSize; return; } - if (munmap(m_ptr, oldSize) != 0) { - MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); + if (!UnmapViewOfFile(m_ptr)) { + MMKVError("fail to munmap [%s], %d", m_mmapID.c_str(), GetLastError()); + } + m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_ptr) { + MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); } - m_ptr = (char *) mmap(m_ptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); - if (m_ptr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); - }*/ delete m_output; m_output = new CodedOutputData(m_ptr + pbFixed32Size(0), m_size - pbFixed32Size(0)); @@ -511,26 +513,24 @@ bool MMKV::ensureMemorySize(size_t newSize) { m_mmapID.c_str(), oldSize, m_size, newSize, futureUsage); // if we can't extend size, rollback to old state - /*if (ftruncate(m_fd, m_size) != 0) { - MMKVError("fail to truncate [%s] to size %zu, %s", m_mmapID.c_str(), m_size, - strerror(errno)); - m_size = oldSize; - return false; - } - if (!zeroFillFile(m_fd, oldSize, m_size - oldSize)) { - MMKVError("fail to zeroFile [%s] to size %zu, %s", m_mmapID.c_str(), m_size, - strerror(errno)); - m_size = oldSize; - return false; - } + if (!ftruncate(m_fd, m_size)) { + MMKVError("fail to truncate [%s] to size %zu", m_mmapID.c_str(), m_size); + m_size = oldSize; + return false; + } + if (!zeroFillFile(m_fd, oldSize, m_size - oldSize)) { + MMKVError("fail to zeroFile [%s] to size %zu", m_mmapID.c_str(), m_size); + m_size = oldSize; + return false; + } - if (munmap(m_ptr, oldSize) != 0) { - MMKVError("fail to munmap [%s], %s", m_mmapID.c_str(), strerror(errno)); - } - m_ptr = (char *) mmap(m_ptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0); - if (m_ptr == MAP_FAILED) { - MMKVError("fail to mmap [%s], %s", m_mmapID.c_str(), strerror(errno)); - }*/ + if (!UnmapViewOfFile(m_ptr)) { + MMKVError("fail to munmap [%s], %d", m_mmapID.c_str(), GetLastError()); + } + m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_ptr) { + MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); + } // check if we fail to make more space if (!isFileValid()) { @@ -538,7 +538,6 @@ bool MMKV::ensureMemorySize(size_t newSize) { return false; } } - if (m_crypter) { m_crypter->reset(); auto ptr = (unsigned char *) data.getPtr(); @@ -557,8 +556,7 @@ bool MMKV::ensureMemorySize(size_t newSize) { } void MMKV::writeAcutalSize(size_t actualSize) { - assert(m_ptr != 0); - //assert(m_ptr != MAP_FAILED); + assert(m_ptr != nullptr); memcpy(m_ptr, &actualSize, Fixed32Size); m_actualSize = actualSize; @@ -774,9 +772,9 @@ void MMKV::checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey) { } bool MMKV::isFileValid() { - /* if (m_fd >= 0 && m_size > 0 && m_output && m_ptr && m_ptr != MAP_FAILED) { + if (m_fd != INVALID_HANDLE_VALUE && m_fileMapping && m_size > 0 && m_output && m_ptr) { return true; - }*/ + } return false; } @@ -1085,9 +1083,9 @@ void MMKV::sync() { return; } SCOPEDLOCK(m_exclusiveProcessLock); - /*if (msync(m_ptr, m_size, MS_SYNC) != 0) { - MMKVError("fail to msync [%s]:%s", m_mmapID.c_str(), strerror(errno)); - }*/ + if (!FlushViewOfFile(m_ptr, m_size)) { + MMKVError("fail to FlushViewOfFile [%s]:%d", m_mmapID.c_str(), GetLastError()); + } } bool MMKV::isFileValid(const std::string &mmapID) { @@ -1133,9 +1131,8 @@ bool MMKV::isFileValid(const std::string &mmapID) { } static void mkSpecialCharacterFileDirectory() { - char *path = _strdup((g_rootDir + "/" + SPECIAL_CHARACTER_DIRECTORY_NAME).c_str()); + string path = g_rootDir + "/" + SPECIAL_CHARACTER_DIRECTORY_NAME; mkPath(path); - free(path); } static string md5(const string &value) { diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index e43ee2ec..23b052a4 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -47,7 +47,8 @@ class MMKV_API MMKV { std::string m_mmapID; std::string m_path; std::string m_crcPath; - int m_fd; + HANDLE m_fd; + HANDLE m_fileMapping; char *m_ptr; size_t m_size; size_t m_actualSize; diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index 575726cf..aa9b67e6 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -37,16 +37,13 @@ std::wstring string2wstring(const std::string &str) { MmapedFile::MmapedFile(const std::string &path, size_t size) : m_name(path), m_file(INVALID_HANDLE_VALUE), m_segmentPtr(nullptr), m_segmentSize(0) { auto filename = string2wstring(m_name); - m_file = (HANDLE) CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + m_file = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (m_file == INVALID_HANDLE_VALUE) { MMKVError("fail to open:%s, %d", m_name.c_str(), GetLastError()); } else { - LARGE_INTEGER filesize = {0}; - if (GetFileSizeEx(m_file, &filesize)) { - m_segmentSize = static_cast(filesize.QuadPart); - } + getfilesize(m_file, m_segmentSize); if (m_segmentSize < DEFAULT_MMAP_SIZE) { m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); if (ftruncate(m_file, m_segmentSize) != 0 || !zeroFillFile(m_file, 0, m_segmentSize)) { @@ -86,7 +83,7 @@ MmapedFile::~MmapedFile() { } if (m_fileMapping) { CloseHandle(m_fileMapping); - m_fileMapping = NULL; + m_fileMapping = nullptr; } if (m_file != INVALID_HANDLE_VALUE) { CloseHandle(m_file); @@ -162,10 +159,7 @@ MMBuffer *readWholeFile(const std::string &nsFilePath) { OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (fd != INVALID_HANDLE_VALUE) { size_t fileLength = 0; - LARGE_INTEGER filesize = {0}; - if (!GetFileSizeEx(fd, &filesize)) { - fileLength = static_cast(filesize.QuadPart); - } + getfilesize(fd, fileLength); if (fileLength > 0) { buffer = new MMBuffer(static_cast(fileLength)); SetFilePointer(fd, 0, 0, FILE_BEGIN); @@ -189,6 +183,9 @@ bool zeroFillFile(HANDLE file, size_t startPos, size_t size) { if (file == INVALID_HANDLE_VALUE) { return false; } + if (size == 0) { + return true; + } LARGE_INTEGER position; position.QuadPart = startPos; @@ -230,3 +227,12 @@ bool ftruncate(HANDLE file, size_t size) { return false; } } + +bool getfilesize(HANDLE file, size_t &size) { + LARGE_INTEGER filesize = {0}; + if (GetFileSizeEx(file, &filesize)) { + size = static_cast(filesize.QuadPart); + return true; + } + return false; +} diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 5138887c..8347237b 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -60,5 +60,6 @@ extern bool removeFile(const std::string &nsFilePath); extern MMBuffer *readWholeFile(const std::string &nsFilePath); extern bool zeroFillFile(HANDLE file, size_t startPos, size_t size); extern bool ftruncate(HANDLE file, size_t size); +extern bool getfilesize(HANDLE file, size_t &size); #endif //MMKV_MMAPEDFILE_H diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index da6a9d91..984014a4 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -61,7 +61,7 @@ void ThreadLock::ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback InterlockedExchange((volatile LONG *) &onceToken, ThreadOnceInitialized); return; case ThreadOnceInitializing: - // another thread is initializing, must wait. + // another thread is initializing, let's wait for 1ms. Sleep(1); break; case ThreadOnceInitialized: From e22aaeb0d8742c6792f9ee0b5105537d980de5f7 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 18 Dec 2018 16:31:21 +0800 Subject: [PATCH 09/57] crc32 for win32 --- Script/formatCode.py | 2 +- Win32/MMKV/InterProcessLock.cpp | 6 +- Win32/MMKV/MMKV.cpp | 42 ++-- Win32/MMKV/MMKV.vcxproj | 5 + Win32/MMKV/MMKV.vcxproj.filters | 15 ++ Win32/MMKV/MMKVLog.h | 1 - Win32/MMKV/MiniPBCoder.cpp | 4 +- Win32/MMKV/MmapedFile.cpp | 14 +- Win32/MMKV/crc32/Checksum.h | 32 +++ Win32/MMKV/crc32/zlib/crc32.c | 168 ++++++++++++++ Win32/MMKV/crc32/zlib/crc32.h | 48 ++++ Win32/MMKV/crc32/zlib/zconf.h | 380 ++++++++++++++++++++++++++++++++ Win32/MMKV/crc32/zlib/zutil.h | 29 +++ 13 files changed, 710 insertions(+), 36 deletions(-) create mode 100644 Win32/MMKV/crc32/Checksum.h create mode 100644 Win32/MMKV/crc32/zlib/crc32.c create mode 100644 Win32/MMKV/crc32/zlib/crc32.h create mode 100644 Win32/MMKV/crc32/zlib/zconf.h create mode 100644 Win32/MMKV/crc32/zlib/zutil.h diff --git a/Script/formatCode.py b/Script/formatCode.py index 365e9669..e34336de 100644 --- a/Script/formatCode.py +++ b/Script/formatCode.py @@ -6,7 +6,7 @@ path = os.getcwd() for root, dirs, files in os.walk(path): - if root.endswith("/aes") or root.endswith("/openssl") or (root.find("/build/generated/") != -1): + if root.endswith("/aes") or root.endswith("/openssl") or root.endswith("/zlib") or (root.find("/build/generated/") != -1): continue for name in files: if (name.endswith(".h") or name.endswith(".m") or name.endswith(".mm") or name.endswith(".hpp") or name.endswith(".cpp") or name.endswith(".java")): diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index 0425dc1f..2315a32c 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -71,13 +71,13 @@ bool FileLock::doLock(LockType lockType, bool tryLock) { // lets be gentleman: unlock my shared-lock to prevent deadlock auto ret = UnlockFileEx(m_fd, 0, 1, 0, &m_overLapped); if (!ret) { - MMKVError("fail to try unlock first fd=%d, error:%d", m_fd, GetLastError()); + MMKVError("fail to try unlock first fd=%p, error:%d", m_fd, GetLastError()); } } auto ret = LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped); if (!ret) { - MMKVError("fail to lock fd=%d, error:%d", m_fd, ret, GetLastError()); + MMKVError("fail to lock fd=%p, error:%d", m_fd, GetLastError()); if (lockType == SharedLockType) { m_sharedLockCount--; } else { @@ -144,7 +144,7 @@ bool FileLock::unlock(LockType lockType) { auto flag = LockType2Flag(lockType, false); auto ret = UnlockFileEx(m_fd, 0, 1, 0, &m_overLapped); if (!ret) { - MMKVError("fail to unlock fd=%d, error:%d", m_fd, GetLastError()); + MMKVError("fail to unlock fd=%p, error:%d", m_fd, GetLastError()); return false; } else { return true; diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 1f610398..7a5c2c20 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -33,6 +33,7 @@ #include "ScopedLock.hpp" #include "aes/AESCrypt.h" #include "aes/openssl/md5.h" +#include "crc32/Checksum.h" #include #include #include @@ -166,7 +167,7 @@ std::string MMKV::cryptKey() { return ""; } -#pragma mark - really dirty work +// really dirty work void decryptBuffer(AESCrypt &crypter, MMBuffer &inputBuffer) { size_t length = inputBuffer.length(); @@ -285,9 +286,8 @@ void MMKV::partialLoadFromFile() { MMBuffer inputBuffer(m_ptr + Fixed32Size + oldActualSize, bufferSize, MMBufferNoCopy); // incremental update crc digest - // TODO: crc32 - /*m_crcDigest = (uint32_t) crc32(m_crcDigest, (const uint8_t *) inputBuffer.getPtr(), - static_cast(inputBuffer.length()));*/ + m_crcDigest = (uint32_t) crc32(m_crcDigest, (const uint8_t *) inputBuffer.getPtr(), + inputBuffer.length()); if (m_crcDigest == m_metaInfo.m_crcDigest) { if (m_crypter) { decryptBuffer(*m_crypter, inputBuffer); @@ -778,42 +778,41 @@ bool MMKV::isFileValid() { return false; } -#pragma mark - crc +// crc // assuming m_ptr & m_size is set bool MMKV::checkFileCRCValid() { - /*if (m_ptr && m_ptr != MAP_FAILED) { + if (m_ptr) { constexpr int offset = pbFixed32Size(0); - m_crcDigest = - (uint32_t) crc32(0, (const uint8_t *) m_ptr + offset, (uint32_t) m_actualSize); + m_crcDigest = (uint32_t) crc32(0, (const uint8_t *) m_ptr + offset, m_actualSize); m_metaInfo.read(m_metaFile.getMemory()); if (m_crcDigest == m_metaInfo.m_crcDigest) { return true; } MMKVError("check crc [%s] fail, crc32:%u, m_crcDigest:%u", m_mmapID.c_str(), m_metaInfo.m_crcDigest, m_crcDigest); - }*/ + } return false; } void MMKV::recaculateCRCDigest() { - /*if (m_ptr && m_ptr != MAP_FAILED) { + if (m_ptr) { m_crcDigest = 0; constexpr int offset = pbFixed32Size(0); updateCRCDigest((const uint8_t *) m_ptr + offset, m_actualSize, IncreaseSequence); - }*/ + } } void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSequence) { if (!ptr) { return; } - //m_crcDigest = (uint32_t) crc32(m_crcDigest, ptr, (uint32_t) length); + m_crcDigest = (uint32_t) crc32(m_crcDigest, ptr, length); void *crcPtr = m_metaFile.getMemory(); - /*if (crcPtr == nullptr || crcPtr == MAP_FAILED) { + if (!crcPtr) { return; - }*/ + } m_metaInfo.m_crcDigest = m_crcDigest; if (increaseSequence) { @@ -825,7 +824,7 @@ void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSeque m_metaInfo.write(crcPtr); } -#pragma mark - set & get +// set & get bool MMKV::setStringForKey(const std::string &value, const std::string &key) { if (key.empty()) { @@ -1014,7 +1013,7 @@ bool MMKV::getVectorForKey(const std::string &key, std::vector &res return false; } -#pragma mark - enumerate +// enumerate bool MMKV::containsKey(const std::string &key) { SCOPEDLOCK(m_lock); @@ -1075,7 +1074,7 @@ void MMKV::removeValuesForKeys(const std::vector &arrKeys) { fullWriteback(); } -#pragma mark - file +// file void MMKV::sync() { SCOPEDLOCK(m_lock); @@ -1120,14 +1119,13 @@ bool MMKV::isFileValid(const std::string &mmapID) { return false; } - /*uint32_t crcDigest = (uint32_t) crc32(0, (const uint8_t *) fileData->getPtr() + offset, - (uint32_t) actualSize); + auto ptr = (const uint8_t *) fileData->getPtr() + offset; + auto crcDigest = (uint32_t) crc32(0, ptr, actualSize); delete fileData; - return crcFile == crcDigest;*/ - } else { - return false; + return crcFile == crcDigest; } + return false; } static void mkSpecialCharacterFileDirectory() { diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index c8c8eebc..abe086fe 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -157,6 +157,10 @@ + + + + @@ -180,6 +184,7 @@ + diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index 7742137d..7850d1dc 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -84,6 +84,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -134,5 +146,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Win32/MMKV/MMKVLog.h b/Win32/MMKV/MMKVLog.h index 31c26920..b68f2c8f 100644 --- a/Win32/MMKV/MMKVLog.h +++ b/Win32/MMKV/MMKVLog.h @@ -23,7 +23,6 @@ #include #include -#include // enable logging #define ENABLE_MMKV_LOG diff --git a/Win32/MMKV/MiniPBCoder.cpp b/Win32/MMKV/MiniPBCoder.cpp index d1544b41..7a805160 100644 --- a/Win32/MMKV/MiniPBCoder.cpp +++ b/Win32/MMKV/MiniPBCoder.cpp @@ -60,7 +60,7 @@ MiniPBCoder::MiniPBCoder(const MMBuffer *inputBuffer) : MiniPBCoder() { new CodedInputData(m_inputBuffer->getPtr(), static_cast(m_inputBuffer->length())); } -#pragma mark - encode +// encode // write object using prepared m_encodeItems[] void MiniPBCoder::writeRootObject() { @@ -227,7 +227,7 @@ MMBuffer MiniPBCoder::getEncodeData(const unordered_map &map) return std::move(*m_outputBuffer); } -#pragma mark - decode +// decode string MiniPBCoder::decodeOneString() { return m_inputData->readString(); diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index aa9b67e6..ae6a6b05 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -46,7 +46,7 @@ MmapedFile::MmapedFile(const std::string &path, size_t size) getfilesize(m_file, m_segmentSize); if (m_segmentSize < DEFAULT_MMAP_SIZE) { m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); - if (ftruncate(m_file, m_segmentSize) != 0 || !zeroFillFile(m_file, 0, m_segmentSize)) { + if (!ftruncate(m_file, m_segmentSize) || !zeroFillFile(m_file, 0, m_segmentSize)) { MMKVError("fail to truncate [%s] to size %zu, %d", m_name.c_str(), m_segmentSize, GetLastError()); CloseHandle(m_file); @@ -91,7 +91,7 @@ MmapedFile::~MmapedFile() { } } -#pragma mark - file +// file int getpagesize(void) { SYSTEM_INFO system_info; @@ -126,12 +126,12 @@ bool mkPath(const std::string &str) { auto attribute = GetFileAttributes(path); if (attribute == INVALID_FILE_ATTRIBUTES) { if (!CreateDirectory(path, nullptr)) { - MMKVError("fail to create dir:%s, %d", path, GetLastError()); + MMKVError("fail to create dir:%s, %d", str.c_str(), GetLastError()); delete[] path; return false; } } else if (!(attribute & FILE_ATTRIBUTE_DIRECTORY)) { - MMKVError("%s attribute:%d not a directry", path, attribute); + MMKVError("%s attribute:%d not a directry", str.c_str(), attribute); delete[] path; return false; } @@ -167,14 +167,14 @@ MMBuffer *readWholeFile(const std::string &nsFilePath) { if (ReadFile(fd, buffer->getPtr(), fileLength, &readSize, nullptr)) { //fileSize = readSize; } else { - MMKVWarning("fail to read %s: %d", path.c_str(), GetLastError()); + MMKVWarning("fail to read %s: %d", nsFilePath.c_str(), GetLastError()); delete buffer; buffer = nullptr; } } CloseHandle(fd); } else { - MMKVWarning("fail to open %s: %d", path, GetLastError()); + MMKVWarning("fail to open %s: %d", nsFilePath.c_str(), GetLastError()); } return buffer; } @@ -189,7 +189,7 @@ bool zeroFillFile(HANDLE file, size_t startPos, size_t size) { LARGE_INTEGER position; position.QuadPart = startPos; - if (!SetFilePointerEx(file, position, nullptr, FILE_BEGIN) < 0) { + if (!SetFilePointerEx(file, position, nullptr, FILE_BEGIN)) { MMKVError("fail to lseek fd[%p], error:%d", file, GetLastError()); return false; } diff --git a/Win32/MMKV/crc32/Checksum.h b/Win32/MMKV/crc32/Checksum.h new file mode 100644 index 00000000..e21554d8 --- /dev/null +++ b/Win32/MMKV/crc32/Checksum.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#pragma once +#include "zlib/zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, z_size_t len)); + +#ifdef __cplusplus +} +#endif diff --git a/Win32/MMKV/crc32/zlib/crc32.c b/Win32/MMKV/crc32/zlib/crc32.c new file mode 100644 index 00000000..04a4271b --- /dev/null +++ b/Win32/MMKV/crc32/zlib/crc32.c @@ -0,0 +1,168 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ +# define TBLS 1 + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + +#include "crc32.h" + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + if (buf == Z_NULL) return 0UL; + + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + return crc32_z(crc, buf, len); +} + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/Win32/MMKV/crc32/zlib/crc32.h b/Win32/MMKV/crc32/zlib/crc32.h new file mode 100644 index 00000000..26df3d49 --- /dev/null +++ b/Win32/MMKV/crc32/zlib/crc32.h @@ -0,0 +1,48 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = { + {0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, + 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, + 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, + 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, + 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, + 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, + 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, + 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, + 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, + 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, + 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, + 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, + 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, + 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, + 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, + 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, + 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, + 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, + 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, + 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, + 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, + 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, + 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, + 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, + 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, + 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, + 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, + 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, + 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, + 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, + 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, + 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, + 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, + 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, + 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL}}; diff --git a/Win32/MMKV/crc32/zlib/zconf.h b/Win32/MMKV/crc32/zlib/zconf.h new file mode 100644 index 00000000..de7c4351 --- /dev/null +++ b/Win32/MMKV/crc32/zlib/zconf.h @@ -0,0 +1,380 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +#define Z_SOLO +#define Z_NEED_DICT 2 + +#if defined(__MSDOS__) && !defined(MSDOS) +#define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +#define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +#define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +#ifndef WIN32 +#define WIN32 +#endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +#if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +#ifndef SYS16BIT +#define SYS16BIT +#endif +#endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +#define MAXSEG_64K +#endif +#ifdef MSDOS +#define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +#ifndef STDC +#define STDC +#endif +#if __STDC_VERSION__ >= 199901L +#ifndef STDC99 +#define STDC99 +#endif +#endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +#define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +#define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +#define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +#define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +#define STDC +#endif + +#ifndef STDC +#ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +#define const /* note: need a more gentle solution here */ +#endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +#define z_const const +#else +#define z_const +#endif + +#ifdef Z_SOLO +typedef unsigned long z_size_t; +#else +#define z_longlong long long +#if defined(NO_SIZE_T) +typedef unsigned NO_SIZE_T z_size_t; +#elif defined(STDC) +#include +typedef size_t z_size_t; +#else +typedef unsigned long z_size_t; +#endif +#undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +#ifdef MAXSEG_64K +#define MAX_MEM_LEVEL 8 +#else +#define MAX_MEM_LEVEL 9 +#endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +#define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + +/* Type declarations */ + +#ifndef OF /* function prototypes */ +#ifdef STDC +#define OF(args) args +#else +#define OF(args) () +#endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +#define Z_ARG(args) args +#else +#define Z_ARG(args) () +#endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +#if defined(M_I86SM) || defined(M_I86MM) +/* MSC small or medium model */ +#define SMALL_MEDIUM +#ifdef _MSC_VER +#define FAR _far +#else +#define FAR far +#endif +#endif +#if (defined(__SMALL__) || defined(__MEDIUM__)) +/* Turbo C small or medium model */ +#define SMALL_MEDIUM +#ifdef __BORLANDC__ +#define FAR _far +#else +#define FAR far +#endif +#endif +#endif + +#if defined(WINDOWS) || defined(WIN32) +/* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +#ifdef ZLIB_DLL +#if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +#ifdef ZLIB_INTERNAL +#define ZEXTERN extern __declspec(dllexport) +#else +#define ZEXTERN extern __declspec(dllimport) +#endif +#endif +#endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +#ifdef ZLIB_WINAPI +#ifdef FAR +#undef FAR +#endif +#include +/* No need for _export, use ZLIB.DEF instead. */ +/* For complete Windows compatibility, use WINAPI, not __stdcall. */ +#define ZEXPORT WINAPI +#ifdef WIN32 +#define ZEXPORTVA WINAPIV +#else +#define ZEXPORTVA FAR CDECL +#endif +#endif +#endif + +#if defined(__BEOS__) +#ifdef ZLIB_DLL +#ifdef ZLIB_INTERNAL +#define ZEXPORT __declspec(dllexport) +#define ZEXPORTVA __declspec(dllexport) +#else +#define ZEXPORT __declspec(dllimport) +#define ZEXPORTVA __declspec(dllimport) +#endif +#endif +#endif + +#ifndef ZEXTERN +#define ZEXTERN extern +#endif +#ifndef ZEXPORT +#define ZEXPORT +#endif +#ifndef ZEXPORTVA +#define ZEXPORTVA +#endif + +#ifndef FAR +#define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM +/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +#define Bytef Byte FAR +#else +typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC +typedef void const *voidpc; +typedef void FAR *voidpf; +typedef void *voidp; +#else +typedef Byte const *voidpc; +typedef Byte FAR *voidpf; +typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +#include +#if (UINT_MAX == 0xffffffffUL) +#define Z_U4 unsigned +#elif (ULONG_MAX == 0xffffffffUL) +#define Z_U4 unsigned long +#elif (USHRT_MAX == 0xffffffffUL) +#define Z_U4 unsigned short +#endif +#endif + +#ifdef Z_U4 +typedef Z_U4 z_crc_t; +#else +typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +#define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +#define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +#ifndef Z_SOLO +#include /* for off_t */ +#endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +#ifndef Z_SOLO +#include /* for va_list */ +#endif +#endif + +#ifdef _WIN32 +#ifndef Z_SOLO +#include /* for wchar_t */ +#endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +#undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +#define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +#include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +#ifdef VMS +#include /* for off_t */ +#endif +#ifndef z_off_t +#define z_off_t off_t +#endif +#endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE - 0 +#define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +#define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS - 0 == 64 && defined(Z_LFS64) +#define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +#define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +#define z_off64_t off64_t +#else +#if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +#define z_off64_t __int64 +#else +#define z_off64_t z_off_t +#endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +#pragma map(deflateInit_, "DEIN") +#pragma map(deflateInit2_, "DEIN2") +#pragma map(deflateEnd, "DEEND") +#pragma map(deflateBound, "DEBND") +#pragma map(inflateInit_, "ININ") +#pragma map(inflateInit2_, "ININ2") +#pragma map(inflateEnd, "INEND") +#pragma map(inflateSync, "INSY") +#pragma map(inflateSetDictionary, "INSEDI") +#pragma map(compressBound, "CMBND") +#pragma map(inflate_table, "INTABL") +#pragma map(inflate_fast, "INFA") +#pragma map(inflate_copyright, "INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/Win32/MMKV/crc32/zlib/zutil.h b/Win32/MMKV/crc32/zlib/zutil.h new file mode 100644 index 00000000..c1c1e89a --- /dev/null +++ b/Win32/MMKV/crc32/zlib/zutil.h @@ -0,0 +1,29 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#include "zconf.h" + +#ifdef Z_SOLO +typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +#define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +#endif /* ZUTIL_H */ From 94a5928588cb4901847f10a1446ea22e7ba79286 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 18 Dec 2018 18:28:07 +0800 Subject: [PATCH 10/57] use std::wstring to reprecent file path --- Win32/MMKV/MMKV.cpp | 43 ++++++++++++++++---------------- Win32/MMKV/MMKV.h | 6 ++--- Win32/MMKV/MMKVLog.h | 10 +++++--- Win32/MMKV/MmapedFile.cpp | 46 +++++++++++++++-------------------- Win32/MMKV/MmapedFile.h | 14 +++++------ Win32/Win32Demo/Win32Demo.cpp | 22 +++++++++++++++-- 6 files changed, 77 insertions(+), 64 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 7a5c2c20..9c36bfaa 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -43,17 +43,17 @@ using namespace std; static unordered_map *g_instanceDic; static ThreadLock g_instanceLock; -static std::string g_rootDir; +static std::wstring g_rootDir; #define DEFAULT_MMAP_ID "mmkv.default" -#define SPECIAL_CHARACTER_DIRECTORY_NAME "specialCharacter" +#define SPECIAL_CHARACTER_DIRECTORY_NAME L"specialCharacter" constexpr uint32_t Fixed32Size = pbFixed32Size(0); -static string mappedKVPathWithID(const string &mmapID, MMKVMode mode); -static string crcPathWithID(const string &mmapID, MMKVMode mode); +static wstring mappedKVPathWithID(const string &mmapID, MMKVMode mode); +static wstring crcPathWithID(const string &mmapID, MMKVMode mode); static void mkSpecialCharacterFileDirectory(); static string md5(const string &value); -static string encodeFilePath(const string &mmapID); +static wstring encodeFilePath(const string &mmapID); enum : bool { KeepSequence = false, @@ -115,14 +115,14 @@ void initialize() { MMKVInfo("page size:%d", DEFAULT_MMAP_SIZE); } -void MMKV::initializeMMKV(const std::string &rootDir) { +void MMKV::initializeMMKV(const std::wstring &rootDir) { static volatile ThreadOnceToken onceToken = ThreadOnceUninitialized; ThreadLock::ThreadOnce(onceToken, initialize); g_rootDir = rootDir; mkPath(g_rootDir); - MMKVInfo("root dir: %s", g_rootDir.c_str()); + MMKVInfo("root dir: %ws", g_rootDir.c_str()); } MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) { @@ -183,13 +183,12 @@ void decryptBuffer(AESCrypt &crypter, MMBuffer &inputBuffer) { void MMKV::loadFromFile() { m_metaInfo.read(m_metaFile.getMemory()); - auto filename = string2wstring(m_path); - m_fd = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, + m_fd = CreateFile(m_path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (m_fd == INVALID_HANDLE_VALUE) { - MMKVError("fail to open:%s, %d", m_path.c_str(), GetLastError()); + MMKVError("fail to open:%ws, %d", m_path.c_str(), GetLastError()); } else { m_size = 0; getfilesize(m_fd, m_size); @@ -357,7 +356,7 @@ void MMKV::clearAll() { SCOPEDLOCK(m_exclusiveProcessLock); if (m_needLoadFromFile) { - removeFile(m_path.c_str()); + removeFile(m_path); loadFromFile(); return; } @@ -1088,13 +1087,13 @@ void MMKV::sync() { } bool MMKV::isFileValid(const std::string &mmapID) { - string kvPath = mappedKVPathWithID(mmapID, MMKV_SINGLE_PROCESS); + auto kvPath = mappedKVPathWithID(mmapID, MMKV_SINGLE_PROCESS); if (!isFileExist(kvPath)) { return true; } - string crcPath = crcPathWithID(mmapID, MMKV_SINGLE_PROCESS); - if (!isFileExist(crcPath.c_str())) { + auto crcPath = crcPathWithID(mmapID, MMKV_SINGLE_PROCESS); + if (!isFileExist(crcPath)) { return false; } @@ -1129,7 +1128,7 @@ bool MMKV::isFileValid(const std::string &mmapID) { } static void mkSpecialCharacterFileDirectory() { - string path = g_rootDir + "/" + SPECIAL_CHARACTER_DIRECTORY_NAME; + wstring path = g_rootDir + L"/" + SPECIAL_CHARACTER_DIRECTORY_NAME; mkPath(path); } @@ -1144,7 +1143,7 @@ static string md5(const string &value) { return buf; } -static string encodeFilePath(const string &mmapID) { +static wstring encodeFilePath(const string &mmapID) { const char *specialCharacters = "\\/:*?\"<>|"; string encodedID; bool hasSpecialCharacter = false; @@ -1158,18 +1157,18 @@ static string encodeFilePath(const string &mmapID) { if (hasSpecialCharacter) { static volatile ThreadOnceToken onceToken = ThreadOnceUninitialized; ThreadLock::ThreadOnce(onceToken, mkSpecialCharacterFileDirectory); - return string(SPECIAL_CHARACTER_DIRECTORY_NAME) + "/" + encodedID; + return wstring(SPECIAL_CHARACTER_DIRECTORY_NAME) + L"/" + string2wstring(encodedID); } else { - return mmapID; + return string2wstring(mmapID); } } -static string mappedKVPathWithID(const string &mmapID, MMKVMode mode) { - return g_rootDir + "/" + encodeFilePath(mmapID); +static wstring mappedKVPathWithID(const string &mmapID, MMKVMode mode) { + return g_rootDir + L"/" + encodeFilePath(mmapID); } -static string crcPathWithID(const string &mmapID, MMKVMode mode) { - return g_rootDir + "/" + encodeFilePath(mmapID) + ".crc"; +static wstring crcPathWithID(const string &mmapID, MMKVMode mode) { + return g_rootDir + L"/" + encodeFilePath(mmapID) + L".crc"; } MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 23b052a4..ba83a022 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -45,8 +45,8 @@ class MMKV_API MMKV { // TODO: avoid warning "needs to have dll-interface to be used by clients of class" std::unordered_map m_dic; std::string m_mmapID; - std::string m_path; - std::string m_crcPath; + std::wstring m_path; + std::wstring m_crcPath; HANDLE m_fd; HANDLE m_fileMapping; char *m_ptr; @@ -111,7 +111,7 @@ class MMKV_API MMKV { ~MMKV(); - static void initializeMMKV(const std::string &rootDir); + static void initializeMMKV(const std::wstring &rootDir); // a generic purpose instance static MMKV *defaultMMKV(MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr); diff --git a/Win32/MMKV/MMKVLog.h b/Win32/MMKV/MMKVLog.h index b68f2c8f..87390e3a 100644 --- a/Win32/MMKV/MMKVLog.h +++ b/Win32/MMKV/MMKVLog.h @@ -31,12 +31,14 @@ #define APPNAME "MMKV" -#define MMKVError(format, ...) ::printf(format, ##__VA_ARGS__) -#define MMKVWarning(format, ...) ::printf(format, ##__VA_ARGS__) -#define MMKVInfo(format, ...) ::printf(format, ##__VA_ARGS__) +#define __NEW_LINE "\n" + +#define MMKVError(format, ...) ::printf(format __NEW_LINE, ##__VA_ARGS__) +#define MMKVWarning(format, ...) ::printf(format __NEW_LINE, ##__VA_ARGS__) +#define MMKVInfo(format, ...) ::printf(format __NEW_LINE, ##__VA_ARGS__) #ifndef NDEBUG -#define MMKVDebug(format, ...) ::printf(format, ##__VA_ARGS__) +#define MMKVDebug(format, ...) ::printf(format __NEW_LINE, ##__VA_ARGS__) #else #define MMKVDebug(format, ...) \ {} diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index ae6a6b05..b1585634 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -34,20 +34,19 @@ std::wstring string2wstring(const std::string &str) { return result; } -MmapedFile::MmapedFile(const std::string &path, size_t size) +MmapedFile::MmapedFile(const std::wstring &path, size_t size) : m_name(path), m_file(INVALID_HANDLE_VALUE), m_segmentPtr(nullptr), m_segmentSize(0) { - auto filename = string2wstring(m_name); - m_file = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, + m_file = CreateFile(m_name.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (m_file == INVALID_HANDLE_VALUE) { - MMKVError("fail to open:%s, %d", m_name.c_str(), GetLastError()); + MMKVError("fail to open:%ws, %d", m_name.c_str(), GetLastError()); } else { getfilesize(m_file, m_segmentSize); if (m_segmentSize < DEFAULT_MMAP_SIZE) { m_segmentSize = static_cast(DEFAULT_MMAP_SIZE); if (!ftruncate(m_file, m_segmentSize) || !zeroFillFile(m_file, 0, m_segmentSize)) { - MMKVError("fail to truncate [%s] to size %zu, %d", m_name.c_str(), m_segmentSize, + MMKVError("fail to truncate [%ws] to size %zu, %d", m_name.c_str(), m_segmentSize, GetLastError()); CloseHandle(m_file); m_file = INVALID_HANDLE_VALUE; @@ -57,7 +56,7 @@ MmapedFile::MmapedFile(const std::string &path, size_t size) } m_fileMapping = CreateFileMapping(m_file, nullptr, PAGE_READWRITE, 0, 0, nullptr); if (!m_fileMapping) { - MMKVError("fail to CreateFileMapping [%s], %d", m_name.c_str(), GetLastError()); + MMKVError("fail to CreateFileMapping [%ws], %d", m_name.c_str(), GetLastError()); CloseHandle(m_file); m_file = INVALID_HANDLE_VALUE; removeFile(m_name); @@ -65,7 +64,7 @@ MmapedFile::MmapedFile(const std::string &path, size_t size) } m_segmentPtr = MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (!m_segmentPtr) { - MMKVError("fail to MapViewOfFile [%s], %d", m_name.c_str(), GetLastError()); + MMKVError("fail to MapViewOfFile [%ws], %d", m_name.c_str(), GetLastError()); CloseHandle(m_fileMapping); m_fileMapping = NULL; CloseHandle(m_file); @@ -99,19 +98,16 @@ int getpagesize(void) { return system_info.dwPageSize; } -bool isFileExist(const string &nsFilePath) { +bool isFileExist(const wstring &nsFilePath) { if (nsFilePath.empty()) { return false; } - auto path = string2wstring(nsFilePath); - auto attribute = GetFileAttributes(path.c_str()); + auto attribute = GetFileAttributes(nsFilePath.c_str()); return (attribute != INVALID_FILE_ATTRIBUTES); } -bool mkPath(const std::string &str) { - auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); - wchar_t *path = new wchar_t[length]; - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, path, length); +bool mkPath(const std::wstring &str) { + wchar_t *path = _wcsdup(str.c_str()); bool done = false; wchar_t *slash = path; @@ -126,35 +122,33 @@ bool mkPath(const std::string &str) { auto attribute = GetFileAttributes(path); if (attribute == INVALID_FILE_ATTRIBUTES) { if (!CreateDirectory(path, nullptr)) { - MMKVError("fail to create dir:%s, %d", str.c_str(), GetLastError()); + MMKVError("fail to create dir:%ws, %d", str.c_str(), GetLastError()); delete[] path; return false; } } else if (!(attribute & FILE_ATTRIBUTE_DIRECTORY)) { - MMKVError("%s attribute:%d not a directry", str.c_str(), attribute); + MMKVError("%ws attribute:%d not a directry", str.c_str(), attribute); delete[] path; return false; } *slash = L'\\'; } - delete[] path; + free(path); return true; } -bool removeFile(const string &nsFilePath) { - auto path = string2wstring(nsFilePath); - if (!DeleteFile(path.c_str())) { - MMKVError("remove file failed. filePath=%s, %d", nsFilePath.c_str(), GetLastError()); +bool removeFile(const wstring &nsFilePath) { + if (!DeleteFile(nsFilePath.c_str())) { + MMKVError("remove file failed. filePath=%ws, %d", nsFilePath.c_str(), GetLastError()); return false; } return true; } -MMBuffer *readWholeFile(const std::string &nsFilePath) { +MMBuffer *readWholeFile(const std::wstring &nsFilePath) { MMBuffer *buffer = nullptr; - auto path = string2wstring(nsFilePath); - auto fd = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, + auto fd = CreateFile(nsFilePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (fd != INVALID_HANDLE_VALUE) { @@ -167,14 +161,14 @@ MMBuffer *readWholeFile(const std::string &nsFilePath) { if (ReadFile(fd, buffer->getPtr(), fileLength, &readSize, nullptr)) { //fileSize = readSize; } else { - MMKVWarning("fail to read %s: %d", nsFilePath.c_str(), GetLastError()); + MMKVWarning("fail to read %ws: %d", nsFilePath.c_str(), GetLastError()); delete buffer; buffer = nullptr; } } CloseHandle(fd); } else { - MMKVWarning("fail to open %s: %d", nsFilePath.c_str(), GetLastError()); + MMKVWarning("fail to open %ws: %d", nsFilePath.c_str(), GetLastError()); } return buffer; } diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 8347237b..8fae8d33 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -27,7 +27,7 @@ extern const int DEFAULT_MMAP_SIZE; class MmapedFile { - std::string m_name; + std::wstring m_name; HANDLE m_file; HANDLE m_fileMapping; void *m_segmentPtr; @@ -38,14 +38,14 @@ class MmapedFile { MmapedFile &operator=(const MmapedFile &other) = delete; public: - MmapedFile(const std::string &path, size_t size = static_cast(DEFAULT_MMAP_SIZE)); + MmapedFile(const std::wstring &path, size_t size = static_cast(DEFAULT_MMAP_SIZE)); ~MmapedFile(); size_t getFileSize() { return m_segmentSize; } void *getMemory() { return m_segmentPtr; } - std::string &getName() { return m_name; } + std::wstring &getName() { return m_name; } HANDLE getFd() { return m_file; } }; @@ -54,10 +54,10 @@ class MMBuffer; extern int getpagesize(); extern std::wstring string2wstring(const std::string &str); -extern bool mkPath(const std::string &str); -extern bool isFileExist(const std::string &nsFilePath); -extern bool removeFile(const std::string &nsFilePath); -extern MMBuffer *readWholeFile(const std::string &nsFilePath); +extern bool mkPath(const std::wstring &str); +extern bool isFileExist(const std::wstring &nsFilePath); +extern bool removeFile(const std::wstring &nsFilePath); +extern MMBuffer *readWholeFile(const std::wstring &nsFilePath); extern bool zeroFillFile(HANDLE file, size_t startPos, size_t size); extern bool ftruncate(HANDLE file, size_t size); extern bool getfilesize(HANDLE file, size_t &size); diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 2e99d7a8..138196dc 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -4,12 +4,30 @@ #include "MMKV.h" #include "pch.h" #include +#include using namespace std; +wstring getAppDataRoaming(const wstring &company, const wstring &appName) { + wchar_t roaming[MAX_PATH] = {0}; + auto size = GetEnvironmentVariable(L"appdata", roaming, MAX_PATH); + if (size >= MAX_PATH || size == 0) { + cout << "fail to get %appdata%: " << GetLastError() << endl; + return L""; + } else { + wstring result(roaming, size); + result += L"\\" + company; + result += L"\\" + appName; + return result; + } +} + int main() { - MMKV::initializeMMKV(""); - cout << "Hello World!\n"; + locale::global(locale("")); + wcout.imbue(locale("")); + + wstring rootDir = getAppDataRoaming(L"Tencent", L"΢-MMKV"); + MMKV::initializeMMKV(rootDir); } // Run program: Ctrl + F5 or Debug > Start Without Debugging menu From 2580152c0037d3d89faba7bcdff4703efae0bed9 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 18 Dec 2018 21:51:20 +0800 Subject: [PATCH 11/57] almost work on bool --- Win32/MMKV/MMKV.cpp | 4 ++-- Win32/MMKV/MmapedFile.cpp | 7 ++++--- Win32/Win32Demo/Win32Demo.cpp | 4 ++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 9c36bfaa..bc48f4bd 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -1164,11 +1164,11 @@ static wstring encodeFilePath(const string &mmapID) { } static wstring mappedKVPathWithID(const string &mmapID, MMKVMode mode) { - return g_rootDir + L"/" + encodeFilePath(mmapID); + return g_rootDir + L"\\" + encodeFilePath(mmapID); } static wstring crcPathWithID(const string &mmapID, MMKVMode mode) { - return g_rootDir + L"/" + encodeFilePath(mmapID) + L".crc"; + return g_rootDir + L"\\" + encodeFilePath(mmapID) + L".crc"; } MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index b1585634..9531bb9e 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -28,9 +28,10 @@ const int DEFAULT_MMAP_SIZE = getpagesize(); std::wstring string2wstring(const std::string &str) { auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); - wstring result; - result.resize(length); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], length); + auto buffer = new wchar_t[length]; + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, length); + wstring result(buffer); + delete[] buffer; return result; } diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 138196dc..496157a2 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -28,6 +28,10 @@ int main() { wstring rootDir = getAppDataRoaming(L"Tencent", L"΢-MMKV"); MMKV::initializeMMKV(rootDir); + + auto mmkv = MMKV::defaultMMKV(); + //mmkv->setBool(true, "bool"); + cout << "bool = " << mmkv->getBoolForKey("bool") << endl; } // Run program: Ctrl + F5 or Debug > Start Without Debugging menu From 07cdeb78d6a6e539388323cf977716d73b336b09 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 11:31:38 +0800 Subject: [PATCH 12/57] works on single process --- Win32/MMKV/CodedInputData.cpp | 8 ++++++ Win32/MMKV/CodedInputData.h | 4 +++ Win32/MMKV/CodedOutputData.cpp | 8 ++++++ Win32/MMKV/CodedOutputData.h | 4 +++ Win32/MMKV/MMKV.cpp | 50 ++++++++++++++++++++++++++++++++++ Win32/MMKV/MMKV.h | 8 ++++++ Win32/MMKV/PBUtility.h | 8 ++++++ Win32/Win32Demo/Win32Demo.cpp | 42 ++++++++++++++++++++++++++-- 8 files changed, 130 insertions(+), 2 deletions(-) diff --git a/Win32/MMKV/CodedInputData.cpp b/Win32/MMKV/CodedInputData.cpp index ef407fff..078fa8e3 100644 --- a/Win32/MMKV/CodedInputData.cpp +++ b/Win32/MMKV/CodedInputData.cpp @@ -59,10 +59,18 @@ int64_t CodedInputData::readInt64() { return 0; } +uint64_t CodedInputData::readUInt64() { + return readInt64(); +} + int32_t CodedInputData::readInt32() { return this->readRawVarint32(); } +uint32_t CodedInputData::readUInt32() { + return this->readRawVarint32(); +} + int32_t CodedInputData::readFixed32() { return this->readRawLittleEndian32(); } diff --git a/Win32/MMKV/CodedInputData.h b/Win32/MMKV/CodedInputData.h index bc7c7a6e..f19b90d7 100644 --- a/Win32/MMKV/CodedInputData.h +++ b/Win32/MMKV/CodedInputData.h @@ -53,8 +53,12 @@ class CodedInputData { int64_t readInt64(); + uint64_t readUInt64(); + int32_t readInt32(); + uint32_t readUInt32(); + int32_t readFixed32(); std::string readString(); diff --git a/Win32/MMKV/CodedOutputData.cpp b/Win32/MMKV/CodedOutputData.cpp index 94e3e6f3..40876935 100644 --- a/Win32/MMKV/CodedOutputData.cpp +++ b/Win32/MMKV/CodedOutputData.cpp @@ -47,6 +47,10 @@ void CodedOutputData::writeInt64(int64_t value) { this->writeRawVarint64(value); } +void CodedOutputData::writeUInt64(uint64_t value) { + this->writeRawVarint64(value); +} + void CodedOutputData::writeInt32(int32_t value) { if (value >= 0) { this->writeRawVarint32(value); @@ -55,6 +59,10 @@ void CodedOutputData::writeInt32(int32_t value) { } } +void CodedOutputData::writeUInt32(uint32_t value) { + this->writeRawVarint32(value); +} + void CodedOutputData::writeBool(bool value) { this->writeRawByte(static_cast(value ? 1 : 0)); } diff --git a/Win32/MMKV/CodedOutputData.h b/Win32/MMKV/CodedOutputData.h index c6a1a854..9da2b57d 100644 --- a/Win32/MMKV/CodedOutputData.h +++ b/Win32/MMKV/CodedOutputData.h @@ -57,8 +57,12 @@ class CodedOutputData { void writeInt64(int64_t value); + void writeUInt64(uint64_t value); + void writeInt32(int32_t value); + void writeUInt32(uint32_t value); + void writeBool(bool value); void writeString(const std::string &value); diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index bc48f4bd..8d2febba 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -865,6 +865,18 @@ bool MMKV::setInt32(int32_t value, const std::string &key) { return setDataForKey(std::move(data), key); } +bool MMKV::setUInt32(uint32_t value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbUInt32Size(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeUInt32(value); + + return setDataForKey(std::move(data), key); +} + bool MMKV::setInt64(int64_t value, const std::string &key) { if (key.empty()) { return false; @@ -877,6 +889,18 @@ bool MMKV::setInt64(int64_t value, const std::string &key) { return setDataForKey(std::move(data), key); } +bool MMKV::setUInt64(uint64_t value, const std::string &key) { + if (key.empty()) { + return false; + } + size_t size = pbUInt64Size(value); + MMBuffer data(size); + CodedOutputData output(data.getPtr(), size); + output.writeUInt64(value); + + return setDataForKey(std::move(data), key); +} + bool MMKV::setFloat(float value, const std::string &key) { if (key.empty()) { return false; @@ -960,6 +984,19 @@ int32_t MMKV::getInt32ForKey(const std::string &key, int32_t defaultValue) { return defaultValue; } +uint32_t MMKV::getUInt32ForKey(const std::string &key, uint32_t defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readUInt32(); + } + return defaultValue; +} + int64_t MMKV::getInt64ForKey(const std::string &key, int64_t defaultValue) { if (key.empty()) { return defaultValue; @@ -973,6 +1010,19 @@ int64_t MMKV::getInt64ForKey(const std::string &key, int64_t defaultValue) { return defaultValue; } +uint64_t MMKV::getUInt64ForKey(const std::string &key, uint64_t defaultValue) { + if (key.empty()) { + return defaultValue; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + if (data.length() > 0) { + CodedInputData input(data.getPtr(), data.length()); + return input.readUInt64(); + } + return defaultValue; +} + float MMKV::getFloatForKey(const std::string &key, float defaultValue) { if (key.empty()) { return defaultValue; diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index ba83a022..9cc4ca37 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -148,8 +148,12 @@ class MMKV_API MMKV { bool setInt32(int32_t value, const std::string &key); + bool setUInt32(uint32_t value, const std::string &key); + bool setInt64(int64_t value, const std::string &key); + bool setUInt64(uint64_t value, const std::string &key); + bool setFloat(float value, const std::string &key); bool setDouble(double value, const std::string &key); @@ -164,8 +168,12 @@ class MMKV_API MMKV { int32_t getInt32ForKey(const std::string &key, int32_t defaultValue = 0); + uint32_t getUInt32ForKey(const std::string &key, uint32_t defaultValue = 0); + int64_t getInt64ForKey(const std::string &key, int64_t defaultValue = 0); + uint64_t getUInt64ForKey(const std::string &key, uint64_t defaultValue = 0); + float getFloatForKey(const std::string &key, float defaultValue = 0); double getDoubleForKey(const std::string &key, double defaultValue = 0); diff --git a/Win32/MMKV/PBUtility.h b/Win32/MMKV/PBUtility.h index 96910a98..1dca7fe5 100644 --- a/Win32/MMKV/PBUtility.h +++ b/Win32/MMKV/PBUtility.h @@ -118,4 +118,12 @@ static inline uint32_t pbInt32Size(int32_t value) { } } +static inline int32_t pbUInt32Size(uint32_t value) { + return pbRawVarint32Size(value); +} + +static inline int32_t pbUInt64Size(uint64_t value) { + return pbInt64Size(value); +} + #endif //MMKV_PBUTILITY_H diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 496157a2..c1bc4a61 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -1,6 +1,8 @@ // Win32Demo.cpp : This file contains the 'main' function. Program execution begins and ends there. // +#define NOMINMAX // undefine max/min + #include "MMKV.h" #include "pch.h" #include @@ -22,6 +24,43 @@ wstring getAppDataRoaming(const wstring &company, const wstring &appName) { } } +void functionalTest(MMKV *mmkv, bool decodeOnly) { + if (!decodeOnly) { + mmkv->setBool(true, "bool"); + } + cout << "bool = " << mmkv->getBoolForKey("bool") << endl; + + if (!decodeOnly) { + mmkv->setInt32(1024, "int32"); + } + cout << "int32 = " << mmkv->getInt32ForKey("int32") << endl; + + if (!decodeOnly) { + mmkv->setUInt32(numeric_limits::max(), "uint32"); + } + cout << "uint32 = " << mmkv->getUInt32ForKey("uint32") << endl; + + if (!decodeOnly) { + mmkv->setInt64(numeric_limits::min(), "int64"); + } + cout << "int64 = " << mmkv->getInt64ForKey("int64") << endl; + + if (!decodeOnly) { + mmkv->setUInt64(numeric_limits::max(), "uint64"); + } + cout << "uint64 = " << mmkv->getUInt64ForKey("uint64") << endl; + + if (!decodeOnly) { + mmkv->setFloat(3.14f, "float"); + } + cout << "float = " << mmkv->getFloatForKey("float") << endl; + + if (!decodeOnly) { + mmkv->setDouble(numeric_limits::max(), "double"); + } + cout << "double = " << mmkv->getDoubleForKey("double") << endl; +} + int main() { locale::global(locale("")); wcout.imbue(locale("")); @@ -30,8 +69,7 @@ int main() { MMKV::initializeMMKV(rootDir); auto mmkv = MMKV::defaultMMKV(); - //mmkv->setBool(true, "bool"); - cout << "bool = " << mmkv->getBoolForKey("bool") << endl; + functionalTest(mmkv, false); } // Run program: Ctrl + F5 or Debug > Start Without Debugging menu From 0ebb32a86ce35ffb5a8226ce6c02c1397dda1367 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 16:55:28 +0800 Subject: [PATCH 13/57] works on threads --- Win32/MMKV/MMKV.cpp | 31 +++++++++--- Win32/MMKV/MMKV.h | 5 +- Win32/MMKV/MmapedFile.h | 2 +- Win32/Win32Demo/Win32Demo.cpp | 92 ++++++++++++++++++++++++++++++----- Win32/Win32Demo/pch.cpp | 20 +++++++- Win32/Win32Demo/pch.h | 26 +++++++--- 6 files changed, 145 insertions(+), 31 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 8d2febba..894555f5 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -257,7 +257,8 @@ void MMKV::loadFromFile() { m_output = new CodedOutputData(m_ptr + Fixed32Size, m_size - Fixed32Size); recaculateCRCDigest(); } - MMKVInfo("loaded [%s] with %zu values", m_mmapID.c_str(), m_dic.size()); + MMKVInfo("loaded [%s] with %zu values InterProcess:%d", m_mmapID.c_str(), + m_dic.size(), m_isInterProcess); } } } @@ -473,9 +474,17 @@ void MMKV::trim() { if (!UnmapViewOfFile(m_ptr)) { MMKVError("fail to munmap [%s], %d", m_mmapID.c_str(), GetLastError()); } - m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (!m_ptr) { - MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); + m_ptr = nullptr; + + CloseHandle(m_fileMapping); + m_fileMapping = CreateFileMapping(m_fd, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!m_fileMapping) { + MMKVError("fail to CreateFileMapping [%s], %d", m_mmapID.c_str(), GetLastError()); + } else { + m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_ptr) { + MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); + } } delete m_output; @@ -526,9 +535,17 @@ bool MMKV::ensureMemorySize(size_t newSize) { if (!UnmapViewOfFile(m_ptr)) { MMKVError("fail to munmap [%s], %d", m_mmapID.c_str(), GetLastError()); } - m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (!m_ptr) { - MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); + m_ptr = nullptr; + + CloseHandle(m_fileMapping); + m_fileMapping = CreateFileMapping(m_fd, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!m_fileMapping) { + MMKVError("fail to CreateFileMapping [%s], %d", m_mmapID.c_str(), GetLastError()); + } else { + m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_ptr) { + MMKVError("fail to mmap [%s], %d", m_mmapID.c_str(), GetLastError()); + } } // check if we fail to make more space diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 9cc4ca37..9181a6bb 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -100,7 +100,6 @@ class MMKV_API MMKV { // just forbid it for possibly misuse MMKV(const MMKV &other) = delete; - MMKV &operator=(const MMKV &other) = delete; public: @@ -213,8 +212,8 @@ class MMKV_API MMKV { static bool isFileValid(const std::string &mmapID); - void lock() { m_exclusiveProcessLock.lock(); } - void unlock() { m_exclusiveProcessLock.unlock(); } + void lock() { m_lock.lock(); } + void unlock() { m_lock.unlock(); } bool try_lock() { return m_exclusiveProcessLock.try_lock(); } }; diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 8fae8d33..2818c195 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -24,7 +24,7 @@ #include "MMKVDef.h" #include -extern const int DEFAULT_MMAP_SIZE; +extern MMKV_API const int DEFAULT_MMAP_SIZE; class MmapedFile { std::wstring m_name; diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index c1bc4a61..be94f3a8 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -1,5 +1,22 @@ -// Win32Demo.cpp : This file contains the 'main' function. Program execution begins and ends there. -// +/* + * 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. + */ #define NOMINMAX // undefine max/min @@ -59,26 +76,77 @@ void functionalTest(MMKV *mmkv, bool decodeOnly) { mmkv->setDouble(numeric_limits::max(), "double"); } cout << "double = " << mmkv->getDoubleForKey("double") << endl; + + if (!decodeOnly) { + mmkv->setStringForKey("Hello, MMKV-΢ for Win32 ", "string"); + } + string result; + mmkv->getStringForKey("string", result); + cout << "string = " << result << endl; +} + +constexpr auto keyCount = 10000; +constexpr auto threadCount = 10; +static const string threadMMKVID = "thread_test"; +vector arrIntKeys; +vector arrStringKeys; + +DWORD WINAPI threadFunction(LPVOID lpParam) { + auto threadIndex = (size_t) lpParam; + auto mmkv = MMKV::mmkvWithID(threadMMKVID, 0, MMKV_MULTI_PROCESS); + mmkv->lock(); + cout << "thread " << threadIndex << " starts" << endl; + mmkv->unlock(); + + auto segmentCount = keyCount / threadCount; + auto startIndex = segmentCount * threadIndex; + for (auto i = startIndex; i < startIndex + segmentCount; i++) { + mmkv->setInt32(i, arrIntKeys[i]); + mmkv->setStringForKey("str-" + i, arrStringKeys[i]); + } + + mmkv->lock(); + cout << "thread " << threadIndex << " ends" << endl; + mmkv->unlock(); + return 0; +} + +void threadTest() { + + HANDLE threadHandles[threadCount] = {0}; + for (size_t i = 0; i < threadCount; i++) { + threadHandles[i] = CreateThread(nullptr, 0, threadFunction, (LPVOID) i, 0, nullptr); + } + WaitForMultipleObjects(threadCount, threadHandles, true, INFINITE); + + auto mmkv = MMKV::mmkvWithID(threadMMKVID, 0, MMKV_MULTI_PROCESS); + cout << "total count " << mmkv->count() << endl; +} + +void brutleTest() { + auto mmkv = MMKV::mmkvWithID(threadMMKVID); + for (size_t i = 0; i < keyCount; i++) { + mmkv->setInt32(i, arrIntKeys[i]); + mmkv->setStringForKey("str-" + i, arrStringKeys[i]); + } } int main() { locale::global(locale("")); wcout.imbue(locale("")); + srand(GetTickCount()); wstring rootDir = getAppDataRoaming(L"Tencent", L"΢-MMKV"); MMKV::initializeMMKV(rootDir); auto mmkv = MMKV::defaultMMKV(); functionalTest(mmkv, false); -} -// Run program: Ctrl + F5 or Debug > Start Without Debugging menu -// Debug program: F5 or Debug > Start Debugging menu + for (size_t i = 0; i < keyCount; i++) { + arrIntKeys.push_back("int-" + to_string(i)); + arrStringKeys.push_back("string-" + to_string(i)); + } -// Tips for Getting Started: -// 1. Use the Solution Explorer window to add/manage files -// 2. Use the Team Explorer window to connect to source control -// 3. Use the Output window to see build output and other messages -// 4. Use the Error List window to view errors -// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project -// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file + threadTest(); + //brutleTest(); +} diff --git a/Win32/Win32Demo/pch.cpp b/Win32/Win32Demo/pch.cpp index 3a3d12b5..be78810c 100644 --- a/Win32/Win32Demo/pch.cpp +++ b/Win32/Win32Demo/pch.cpp @@ -1,4 +1,22 @@ -// pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed +/* + * 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 "pch.h" diff --git a/Win32/Win32Demo/pch.h b/Win32/Win32Demo/pch.h index 0ddf6ec2..643b383c 100644 --- a/Win32/Win32Demo/pch.h +++ b/Win32/Win32Demo/pch.h @@ -1,10 +1,22 @@ -// Tips for Getting Started: -// 1. Use the Solution Explorer window to add/manage files -// 2. Use the Team Explorer window to connect to source control -// 3. Use the Output window to see build output and other messages -// 4. Use the Error List window to view errors -// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project -// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file +/* + * 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. + */ #ifndef PCH_H #define PCH_H From 7eed6ac43c31bfcd179b0ea867ca2b6200134c18 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 18:40:52 +0800 Subject: [PATCH 14/57] works on multi-process --- Win32/MMKV/MMKV.h | 4 +- Win32/Win32.sln | 14 ++ Win32/Win32Demo/Win32Demo.cpp | 72 ++++++-- Win32/Win32Demo/Win32Demo.vcxproj | 4 +- Win32/Win32Demo/pch.h | 2 +- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 86 +++++++++ .../Win32DemoProcess/Win32DemoProcess.vcxproj | 174 ++++++++++++++++++ .../Win32DemoProcess.vcxproj.filters | 30 +++ Win32/Win32DemoProcess/pch.cpp | 21 +++ Win32/Win32DemoProcess/pch.h | 26 +++ 10 files changed, 415 insertions(+), 18 deletions(-) create mode 100644 Win32/Win32DemoProcess/Win32DemoProcess.cpp create mode 100644 Win32/Win32DemoProcess/Win32DemoProcess.vcxproj create mode 100644 Win32/Win32DemoProcess/Win32DemoProcess.vcxproj.filters create mode 100644 Win32/Win32DemoProcess/pch.cpp create mode 100644 Win32/Win32DemoProcess/pch.h diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 9181a6bb..416594ae 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -212,8 +212,8 @@ class MMKV_API MMKV { static bool isFileValid(const std::string &mmapID); - void lock() { m_lock.lock(); } - void unlock() { m_lock.unlock(); } + void lock() { m_exclusiveProcessLock.lock(); } + void unlock() { m_exclusiveProcessLock.unlock(); } bool try_lock() { return m_exclusiveProcessLock.try_lock(); } }; diff --git a/Win32/Win32.sln b/Win32/Win32.sln index 6ea80da7..2b4f8168 100644 --- a/Win32/Win32.sln +++ b/Win32/Win32.sln @@ -5,11 +5,17 @@ VisualStudioVersion = 15.0.28307.136 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win32Demo", "Win32Demo\Win32Demo.vcxproj", "{532303C4-38D9-45D3-B925-18056C66CD01}" ProjectSection(ProjectDependencies) = postProject + {86D6C605-81F3-407B-A766-690EDF4CD346} = {86D6C605-81F3-407B-A766-690EDF4CD346} {9D4250EF-E8D6-4652-B738-3D4B2E982126} = {9D4250EF-E8D6-4652-B738-3D4B2E982126} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMKV", "MMKV\MMKV.vcxproj", "{9D4250EF-E8D6-4652-B738-3D4B2E982126}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win32DemoProcess", "Win32DemoProcess\Win32DemoProcess.vcxproj", "{86D6C605-81F3-407B-A766-690EDF4CD346}" + ProjectSection(ProjectDependencies) = postProject + {9D4250EF-E8D6-4652-B738-3D4B2E982126} = {9D4250EF-E8D6-4652-B738-3D4B2E982126} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -34,6 +40,14 @@ Global {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x64.Build.0 = Release|x64 {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x86.ActiveCfg = Release|Win32 {9D4250EF-E8D6-4652-B738-3D4B2E982126}.Release|x86.Build.0 = Release|Win32 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Debug|x64.ActiveCfg = Debug|x64 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Debug|x64.Build.0 = Debug|x64 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Debug|x86.ActiveCfg = Debug|Win32 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Debug|x86.Build.0 = Debug|Win32 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Release|x64.ActiveCfg = Release|x64 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Release|x64.Build.0 = Release|x64 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Release|x86.ActiveCfg = Release|Win32 + {86D6C605-81F3-407B-A766-690EDF4CD346}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index be94f3a8..253ac640 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -87,22 +87,22 @@ void functionalTest(MMKV *mmkv, bool decodeOnly) { constexpr auto keyCount = 10000; constexpr auto threadCount = 10; -static const string threadMMKVID = "thread_test"; +static const string MMKV_ID = "thread_test"; vector arrIntKeys; vector arrStringKeys; DWORD WINAPI threadFunction(LPVOID lpParam) { auto threadIndex = (size_t) lpParam; - auto mmkv = MMKV::mmkvWithID(threadMMKVID, 0, MMKV_MULTI_PROCESS); + auto mmkv = MMKV::mmkvWithID(MMKV_ID); mmkv->lock(); cout << "thread " << threadIndex << " starts" << endl; mmkv->unlock(); auto segmentCount = keyCount / threadCount; auto startIndex = segmentCount * threadIndex; - for (auto i = startIndex; i < startIndex + segmentCount; i++) { - mmkv->setInt32(i, arrIntKeys[i]); - mmkv->setStringForKey("str-" + i, arrStringKeys[i]); + for (auto index = startIndex; index < startIndex + segmentCount; index++) { + mmkv->setInt32(index, arrIntKeys[index]); + mmkv->setStringForKey("str-" + index, arrStringKeys[index]); } mmkv->lock(); @@ -114,23 +114,68 @@ DWORD WINAPI threadFunction(LPVOID lpParam) { void threadTest() { HANDLE threadHandles[threadCount] = {0}; - for (size_t i = 0; i < threadCount; i++) { - threadHandles[i] = CreateThread(nullptr, 0, threadFunction, (LPVOID) i, 0, nullptr); + for (size_t index = 0; index < threadCount; index++) { + threadHandles[index] = CreateThread(nullptr, 0, threadFunction, (LPVOID) index, 0, nullptr); } WaitForMultipleObjects(threadCount, threadHandles, true, INFINITE); - auto mmkv = MMKV::mmkvWithID(threadMMKVID, 0, MMKV_MULTI_PROCESS); + auto mmkv = MMKV::mmkvWithID(MMKV_ID); cout << "total count " << mmkv->count() << endl; } void brutleTest() { - auto mmkv = MMKV::mmkvWithID(threadMMKVID); + auto mmkv = MMKV::mmkvWithID(MMKV_ID); for (size_t i = 0; i < keyCount; i++) { mmkv->setInt32(i, arrIntKeys[i]); mmkv->setStringForKey("str-" + i, arrStringKeys[i]); } } +void processTest() { + constexpr auto processCount = 2; + STARTUPINFO si[processCount] = {0}; + PROCESS_INFORMATION pi[processCount] = {0}; + + for (auto index = 0; index < processCount; index++) { + si[index].cb = sizeof(si[0]); + } + + wchar_t path[MAX_PATH] = {0}; + GetModuleFileName(nullptr, path, MAX_PATH); + PathRemoveFileSpec(path); + PathAppend(path, L"Win32DemoProcess.exe"); + + HANDLE processHandles[processCount] = {0}; + for (auto index = 0; index < processCount; index++) { + // Start the child process. + if (!CreateProcess(path, // No module name (use command line) + nullptr, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si[index], // Pointer to STARTUPINFO structure + &pi[index]) // Pointer to PROCESS_INFORMATION structure + ) { + printf("CreateProcess failed (%d).\n", GetLastError()); + continue; + } + processHandles[index] = pi[index].hProcess; + } + + WaitForMultipleObjects(processCount, processHandles, true, INFINITE); + + for (auto index = 0; index < processCount; index++) { + CloseHandle(pi[index].hProcess); + CloseHandle(pi[index].hThread); + } + + auto mmkv = MMKV::mmkvWithID("process_test", 0, MMKV_MULTI_PROCESS); + cout << "total count of process_test: " << mmkv->count() << endl; +} + int main() { locale::global(locale("")); wcout.imbue(locale("")); @@ -142,11 +187,12 @@ int main() { auto mmkv = MMKV::defaultMMKV(); functionalTest(mmkv, false); - for (size_t i = 0; i < keyCount; i++) { - arrIntKeys.push_back("int-" + to_string(i)); - arrStringKeys.push_back("string-" + to_string(i)); + for (size_t index = 0; index < keyCount; index++) { + arrIntKeys.push_back("int-" + to_string(index)); + arrStringKeys.push_back("string-" + to_string(index)); } - threadTest(); //brutleTest(); + //threadTest(); + processTest(); } diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj index 9383a204..76fa79c3 100644 --- a/Win32/Win32Demo/Win32Demo.vcxproj +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -97,7 +97,7 @@ Console true ..\$(IntDir);%(AdditionalLibraryDirectories) - MMKV.lib;%(AdditionalDependencies) + MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" @@ -137,7 +137,7 @@ true true ..\$(IntDir);%(AdditionalLibraryDirectories) - MMKV.lib;%(AdditionalDependencies) + MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" diff --git a/Win32/Win32Demo/pch.h b/Win32/Win32Demo/pch.h index 643b383c..f325aba6 100644 --- a/Win32/Win32Demo/pch.h +++ b/Win32/Win32Demo/pch.h @@ -21,6 +21,6 @@ #ifndef PCH_H #define PCH_H -// TODO: add headers that you want to pre-compile here +#include #endif //PCH_H diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp new file mode 100644 index 00000000..8b58498f --- /dev/null +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -0,0 +1,86 @@ +/* + * 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.h" +#include "pch.h" +#include +#include +#include + +using namespace std; + +wstring getAppDataRoaming(const wstring &company, const wstring &appName) { + wchar_t roaming[MAX_PATH] = {0}; + auto size = GetEnvironmentVariable(L"appdata", roaming, MAX_PATH); + if (size >= MAX_PATH || size == 0) { + cout << "fail to get %appdata%: " << GetLastError() << endl; + return L""; + } else { + wstring result(roaming, size); + result += L"\\" + company; + result += L"\\" + appName; + return result; + } +} + +constexpr auto keyCount = 1000; +static const string MMKV_ID = "process_test"; +vector arrIntKeys; +vector arrStringKeys; + +void brutleTest(DWORD processID) { + using hclock = chrono::high_resolution_clock; + auto start = hclock::now(); + + auto mmkv = MMKV::mmkvWithID(MMKV_ID, 0, MMKV_MULTI_PROCESS); + for (size_t i = 0; i < keyCount; i++) { + mmkv->setInt32(i, arrIntKeys[i]); + //mmkv->setStringForKey("str-" + i, arrStringKeys[i]); + //mmkv->getInt32ForKey(arrIntKeys[i]); + //string result; + //mmkv->getStringForKey(arrStringKeys[i], result); + } + + auto finish = hclock::now(); + auto used = chrono::duration_cast(finish - start).count(); + mmkv->lock(); + cout << endl << processID << ": " << used << " ms\n"; + mmkv->unlock(); +} + +int main() { + locale::global(locale("")); + wcout.imbue(locale("")); + srand(GetTickCount()); + + wstring rootDir = getAppDataRoaming(L"Tencent", L"΢-MMKV"); + MMKV::initializeMMKV(rootDir); + + auto processID = GetCurrentProcessId(); + cout << processID << ": started\n"; + + for (size_t index = 0; index < keyCount; index++) { + arrIntKeys.push_back("int-" + to_string(index)); + arrStringKeys.push_back("string-" + to_string(index)); + } + brutleTest(processID); + + cout << processID << ": ended\n"; +} diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj new file mode 100644 index 00000000..46161855 --- /dev/null +++ b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {86D6C605-81F3-407B-A766-690EDF4CD346} + Win32Proj + Win32DemoProcess + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\MMKV + + + Console + true + MMKV.lib;%(AdditionalDependencies) + ..\$(IntDir);%(AdditionalLibraryDirectories) + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\MMKV + + + Console + true + true + true + MMKV.lib;%(AdditionalDependencies) + ..\$(IntDir);%(AdditionalLibraryDirectories) + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj.filters b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj.filters new file mode 100644 index 00000000..8eb7fa79 --- /dev/null +++ b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Win32/Win32DemoProcess/pch.cpp b/Win32/Win32DemoProcess/pch.cpp new file mode 100644 index 00000000..5b8068f7 --- /dev/null +++ b/Win32/Win32DemoProcess/pch.cpp @@ -0,0 +1,21 @@ +/* + * 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 "pch.h" diff --git a/Win32/Win32DemoProcess/pch.h b/Win32/Win32DemoProcess/pch.h new file mode 100644 index 00000000..34902710 --- /dev/null +++ b/Win32/Win32DemoProcess/pch.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#ifndef PCH_H +#define PCH_H + +#include + +#endif //PCH_H From 3e327a308212950f9fdd391cb05eadb8f8d4c85d Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 19:53:32 +0800 Subject: [PATCH 15/57] refactor with override --- Win32/MMKV/MMKV.cpp | 16 ++++++++-------- Win32/MMKV/MMKV.h | 16 ++++++++-------- Win32/Win32Demo/Win32Demo.cpp | 18 +++++++++--------- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 894555f5..fc9e652b 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -858,7 +858,7 @@ bool MMKV::setBytesForKey(const MMBuffer &value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setBool(bool value, const std::string &key) { +bool MMKV::set(bool value, const std::string &key) { if (key.empty()) { return false; } @@ -870,7 +870,7 @@ bool MMKV::setBool(bool value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setInt32(int32_t value, const std::string &key) { +bool MMKV::set(int32_t value, const std::string &key) { if (key.empty()) { return false; } @@ -882,7 +882,7 @@ bool MMKV::setInt32(int32_t value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setUInt32(uint32_t value, const std::string &key) { +bool MMKV::set(uint32_t value, const std::string &key) { if (key.empty()) { return false; } @@ -894,7 +894,7 @@ bool MMKV::setUInt32(uint32_t value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setInt64(int64_t value, const std::string &key) { +bool MMKV::set(int64_t value, const std::string &key) { if (key.empty()) { return false; } @@ -906,7 +906,7 @@ bool MMKV::setInt64(int64_t value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setUInt64(uint64_t value, const std::string &key) { +bool MMKV::set(uint64_t value, const std::string &key) { if (key.empty()) { return false; } @@ -918,7 +918,7 @@ bool MMKV::setUInt64(uint64_t value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setFloat(float value, const std::string &key) { +bool MMKV::set(float value, const std::string &key) { if (key.empty()) { return false; } @@ -930,7 +930,7 @@ bool MMKV::setFloat(float value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setDouble(double value, const std::string &key) { +bool MMKV::set(double value, const std::string &key) { if (key.empty()) { return false; } @@ -942,7 +942,7 @@ bool MMKV::setDouble(double value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setVectorForKey(const std::vector &v, const std::string &key) { +bool MMKV::set(const std::vector &v, const std::string &key) { if (key.empty()) { return false; } diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 416594ae..43d1dbae 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -143,21 +143,21 @@ class MMKV_API MMKV { bool setBytesForKey(const MMBuffer &value, const std::string &key); - bool setBool(bool value, const std::string &key); + bool set(bool value, const std::string &key); - bool setInt32(int32_t value, const std::string &key); + bool set(int32_t value, const std::string &key); - bool setUInt32(uint32_t value, const std::string &key); + bool set(uint32_t value, const std::string &key); - bool setInt64(int64_t value, const std::string &key); + bool set(int64_t value, const std::string &key); - bool setUInt64(uint64_t value, const std::string &key); + bool set(uint64_t value, const std::string &key); - bool setFloat(float value, const std::string &key); + bool set(float value, const std::string &key); - bool setDouble(double value, const std::string &key); + bool set(double value, const std::string &key); - bool setVectorForKey(const std::vector &vector, const std::string &key); + bool set(const std::vector &vector, const std::string &key); bool getStringForKey(const std::string &key, std::string &result); diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 253ac640..bbc125a1 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -43,37 +43,37 @@ wstring getAppDataRoaming(const wstring &company, const wstring &appName) { void functionalTest(MMKV *mmkv, bool decodeOnly) { if (!decodeOnly) { - mmkv->setBool(true, "bool"); + mmkv->set(true, "bool"); } cout << "bool = " << mmkv->getBoolForKey("bool") << endl; if (!decodeOnly) { - mmkv->setInt32(1024, "int32"); + mmkv->set(1024, "int32"); } cout << "int32 = " << mmkv->getInt32ForKey("int32") << endl; if (!decodeOnly) { - mmkv->setUInt32(numeric_limits::max(), "uint32"); + mmkv->set(numeric_limits::max(), "uint32"); } cout << "uint32 = " << mmkv->getUInt32ForKey("uint32") << endl; if (!decodeOnly) { - mmkv->setInt64(numeric_limits::min(), "int64"); + mmkv->set(numeric_limits::min(), "int64"); } cout << "int64 = " << mmkv->getInt64ForKey("int64") << endl; if (!decodeOnly) { - mmkv->setUInt64(numeric_limits::max(), "uint64"); + mmkv->set(numeric_limits::max(), "uint64"); } cout << "uint64 = " << mmkv->getUInt64ForKey("uint64") << endl; if (!decodeOnly) { - mmkv->setFloat(3.14f, "float"); + mmkv->set(3.14f, "float"); } cout << "float = " << mmkv->getFloatForKey("float") << endl; if (!decodeOnly) { - mmkv->setDouble(numeric_limits::max(), "double"); + mmkv->set(numeric_limits::max(), "double"); } cout << "double = " << mmkv->getDoubleForKey("double") << endl; @@ -101,7 +101,7 @@ DWORD WINAPI threadFunction(LPVOID lpParam) { auto segmentCount = keyCount / threadCount; auto startIndex = segmentCount * threadIndex; for (auto index = startIndex; index < startIndex + segmentCount; index++) { - mmkv->setInt32(index, arrIntKeys[index]); + mmkv->set(index, arrIntKeys[index]); mmkv->setStringForKey("str-" + index, arrStringKeys[index]); } @@ -126,7 +126,7 @@ void threadTest() { void brutleTest() { auto mmkv = MMKV::mmkvWithID(MMKV_ID); for (size_t i = 0; i < keyCount; i++) { - mmkv->setInt32(i, arrIntKeys[i]); + mmkv->set(i, arrIntKeys[i]); mmkv->setStringForKey("str-" + i, arrStringKeys[i]); } } diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index 8b58498f..e17ffac5 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -51,7 +51,7 @@ void brutleTest(DWORD processID) { auto mmkv = MMKV::mmkvWithID(MMKV_ID, 0, MMKV_MULTI_PROCESS); for (size_t i = 0; i < keyCount; i++) { - mmkv->setInt32(i, arrIntKeys[i]); + mmkv->set(i, arrIntKeys[i]); //mmkv->setStringForKey("str-" + i, arrStringKeys[i]); //mmkv->getInt32ForKey(arrIntKeys[i]); //string result; From 7ff6a1e46c7174ddc054d4318560ebdbe3e438aa Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 20:01:08 +0800 Subject: [PATCH 16/57] compile --- Win32/Win32Demo/Win32Demo.cpp | 16 +++------------- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index bbc125a1..8c0e9b37 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -147,19 +147,9 @@ void processTest() { HANDLE processHandles[processCount] = {0}; for (auto index = 0; index < processCount; index++) { - // Start the child process. - if (!CreateProcess(path, // No module name (use command line) - nullptr, // Command line - NULL, // Process handle not inheritable - NULL, // Thread handle not inheritable - FALSE, // Set handle inheritance to FALSE - 0, // No creation flags - NULL, // Use parent's environment block - NULL, // Use parent's starting directory - &si[index], // Pointer to STARTUPINFO structure - &pi[index]) // Pointer to PROCESS_INFORMATION structure - ) { - printf("CreateProcess failed (%d).\n", GetLastError()); + if (!CreateProcess(path, nullptr, nullptr, nullptr, false, 0, nullptr, nullptr, &si[index], + &pi[index])) { + cout << "CreateProcess failed: " << GetLastError() << endl; continue; } processHandles[index] = pi[index].hProcess; diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index e17ffac5..43a38154 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -18,8 +18,8 @@ * limitations under the License. */ -#include "MMKV.h" #include "pch.h" +#include "MMKV.h" #include #include #include From 69b470011955fbffe2dd80a46f0156804a1124f5 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 20:29:45 +0800 Subject: [PATCH 17/57] remove bugy try_lock --- Win32/MMKV/InterProcessLock.cpp | 31 ++++--------------------------- Win32/MMKV/InterProcessLock.h | 11 ----------- Win32/MMKV/MMKV.h | 1 - Win32/MMKV/ScopedLock.hpp | 7 ------- Win32/MMKV/ThreadLock.cpp | 8 -------- Win32/MMKV/ThreadLock.h | 1 - 6 files changed, 4 insertions(+), 55 deletions(-) diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index 2315a32c..af145a0a 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -21,7 +21,7 @@ #include "InterProcessLock.h" #include "MMKVLog.h" -static DWORD LockType2Flag(LockType lockType, bool tryLock) { +static DWORD LockType2Flag(LockType lockType) { DWORD flag = 0; switch (lockType) { case SharedLockType: @@ -31,16 +31,13 @@ static DWORD LockType2Flag(LockType lockType, bool tryLock) { flag = LOCKFILE_EXCLUSIVE_LOCK; break; } - if (tryLock) { - flag |= LOCKFILE_FAIL_IMMEDIATELY; - } return flag; } FileLock::FileLock(HANDLE fd) : m_fd(fd), m_overLapped{0}, m_sharedLockCount(0), m_exclusiveLockCount(0) {} -bool FileLock::doLock(LockType lockType, bool tryLock) { +bool FileLock::lock(LockType lockType) { bool unLockFirstIfNeeded = false; if (lockType == SharedLockType) { @@ -61,7 +58,7 @@ bool FileLock::doLock(LockType lockType, bool tryLock) { } } - auto flag = LockType2Flag(lockType, tryLock); + auto flag = LockType2Flag(lockType); if (unLockFirstIfNeeded) { /* try exclusive-lock above shared-lock will always fail in Win32 auto ret = LockFileEx(m_fd, flag | LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &m_overLapped); @@ -78,31 +75,12 @@ bool FileLock::doLock(LockType lockType, bool tryLock) { auto ret = LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped); if (!ret) { MMKVError("fail to lock fd=%p, error:%d", m_fd, GetLastError()); - if (lockType == SharedLockType) { - m_sharedLockCount--; - } else { - m_exclusiveLockCount--; - if (unLockFirstIfNeeded) { - flag = LockType2Flag(SharedLockType, false); - if (!LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped)) { - MMKVError("fail to roll back, error:%d", GetLastError()); - } - } - } return false; } else { return true; } } -bool FileLock::lock(LockType lockType) { - return doLock(lockType, false); -} - -bool FileLock::try_lock(LockType lockType) { - return doLock(lockType, true); -} - bool FileLock::unlock(LockType lockType) { bool unlockToSharedLock = false; @@ -136,12 +114,11 @@ bool FileLock::unlock(LockType lockType) { * the second unlock operation unlocks the shared lock. */ if (unlockToSharedLock) { - auto flag = LockType2Flag(SharedLockType, false); + auto flag = LockType2Flag(SharedLockType); if (!LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped)) { MMKVError("fail to roll back to shared-lock, error:%d", GetLastError()); } } - auto flag = LockType2Flag(lockType, false); auto ret = UnlockFileEx(m_fd, 0, 1, 0, &m_overLapped); if (!ret) { MMKVError("fail to unlock fd=%p, error:%d", m_fd, GetLastError()); diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h index c69d6deb..b30a39ce 100644 --- a/Win32/MMKV/InterProcessLock.h +++ b/Win32/MMKV/InterProcessLock.h @@ -37,8 +37,6 @@ class FileLock { size_t m_sharedLockCount; size_t m_exclusiveLockCount; - bool doLock(LockType lockType, bool tryLock); - // just forbid it for possibly misuse FileLock(const FileLock &other) = delete; @@ -49,8 +47,6 @@ class FileLock { bool lock(LockType lockType); - bool try_lock(LockType lockType); - bool unlock(LockType lockType); }; @@ -71,13 +67,6 @@ class InterProcessLock { m_fileLock->lock(m_lockType); } } - // TODO: remove try_lock() - bool try_lock() { - if (m_enable) { - return m_fileLock->try_lock(m_lockType); - } - return false; - } void unlock() { if (m_enable) { diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 43d1dbae..291aa38b 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -214,7 +214,6 @@ class MMKV_API MMKV { void lock() { m_exclusiveProcessLock.lock(); } void unlock() { m_exclusiveProcessLock.unlock(); } - bool try_lock() { return m_exclusiveProcessLock.try_lock(); } }; enum MMKVRecoverStrategic : int { diff --git a/Win32/MMKV/ScopedLock.hpp b/Win32/MMKV/ScopedLock.hpp index 33f9c3a0..fe62c0d7 100644 --- a/Win32/MMKV/ScopedLock.hpp +++ b/Win32/MMKV/ScopedLock.hpp @@ -49,13 +49,6 @@ class ScopedLock { } } - bool try_lock() { - if (m_lock) { - return m_lock->try_lock(); - } - return false; - } - void unlock() { if (m_lock) { m_lock->unlock(); diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index 984014a4..bfa434a5 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -36,14 +36,6 @@ void ThreadLock::lock() { EnterCriticalSection(&m_lock); } -bool ThreadLock::try_lock() { - auto ret = TryEnterCriticalSection(&m_lock); - if (!ret) { - MMKVError("fail to try lock %p, ret=%d", &m_lock, ret); - } - return ret; -} - void ThreadLock::unlock() { LeaveCriticalSection(&m_lock); } diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h index 0fff08ea..83879bd4 100644 --- a/Win32/MMKV/ThreadLock.h +++ b/Win32/MMKV/ThreadLock.h @@ -38,7 +38,6 @@ class ThreadLock { ~ThreadLock(); void lock(); - bool try_lock(); void unlock(); static void ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback)(void)); From dcb06ca5956ac244d9c0cb1016c8f63d85a4d3ce Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 19 Dec 2018 20:58:19 +0800 Subject: [PATCH 18/57] use static lib for MMKV --- Win32/MMKV/CodedOutputData.cpp | 4 ++-- Win32/MMKV/CodedOutputData.h | 4 ++-- Win32/MMKV/MMBuffer.h | 3 +-- Win32/MMKV/MMKV.cpp | 5 +++-- Win32/MMKV/MMKV.h | 1 - Win32/MMKV/MMKV.vcxproj | 5 ++--- Win32/MMKV/MMKV.vcxproj.filters | 3 --- Win32/MMKV/MMKVDef.h | 11 ++++++----- Win32/MMKV/MmapedFile.cpp | 4 ++-- Win32/MMKV/MmapedFile.h | 4 ++-- Win32/MMKV/dllmain.cpp | 13 ------------- Win32/Win32Demo/Win32Demo.vcxproj | 4 ++-- Win32/Win32DemoProcess/pch.h | 2 -- 13 files changed, 22 insertions(+), 41 deletions(-) delete mode 100644 Win32/MMKV/dllmain.cpp diff --git a/Win32/MMKV/CodedOutputData.cpp b/Win32/MMKV/CodedOutputData.cpp index 40876935..fc5927ed 100644 --- a/Win32/MMKV/CodedOutputData.cpp +++ b/Win32/MMKV/CodedOutputData.cpp @@ -79,8 +79,8 @@ void CodedOutputData::writeData(const MMBuffer &value) { this->writeRawData(value); } -int32_t CodedOutputData::spaceLeft() { - return int32_t(m_size - m_position); +size_t CodedOutputData::spaceLeft() { + return m_size - m_position; } void CodedOutputData::seek(size_t addedSize) { diff --git a/Win32/MMKV/CodedOutputData.h b/Win32/MMKV/CodedOutputData.h index 9da2b57d..73210faa 100644 --- a/Win32/MMKV/CodedOutputData.h +++ b/Win32/MMKV/CodedOutputData.h @@ -28,14 +28,14 @@ class CodedOutputData { uint8_t *m_ptr; size_t m_size; - int32_t m_position; + size_t m_position; public: CodedOutputData(void *ptr, size_t len); ~CodedOutputData(); - int32_t spaceLeft(); + size_t spaceLeft(); void seek(size_t addedSize); diff --git a/Win32/MMKV/MMBuffer.h b/Win32/MMKV/MMBuffer.h index ab3c604d..a6d0cdb2 100644 --- a/Win32/MMKV/MMBuffer.h +++ b/Win32/MMKV/MMBuffer.h @@ -21,7 +21,6 @@ #ifndef MMKV_MMBUFFER_H #define MMKV_MMBUFFER_H -#include "MMKVDef.h" #include enum MMBufferCopyFlag : bool { @@ -29,7 +28,7 @@ enum MMBufferCopyFlag : bool { MMBufferNoCopy = true, }; -class MMKV_API MMBuffer { +class MMBuffer { private: void *ptr; size_t size; diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index fc9e652b..722941eb 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -22,6 +22,7 @@ */ #include "MMKV.h" +#include "MMKVDef.h" #include "CodedInputData.h" #include "CodedOutputData.h" #include "InterProcessLock.h" @@ -1214,8 +1215,8 @@ static wstring encodeFilePath(const string &mmapID) { const char *specialCharacters = "\\/:*?\"<>|"; string encodedID; bool hasSpecialCharacter = false; - for (int i = 0; i < mmapID.size(); i++) { - if (strchr(specialCharacters, mmapID[i]) != NULL) { + for (size_t index = 0; index < mmapID.size(); index++) { + if (strchr(specialCharacters, mmapID[index]) != NULL) { encodedID = md5(mmapID); hasSpecialCharacter = true; break; diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 291aa38b..41b8d59a 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -23,7 +23,6 @@ #include "InterProcessLock.h" #include "MMBuffer.h" -#include "MMKVDef.h" #include "MMKVMetaInfo.hpp" #include "MmapedFile.h" #include "ThreadLock.h" diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index abe086fe..d7dc1067 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -27,13 +27,13 @@ - DynamicLibrary + StaticLibrary true v141 Unicode - DynamicLibrary + StaticLibrary false v141 true @@ -185,7 +185,6 @@ - diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index 7850d1dc..142a6e57 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -101,9 +101,6 @@ Source Files - - Source Files - Source Files diff --git a/Win32/MMKV/MMKVDef.h b/Win32/MMKV/MMKVDef.h index b356b803..d896096c 100644 --- a/Win32/MMKV/MMKVDef.h +++ b/Win32/MMKV/MMKVDef.h @@ -6,8 +6,9 @@ // Windows Header Files #include -#ifdef MMKV_EXPORTS -#define MMKV_API __declspec(dllexport) -#else -#define MMKV_API __declspec(dllimport) -#endif +//#ifdef MMKV_EXPORTS +//#define MMKV_API __declspec(dllexport) +//#else +//#define MMKV_API __declspec(dllimport) +//#endif +#define MMKV_API diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index 9531bb9e..589807de 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -24,7 +24,7 @@ using namespace std; -const int DEFAULT_MMAP_SIZE = getpagesize(); +const size_t DEFAULT_MMAP_SIZE = getpagesize(); std::wstring string2wstring(const std::string &str) { auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); @@ -93,7 +93,7 @@ MmapedFile::~MmapedFile() { // file -int getpagesize(void) { +size_t getpagesize(void) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); return system_info.dwPageSize; diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 2818c195..8f588873 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -24,7 +24,7 @@ #include "MMKVDef.h" #include -extern MMKV_API const int DEFAULT_MMAP_SIZE; +extern MMKV_API const size_t DEFAULT_MMAP_SIZE; class MmapedFile { std::wstring m_name; @@ -52,7 +52,7 @@ class MmapedFile { class MMBuffer; -extern int getpagesize(); +extern size_t getpagesize(); extern std::wstring string2wstring(const std::string &str); extern bool mkPath(const std::wstring &str); extern bool isFileExist(const std::wstring &nsFilePath); diff --git a/Win32/MMKV/dllmain.cpp b/Win32/MMKV/dllmain.cpp deleted file mode 100644 index cdf28879..00000000 --- a/Win32/MMKV/dllmain.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "MMKVDef.h" - -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj index 76fa79c3..3cd2598f 100644 --- a/Win32/Win32Demo/Win32Demo.vcxproj +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -100,7 +100,7 @@ MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) - xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" + xcopy /y /d "..\$(IntDir)MMKV.lib" "$(OutDir)" @@ -140,7 +140,7 @@ MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) - xcopy /y /d "..\$(IntDir)MMKV.dll" "$(OutDir)" + xcopy /y /d "..\$(IntDir)MMKV.lib" "$(OutDir)" diff --git a/Win32/Win32DemoProcess/pch.h b/Win32/Win32DemoProcess/pch.h index 34902710..386a9832 100644 --- a/Win32/Win32DemoProcess/pch.h +++ b/Win32/Win32DemoProcess/pch.h @@ -21,6 +21,4 @@ #ifndef PCH_H #define PCH_H -#include - #endif //PCH_H From bcc502facb1a3d47524264e12c0e3cd788d76a07 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 20 Dec 2018 12:01:52 +0800 Subject: [PATCH 19/57] support vs 2015 --- .gitignore | 4 +++- Win32/MMKV/CodedOutputData.cpp | 2 +- Win32/MMKV/MMKV.cpp | 10 +++++----- Win32/MMKV/MMKV.vcxproj | 16 +++++++++------- Win32/Win32Demo/Win32Demo.cpp | 4 +--- Win32/Win32Demo/Win32Demo.vcxproj | 14 +++++++++++--- Win32/Win32Demo/pch.h | 2 ++ Win32/Win32DemoProcess/Win32DemoProcess.vcxproj | 14 +++++++++++--- 8 files changed, 43 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 76393348..837578cb 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ DerivedData [Dd]ebug/ [Rr]elease/ *.user - +*.VC.opendb +*.VC.db +ipch/ diff --git a/Win32/MMKV/CodedOutputData.cpp b/Win32/MMKV/CodedOutputData.cpp index fc5927ed..9e7c95fd 100644 --- a/Win32/MMKV/CodedOutputData.cpp +++ b/Win32/MMKV/CodedOutputData.cpp @@ -93,7 +93,7 @@ void CodedOutputData::seek(size_t addedSize) { void CodedOutputData::writeRawByte(uint8_t value) { if (m_position == m_size) { - MMKVError("m_position: %d, m_size: %zd", m_position, m_size); + MMKVError("m_position: %zd, m_size: %zd", m_position, m_size); return; } diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 722941eb..2619d303 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -113,7 +113,7 @@ void initialize() { g_instanceDic = new unordered_map; g_instanceLock = ThreadLock(); - MMKVInfo("page size:%d", DEFAULT_MMAP_SIZE); + MMKVInfo("page size:%zd", DEFAULT_MMAP_SIZE); } void MMKV::initializeMMKV(const std::wstring &rootDir) { @@ -373,9 +373,9 @@ void MMKV::clearAll() { } if (m_fd >= 0) { if (m_size != DEFAULT_MMAP_SIZE) { - MMKVInfo("truncating [%s] from %zu to %d", m_mmapID.c_str(), m_size, DEFAULT_MMAP_SIZE); + MMKVInfo("truncating [%s] from %zu to %zd", m_mmapID.c_str(), m_size, DEFAULT_MMAP_SIZE); if (!ftruncate(m_fd, DEFAULT_MMAP_SIZE)) { - MMKVError("fail to truncate [%s] to size %d", m_mmapID.c_str(), DEFAULT_MMAP_SIZE); + MMKVError("fail to truncate [%s] to size %zd", m_mmapID.c_str(), DEFAULT_MMAP_SIZE); } } } @@ -1205,8 +1205,8 @@ static string md5(const string &value) { char tmp[3] = {0}, buf[33] = {0}; MD5((const unsigned char *) value.c_str(), value.size(), md); for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { - sprintf(tmp, "%2.2x", md[i]); - strcat(buf, tmp); + sprintf_s(tmp, sizeof(tmp), "%2.2x", md[i]); + strcat_s(buf, sizeof(tmp), tmp); } return buf; } diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index d7dc1067..77d4f6a0 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -1,4 +1,4 @@ - + @@ -40,17 +40,17 @@ Unicode - DynamicLibrary + StaticLibrary true - v141 Unicode + v140 - DynamicLibrary + StaticLibrary false - v141 true Unicode + v140 @@ -98,12 +98,13 @@ - Use + NotUsing Level3 Disabled true _DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -130,7 +131,7 @@ - Use + NotUsing Level3 MaxSpeed true @@ -138,6 +139,7 @@ true NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true + MultiThreaded Windows diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 8c0e9b37..a79cb706 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -18,10 +18,8 @@ * limitations under the License. */ -#define NOMINMAX // undefine max/min - -#include "MMKV.h" #include "pch.h" +#include "MMKV.h" #include #include diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj index 3cd2598f..b4a1c064 100644 --- a/Win32/Win32Demo/Win32Demo.vcxproj +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -1,4 +1,4 @@ - + @@ -42,15 +42,15 @@ Application true - v141 Unicode + v140 Application false - v141 true Unicode + v140 @@ -112,10 +112,14 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h + MultiThreadedDebug + ..\MMKV Console true + $(OutDir) + MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) @@ -154,12 +158,16 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h + MultiThreaded + ..\MMKV Console true true true + $(OutDir) + MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) diff --git a/Win32/Win32Demo/pch.h b/Win32/Win32Demo/pch.h index f325aba6..1577ec10 100644 --- a/Win32/Win32Demo/pch.h +++ b/Win32/Win32Demo/pch.h @@ -21,6 +21,8 @@ #ifndef PCH_H #define PCH_H +#define NOMINMAX // undefine max/min + #include #endif //PCH_H diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj index 46161855..b3e685b5 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj +++ b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj @@ -1,4 +1,4 @@ - + @@ -42,15 +42,15 @@ Application true - v141 Unicode + v140 Application false - v141 true Unicode + v140 @@ -109,10 +109,14 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h + MultiThreadedDebug + ..\MMKV Console true + $(OutDir) + MMKV.lib;%(AdditionalDependencies) @@ -148,12 +152,16 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h + MultiThreaded + ..\MMKV Console true true true + $(OutDir) + MMKV.lib;%(AdditionalDependencies) From b03049c37fc15d43e7f5c35ba24b86f5460f295e Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 20 Dec 2018 17:21:45 +0800 Subject: [PATCH 20/57] remove warning --- Win32/MMKV/MMKV.h | 1 - Win32/MMKV/targetver.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 41b8d59a..145cb9e9 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -41,7 +41,6 @@ enum MMKVMode : uint32_t { }; class MMKV_API MMKV { - // TODO: avoid warning "needs to have dll-interface to be used by clients of class" std::unordered_map m_dic; std::string m_mmapID; std::wstring m_path; diff --git a/Win32/MMKV/targetver.h b/Win32/MMKV/targetver.h index a2c3bc00..83e1d27e 100644 --- a/Win32/MMKV/targetver.h +++ b/Win32/MMKV/targetver.h @@ -5,6 +5,8 @@ // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. +#if !defined(_WIN32_WINNT) #define _WIN32_WINNT _WIN32_WINNT_WINXP +#endif #include From a40911eb3bec611979a2d81e29f3c143863f0fa9 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 20 Dec 2018 17:33:39 +0800 Subject: [PATCH 21/57] mt/mtd --- Win32/MMKV/MMKV.vcxproj | 2 ++ Win32/Win32Demo/Win32Demo.vcxproj | 2 ++ Win32/Win32DemoProcess/Win32DemoProcess.vcxproj | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 77d4f6a0..65e8dff9 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -90,6 +90,7 @@ true WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -121,6 +122,7 @@ true WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true + MultiThreaded Windows diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj index b4a1c064..fca69126 100644 --- a/Win32/Win32Demo/Win32Demo.vcxproj +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -92,6 +92,7 @@ true pch.h ..\MMKV;%(AdditionalIncludeDirectories) + MultiThreadedDebug Console @@ -134,6 +135,7 @@ true pch.h ..\MMKV;%(AdditionalIncludeDirectories) + MultiThreaded Console diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj index b3e685b5..e40a60eb 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj +++ b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj @@ -92,6 +92,7 @@ true pch.h ..\MMKV + MultiThreadedDebug Console @@ -131,6 +132,7 @@ true pch.h ..\MMKV + MultiThreaded Console From 1cc921dd5a7e5485f77a8c4a60c8eb4da458c10a Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 21 Dec 2018 10:42:25 +0800 Subject: [PATCH 22/57] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=B9=E6=B3=95=20ac?= =?UTF-8?q?tualSize=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MMKV.h | 1 + iOS/MMKV/MMKV/MMKV.mm | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index 5460b11a..c7dbb030 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -98,6 +98,7 @@ NS_ASSUME_NONNULL_BEGIN - (size_t)count; - (size_t)totalSize; +- (size_t)actualSize; - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 512e5c58..13f0c3f0 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -1218,6 +1218,12 @@ - (size_t)totalSize { return m_size; } +- (size_t)actualSize { + CScopedLock lock(m_lock); + [self checkLoadData]; + return m_actualSize; +} + - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block { if (block == nil) { return; From b4bca7c94e5d67203f4422edd8bd4fe3cdff111c Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 21 Dec 2018 16:13:33 +0800 Subject: [PATCH 23/57] visibility --- Win32/MMKV/CodedInputData.cpp | 4 + Win32/MMKV/CodedInputData.h | 4 + Win32/MMKV/CodedOutputData.cpp | 4 + Win32/MMKV/CodedOutputData.h | 4 + Win32/MMKV/InterProcessLock.cpp | 4 + Win32/MMKV/InterProcessLock.h | 4 + Win32/MMKV/MMBuffer.cpp | 4 + Win32/MMKV/MMBuffer.h | 4 + Win32/MMKV/MMKV.cpp | 31 ++-- Win32/MMKV/MMKV.h | 38 ++-- Win32/MMKV/MMKV.vcxproj | 12 +- Win32/MMKV/MMKV.vcxproj.filters | 12 +- Win32/MMKV/MMKVDef.h | 7 - Win32/MMKV/MMKVMetaInfo.hpp | 10 +- Win32/MMKV/MiniPBCoder.cpp | 4 + Win32/MMKV/MiniPBCoder.h | 7 +- Win32/MMKV/MmapedFile.cpp | 4 + Win32/MMKV/MmapedFile.h | 6 +- Win32/MMKV/PBEncodeItem.hpp | 4 + Win32/MMKV/PBUtility.cpp | 4 + Win32/MMKV/PBUtility.h | 4 + Win32/MMKV/ScopedLock.hpp | 4 + Win32/MMKV/ThreadLock.cpp | 4 + Win32/MMKV/ThreadLock.h | 4 + Win32/MMKV/aes/AESCrypt.cpp | 13 +- Win32/MMKV/aes/AESCrypt.h | 8 +- Win32/MMKV/aes/openssl/aes.h | 9 +- .../aes/openssl/{aes_cfb.c => aes_cfb.cpp} | 4 + .../aes/openssl/{aes_core.c => aes_core.cpp} | 4 + .../MMKV/aes/openssl/{cfb128.c => cfb128.cpp} | 4 + Win32/MMKV/aes/openssl/md32_common.h | 16 +- Win32/MMKV/aes/openssl/md5.h | 12 +- .../aes/openssl/{md5_dgst.c => md5_dgst.cpp} | 6 +- Win32/MMKV/aes/openssl/md5_locl.h | 6 +- .../aes/openssl/{md5_one.c => md5_one.cpp} | 4 + Win32/MMKV/aes/openssl/modes.h | 8 +- Win32/MMKV/crc32/Checksum.h | 8 +- Win32/MMKV/crc32/zlib/crc32.c | 168 ------------------ Win32/MMKV/crc32/zlib/crc32.cpp | 49 +++++ Win32/Win32Demo/Win32Demo.cpp | 2 +- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 2 +- 41 files changed, 243 insertions(+), 267 deletions(-) rename Win32/MMKV/aes/openssl/{aes_cfb.c => aes_cfb.cpp} (97%) rename Win32/MMKV/aes/openssl/{aes_core.c => aes_core.cpp} (99%) rename Win32/MMKV/aes/openssl/{cfb128.c => cfb128.cpp} (98%) rename Win32/MMKV/aes/openssl/{md5_dgst.c => md5_dgst.cpp} (98%) rename Win32/MMKV/aes/openssl/{md5_one.c => md5_one.cpp} (96%) delete mode 100644 Win32/MMKV/crc32/zlib/crc32.c create mode 100644 Win32/MMKV/crc32/zlib/crc32.cpp diff --git a/Win32/MMKV/CodedInputData.cpp b/Win32/MMKV/CodedInputData.cpp index 078fa8e3..812adbe9 100644 --- a/Win32/MMKV/CodedInputData.cpp +++ b/Win32/MMKV/CodedInputData.cpp @@ -26,6 +26,8 @@ using namespace std; +namespace mmkv { + CodedInputData::CodedInputData(const void *oData, int32_t length) : m_ptr((uint8_t *) oData), m_size(length), m_position(0) { assert(m_ptr); @@ -176,3 +178,5 @@ int8_t CodedInputData::readRawByte() { int8_t *bytes = (int8_t *) m_ptr; return bytes[m_position++]; } + +} // namespace mmkv diff --git a/Win32/MMKV/CodedInputData.h b/Win32/MMKV/CodedInputData.h index f19b90d7..65c59699 100644 --- a/Win32/MMKV/CodedInputData.h +++ b/Win32/MMKV/CodedInputData.h @@ -25,6 +25,8 @@ #include #include +namespace mmkv { + class CodedInputData { uint8_t *m_ptr; int32_t m_size; @@ -66,4 +68,6 @@ class CodedInputData { MMBuffer readData(); }; +} // namespace mmkv + #endif //MMKV_CODEDINPUTDATA_H diff --git a/Win32/MMKV/CodedOutputData.cpp b/Win32/MMKV/CodedOutputData.cpp index 9e7c95fd..6dae1dbb 100644 --- a/Win32/MMKV/CodedOutputData.cpp +++ b/Win32/MMKV/CodedOutputData.cpp @@ -25,6 +25,8 @@ using namespace std; +namespace mmkv { + CodedOutputData::CodedOutputData(void *ptr, size_t len) : m_ptr((uint8_t *) ptr), m_size(len), m_position(0) { assert(m_ptr); @@ -147,3 +149,5 @@ void CodedOutputData::writeRawLittleEndian64(int64_t value) { this->writeRawByte(static_cast((value >> 48) & 0xff)); this->writeRawByte(static_cast((value >> 56) & 0xff)); } + +} // namespace mmkv diff --git a/Win32/MMKV/CodedOutputData.h b/Win32/MMKV/CodedOutputData.h index 73210faa..e27c652e 100644 --- a/Win32/MMKV/CodedOutputData.h +++ b/Win32/MMKV/CodedOutputData.h @@ -25,6 +25,8 @@ #include #include +namespace mmkv { + class CodedOutputData { uint8_t *m_ptr; size_t m_size; @@ -70,4 +72,6 @@ class CodedOutputData { void writeData(const MMBuffer &value); }; +} // namespace mmkv + #endif //MMKV_CODEDOUTPUTDATA_H diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index af145a0a..4230c40c 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -21,6 +21,8 @@ #include "InterProcessLock.h" #include "MMKVLog.h" +namespace mmkv { + static DWORD LockType2Flag(LockType lockType) { DWORD flag = 0; switch (lockType) { @@ -127,3 +129,5 @@ bool FileLock::unlock(LockType lockType) { return true; } } + +} // namespace mmkv diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h index b30a39ce..e72222e8 100644 --- a/Win32/MMKV/InterProcessLock.h +++ b/Win32/MMKV/InterProcessLock.h @@ -24,6 +24,8 @@ #include "MMKVDef.h" #include +namespace mmkv { + enum LockType { SharedLockType, ExclusiveLockType, @@ -75,4 +77,6 @@ class InterProcessLock { } }; +} // namespace mmkv + #endif //MMKV_INTERPROCESSLOCK_H diff --git a/Win32/MMKV/MMBuffer.cpp b/Win32/MMKV/MMBuffer.cpp index a8d0e156..641d14c5 100644 --- a/Win32/MMKV/MMBuffer.cpp +++ b/Win32/MMKV/MMBuffer.cpp @@ -23,6 +23,8 @@ #include #include +namespace mmkv { + MMBuffer::MMBuffer(size_t length) : ptr(nullptr), size(length), isNoCopy(MMBufferCopy) { if (size > 0) { ptr = malloc(size); @@ -58,3 +60,5 @@ MMBuffer::~MMBuffer() { } ptr = nullptr; } + +} // namespace mmkv diff --git a/Win32/MMKV/MMBuffer.h b/Win32/MMKV/MMBuffer.h index a6d0cdb2..5925603b 100644 --- a/Win32/MMKV/MMBuffer.h +++ b/Win32/MMKV/MMBuffer.h @@ -23,6 +23,8 @@ #include +namespace mmkv { + enum MMBufferCopyFlag : bool { MMBufferCopy = false, MMBufferNoCopy = true, @@ -53,4 +55,6 @@ class MMBuffer { MMBuffer &operator=(const MMBuffer &other) = delete; }; +} // namespace mmkv + #endif //MMKV_MMBUFFER_H diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 2619d303..1eeebc1c 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -22,11 +22,11 @@ */ #include "MMKV.h" -#include "MMKVDef.h" #include "CodedInputData.h" #include "CodedOutputData.h" #include "InterProcessLock.h" #include "MMBuffer.h" +#include "MMKVDef.h" #include "MMKVLog.h" #include "MiniPBCoder.h" #include "MmapedFile.h" @@ -41,6 +41,7 @@ #include using namespace std; +using namespace mmkv; static unordered_map *g_instanceDic; static ThreadLock g_instanceLock; @@ -61,7 +62,7 @@ enum : bool { IncreaseSequence = true, }; -MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) +MMKV::MMKV(const std::string &mmapID, MMKVMode mode, int size, string *cryptKey) : m_mmapID(mmapID) , m_path(mappedKVPathWithID(m_mmapID, mode)) , m_crcPath(crcPathWithID(m_mmapID, mode)) @@ -106,7 +107,7 @@ MMKV::~MMKV() { } MMKV *MMKV::defaultMMKV(MMKVMode mode, string *cryptKey) { - return mmkvWithID(DEFAULT_MMAP_ID, DEFAULT_MMAP_SIZE, mode, cryptKey); + return mmkvWithID(DEFAULT_MMAP_ID, mode, DEFAULT_MMAP_SIZE, cryptKey); } void initialize() { @@ -126,8 +127,7 @@ void MMKV::initializeMMKV(const std::wstring &rootDir) { MMKVInfo("root dir: %ws", g_rootDir.c_str()); } -MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) { - +MMKV *MMKV::mmkvWithID(const std::string &mmapID, MMKVMode mode, int size, string *cryptKey) { if (mmapID.empty()) { return nullptr; } @@ -138,7 +138,7 @@ MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, strin MMKV *kv = itr->second; return kv; } - auto kv = new MMKV(mmapID, size, mode, cryptKey); + auto kv = new MMKV(mmapID, mode, size, cryptKey); (*g_instanceDic)[mmapID] = kv; return kv; } @@ -287,8 +287,8 @@ void MMKV::partialLoadFromFile() { MMBuffer inputBuffer(m_ptr + Fixed32Size + oldActualSize, bufferSize, MMBufferNoCopy); // incremental update crc digest - m_crcDigest = (uint32_t) crc32(m_crcDigest, (const uint8_t *) inputBuffer.getPtr(), - inputBuffer.length()); + m_crcDigest = (uint32_t) zlib::crc32( + m_crcDigest, (const uint8_t *) inputBuffer.getPtr(), inputBuffer.length()); if (m_crcDigest == m_metaInfo.m_crcDigest) { if (m_crypter) { decryptBuffer(*m_crypter, inputBuffer); @@ -325,7 +325,7 @@ void MMKV::checkLoadData() { } // TODO: atomic lock m_metaFile? - MMKVMetaInfo metaInfo; + MetaInfo metaInfo; metaInfo.read(m_metaFile.getMemory()); if (m_metaInfo.m_sequence != metaInfo.m_sequence) { MMKVInfo("[%s] oldSeq %u, newSeq %u", m_mmapID.c_str(), m_metaInfo.m_sequence, @@ -373,7 +373,8 @@ void MMKV::clearAll() { } if (m_fd >= 0) { if (m_size != DEFAULT_MMAP_SIZE) { - MMKVInfo("truncating [%s] from %zu to %zd", m_mmapID.c_str(), m_size, DEFAULT_MMAP_SIZE); + MMKVInfo("truncating [%s] from %zu to %zd", m_mmapID.c_str(), m_size, + DEFAULT_MMAP_SIZE); if (!ftruncate(m_fd, DEFAULT_MMAP_SIZE)) { MMKVError("fail to truncate [%s] to size %zd", m_mmapID.c_str(), DEFAULT_MMAP_SIZE); } @@ -801,7 +802,7 @@ bool MMKV::isFileValid() { bool MMKV::checkFileCRCValid() { if (m_ptr) { constexpr int offset = pbFixed32Size(0); - m_crcDigest = (uint32_t) crc32(0, (const uint8_t *) m_ptr + offset, m_actualSize); + m_crcDigest = (uint32_t) zlib::crc32(0, (const uint8_t *) m_ptr + offset, m_actualSize); m_metaInfo.read(m_metaFile.getMemory()); if (m_crcDigest == m_metaInfo.m_crcDigest) { return true; @@ -824,7 +825,7 @@ void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSeque if (!ptr) { return; } - m_crcDigest = (uint32_t) crc32(m_crcDigest, ptr, length); + m_crcDigest = (uint32_t) zlib::crc32(m_crcDigest, ptr, length); void *crcPtr = m_metaFile.getMemory(); if (!crcPtr) { @@ -1168,7 +1169,7 @@ bool MMKV::isFileValid(const std::string &mmapID) { uint32_t crcFile = 0; MMBuffer *data = readWholeFile(crcPath); if (data) { - MMKVMetaInfo metaInfo; + MetaInfo metaInfo; metaInfo.read(data->getPtr()); crcFile = metaInfo.m_crcDigest; delete data; @@ -1187,7 +1188,7 @@ bool MMKV::isFileValid(const std::string &mmapID) { } auto ptr = (const uint8_t *) fileData->getPtr() + offset; - auto crcDigest = (uint32_t) crc32(0, ptr, actualSize); + auto crcDigest = (uint32_t) zlib::crc32(0, ptr, actualSize); delete fileData; return crcFile == crcDigest; @@ -1203,7 +1204,7 @@ static void mkSpecialCharacterFileDirectory() { static string md5(const string &value) { unsigned char md[MD5_DIGEST_LENGTH] = {0}; char tmp[3] = {0}, buf[33] = {0}; - MD5((const unsigned char *) value.c_str(), value.size(), md); + openssl::MD5((const unsigned char *) value.c_str(), value.size(), md); for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { sprintf_s(tmp, sizeof(tmp), "%2.2x", md[i]); strcat_s(buf, sizeof(tmp), tmp); diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 145cb9e9..1ef51488 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -32,16 +32,18 @@ #include #include -class CodedOutputData; +namespace mmkv { class AESCrypt; +class CodedOutputData; +} // namespace mmkv enum MMKVMode : uint32_t { MMKV_SINGLE_PROCESS = 0x1, MMKV_MULTI_PROCESS = 0x2, }; -class MMKV_API MMKV { - std::unordered_map m_dic; +class MMKV { + std::unordered_map m_dic; std::string m_mmapID; std::wstring m_path; std::wstring m_crcPath; @@ -50,21 +52,21 @@ class MMKV_API MMKV { char *m_ptr; size_t m_size; size_t m_actualSize; - CodedOutputData *m_output; + mmkv::CodedOutputData *m_output; bool m_needLoadFromFile; bool m_hasFullWriteback; uint32_t m_crcDigest; - MmapedFile m_metaFile; - MMKVMetaInfo m_metaInfo; + mmkv::MmapedFile m_metaFile; + mmkv::MetaInfo m_metaInfo; - AESCrypt *m_crypter; + mmkv::AESCrypt *m_crypter; - ThreadLock m_lock; - FileLock m_fileLock; - InterProcessLock m_sharedProcessLock; - InterProcessLock m_exclusiveProcessLock; + mmkv::ThreadLock m_lock; + mmkv::FileLock m_fileLock; + mmkv::InterProcessLock m_sharedProcessLock; + mmkv::InterProcessLock m_exclusiveProcessLock; void loadFromFile(); @@ -86,13 +88,13 @@ class MMKV_API MMKV { bool fullWriteback(); - const MMBuffer &getDataForKey(const std::string &key); + const mmkv::MMBuffer &getDataForKey(const std::string &key); - bool setDataForKey(MMBuffer &&data, const std::string &key); + bool setDataForKey(mmkv::MMBuffer &&data, const std::string &key); bool removeDataForKey(const std::string &key); - bool appendDataWithKey(const MMBuffer &data, const std::string &key); + bool appendDataWithKey(const mmkv::MMBuffer &data, const std::string &key); void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey); @@ -102,8 +104,8 @@ class MMKV_API MMKV { public: MMKV(const std::string &mmapID, - int size = DEFAULT_MMAP_SIZE, MMKVMode mode = MMKV_SINGLE_PROCESS, + int size = mmkv::DEFAULT_MMAP_SIZE, std::string *cryptKey = nullptr); ~MMKV(); @@ -116,8 +118,8 @@ class MMKV_API MMKV { // mmapID: any unique ID (com.tencent.xin.pay, etc) // if you want a per-user mmkv, you could merge user-id within mmapID static MMKV *mmkvWithID(const std::string &mmapID, - int size = DEFAULT_MMAP_SIZE, MMKVMode mode = MMKV_SINGLE_PROCESS, + int size = mmkv::DEFAULT_MMAP_SIZE, std::string *cryptKey = nullptr); static void onExit(); @@ -139,7 +141,7 @@ class MMKV_API MMKV { bool setStringForKey(const std::string &value, const std::string &key); - bool setBytesForKey(const MMBuffer &value, const std::string &key); + bool setBytesForKey(const mmkv::MMBuffer &value, const std::string &key); bool set(bool value, const std::string &key); @@ -159,7 +161,7 @@ class MMKV_API MMKV { bool getStringForKey(const std::string &key, std::string &result); - MMBuffer getBytesForKey(const std::string &key); + mmkv::MMBuffer getBytesForKey(const std::string &key); bool getBoolForKey(const std::string &key, bool defaultValue = false); diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 65e8dff9..2354daf3 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -181,14 +181,14 @@ - - - - - + + + + + - + diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index 142a6e57..6389c138 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -128,22 +128,22 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files diff --git a/Win32/MMKV/MMKVDef.h b/Win32/MMKV/MMKVDef.h index d896096c..871ec8ee 100644 --- a/Win32/MMKV/MMKVDef.h +++ b/Win32/MMKV/MMKVDef.h @@ -5,10 +5,3 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files #include - -//#ifdef MMKV_EXPORTS -//#define MMKV_API __declspec(dllexport) -//#else -//#define MMKV_API __declspec(dllimport) -//#endif -#define MMKV_API diff --git a/Win32/MMKV/MMKVMetaInfo.hpp b/Win32/MMKV/MMKVMetaInfo.hpp index 157bf832..10869063 100644 --- a/Win32/MMKV/MMKVMetaInfo.hpp +++ b/Win32/MMKV/MMKVMetaInfo.hpp @@ -25,20 +25,24 @@ #include #include -struct MMKVMetaInfo { +namespace mmkv { + +struct MetaInfo { uint32_t m_crcDigest = 0; uint32_t m_version = 1; uint32_t m_sequence = 0; // full write-back count void write(void *ptr) { assert(ptr); - memcpy(ptr, this, sizeof(MMKVMetaInfo)); + memcpy(ptr, this, sizeof(MetaInfo)); } void read(const void *ptr) { assert(ptr); - memcpy(this, ptr, sizeof(MMKVMetaInfo)); + memcpy(this, ptr, sizeof(MetaInfo)); } }; +} // namespace mmkv + #endif //MMKV_MMKVMETAINFO_H diff --git a/Win32/MMKV/MiniPBCoder.cpp b/Win32/MMKV/MiniPBCoder.cpp index 7a805160..bbd07b0f 100644 --- a/Win32/MMKV/MiniPBCoder.cpp +++ b/Win32/MMKV/MiniPBCoder.cpp @@ -30,6 +30,8 @@ using namespace std; +namespace mmkv { + MiniPBCoder::MiniPBCoder() { m_inputBuffer = nullptr; m_inputData = nullptr; @@ -288,3 +290,5 @@ vector MiniPBCoder::decodeSet(const MMBuffer &oData) { MiniPBCoder oCoder(&oData); return oCoder.decodeOneSet(); } + +} // namespace mmkv diff --git a/Win32/MMKV/MiniPBCoder.h b/Win32/MMKV/MiniPBCoder.h index d7706346..b1dd569a 100644 --- a/Win32/MMKV/MiniPBCoder.h +++ b/Win32/MMKV/MiniPBCoder.h @@ -29,15 +29,16 @@ #include #include +namespace mmkv { class CodedInputData; class CodedOutputData; class MiniPBCoder { const MMBuffer *m_inputBuffer; - CodedInputData *m_inputData; + mmkv::CodedInputData *m_inputData; MMBuffer *m_outputBuffer; - CodedOutputData *m_outputData; + mmkv::CodedOutputData *m_outputData; std::vector *m_encodeItems; private: @@ -76,4 +77,6 @@ class MiniPBCoder { size_t size = 0); }; +} // namespace mmkv + #endif //MMKV_MINIPBCODER_H diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index 589807de..124d2c10 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -24,6 +24,8 @@ using namespace std; +namespace mmkv { + const size_t DEFAULT_MMAP_SIZE = getpagesize(); std::wstring string2wstring(const std::string &str) { @@ -231,3 +233,5 @@ bool getfilesize(HANDLE file, size_t &size) { } return false; } + +} // namespace mmkv diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 8f588873..11d17ad3 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -24,7 +24,9 @@ #include "MMKVDef.h" #include -extern MMKV_API const size_t DEFAULT_MMAP_SIZE; +namespace mmkv { + +extern const size_t DEFAULT_MMAP_SIZE; class MmapedFile { std::wstring m_name; @@ -62,4 +64,6 @@ extern bool zeroFillFile(HANDLE file, size_t startPos, size_t size); extern bool ftruncate(HANDLE file, size_t size); extern bool getfilesize(HANDLE file, size_t &size); +} // namespace mmkv + #endif //MMKV_MMAPEDFILE_H diff --git a/Win32/MMKV/PBEncodeItem.hpp b/Win32/MMKV/PBEncodeItem.hpp index 47a8cb1f..80a49d0b 100644 --- a/Win32/MMKV/PBEncodeItem.hpp +++ b/Win32/MMKV/PBEncodeItem.hpp @@ -26,6 +26,8 @@ #include #include +namespace mmkv { + enum PBEncodeItemType { PBEncodeItemType_None, PBEncodeItemType_String, @@ -47,4 +49,6 @@ struct PBEncodeItem { } }; +} // namespace mmkv + #endif //MMKV_PBENCODEITEM_HPP diff --git a/Win32/MMKV/PBUtility.cpp b/Win32/MMKV/PBUtility.cpp index 5fdcb119..62780781 100644 --- a/Win32/MMKV/PBUtility.cpp +++ b/Win32/MMKV/PBUtility.cpp @@ -20,6 +20,8 @@ #include "PBUtility.h" +namespace mmkv { + uint32_t pbRawVarint32Size(int32_t value) { if ((value & (0xffffffff << 7)) == 0) { return 1; @@ -55,3 +57,5 @@ uint32_t pbInt64Size(int64_t value) { } return 10; } + +} // namespace mmkv diff --git a/Win32/MMKV/PBUtility.h b/Win32/MMKV/PBUtility.h index 1dca7fe5..63824cc7 100644 --- a/Win32/MMKV/PBUtility.h +++ b/Win32/MMKV/PBUtility.h @@ -23,6 +23,8 @@ #include +namespace mmkv { + template union Converter { static_assert(sizeof(T) == sizeof(P), "size not match"); @@ -126,4 +128,6 @@ static inline int32_t pbUInt64Size(uint64_t value) { return pbInt64Size(value); } +} // namespace mmkv + #endif //MMKV_PBUTILITY_H diff --git a/Win32/MMKV/ScopedLock.hpp b/Win32/MMKV/ScopedLock.hpp index fe62c0d7..d940be83 100644 --- a/Win32/MMKV/ScopedLock.hpp +++ b/Win32/MMKV/ScopedLock.hpp @@ -23,6 +23,8 @@ #include "MMKVLog.h" +namespace mmkv { + template class ScopedLock { T *m_lock; @@ -63,4 +65,6 @@ class ScopedLock { //#include //#define __SCOPEDLOCK(lock, counter) ScopedLock::type> __scopedLock##counter(lock) +} // namespace mmkv + #endif //MMKV_SCOPEDLOCK_HPP diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index bfa434a5..796d6290 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -21,6 +21,8 @@ #include "ThreadLock.h" #include "MMKVLog.h" +namespace mmkv { + ThreadLock::ThreadLock() : m_lock{0} { // TODO: a better spin count? if (!InitializeCriticalSectionAndSpinCount(&m_lock, 1024)) { @@ -64,3 +66,5 @@ void ThreadLock::ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback } } } + +} // namespace mmkv diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h index 83879bd4..7a8febbf 100644 --- a/Win32/MMKV/ThreadLock.h +++ b/Win32/MMKV/ThreadLock.h @@ -23,6 +23,8 @@ #include "MMKVDef.h" +namespace mmkv { + enum ThreadOnceToken : LONG { ThreadOnceUninitialized = 0, ThreadOnceInitializing, @@ -43,4 +45,6 @@ class ThreadLock { static void ThreadOnce(ThreadOnceToken volatile &onceToken, void (*callback)(void)); }; +} // namespace mmkv + #endif //MMKV_THREADLOCK_H diff --git a/Win32/MMKV/aes/AESCrypt.cpp b/Win32/MMKV/aes/AESCrypt.cpp index 78a4b133..b47705a1 100644 --- a/Win32/MMKV/aes/AESCrypt.cpp +++ b/Win32/MMKV/aes/AESCrypt.cpp @@ -19,10 +19,13 @@ */ #include "AESCrypt.h" -#include "openssl/aes.h" #include #include +using namespace openssl; + +namespace mmkv { + AESCrypt::AESCrypt(const unsigned char *key, size_t keyLength) { if (key && keyLength > 0) { memcpy(m_key, key, (keyLength > AES_KEY_LEN) ? AES_KEY_LEN : keyLength); @@ -58,11 +61,15 @@ void AESCrypt::decrypt(const unsigned char *input, unsigned char *output, size_t AES_cfb128_encrypt(input, output, length, &m_aesKey, m_vector, &m_number, AES_DECRYPT); } +} // namespace mmkv + #ifndef NDEBUG #include "../MMKVLog.h" #include "../MmapedFile.h" +namespace mmkv { + // check if AESCrypt is encrypt-decrypt full-duplex void testAESCrypt() { const unsigned char plainText[] = "Hello, OpenSSL with AES CFB 128."; @@ -114,4 +121,6 @@ void testAESCrypt() { delete[] decryptText; } -#endif \ No newline at end of file +} // namespace mmkv + +#endif // NDEBUG diff --git a/Win32/MMKV/aes/AESCrypt.h b/Win32/MMKV/aes/AESCrypt.h index 0196bd9e..21c4ea6e 100644 --- a/Win32/MMKV/aes/AESCrypt.h +++ b/Win32/MMKV/aes/AESCrypt.h @@ -27,11 +27,13 @@ constexpr size_t AES_KEY_LEN = 16; constexpr size_t AES_KEY_BITSET_LEN = 128; -// a AES CFB-128 encrypt-decrypt full-duplex wrapper +namespace mmkv { + + // a AES CFB-128 encrypt-decrypt full-duplex wrapper class AESCrypt { unsigned char m_vector[AES_KEY_LEN] = {0}; unsigned char m_key[AES_KEY_LEN] = {0}; - AES_KEY m_aesKey = {0}; + openssl::AES_KEY m_aesKey = {0}; int m_number = 0; public: @@ -54,4 +56,6 @@ void testAESCrypt(); #endif +} // namespace mmkv + #endif /* AES_CRYPT_H_ */ diff --git a/Win32/MMKV/aes/openssl/aes.h b/Win32/MMKV/aes/openssl/aes.h index 33da448c..b671f614 100644 --- a/Win32/MMKV/aes/openssl/aes.h +++ b/Win32/MMKV/aes/openssl/aes.h @@ -13,9 +13,8 @@ # include "opensslconf.h" # include -# ifdef __cplusplus -extern "C" { -# endif + +namespace openssl { # define AES_ENCRYPT 1 # define AES_DECRYPT 0 @@ -48,8 +47,6 @@ void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, int *num, const int enc); -# ifdef __cplusplus -} -# endif +} // namespace openssl #endif diff --git a/Win32/MMKV/aes/openssl/aes_cfb.c b/Win32/MMKV/aes/openssl/aes_cfb.cpp similarity index 97% rename from Win32/MMKV/aes/openssl/aes_cfb.c rename to Win32/MMKV/aes/openssl/aes_cfb.cpp index ffe6438b..da23dcd6 100644 --- a/Win32/MMKV/aes/openssl/aes_cfb.c +++ b/Win32/MMKV/aes/openssl/aes_cfb.cpp @@ -10,6 +10,8 @@ #include "aes.h" #include "modes.h" +namespace openssl { + /* * The input and output encrypted as though 128bit cfb mode is being used. * The extra state information to record how much of the 128bit block we have @@ -24,3 +26,5 @@ void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, (block128_f) AES_encrypt); } + +} diff --git a/Win32/MMKV/aes/openssl/aes_core.c b/Win32/MMKV/aes/openssl/aes_core.cpp similarity index 99% rename from Win32/MMKV/aes/openssl/aes_core.c rename to Win32/MMKV/aes/openssl/aes_core.cpp index 74ac4193..92cc7ba3 100644 --- a/Win32/MMKV/aes/openssl/aes_core.c +++ b/Win32/MMKV/aes/openssl/aes_core.cpp @@ -42,6 +42,8 @@ #include "aes.h" #include "aes_locl.h" +namespace openssl { + /*- Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; @@ -916,3 +918,5 @@ void AES_encrypt(const unsigned char *in, unsigned char *out, rk[3]; PUTU32(out + 12, s3); } + +} // namespace openssl diff --git a/Win32/MMKV/aes/openssl/cfb128.c b/Win32/MMKV/aes/openssl/cfb128.cpp similarity index 98% rename from Win32/MMKV/aes/openssl/cfb128.c rename to Win32/MMKV/aes/openssl/cfb128.cpp index 3f5a809b..019e28bf 100644 --- a/Win32/MMKV/aes/openssl/cfb128.c +++ b/Win32/MMKV/aes/openssl/cfb128.cpp @@ -11,6 +11,8 @@ #include "modes.h" #include +namespace openssl { + /* * The input and output encrypted as though 128bit cfb mode is being used. * The extra state information to record how much of the 128bit block we have @@ -129,3 +131,5 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, *num = n; } } + +} // namespace openssl diff --git a/Win32/MMKV/aes/openssl/md32_common.h b/Win32/MMKV/aes/openssl/md32_common.h index ae397e84..5a879ffe 100644 --- a/Win32/MMKV/aes/openssl/md32_common.h +++ b/Win32/MMKV/aes/openssl/md32_common.h @@ -81,9 +81,9 @@ #ifndef HASH_UPDATE # error "HASH_UPDATE must be defined!" #endif -#ifndef HASH_TRANSFORM -# error "HASH_TRANSFORM must be defined!" -#endif +//#ifndef HASH_TRANSFORM +//# error "HASH_TRANSFORM must be defined!" +//#endif #ifndef HASH_FINAL # error "HASH_FINAL must be defined!" #endif @@ -126,7 +126,7 @@ int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { - const unsigned char *data = data_; + auto data = (const unsigned char *) data_; unsigned char *p; HASH_LONG l; size_t n; @@ -182,10 +182,10 @@ int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) return 1; } -void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data) -{ - HASH_BLOCK_DATA_ORDER(c, data, 1); -} +//void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data) +//{ +// HASH_BLOCK_DATA_ORDER(c, data, 1); +//} int HASH_FINAL(unsigned char *md, HASH_CTX *c) { diff --git a/Win32/MMKV/aes/openssl/md5.h b/Win32/MMKV/aes/openssl/md5.h index 18fac685..3636c4de 100644 --- a/Win32/MMKV/aes/openssl/md5.h +++ b/Win32/MMKV/aes/openssl/md5.h @@ -14,9 +14,8 @@ # ifndef OPENSSL_NO_MD5 # include -# ifdef __cplusplus -extern "C" { -# endif + +namespace openssl { /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -40,10 +39,9 @@ int MD5_Init(MD5_CTX *c); int MD5_Update(MD5_CTX *c, const void *data, size_t len); int MD5_Final(unsigned char *md, MD5_CTX *c); unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); -void MD5_Transform(MD5_CTX *c, const unsigned char *b); -# ifdef __cplusplus -} -# endif + +} // namespace openssl + # endif #endif diff --git a/Win32/MMKV/aes/openssl/md5_dgst.c b/Win32/MMKV/aes/openssl/md5_dgst.cpp similarity index 98% rename from Win32/MMKV/aes/openssl/md5_dgst.c rename to Win32/MMKV/aes/openssl/md5_dgst.cpp index d3b89ff0..85c2feb8 100644 --- a/Win32/MMKV/aes/openssl/md5_dgst.c +++ b/Win32/MMKV/aes/openssl/md5_dgst.cpp @@ -10,6 +10,8 @@ #include #include "md5_locl.h" +namespace openssl { + /* * Implemented from RFC1321 The MD5 Message-Digest Algorithm */ @@ -35,7 +37,7 @@ int MD5_Init(MD5_CTX *c) # endif void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num) { - const unsigned char *data = data_; + auto data = (const unsigned char *) data_; register unsigned MD32_REG_T A, B, C, D, l; # ifndef MD32_XARRAY /* See comment in crypto/sha/sha_locl.h for details. */ @@ -161,3 +163,5 @@ void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num) } } #endif + +} // namespace openssl diff --git a/Win32/MMKV/aes/openssl/md5_locl.h b/Win32/MMKV/aes/openssl/md5_locl.h index 03e68d44..d20eaed7 100644 --- a/Win32/MMKV/aes/openssl/md5_locl.h +++ b/Win32/MMKV/aes/openssl/md5_locl.h @@ -11,6 +11,8 @@ #include #include "md5.h" +namespace openssl { + void md5_block_data_order(MD5_CTX *c, const void *p, size_t num); #define DATA_ORDER_IS_LITTLE_ENDIAN @@ -19,7 +21,7 @@ void md5_block_data_order(MD5_CTX *c, const void *p, size_t num); #define HASH_CTX MD5_CTX #define HASH_CBLOCK MD5_CBLOCK #define HASH_UPDATE MD5_Update -#define HASH_TRANSFORM MD5_Transform +//#define HASH_TRANSFORM MD5_Transform #define HASH_FINAL MD5_Final #define HASH_MAKE_STRING(c,s) do { \ unsigned long ll; \ @@ -66,3 +68,5 @@ void md5_block_data_order(MD5_CTX *c, const void *p, size_t num); a+=((k)+(t)+I((b),(c),(d))); \ a=ROTATE(a,s); \ a+=b; }; + +} // namespace openssl diff --git a/Win32/MMKV/aes/openssl/md5_one.c b/Win32/MMKV/aes/openssl/md5_one.cpp similarity index 96% rename from Win32/MMKV/aes/openssl/md5_one.c rename to Win32/MMKV/aes/openssl/md5_one.cpp index 30d56c0d..0f37b318 100644 --- a/Win32/MMKV/aes/openssl/md5_one.c +++ b/Win32/MMKV/aes/openssl/md5_one.cpp @@ -11,6 +11,8 @@ #include #include "md5.h" +namespace openssl { + unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md) { MD5_CTX c; @@ -24,3 +26,5 @@ unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md) MD5_Final(md, &c); return md; } + +} diff --git a/Win32/MMKV/aes/openssl/modes.h b/Win32/MMKV/aes/openssl/modes.h index 6fab3d6f..0d8c2d76 100644 --- a/Win32/MMKV/aes/openssl/modes.h +++ b/Win32/MMKV/aes/openssl/modes.h @@ -9,9 +9,8 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +namespace openssl { + typedef void (*block128_f) (const unsigned char in[16], unsigned char out[16], const void *key); @@ -19,9 +18,6 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t len, const void *key, unsigned char ivec[16], int *num, int enc, block128_f block); -#ifdef __cplusplus } #define STRICT_ALIGNMENT 1 - -#endif diff --git a/Win32/MMKV/crc32/Checksum.h b/Win32/MMKV/crc32/Checksum.h index e21554d8..7a00dfb0 100644 --- a/Win32/MMKV/crc32/Checksum.h +++ b/Win32/MMKV/crc32/Checksum.h @@ -21,12 +21,8 @@ #pragma once #include "zlib/zconf.h" -#ifdef __cplusplus -extern "C" { -#endif +namespace zlib { -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, z_size_t len)); +uLong crc32(uLong crc, const Bytef *buf, z_size_t len); -#ifdef __cplusplus } -#endif diff --git a/Win32/MMKV/crc32/zlib/crc32.c b/Win32/MMKV/crc32/zlib/crc32.c deleted file mode 100644 index 04a4271b..00000000 --- a/Win32/MMKV/crc32/zlib/crc32.c +++ /dev/null @@ -1,168 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -# define TBLS 1 - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); - -#include "crc32.h" - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - if (buf == Z_NULL) return 0UL; - - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - return crc32_z(crc, buf, len); -} - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} - -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} diff --git a/Win32/MMKV/crc32/zlib/crc32.cpp b/Win32/MMKV/crc32/zlib/crc32.cpp new file mode 100644 index 00000000..51bd8406 --- /dev/null +++ b/Win32/MMKV/crc32/zlib/crc32.cpp @@ -0,0 +1,49 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ +# define TBLS 1 + +#include "crc32.h" + +namespace zlib { + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long local crc32_z(unsigned long crc, const unsigned char FAR *buf, z_size_t len) +{ + if (buf == Z_NULL) return 0UL; + + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ + +unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, z_size_t len) { + return crc32_z(crc, buf, len); +} + +} // namespace zlib diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index a79cb706..060826ae 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -160,7 +160,7 @@ void processTest() { CloseHandle(pi[index].hThread); } - auto mmkv = MMKV::mmkvWithID("process_test", 0, MMKV_MULTI_PROCESS); + auto mmkv = MMKV::mmkvWithID("process_test", MMKV_MULTI_PROCESS); cout << "total count of process_test: " << mmkv->count() << endl; } diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index 43a38154..8bf70ec3 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -49,7 +49,7 @@ void brutleTest(DWORD processID) { using hclock = chrono::high_resolution_clock; auto start = hclock::now(); - auto mmkv = MMKV::mmkvWithID(MMKV_ID, 0, MMKV_MULTI_PROCESS); + auto mmkv = MMKV::mmkvWithID(MMKV_ID, MMKV_MULTI_PROCESS); for (size_t i = 0; i < keyCount; i++) { mmkv->set(i, arrIntKeys[i]); //mmkv->setStringForKey("str-" + i, arrStringKeys[i]); From 999e3609bd10f74d845d69a688fc290e27260c48 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 21 Dec 2018 16:57:44 +0800 Subject: [PATCH 24/57] error handler & interface cleanup --- Win32/MMKV/MMKV.cpp | 26 ++++++++++++++++--- Win32/MMKV/MMKV.h | 49 ++++++++++++++++++++--------------- Win32/Win32Demo/Win32Demo.cpp | 2 +- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 1eeebc1c..6dc6d280 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -46,6 +46,7 @@ using namespace mmkv; static unordered_map *g_instanceDic; static ThreadLock g_instanceLock; static std::wstring g_rootDir; +static MMKV::ErrorHandler g_errorHandler; #define DEFAULT_MMAP_ID "mmkv.default" #define SPECIAL_CHARACTER_DIRECTORY_NAME L"specialCharacter" @@ -57,6 +58,9 @@ static void mkSpecialCharacterFileDirectory(); static string md5(const string &value); static wstring encodeFilePath(const string &mmapID); +static MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID); +static MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID); + enum : bool { KeepSequence = false, IncreaseSequence = true, @@ -1196,6 +1200,16 @@ bool MMKV::isFileValid(const std::string &mmapID) { return false; } +void MMKV::regiserErrorHandler(ErrorHandler handler) { + SCOPEDLOCK(g_instanceLock); + g_errorHandler = handler; +} + +void MMKV::unRegisetErrorHandler() { + SCOPEDLOCK(g_instanceLock); + g_errorHandler = nullptr; +} + static void mkSpecialCharacterFileDirectory() { wstring path = g_rootDir + L"/" + SPECIAL_CHARACTER_DIRECTORY_NAME; mkPath(path); @@ -1240,10 +1254,16 @@ static wstring crcPathWithID(const string &mmapID, MMKVMode mode) { return g_rootDir + L"\\" + encodeFilePath(mmapID) + L".crc"; } -MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { +static MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) { + if (g_errorHandler) { + return g_errorHandler(mmapID, MMKVErrorType::MMKVCRCCheckFail); + } return OnErrorDiscard; } -MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) { +static MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) { + if (g_errorHandler) { + return g_errorHandler(mmapID, MMKVErrorType::MMKVFileLength); + } return OnErrorDiscard; -} +} \ No newline at end of file diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 1ef51488..e33f735d 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -42,6 +42,16 @@ enum MMKVMode : uint32_t { MMKV_MULTI_PROCESS = 0x2, }; +enum MMKVRecoverStrategic : int { + OnErrorDiscard = 0, + OnErrorRecover, +}; + +enum MMKVErrorType : int { + MMKVCRCCheckFail = 0, + MMKVFileLength, +}; + class MMKV { std::unordered_map m_dic; std::string m_mmapID; @@ -68,6 +78,13 @@ class MMKV { mmkv::InterProcessLock m_sharedProcessLock; mmkv::InterProcessLock m_exclusiveProcessLock; + MMKV(const std::string &mmapID, + MMKVMode mode = MMKV_SINGLE_PROCESS, + int size = mmkv::DEFAULT_MMAP_SIZE, + std::string *cryptKey = nullptr); + + ~MMKV(); + void loadFromFile(); void partialLoadFromFile(); @@ -103,13 +120,7 @@ class MMKV { MMKV &operator=(const MMKV &other) = delete; public: - MMKV(const std::string &mmapID, - MMKVMode mode = MMKV_SINGLE_PROCESS, - int size = mmkv::DEFAULT_MMAP_SIZE, - std::string *cryptKey = nullptr); - - ~MMKV(); - + // call this before getting any MMKV instance static void initializeMMKV(const std::wstring &rootDir); // a generic purpose instance @@ -139,10 +150,6 @@ class MMKV { // usually you should call this method after other process reKey() the inter-process mmkv void checkReSetCryptKey(const std::string *cryptKey); - bool setStringForKey(const std::string &value, const std::string &key); - - bool setBytesForKey(const mmkv::MMBuffer &value, const std::string &key); - bool set(bool value, const std::string &key); bool set(int32_t value, const std::string &key); @@ -159,6 +166,10 @@ class MMKV { bool set(const std::vector &vector, const std::string &key); + bool setStringForKey(const std::string &value, const std::string &key); + + bool setBytesForKey(const mmkv::MMBuffer &value, const std::string &key); + bool getStringForKey(const std::string &key, std::string &result); mmkv::MMBuffer getBytesForKey(const std::string &key); @@ -212,17 +223,13 @@ class MMKV { static bool isFileValid(const std::string &mmapID); - void lock() { m_exclusiveProcessLock.lock(); } - void unlock() { m_exclusiveProcessLock.unlock(); } -}; + void lock() { m_isInterProcess ? m_exclusiveProcessLock.lock() : m_lock.lock(); } + void unlock() { m_isInterProcess ? m_exclusiveProcessLock.unlock() : m_lock.unlock(); } -enum MMKVRecoverStrategic : int { - OnErrorDiscard = 0, - OnErrorRecover, + typedef MMKVRecoverStrategic (*ErrorHandler)(const std::string &mmapID, + MMKVErrorType errorType); + static void regiserErrorHandler(ErrorHandler handler); + static void unRegisetErrorHandler(); }; -MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID); - -MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID); - #endif // MMKV_MMKV_H diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 060826ae..7f58826f 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -181,6 +181,6 @@ int main() { } //brutleTest(); - //threadTest(); + threadTest(); processTest(); } From 967b955a21e0882892dc5c565a801c9d4f10bfb7 Mon Sep 17 00:00:00 2001 From: JonyFang Date: Mon, 24 Dec 2018 11:06:40 +0800 Subject: [PATCH 25/57] Ignore .DS_Store Signed-off-by: JonyFang --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index cb2e9819..8ff0b548 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,8 @@ xcuserdata *.xcscmblueprint *.xcscheme +## OS X +.DS_Store + ## Xcode DerivedData \ No newline at end of file From 71d1f4ec99654f89c52aff0808c8e51c0dc8c522 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 24 Dec 2018 11:59:59 +0800 Subject: [PATCH 26/57] =?UTF-8?q?iOS:=20=E6=96=B0=E5=A2=9E=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E6=94=AF=E6=8C=81custom=20folder=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MMKV.h | 5 ++ iOS/MMKV/MMKV/MMKV.mm | 148 ++++++++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 63 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index c7dbb030..51bed9fb 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -36,6 +36,9 @@ NS_ASSUME_NONNULL_BEGIN // cryptKey: 16 byte at most + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey NS_SWIFT_NAME(init(mmapID:cryptKey:)); ++ (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path; ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path; + - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); - (nullable NSData *)cryptKey; @@ -98,6 +101,7 @@ NS_ASSUME_NONNULL_BEGIN - (size_t)count; - (size_t)totalSize; + - (size_t)actualSize; - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; @@ -127,6 +131,7 @@ NS_ASSUME_NONNULL_BEGIN // for CrashProtected Only!! + (BOOL)isFileValid:(NSString *)mmapID NS_SWIFT_NAME(isFileValid(for:)); ++ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path; + (void)registerHandler:(id)handler; + (void)unregiserHandler; diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 13f0c3f0..9cc678b2 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -89,66 +89,64 @@ + (instancetype)defaultMMKV { // any unique ID (com.tencent.xin.pay, etc) + (instancetype)mmkvWithID:(NSString *)mmapID { - if (mmapID.length <= 0) { - return nil; - } - CScopedLock lock(g_instanceLock); - - MMKV *kv = [g_instanceDic objectForKey:mmapID]; - if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:nil]; - [g_instanceDic setObject:kv forKey:mmapID]; - } - return kv; + return [self mmkvWithID:mmapID cryptKey:nil]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - if (mmapID.length <= 0) { - return nil; - } - CScopedLock lock(g_instanceLock); - - MMKV *kv = [g_instanceDic objectForKey:mmapID]; - if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey]; - [g_instanceDic setObject:kv forKey:mmapID]; - } - return kv; -} - -- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - if (self = [super init]) { - m_lock = [[NSRecursiveLock alloc] init]; - - m_mmapID = mmapID; - - m_path = [MMKV mappedKVPathWithID:m_mmapID]; - if (!isFileExist(m_path)) { - createFile(m_path); - } - m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; - - if (cryptKey.length > 0) { - m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); - } - - [self loadFromFile]; - + return [self mmkvWithID:mmapID cryptKey:cryptKey relativePath:nil]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { + return [self mmkvWithID:mmapID cryptKey:nil relativePath:path]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)path { + if (mmapID.length <= 0) { + return nil; + } + CScopedLock lock(g_instanceLock); + + MMKV *kv = [g_instanceDic objectForKey:mmapID]; + if (kv == nil) { + kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; + [g_instanceDic setObject:kv forKey:mmapID]; + } + return kv; +} + +- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { + if (self = [super init]) { + m_lock = [[NSRecursiveLock alloc] init]; + + m_mmapID = mmapID; + + m_path = [MMKV mappedKVPathWithID:m_mmapID relativePath:relativePath]; + if (!isFileExist(m_path)) { + createFile(m_path); + } + m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; + + if (cryptKey.length > 0) { + m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); + } + + [self loadFromFile]; + #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED - auto appState = [UIApplication sharedApplication].applicationState; - if (appState == UIApplicationStateBackground) { - m_isInBackground = YES; - } else { - m_isInBackground = NO; - } - MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; + auto appState = [UIApplication sharedApplication].applicationState; + if (appState == UIApplicationStateBackground) { + m_isInBackground = YES; + } else { + m_isInBackground = NO; + } + MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; #endif - } - return self; + } + return self; } - (void)dealloc { @@ -1281,14 +1279,34 @@ - (void)sync { } } ++ (NSString *)mappedKVBasePath { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *nsLibraryPath = (NSString *)[paths firstObject]; + if ([nsLibraryPath length] > 0) { + return [nsLibraryPath stringByAppendingPathComponent:@"mmkv"]; + } else { + return @""; + } +} + + (NSString *)mappedKVPathWithID:(NSString *)mmapID { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *nsLibraryPath = (NSString *) [paths firstObject]; - if ([nsLibraryPath length] > 0) { - return [nsLibraryPath stringByAppendingFormat:@"/mmkv/%@", encodeMmapID(mmapID)]; - } else { - return @""; - } + return [self mappedKVPathWithID:mmapID relativePath:nil]; +} + ++ (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { + // TODO: 检查path. + if ([path length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [path stringByAppendingPathComponent:mmapIDstring]; + } else { + NSString *basePath = [self mappedKVBasePath]; + if ([basePath length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [basePath stringByAppendingPathComponent:mmapIDstring]; + } else { + return @""; + } + } } + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { @@ -1296,9 +1314,13 @@ + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { } + (BOOL)isFileValid:(NSString *)mmapID { + return [self isFileValid:mmapID relativePath:nil]; +} + ++ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *kvPath = [self mappedKVPathWithID:mmapID]; + NSString *kvPath = [self mappedKVPathWithID:mmapID relativePath:path]; if ([fileManager fileExistsAtPath:kvPath] == NO) { // kv file not exist return YES; From 3605358f303bd72c5567d38c717250f7cfbb23f9 Mon Sep 17 00:00:00 2001 From: JonyFang Date: Mon, 24 Dec 2018 17:59:33 +0800 Subject: [PATCH 27/57] Update to relative links Signed-off-by: JonyFang --- CONTRIBUTING.md | 4 ++-- README.md | 12 ++++++------ readme_cn.md | 10 +++++++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea19f30f..f90ce902 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,10 +51,10 @@ Before submitting a pull request, please make sure the followings are done: 6. Now, you can submit your pull request on `dev` or `hotfix` branch. ## Code Style Guide -Use [Code Style](https://github.com/Tencent/MMKV/blob/master/Android/MMKV/checkstyle.xml) for Java and Android. +Use [Code Style](./Android/MMKV/checkstyle.xml) for Java and Android. * 4 spaces for indentation rather than tabs ## License By contributing to MMKV, you agree that your contributions will be licensed -under its [BSD LICENSE](https://github.com/Tencent/MMKV/blob/master/LICENSE.txt) +under its [BSD LICENSE](./LICENSE.txt) diff --git a/README.md b/README.md index 51517d05..5c9f8356 100644 --- a/README.md +++ b/README.md @@ -122,15 +122,15 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc ## License MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT). - -## Change Log -Check out the [CHANGELOG.md](./CHANGELOG.md) for details of change history. + +## Change Log +Check out the [CHANGELOG.md](./CHANGELOG.md) for details of change history. ## Contributing -If you are interested in contributing, check out the [CONTRIBUTING.md](https://github.com/Tencent/MMKV/blob/master/CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). - -To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](https://github.com/Tencent/MMKV/blob/master/CODE_OF_CONDUCT.md). +If you are interested in contributing, check out the [CONTRIBUTING.md](./CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). + +To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](./CODE_OF_CONDUCT.md). ## FAQ & Feedback Check out the [FAQ](https://github.com/Tencent/MMKV/wiki/FAQ) first. Should there be any questions, don't hesitate to create [issues](https://github.com/Tencent/MMKV/issues). diff --git a/readme_cn.md b/readme_cn.md index da3d88d3..5fac214a 100644 --- a/readme_cn.md +++ b/readme_cn.md @@ -105,12 +105,16 @@ MMKV 支持**多进程访问**,更详细的用法参考 [Android Tutorial](htt 更详细的性能对比参考 [Android Benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark_cn)。 ## License -MMKV 以 BSD 3-Clause 证书开源,详情参见 [LICENSE.TXT](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT)。 +MMKV 以 BSD 3-Clause 证书开源,详情参见 [LICENSE.TXT](./LICENSE.TXT)。 ## 版本历史 具体版本历史请参看 [CHANGELOG.md](./CHANGELOG.md)。 -## 参与贡献 如果你有兴趣参与贡献,可以参考 [CONTRIBUTING.md](https://github.com/Tencent/MMKV/blob/master/CONTRIBUTING.md)。 [腾讯开源激励计划](https://opensource.tencent.com/contribution) 鼓励开发者的参与和贡献,期待你的加入。 为了明确我们对参与者的期望,MMKV 采用了被广泛使用的、由 Contributor Covenant 所定义的行为准则。我们认为它很好地阐明了我们的价值观。有关更多信息请查看 [Code of Conduct](https://github.com/Tencent/MMKV/blob/master/CODE_OF_CONDUCT.md)。 - +## 参与贡献 +如果你有兴趣参与贡献,可以参考 [CONTRIBUTING.md](./CONTRIBUTING.md)。 +[腾讯开源激励计划](https://opensource.tencent.com/contribution) 鼓励开发者的参与和贡献,期待你的加入。 + +为了明确我们对参与者的期望,MMKV 采用了被广泛使用的、由 Contributor Covenant 所定义的行为准则。我们认为它很好地阐明了我们的价值观。有关更多信息请查看 [Code of Conduct](./CODE_OF_CONDUCT.md)。 + ## 问题 & 反馈 常见问题参见 [FAQ](https://github.com/Tencent/MMKV/wiki/FAQ_cn),欢迎提 [issues](https://github.com/Tencent/MMKV/issues) 提问反馈。 From e35d36a1e09afeeb20b039b5e2a61ac905a35cc1 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 24 Dec 2018 21:48:02 +0800 Subject: [PATCH 28/57] copy header for outside sln --- README.md | 62 ++++++++++----------- Win32/MMKV/CodedInputData.cpp | 1 - Win32/MMKV/InterProcessLock.cpp | 2 + Win32/MMKV/InterProcessLock.h | 3 +- Win32/MMKV/MMKV.cpp | 5 +- Win32/MMKV/MMKV.h | 2 +- Win32/MMKV/MMKV.vcxproj | 28 +++++++--- Win32/MMKV/MMKV.vcxproj.filters | 47 +++++++++------- Win32/MMKV/MMKVDef.h | 7 --- Win32/MMKV/MMKVMetaInfo.hpp | 2 +- Win32/MMKV/MiniPBCoder.cpp | 4 +- Win32/MMKV/MmapedFile.cpp | 4 +- Win32/MMKV/MmapedFile.h | 1 - Win32/MMKV/ThreadLock.cpp | 4 +- Win32/MMKV/ThreadLock.h | 2 - Win32/MMKV/aes/AESCrypt.cpp | 2 + Win32/MMKV/pch.cpp | 21 +++++++ Win32/MMKV/pch.h | 27 +++++++++ Win32/Win32Demo/Win32Demo.cpp | 1 + Win32/Win32DemoProcess/Win32DemoProcess.cpp | 1 + 20 files changed, 146 insertions(+), 80 deletions(-) delete mode 100644 Win32/MMKV/MMKVDef.h create mode 100644 Win32/MMKV/pch.cpp create mode 100644 Win32/MMKV/pch.h diff --git a/README.md b/README.md index 9da33dd1..6c504cab 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Writing random `int` for 10000 times, we get this chart: ![](https://github.com/Tencent/MMKV/wiki/assets/profile_mini.jpg) For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/iOS_benchmark). -# MMKV for Android +# MMKV for Windows ## Features @@ -70,47 +70,46 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc ## Getting Started -### Installation Via Maven -Add the following lines to `build.gradle` on your app module: - -```gradle -dependencies { - implementation 'com.tencent:mmkv:1.0.14' - // replace "1.0.14" with any available version -} -``` +### Installation Via Source +* Clone or Download source from GitHub; +* Add `Win32/MMKV/MMKV.vcxproj` to your solution; +* Add `$(OutDir)` to your project's `C/C++` -> `General` -> `Additional Include Directories`; +* Add `$(OutDir)` to your project's `Linker` -> `General` -> `Additional Library Directories`; +* Add `MMKV.lib` to your project's `Linker` -> `Input` -> `Additional Dependencies`; +* MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or wise versa. For other installation options, see [Android Setup](https://github.com/Tencent/MMKV/wiki/android_setup). ### Quick Tutorial -You can use MMKV as you go. All changes are saved immediately, no `sync`, no `apply` calls needed. -Setup MMKV on App startup, say your `MainActivity`, add these lines: +You can use MMKV as you go. All changes are saved immediately, no `sync`, no `save` calls needed. +Setup MMKV on App startup, say in your `main()`, add these lines: -```Java -protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - String rootDir = MMKV.initialize(this); - System.out.println("mmkv root: " + rootDir); - //…… +```C++ +#include "MMKV.h" +using namespace std; + +int main() { + wstring rootDir = getYourAppDocumentDir(); + MMKV::initializeMMKV(rootDir); + //... } ``` MMKV has a global instance, that can be used directly: -```Java -import com.tencent.mmkv.MMKV; - -MMKV kv = MMKV.defaultMMKV(); +```C++ +auto mmkv = MMKV::defaultMMKV(); -kv.encode("bool", true); -boolean bValue = kv.decodeBool("bool"); - -kv.encode("int", Integer.MIN_VALUE); -int iValue = kv.decodeInt("int"); - -kv.encode("string", "Hello from mmkv"); -String str = kv.decodeString("string"); +mmkv->set(true, "bool"); +cout << "bool = " << mmkv->getBoolForKey("bool") << endl; + +mmkv->set(1024, "int32"); +cout << "int32 = " << mmkv->getInt32ForKey("int32") << endl; + +mmkv->setStringForKey("Hello, MMKV for Win32 ", "string"); +string result; +mmkv->getStringForKey("string", result); +cout << "string = " << result << endl; ``` MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Android Tutorial](https://github.com/Tencent/MMKV/wiki/android_tutorial). @@ -119,6 +118,7 @@ MMKV also supports **Multi-Process Access**. Full tutorials can be found here [A Writing random `int` for 1000 times, we get this chart: ![](https://github.com/Tencent/MMKV/wiki/assets/profile_android_mini.jpg) For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark). + ## License MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT). diff --git a/Win32/MMKV/CodedInputData.cpp b/Win32/MMKV/CodedInputData.cpp index 812adbe9..976ba9ce 100644 --- a/Win32/MMKV/CodedInputData.cpp +++ b/Win32/MMKV/CodedInputData.cpp @@ -22,7 +22,6 @@ #include "MMKVLog.h" #include "PBUtility.h" #include -#include using namespace std; diff --git a/Win32/MMKV/InterProcessLock.cpp b/Win32/MMKV/InterProcessLock.cpp index 4230c40c..06eb51e0 100644 --- a/Win32/MMKV/InterProcessLock.cpp +++ b/Win32/MMKV/InterProcessLock.cpp @@ -18,6 +18,8 @@ * limitations under the License. */ +#include "pch.h" + #include "InterProcessLock.h" #include "MMKVLog.h" diff --git a/Win32/MMKV/InterProcessLock.h b/Win32/MMKV/InterProcessLock.h index e72222e8..4980a63b 100644 --- a/Win32/MMKV/InterProcessLock.h +++ b/Win32/MMKV/InterProcessLock.h @@ -21,8 +21,7 @@ #ifndef MMKV_INTERPROCESSLOCK_H #define MMKV_INTERPROCESSLOCK_H -#include "MMKVDef.h" -#include +#include namespace mmkv { diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 6dc6d280..e3c5d072 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -21,12 +21,13 @@ * limitations under the License. */ -#include "MMKV.h" +#include "pch.h" + #include "CodedInputData.h" #include "CodedOutputData.h" #include "InterProcessLock.h" #include "MMBuffer.h" -#include "MMKVDef.h" +#include "MMKV.h" #include "MMKVLog.h" #include "MiniPBCoder.h" #include "MmapedFile.h" diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index e33f735d..1d3f6d2f 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -227,7 +227,7 @@ class MMKV { void unlock() { m_isInterProcess ? m_exclusiveProcessLock.unlock() : m_lock.unlock(); } typedef MMKVRecoverStrategic (*ErrorHandler)(const std::string &mmapID, - MMKVErrorType errorType); + MMKVErrorType errorType); static void regiserErrorHandler(ErrorHandler handler); static void unRegisetErrorHandler(); }; diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 2354daf3..a1621d10 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -114,7 +114,7 @@ - NotUsing + Use Level3 MaxSpeed true @@ -123,6 +123,7 @@ WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true MultiThreaded + pch.h Windows @@ -165,19 +166,29 @@ - + - - - - + + + false + true + false + true + + + false + true + false + true + + - + - + @@ -195,6 +206,7 @@ + diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index 6389c138..69eb3db4 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -18,36 +18,18 @@ Header Files - - Header Files - - - Header Files - Header Files Header Files - - Header Files - Header Files - - Header Files - - - Header Files - Header Files - - Header Files - Header Files @@ -57,9 +39,6 @@ Header Files - - Header Files - Header Files @@ -96,6 +75,9 @@ Header Files + + Header Files + @@ -146,5 +128,28 @@ Source Files + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/Win32/MMKV/MMKVDef.h b/Win32/MMKV/MMKVDef.h deleted file mode 100644 index 871ec8ee..00000000 --- a/Win32/MMKV/MMKVDef.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include diff --git a/Win32/MMKV/MMKVMetaInfo.hpp b/Win32/MMKV/MMKVMetaInfo.hpp index 10869063..ae1a6713 100644 --- a/Win32/MMKV/MMKVMetaInfo.hpp +++ b/Win32/MMKV/MMKVMetaInfo.hpp @@ -29,7 +29,7 @@ namespace mmkv { struct MetaInfo { uint32_t m_crcDigest = 0; - uint32_t m_version = 1; + uint32_t m_version = 1; // not in use uint32_t m_sequence = 0; // full write-back count void write(void *ptr) { diff --git a/Win32/MMKV/MiniPBCoder.cpp b/Win32/MMKV/MiniPBCoder.cpp index bbd07b0f..5272a9f6 100644 --- a/Win32/MMKV/MiniPBCoder.cpp +++ b/Win32/MMKV/MiniPBCoder.cpp @@ -18,10 +18,12 @@ * limitations under the License. */ -#include "MiniPBCoder.h" +#include "pch.h" + #include "CodedInputData.h" #include "CodedOutputData.h" #include "MMBuffer.h" +#include "MiniPBCoder.h" #include "PBEncodeItem.hpp" #include "PBUtility.h" #include diff --git a/Win32/MMKV/MmapedFile.cpp b/Win32/MMKV/MmapedFile.cpp index 124d2c10..8cacaa6c 100644 --- a/Win32/MMKV/MmapedFile.cpp +++ b/Win32/MMKV/MmapedFile.cpp @@ -18,9 +18,11 @@ * limitations under the License. */ -#include "MmapedFile.h" +#include "pch.h" + #include "MMBuffer.h" #include "MMKVLog.h" +#include "MmapedFile.h" using namespace std; diff --git a/Win32/MMKV/MmapedFile.h b/Win32/MMKV/MmapedFile.h index 11d17ad3..46aef49a 100644 --- a/Win32/MMKV/MmapedFile.h +++ b/Win32/MMKV/MmapedFile.h @@ -21,7 +21,6 @@ #ifndef MMKV_MMAPEDFILE_H #define MMKV_MMAPEDFILE_H -#include "MMKVDef.h" #include namespace mmkv { diff --git a/Win32/MMKV/ThreadLock.cpp b/Win32/MMKV/ThreadLock.cpp index 796d6290..64c900c1 100644 --- a/Win32/MMKV/ThreadLock.cpp +++ b/Win32/MMKV/ThreadLock.cpp @@ -18,8 +18,10 @@ * limitations under the License. */ -#include "ThreadLock.h" +#include "pch.h" + #include "MMKVLog.h" +#include "ThreadLock.h" namespace mmkv { diff --git a/Win32/MMKV/ThreadLock.h b/Win32/MMKV/ThreadLock.h index 7a8febbf..227eb37b 100644 --- a/Win32/MMKV/ThreadLock.h +++ b/Win32/MMKV/ThreadLock.h @@ -21,8 +21,6 @@ #ifndef MMKV_THREADLOCK_H #define MMKV_THREADLOCK_H -#include "MMKVDef.h" - namespace mmkv { enum ThreadOnceToken : LONG { diff --git a/Win32/MMKV/aes/AESCrypt.cpp b/Win32/MMKV/aes/AESCrypt.cpp index b47705a1..02f77c07 100644 --- a/Win32/MMKV/aes/AESCrypt.cpp +++ b/Win32/MMKV/aes/AESCrypt.cpp @@ -65,6 +65,8 @@ void AESCrypt::decrypt(const unsigned char *input, unsigned char *output, size_t #ifndef NDEBUG +#include "../pch.h" + #include "../MMKVLog.h" #include "../MmapedFile.h" diff --git a/Win32/MMKV/pch.cpp b/Win32/MMKV/pch.cpp new file mode 100644 index 00000000..5b8068f7 --- /dev/null +++ b/Win32/MMKV/pch.cpp @@ -0,0 +1,21 @@ +/* + * 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 "pch.h" diff --git a/Win32/MMKV/pch.h b/Win32/MMKV/pch.h new file mode 100644 index 00000000..b4572663 --- /dev/null +++ b/Win32/MMKV/pch.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 7f58826f..16d3e4ac 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -19,6 +19,7 @@ */ #include "pch.h" + #include "MMKV.h" #include #include diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index 8bf70ec3..32e07482 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -19,6 +19,7 @@ */ #include "pch.h" + #include "MMKV.h" #include #include From 46188486d2a7f713f62120f71a1df1fa9d5e8265 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 24 Dec 2018 11:59:59 +0800 Subject: [PATCH 29/57] =?UTF-8?q?iOS:=20=E6=96=B0=E5=A2=9E=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E6=94=AF=E6=8C=81custom=20folder=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MMKV.h | 5 ++ iOS/MMKV/MMKV/MMKV.mm | 148 ++++++++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 63 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index c7dbb030..ffa94dc7 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -36,6 +36,9 @@ NS_ASSUME_NONNULL_BEGIN // cryptKey: 16 byte at most + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey NS_SWIFT_NAME(init(mmapID:cryptKey:)); ++ (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:relativePath:)); ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); + - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); - (nullable NSData *)cryptKey; @@ -98,6 +101,7 @@ NS_ASSUME_NONNULL_BEGIN - (size_t)count; - (size_t)totalSize; + - (size_t)actualSize; - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; @@ -127,6 +131,7 @@ NS_ASSUME_NONNULL_BEGIN // for CrashProtected Only!! + (BOOL)isFileValid:(NSString *)mmapID NS_SWIFT_NAME(isFileValid(for:)); ++ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(isFileValid(for:relativePath:)); + (void)registerHandler:(id)handler; + (void)unregiserHandler; diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 13f0c3f0..9cc678b2 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -89,66 +89,64 @@ + (instancetype)defaultMMKV { // any unique ID (com.tencent.xin.pay, etc) + (instancetype)mmkvWithID:(NSString *)mmapID { - if (mmapID.length <= 0) { - return nil; - } - CScopedLock lock(g_instanceLock); - - MMKV *kv = [g_instanceDic objectForKey:mmapID]; - if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:nil]; - [g_instanceDic setObject:kv forKey:mmapID]; - } - return kv; + return [self mmkvWithID:mmapID cryptKey:nil]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - if (mmapID.length <= 0) { - return nil; - } - CScopedLock lock(g_instanceLock); - - MMKV *kv = [g_instanceDic objectForKey:mmapID]; - if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey]; - [g_instanceDic setObject:kv forKey:mmapID]; - } - return kv; -} - -- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - if (self = [super init]) { - m_lock = [[NSRecursiveLock alloc] init]; - - m_mmapID = mmapID; - - m_path = [MMKV mappedKVPathWithID:m_mmapID]; - if (!isFileExist(m_path)) { - createFile(m_path); - } - m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; - - if (cryptKey.length > 0) { - m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); - } - - [self loadFromFile]; - + return [self mmkvWithID:mmapID cryptKey:cryptKey relativePath:nil]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { + return [self mmkvWithID:mmapID cryptKey:nil relativePath:path]; +} + ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)path { + if (mmapID.length <= 0) { + return nil; + } + CScopedLock lock(g_instanceLock); + + MMKV *kv = [g_instanceDic objectForKey:mmapID]; + if (kv == nil) { + kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; + [g_instanceDic setObject:kv forKey:mmapID]; + } + return kv; +} + +- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { + if (self = [super init]) { + m_lock = [[NSRecursiveLock alloc] init]; + + m_mmapID = mmapID; + + m_path = [MMKV mappedKVPathWithID:m_mmapID relativePath:relativePath]; + if (!isFileExist(m_path)) { + createFile(m_path); + } + m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; + + if (cryptKey.length > 0) { + m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); + } + + [self loadFromFile]; + #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED - auto appState = [UIApplication sharedApplication].applicationState; - if (appState == UIApplicationStateBackground) { - m_isInBackground = YES; - } else { - m_isInBackground = NO; - } - MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; + auto appState = [UIApplication sharedApplication].applicationState; + if (appState == UIApplicationStateBackground) { + m_isInBackground = YES; + } else { + m_isInBackground = NO; + } + MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; #endif - } - return self; + } + return self; } - (void)dealloc { @@ -1281,14 +1279,34 @@ - (void)sync { } } ++ (NSString *)mappedKVBasePath { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *nsLibraryPath = (NSString *)[paths firstObject]; + if ([nsLibraryPath length] > 0) { + return [nsLibraryPath stringByAppendingPathComponent:@"mmkv"]; + } else { + return @""; + } +} + + (NSString *)mappedKVPathWithID:(NSString *)mmapID { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *nsLibraryPath = (NSString *) [paths firstObject]; - if ([nsLibraryPath length] > 0) { - return [nsLibraryPath stringByAppendingFormat:@"/mmkv/%@", encodeMmapID(mmapID)]; - } else { - return @""; - } + return [self mappedKVPathWithID:mmapID relativePath:nil]; +} + ++ (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { + // TODO: 检查path. + if ([path length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [path stringByAppendingPathComponent:mmapIDstring]; + } else { + NSString *basePath = [self mappedKVBasePath]; + if ([basePath length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [basePath stringByAppendingPathComponent:mmapIDstring]; + } else { + return @""; + } + } } + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { @@ -1296,9 +1314,13 @@ + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { } + (BOOL)isFileValid:(NSString *)mmapID { + return [self isFileValid:mmapID relativePath:nil]; +} + ++ (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *kvPath = [self mappedKVPathWithID:mmapID]; + NSString *kvPath = [self mappedKVPathWithID:mmapID relativePath:path]; if ([fileManager fileExistsAtPath:kvPath] == NO) { // kv file not exist return YES; From 8c94c4f780181626926bd6ae0f8391fe24efce03 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 25 Dec 2018 01:13:54 +0800 Subject: [PATCH 30/57] =?UTF-8?q?relativePath=20=E6=9C=89=E6=95=88?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=20m=5FmmapID=20=E7=94=B1=20relativePath=20+?= =?UTF-8?q?=20mmapID=20md5=20=E7=94=9F=E6=88=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MMKV.mm | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 9cc678b2..29c7d49b 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -47,6 +47,7 @@ #define CRC_FILE_SIZE DEFAULT_MMAP_SIZE #define SPECIAL_CHARACTER_DIRECTORY_NAME @"specialCharacter" +static NSString *md5(NSString *value); static NSString *encodeMmapID(NSString *mmapID); @implementation MMKV { @@ -106,21 +107,33 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati } CScopedLock lock(g_instanceLock); - MMKV *kv = [g_instanceDic objectForKey:mmapID]; + NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path]; + MMKV *kv = [g_instanceDic objectForKey:kvKey]; if (kv == nil) { kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; - [g_instanceDic setObject:kv forKey:mmapID]; + [g_instanceDic setObject:kv forKey:kvKey]; } return kv; } ++ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { + NSString *string = nil; + if (relativePath) { + string = md5([relativePath stringByAppendingPathComponent:mmapID]); + } else { + string = mmapID; + } + MMKVInfo(@"%s mmapKey: %@", __PRETTY_FUNCTION__, string); + return string; +} + - (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { if (self = [super init]) { m_lock = [[NSRecursiveLock alloc] init]; - m_mmapID = mmapID; + m_mmapID = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; - m_path = [MMKV mappedKVPathWithID:m_mmapID relativePath:relativePath]; + m_path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; if (!isFileExist(m_path)) { createFile(m_path); } From 14bade408e5925b4cd0264c7a8c6f670cbb91914 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 25 Dec 2018 01:37:00 +0800 Subject: [PATCH 31/57] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=88=A4=E6=96=AD=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=88=9B=E5=BB=BAmmap=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E8=8B=A5=E5=8F=AF=E4=BB=A5=EF=BC=8C=E5=88=99=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD=E5=88=9D=E5=A7=8B=E5=8C=96=E6=93=8D=E4=BD=9C=EF=BC=8C?= =?UTF-8?q?=E8=8B=A5=E4=B8=8D=E5=8F=AF=E4=BB=A5=EF=BC=8C=E5=88=99=E8=BF=94?= =?UTF-8?q?=E5=9B=9Enil=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MMKV.mm | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 29c7d49b..9e2356df 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -105,6 +105,10 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati if (mmapID.length <= 0) { return nil; } + if (![self canCreateMMKVPath:mmapID relativePath:path]) { + return nil; + } + CScopedLock lock(g_instanceLock); NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path]; @@ -116,9 +120,23 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati return kv; } ++ (BOOL)canCreateMMKVPath:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { + if (relativePath) { + NSString *path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; + if (isFileExist(path)) { + return true; + } else { + BOOL ret = createFile(path); + return ret; + } + } else { + return true; + } +} + + (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { NSString *string = nil; - if (relativePath) { + if ([relativePath length] > 0) { string = md5([relativePath stringByAppendingPathComponent:mmapID]); } else { string = mmapID; @@ -1307,7 +1325,6 @@ + (NSString *)mappedKVPathWithID:(NSString *)mmapID { } + (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { - // TODO: 检查path. if ([path length] > 0) { NSString *mmapIDstring = encodeMmapID(mmapID); return [path stringByAppendingPathComponent:mmapIDstring]; From 55d571dfe1a4be8cf0430324d35ca435e0781385 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 25 Dec 2018 18:45:21 +0800 Subject: [PATCH 32/57] support vs 2015 --- README.md | 4 +++- Win32/MMKV/MMKV.vcxproj | 34 ++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 6c504cab..ba1498e0 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,12 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc ### Installation Via Source * Clone or Download source from GitHub; * Add `Win32/MMKV/MMKV.vcxproj` to your solution; +* Add MMKV to your project's dependencies; * Add `$(OutDir)` to your project's `C/C++` -> `General` -> `Additional Include Directories`; * Add `$(OutDir)` to your project's `Linker` -> `General` -> `Additional Library Directories`; * Add `MMKV.lib` to your project's `Linker` -> `Input` -> `Additional Dependencies`; -* MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or wise versa. +* MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or wise versa. +* MMKV is developed with Visual Studio 2017, change the `Platform Toolset` if you use a different version of Visual Studio. For other installation options, see [Android Setup](https://github.com/Tencent/MMKV/wiki/android_setup). diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index a1621d10..bcea5d56 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -96,6 +96,12 @@ Windows true + + for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y %%f "$(OutDir)" + + + Copying Header Files + @@ -131,6 +137,12 @@ true true + + for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y %%f "$(OutDir)" + + + Copying Header Files + @@ -166,29 +178,19 @@ - + - - - false - true - false - true - - - false - true - false - true - + + + - + - + From 7c89ce162a4b78f8c4f700f249c4e5470ae86ad8 Mon Sep 17 00:00:00 2001 From: Sunnyyoung Date: Wed, 26 Dec 2018 00:18:53 +0800 Subject: [PATCH 33/57] Initializers should be nullable --- iOS/MMKV/MMKV/MMKV.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index ffa94dc7..0855d411 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -36,8 +36,8 @@ NS_ASSUME_NONNULL_BEGIN // cryptKey: 16 byte at most + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey NS_SWIFT_NAME(init(mmapID:cryptKey:)); -+ (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:relativePath:)); -+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:relativePath:)); ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); - (nullable NSData *)cryptKey; From 8ecc09a8fb3a5cc462b71ed1f031da121ca13a90 Mon Sep 17 00:00:00 2001 From: Sunnyyoung Date: Wed, 26 Dec 2018 00:28:15 +0800 Subject: [PATCH 34/57] Added missing comments --- iOS/MMKV/MMKV/MMKV.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index 0855d411..c38d480a 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -36,7 +36,15 @@ NS_ASSUME_NONNULL_BEGIN // cryptKey: 16 byte at most + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey NS_SWIFT_NAME(init(mmapID:cryptKey:)); +// mmapID: any unique ID (com.tencent.xin.pay, etc) +// if you want a per-user mmkv, you could merge user-id within mmapID +// relativePath: custom path of the file, `NSDocumentDirectory/mmkv` by default + (nullable instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:relativePath:)); + +// mmapID: any unique ID (com.tencent.xin.pay, etc) +// if you want a per-user mmkv, you could merge user-id within mmapID +// cryptKey: 16 byte at most +// relativePath: custom path of the file, `NSDocumentDirectory/mmkv` by default + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); From 66b231d4f43e314b619730305b064d6e1ddbd4ca Mon Sep 17 00:00:00 2001 From: Sunnyyoung Date: Wed, 26 Dec 2018 00:28:56 +0800 Subject: [PATCH 35/57] Formatted code --- iOS/MMKV/MMKV/MMKV.mm | 184 +++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 9e2356df..a284a0ec 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -90,94 +90,94 @@ + (instancetype)defaultMMKV { // any unique ID (com.tencent.xin.pay, etc) + (instancetype)mmkvWithID:(NSString *)mmapID { - return [self mmkvWithID:mmapID cryptKey:nil]; + return [self mmkvWithID:mmapID cryptKey:nil]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey { - return [self mmkvWithID:mmapID cryptKey:cryptKey relativePath:nil]; + return [self mmkvWithID:mmapID cryptKey:cryptKey relativePath:nil]; } + (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { - return [self mmkvWithID:mmapID cryptKey:nil relativePath:path]; + return [self mmkvWithID:mmapID cryptKey:nil relativePath:path]; } + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)path { - if (mmapID.length <= 0) { - return nil; - } - if (![self canCreateMMKVPath:mmapID relativePath:path]) { - return nil; - } - - CScopedLock lock(g_instanceLock); - - NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path]; - MMKV *kv = [g_instanceDic objectForKey:kvKey]; - if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; - [g_instanceDic setObject:kv forKey:kvKey]; - } - return kv; + if (mmapID.length <= 0) { + return nil; + } + if (![self canCreateMMKVPath:mmapID relativePath:path]) { + return nil; + } + + CScopedLock lock(g_instanceLock); + + NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path]; + MMKV *kv = [g_instanceDic objectForKey:kvKey]; + if (kv == nil) { + kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; + [g_instanceDic setObject:kv forKey:kvKey]; + } + return kv; } + (BOOL)canCreateMMKVPath:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { - if (relativePath) { - NSString *path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; - if (isFileExist(path)) { - return true; - } else { - BOOL ret = createFile(path); - return ret; - } - } else { - return true; - } + if (relativePath) { + NSString *path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; + if (isFileExist(path)) { + return true; + } else { + BOOL ret = createFile(path); + return ret; + } + } else { + return true; + } } + (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { - NSString *string = nil; - if ([relativePath length] > 0) { - string = md5([relativePath stringByAppendingPathComponent:mmapID]); - } else { - string = mmapID; - } - MMKVInfo(@"%s mmapKey: %@", __PRETTY_FUNCTION__, string); - return string; + NSString *string = nil; + if ([relativePath length] > 0) { + string = md5([relativePath stringByAppendingPathComponent:mmapID]); + } else { + string = mmapID; + } + MMKVInfo(@"%s mmapKey: %@", __PRETTY_FUNCTION__, string); + return string; } - (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { - if (self = [super init]) { - m_lock = [[NSRecursiveLock alloc] init]; - - m_mmapID = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; - - m_path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; - if (!isFileExist(m_path)) { - createFile(m_path); - } - m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; - - if (cryptKey.length > 0) { - m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); - } - - [self loadFromFile]; - + if (self = [super init]) { + m_lock = [[NSRecursiveLock alloc] init]; + + m_mmapID = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; + + m_path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; + if (!isFileExist(m_path)) { + createFile(m_path); + } + m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; + + if (cryptKey.length > 0) { + m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length); + } + + [self loadFromFile]; + #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED - auto appState = [UIApplication sharedApplication].applicationState; - if (appState == UIApplicationStateBackground) { - m_isInBackground = YES; - } else { - m_isInBackground = NO; - } - MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; + auto appState = [UIApplication sharedApplication].applicationState; + if (appState == UIApplicationStateBackground) { + m_isInBackground = YES; + } else { + m_isInBackground = NO; + } + MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; #endif - } - return self; + } + return self; } - (void)dealloc { @@ -1248,9 +1248,9 @@ - (size_t)totalSize { } - (size_t)actualSize { - CScopedLock lock(m_lock); - [self checkLoadData]; - return m_actualSize; + CScopedLock lock(m_lock); + [self checkLoadData]; + return m_actualSize; } - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block { @@ -1311,32 +1311,32 @@ - (void)sync { } + (NSString *)mappedKVBasePath { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *nsLibraryPath = (NSString *)[paths firstObject]; - if ([nsLibraryPath length] > 0) { - return [nsLibraryPath stringByAppendingPathComponent:@"mmkv"]; - } else { - return @""; - } + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *nsLibraryPath = (NSString *) [paths firstObject]; + if ([nsLibraryPath length] > 0) { + return [nsLibraryPath stringByAppendingPathComponent:@"mmkv"]; + } else { + return @""; + } } + (NSString *)mappedKVPathWithID:(NSString *)mmapID { - return [self mappedKVPathWithID:mmapID relativePath:nil]; + return [self mappedKVPathWithID:mmapID relativePath:nil]; } + (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { - if ([path length] > 0) { - NSString *mmapIDstring = encodeMmapID(mmapID); - return [path stringByAppendingPathComponent:mmapIDstring]; - } else { - NSString *basePath = [self mappedKVBasePath]; - if ([basePath length] > 0) { - NSString *mmapIDstring = encodeMmapID(mmapID); - return [basePath stringByAppendingPathComponent:mmapIDstring]; - } else { - return @""; - } - } + if ([path length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [path stringByAppendingPathComponent:mmapIDstring]; + } else { + NSString *basePath = [self mappedKVBasePath]; + if ([basePath length] > 0) { + NSString *mmapIDstring = encodeMmapID(mmapID); + return [basePath stringByAppendingPathComponent:mmapIDstring]; + } else { + return @""; + } + } } + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { @@ -1344,7 +1344,7 @@ + (NSString *)crcPathWithMappedKVPath:(NSString *)kvPath { } + (BOOL)isFileValid:(NSString *)mmapID { - return [self isFileValid:mmapID relativePath:nil]; + return [self isFileValid:mmapID relativePath:nil]; } + (BOOL)isFileValid:(NSString *)mmapID relativePath:(nullable NSString *)path { From 6e8c0d70b51157d4dcc0ddf7c15de4589fdd68d8 Mon Sep 17 00:00:00 2001 From: TL Date: Fri, 28 Dec 2018 18:44:56 +0800 Subject: [PATCH 36/57] update LRUCache size checking --- iOS/MMKV/MMKV/LRUCache.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/MMKV/MMKV/LRUCache.hpp b/iOS/MMKV/MMKV/LRUCache.hpp index b9f0e535..00c95279 100644 --- a/iOS/MMKV/MMKV/LRUCache.hpp +++ b/iOS/MMKV/MMKV/LRUCache.hpp @@ -50,7 +50,7 @@ class LRUCache { m_list.splice(m_list.begin(), m_list, itr->second); itr->second->second = value; } else { - if (m_map.size() == m_capacity) { + if (m_map.size() >= m_capacity) { m_map.erase(m_list.back().first); m_list.pop_back(); } From d9d19f6968e1e56c5e7ba6ca5f20760403654ddd Mon Sep 17 00:00:00 2001 From: connorlu Date: Fri, 28 Dec 2018 22:11:25 +0800 Subject: [PATCH 37/57] =?UTF-8?q?fix(location=20MiniPBCoder):=20m=5FisTopO?= =?UTF-8?q?bject=E5=B9=B6=E6=B2=A1=E6=9C=89=E4=BB=80=E4=B9=88=E4=BD=9C?= =?UTF-8?q?=E7=94=A8=EF=BC=8C=E5=BB=BA=E8=AE=AE=E5=88=A0=E9=99=A4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MMKV/MMKV/MiniPBCoder.mm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/iOS/MMKV/MMKV/MiniPBCoder.mm b/iOS/MMKV/MMKV/MiniPBCoder.mm index 78842a54..12f50e03 100644 --- a/iOS/MMKV/MMKV/MiniPBCoder.mm +++ b/iOS/MMKV/MMKV/MiniPBCoder.mm @@ -31,7 +31,6 @@ @implementation MiniPBCoder { NSObject *m_obj; - BOOL m_isTopObject; NSData *m_inputBuffer; MiniCodedInputData *m_inputData; @@ -42,7 +41,6 @@ @implementation MiniPBCoder { - (id)initForReadingWithData:(NSData *)data { if (self = [super init]) { - m_isTopObject = YES; m_inputBuffer = data; m_inputData = new MiniCodedInputData(data); } @@ -218,7 +216,6 @@ + (NSData *)encodeDataWithObject:(NSObject *)obj { #pragma mark - decode - (NSMutableDictionary *)decodeOneDictionaryOfValueClass:(Class)cls { - m_isTopObject = NO; if (cls == nullptr) { return nil; } @@ -249,9 +246,7 @@ - (id)decodeOneObject:(id)obj ofClass:(Class)cls { if (!cls) { cls = [(NSObject *) obj class]; } - - m_isTopObject = NO; - + if (cls == [NSString class]) { return m_inputData->readString(); } else if (cls == [NSMutableString class]) { From a845187f2a9a0556fc7e5ba72585123a51136853 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 16:28:46 +0800 Subject: [PATCH 38/57] refactor path creation & pretty log --- iOS/MMKV/MMKV/MMKV.h | 2 + iOS/MMKV/MMKV/MMKV.mm | 58 +++++++++---------------- iOS/MMKV/MMKV/MMKVLog.h | 8 ++-- iOS/MMKVDemo/MMKVDemo/ViewController.mm | 5 ++- 4 files changed, 30 insertions(+), 43 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index c38d480a..d31d7f25 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -144,6 +144,8 @@ NS_ASSUME_NONNULL_BEGIN + (void)registerHandler:(id)handler; + (void)unregiserHandler; ++ (NSString *)mappedKVBasePath; + NS_ASSUME_NONNULL_END @end diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index a284a0ec..bc0d491d 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -101,39 +101,28 @@ + (instancetype)mmkvWithID:(NSString *)mmapID relativePath:(nullable NSString *) return [self mmkvWithID:mmapID cryptKey:nil relativePath:path]; } -+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)path { ++ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { if (mmapID.length <= 0) { return nil; } - if (![self canCreateMMKVPath:mmapID relativePath:path]) { + + NSString *kvPath = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; + if (!isFileExist(kvPath)) { + if (!createFile(kvPath)) return nil; } + NSString *kvKey = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; CScopedLock lock(g_instanceLock); - NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path]; MMKV *kv = [g_instanceDic objectForKey:kvKey]; if (kv == nil) { - kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path]; + kv = [[MMKV alloc] initWithMMapID:kvKey cryptKey:cryptKey path:kvPath]; [g_instanceDic setObject:kv forKey:kvKey]; } return kv; } -+ (BOOL)canCreateMMKVPath:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { - if (relativePath) { - NSString *path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; - if (isFileExist(path)) { - return true; - } else { - BOOL ret = createFile(path); - return ret; - } - } else { - return true; - } -} - + (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { NSString *string = nil; if ([relativePath length] > 0) { @@ -141,20 +130,16 @@ + (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSStri } else { string = mmapID; } - MMKVInfo(@"%s mmapKey: %@", __PRETTY_FUNCTION__, string); + MMKVInfo(@"mmapKey: %@", string); return string; } -- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath { +- (instancetype)initWithMMapID:(NSString *)kvKey cryptKey:(NSData *)cryptKey path:(NSString *)path { if (self = [super init]) { m_lock = [[NSRecursiveLock alloc] init]; - m_mmapID = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; - - m_path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; - if (!isFileExist(m_path)) { - createFile(m_path); - } + m_mmapID = kvKey; + m_path = path; m_crcPath = [MMKV crcPathWithMappedKVPath:m_path]; if (cryptKey.length > 0) { @@ -1320,22 +1305,19 @@ + (NSString *)mappedKVBasePath { } } -+ (NSString *)mappedKVPathWithID:(NSString *)mmapID { - return [self mappedKVPathWithID:mmapID relativePath:nil]; -} - + (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { + NSString *basePath = nil; if ([path length] > 0) { + basePath = path; + } else { + basePath = [self mappedKVBasePath]; + } + + if ([basePath length] > 0) { NSString *mmapIDstring = encodeMmapID(mmapID); - return [path stringByAppendingPathComponent:mmapIDstring]; + return [basePath stringByAppendingPathComponent:mmapIDstring]; } else { - NSString *basePath = [self mappedKVBasePath]; - if ([basePath length] > 0) { - NSString *mmapIDstring = encodeMmapID(mmapID); - return [basePath stringByAppendingPathComponent:mmapIDstring]; - } else { - return @""; - } + return @""; } } diff --git a/iOS/MMKV/MMKV/MMKVLog.h b/iOS/MMKV/MMKV/MMKVLog.h index 825931cd..272d72a2 100644 --- a/iOS/MMKV/MMKV/MMKVLog.h +++ b/iOS/MMKV/MMKV/MMKVLog.h @@ -28,12 +28,12 @@ #ifdef ENABLE_MMKV_LOG -#define MMKVError(format, ...) NSLog(format, ##__VA_ARGS__) -#define MMKVWarning(format, ...) NSLog(format, ##__VA_ARGS__) -#define MMKVInfo(format, ...) NSLog(format, ##__VA_ARGS__) +#define MMKVError(format, ...) NSLog(@"[E] [%s, %d] " format, __func__, __LINE__, ##__VA_ARGS__) +#define MMKVWarning(format, ...) NSLog(@"[W] [%s, %d] " format, __func__, __LINE__, ##__VA_ARGS__) +#define MMKVInfo(format, ...) NSLog(@"[I] [%s, %d] " format, __func__, __LINE__, ##__VA_ARGS__) #ifndef NDEBUG -#define MMKVDebug(format, ...) NSLog(format, ##__VA_ARGS__) +#define MMKVDebug(format, ...) NSLog(@"[D] %s-%d " format, __func__, __LINE__, ##__VA_ARGS__) #else #define MMKVDebug(format, ...) \ {} diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController.mm b/iOS/MMKVDemo/MMKVDemo/ViewController.mm index 07d5bdc4..2371e341 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController.mm @@ -61,7 +61,10 @@ - (void)viewDidLoad { } - (void)funcionalTest { - MMKV *mmkv = [MMKV mmkvWithID:@"test/case1"]; + auto path = [MMKV mappedKVBasePath]; + path = [path stringByDeletingLastPathComponent]; + path = [path stringByAppendingPathComponent:@"mmkv_2"]; + auto mmkv = [MMKV mmkvWithID:@"test/case1" relativePath:path]; [mmkv setBool:YES forKey:@"bool"]; NSLog(@"bool:%d", [mmkv getBoolForKey:@"bool"]); From 55e17af96e58319c6d9bcf1b73a40507ae339ae2 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 16:36:25 +0800 Subject: [PATCH 39/57] log for fail to create mmkv file --- iOS/MMKV/MMKV/MMKV.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index bc0d491d..7addebae 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -108,8 +108,10 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati NSString *kvPath = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath]; if (!isFileExist(kvPath)) { - if (!createFile(kvPath)) - return nil; + if (!createFile(kvPath)) { + MMKVError(@"fail to create file at %@", kvPath); + return nil; + } } NSString *kvKey = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath]; From 2dcbbffec0532432b0826f4c23ae2847d44dced3 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 16:46:49 +0800 Subject: [PATCH 40/57] getValueSizeForKey --- iOS/MMKV/MMKV/MMKV.h | 4 ++++ iOS/MMKV/MMKV/MMKV.mm | 8 ++++++++ iOS/MMKVDemo/MMKVDemo/ViewController.mm | 1 + 3 files changed, 13 insertions(+) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index d31d7f25..a502aeb0 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -104,6 +104,10 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSData *)getDataForKey:(NSString *)key NS_SWIFT_NAME(data(forKey:)); - (nullable NSData *)getDataForKey:(NSString *)key defaultValue:(nullable NSData *)defaultValue NS_SWIFT_NAME(data(forKey:defaultValue:)); +// return the actual size consumption of the key's value +// Note: might be a little bigger than value's length +- (size_t)getValueSizeForKey:(NSString *)key NS_SWIFT_NAME(valueSize(forKey:)); + - (BOOL)containsKey:(NSString *)key NS_SWIFT_NAME(contains(key:)); - (size_t)count; diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 7addebae..fa032518 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -1214,6 +1214,14 @@ - (nullable NSData *)getDataForKey:(NSString *)key defaultValue:(nullable NSData return [self getObjectOfClass:NSData.class forKey:key]; } +- (size_t)getValueSizeForKey:(NSString *)key NS_SWIFT_NAME(valueSize(forKey:)) { + if (key.length <= 0) { + return 0; + } + NSData *data = [self getRawDataForKey:key]; + return data.length; +} + #pragma mark - enumerate - (BOOL)containsKey:(NSString *)key { diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController.mm b/iOS/MMKVDemo/MMKVDemo/ViewController.mm index 2371e341..667ceffc 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController.mm @@ -102,6 +102,7 @@ - (void)funcionalTest { [mmkv setData:[@"hello, mmkv again and again" dataUsingEncoding:NSUTF8StringEncoding] forKey:@"data"]; NSData *data = [mmkv getDataForKey:@"data"]; NSLog(@"data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + NSLog(@"data length:%zu, value size consumption:%zu", data.length, [mmkv getValueSizeForKey:@"data"]); [mmkv removeValueForKey:@"bool"]; NSLog(@"bool:%d", [mmkv getBoolForKey:@"bool"]); From f997f332cb87486f8c3b3a6e7ba16558176b51f7 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 16:58:36 +0800 Subject: [PATCH 41/57] setMMKVBasePath --- iOS/MMKV/MMKV/MMKV.h | 5 +++-- iOS/MMKV/MMKV/MMKV.mm | 23 ++++++++++++++++++----- iOS/MMKVDemo/MMKVDemo/ViewController.mm | 8 +++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index a502aeb0..1cadfffd 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -47,6 +47,9 @@ NS_ASSUME_NONNULL_BEGIN // relativePath: custom path of the file, `NSDocumentDirectory/mmkv` by default + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); ++ (NSString *)mmkvBasePath; ++ (void)setMMKVBasePath:(NSString *)basePath; + - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); - (nullable NSData *)cryptKey; @@ -148,8 +151,6 @@ NS_ASSUME_NONNULL_BEGIN + (void)registerHandler:(id)handler; + (void)unregiserHandler; -+ (NSString *)mappedKVBasePath; - NS_ASSUME_NONNULL_END @end diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index fa032518..254636a4 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -1305,22 +1305,35 @@ - (void)sync { } } -+ (NSString *)mappedKVBasePath { +static NSString *g_basePath = nil; ++ (NSString *)mmkvBasePath { + if (g_basePath.length > 0) { + return g_basePath; + } + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *nsLibraryPath = (NSString *) [paths firstObject]; - if ([nsLibraryPath length] > 0) { - return [nsLibraryPath stringByAppendingPathComponent:@"mmkv"]; + NSString *documentPath = (NSString *) [paths firstObject]; + if ([documentPath length] > 0) { + g_basePath = [documentPath stringByAppendingPathComponent:@"mmkv"]; + return g_basePath; } else { return @""; } } ++ (void)setMMKVBasePath:(NSString *)basePath { + if (basePath.length > 0) { + g_basePath = basePath; + MMKVInfo(@"set MMKV base path to: %@", g_basePath); + } +} + + (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { NSString *basePath = nil; if ([path length] > 0) { basePath = path; } else { - basePath = [self mappedKVBasePath]; + basePath = [self mmkvBasePath]; } if ([basePath length] > 0) { diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController.mm b/iOS/MMKVDemo/MMKVDemo/ViewController.mm index 667ceffc..11d23ae4 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController.mm @@ -36,6 +36,12 @@ @implementation ViewController { - (void)viewDidLoad { [super viewDidLoad]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); + NSString *libraryPath = (NSString *) [paths firstObject]; + if ([libraryPath length] > 0) { + NSString *rootDir = [libraryPath stringByAppendingPathComponent:@"mmkv"]; + [MMKV setMMKVBasePath:rootDir]; + } [MMKV registerHandler:self]; [self funcionalTest]; @@ -61,7 +67,7 @@ - (void)viewDidLoad { } - (void)funcionalTest { - auto path = [MMKV mappedKVBasePath]; + auto path = [MMKV mmkvBasePath]; path = [path stringByDeletingLastPathComponent]; path = [path stringByAppendingPathComponent:@"mmkv_2"]; auto mmkv = [MMKV mmkvWithID:@"test/case1" relativePath:path]; From 2588d032c1a642ab6bbb26402f80fd2c49eadc7c Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 17:06:44 +0800 Subject: [PATCH 42/57] robust mmapKey --- iOS/MMKV/MMKV/MMKV.mm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/iOS/MMKV/MMKV/MMKV.mm b/iOS/MMKV/MMKV/MMKV.mm index 254636a4..ddd6ed0a 100644 --- a/iOS/MMKV/MMKV/MMKV.mm +++ b/iOS/MMKV/MMKV/MMKV.mm @@ -125,17 +125,6 @@ + (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relati return kv; } -+ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { - NSString *string = nil; - if ([relativePath length] > 0) { - string = md5([relativePath stringByAppendingPathComponent:mmapID]); - } else { - string = mmapID; - } - MMKVInfo(@"mmapKey: %@", string); - return string; -} - - (instancetype)initWithMMapID:(NSString *)kvKey cryptKey:(NSData *)cryptKey path:(NSString *)path { if (self = [super init]) { m_lock = [[NSRecursiveLock alloc] init]; @@ -1328,6 +1317,17 @@ + (void)setMMKVBasePath:(NSString *)basePath { } } ++ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath { + NSString *string = nil; + if ([relativePath length] > 0 && [relativePath isEqualToString:[MMKV mmkvBasePath]] == NO) { + string = md5([relativePath stringByAppendingPathComponent:mmapID]); + } else { + string = mmapID; + } + MMKVInfo(@"mmapKey: %@", string); + return string; +} + + (NSString *)mappedKVPathWithID:(NSString *)mmapID relativePath:(nullable NSString *)path { NSString *basePath = nil; if ([path length] > 0) { From 7c4fe8ffc7b2c4d7a10809e998f7a898b6282e61 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 17:11:41 +0800 Subject: [PATCH 43/57] doc for setMMKVBasePath --- iOS/MMKV/MMKV/MMKV.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index 1cadfffd..81442bd6 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -47,7 +47,11 @@ NS_ASSUME_NONNULL_BEGIN // relativePath: custom path of the file, `NSDocumentDirectory/mmkv` by default + (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); +// default to `NSDocumentDirectory/mmkv` + (NSString *)mmkvBasePath; + +// if you want to change the base path, do it BEFORE getting any MMKV instance +// otherwise the behavior is undefined + (void)setMMKVBasePath:(NSString *)basePath; - (BOOL)reKey:(nullable NSData *)newKey NS_SWIFT_NAME(reset(cryptKey:)); From ea751a2859a7c9dbe4a1649ff2b3e6c25597a5c8 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 17:22:52 +0800 Subject: [PATCH 44/57] some log for demo --- iOS/MMKVDemo/MMKVDemo/ViewController.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iOS/MMKVDemo/MMKVDemo/ViewController.mm b/iOS/MMKVDemo/MMKVDemo/ViewController.mm index 11d23ae4..e905a018 100644 --- a/iOS/MMKVDemo/MMKVDemo/ViewController.mm +++ b/iOS/MMKVDemo/MMKVDemo/ViewController.mm @@ -36,12 +36,15 @@ @implementation ViewController { - (void)viewDidLoad { [super viewDidLoad]; + // not necessary: set MMKV's root dir NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *libraryPath = (NSString *) [paths firstObject]; if ([libraryPath length] > 0) { NSString *rootDir = [libraryPath stringByAppendingPathComponent:@"mmkv"]; [MMKV setMMKVBasePath:rootDir]; } + + // register error handler [MMKV registerHandler:self]; [self funcionalTest]; From 3df5a7b5ac6f67fdcfb3cd5d6aead1c3d6eb7e31 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 19:41:14 +0800 Subject: [PATCH 45/57] relativePath & custom root dir --- Android/MMKV/mmkv/src/main/cpp/MMKV.cpp | 64 ++++++++++++++----- Android/MMKV/mmkv/src/main/cpp/MMKV.h | 10 +-- Android/MMKV/mmkv/src/main/cpp/MmapedFile.cpp | 34 +++++++++- Android/MMKV/mmkv/src/main/cpp/MmapedFile.h | 1 + .../MMKV/mmkv/src/main/cpp/native-bridge.cpp | 30 ++++++--- .../src/main/java/com/tencent/mmkv/MMKV.java | 53 ++++++++++++--- Android/MMKV/mmkvdemo/build.gradle | 4 +- .../com/tencent/mmkvdemo/MainActivity.java | 30 ++++++--- iOS/MMKV/MMKV/MMKV.h | 3 +- iOS/MMKV/MMKV/MMKVLog.h | 20 +++--- iOS/MMKV/MMKV/MiniPBCoder.mm | 2 +- 11 files changed, 188 insertions(+), 63 deletions(-) diff --git a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp index f1af2904..8c63f710 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp @@ -53,8 +53,10 @@ static std::string g_rootDir; #define SPECIAL_CHARACTER_DIRECTORY_NAME "specialCharacter" constexpr uint32_t Fixed32Size = pbFixed32Size(0); -static string mappedKVPathWithID(const string &mmapID, MMKVMode mode); -static string crcPathWithID(const string &mmapID, MMKVMode mode); +static string mmapedKVKey(const string &mmapID, string *relativePath = nullptr); +static string +mappedKVPathWithID(const string &mmapID, MMKVMode mode, string *relativePath = nullptr); +static string crcPathWithID(const string &mmapID, MMKVMode mode, string *relativePath = nullptr); static void mkSpecialCharacterFileDirectory(); static string md5(const string &value); static string encodeFilePath(const string &mmapID); @@ -64,10 +66,11 @@ enum : bool { IncreaseSequence = true, }; -MMKV::MMKV(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) - : m_mmapID(mmapID) - , m_path(mappedKVPathWithID(m_mmapID, mode)) - , m_crcPath(crcPathWithID(m_mmapID, mode)) +MMKV::MMKV( + const std::string &mmapID, int size, MMKVMode mode, string *cryptKey, string *relativePath) + : m_mmapID(mmapedKVKey(mmapID, relativePath)) + , m_path(mappedKVPathWithID(m_mmapID, mode, relativePath)) + , m_crcPath(crcPathWithID(m_mmapID, mode, relativePath)) , m_metaFile(m_crcPath, DEFAULT_MMAP_SIZE, (mode & MMKV_ASHMEM) ? MMAP_ASHMEM : MMAP_FILE) , m_crypter(nullptr) , m_fileLock(m_metaFile.getFd()) @@ -201,20 +204,32 @@ void MMKV::initializeMMKV(const std::string &rootDir) { MMKVInfo("root dir: %s", g_rootDir.c_str()); } -MMKV *MMKV::mmkvWithID(const std::string &mmapID, int size, MMKVMode mode, string *cryptKey) { +MMKV *MMKV::mmkvWithID( + const std::string &mmapID, int size, MMKVMode mode, string *cryptKey, string *relativePath) { if (mmapID.empty()) { return nullptr; } SCOPEDLOCK(g_instanceLock); - auto itr = g_instanceDic->find(mmapID); + auto mmapKey = mmapedKVKey(mmapID, relativePath); + auto itr = g_instanceDic->find(mmapKey); if (itr != g_instanceDic->end()) { MMKV *kv = itr->second; return kv; } - auto kv = new MMKV(mmapID, size, mode, cryptKey); - (*g_instanceDic)[mmapID] = kv; + if (relativePath) { + auto filePath = mappedKVPathWithID(mmapID, mode, relativePath); + if (!isFileExist(filePath)) { + if (!createFile(filePath)) { + return nullptr; + } + } + MMKVInfo("prepare to load %s (id %s) from relativePath %s", mmapID.c_str(), mmapKey.c_str(), + relativePath->c_str()); + } + auto kv = new MMKV(mmapID, size, mode, cryptKey, relativePath); + (*g_instanceDic)[mmapKey] = kv; return kv; } @@ -1319,7 +1334,7 @@ static string md5(const string &value) { sprintf(tmp, "%2.2x", md[i]); strcat(buf, tmp); } - return buf; + return string(buf); } static string encodeFilePath(const string &mmapID) { @@ -1342,12 +1357,27 @@ static string encodeFilePath(const string &mmapID) { } } -static string mappedKVPathWithID(const string &mmapID, MMKVMode mode) { - return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) - : string(ASHMEM_NAME_DEF) + "/" + encodeFilePath(mmapID); +static string mmapedKVKey(const string &mmapID, string *relativePath) { + if (relativePath && g_rootDir != (*relativePath)) { + return md5(*relativePath + "/" + mmapID); + } + return mmapID; } -static string crcPathWithID(const string &mmapID, MMKVMode mode) { - return (mode & MMKV_ASHMEM) == 0 ? g_rootDir + "/" + encodeFilePath(mmapID) + ".crc" - : encodeFilePath(mmapID) + ".crc"; +static string mappedKVPathWithID(const string &mmapID, MMKVMode mode, string *relativePath) { + if (mode & MMKV_ASHMEM) { + return string(ASHMEM_NAME_DEF) + "/" + encodeFilePath(mmapID); + } else if (relativePath) { + return *relativePath + "/" + encodeFilePath(mmapID); + } + return g_rootDir + "/" + encodeFilePath(mmapID); +} + +static string crcPathWithID(const string &mmapID, MMKVMode mode, string *relativePath) { + if (mode & MMKV_ASHMEM) { + return encodeFilePath(mmapID) + ".crc"; + } else if (relativePath) { + return *relativePath + "/" + encodeFilePath(mmapID) + ".crc"; + } + return g_rootDir + "/" + encodeFilePath(mmapID) + ".crc"; } diff --git a/Android/MMKV/mmkv/src/main/cpp/MMKV.h b/Android/MMKV/mmkv/src/main/cpp/MMKV.h index e73ec5a8..3789f1f0 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MMKV.h +++ b/Android/MMKV/mmkv/src/main/cpp/MMKV.h @@ -106,9 +106,10 @@ class MMKV { public: MMKV(const std::string &mmapID, - int size = DEFAULT_MMAP_SIZE, - MMKVMode mode = MMKV_SINGLE_PROCESS, - std::string *cryptKey = nullptr); + int size, + MMKVMode mode, + std::string *cryptKey, + std::string *relativePath); MMKV(const std::string &mmapID, int ashmemFD, @@ -127,7 +128,8 @@ class MMKV { static MMKV *mmkvWithID(const std::string &mmapID, int size = DEFAULT_MMAP_SIZE, MMKVMode mode = MMKV_SINGLE_PROCESS, - std::string *cryptKey = nullptr); + std::string *cryptKey = nullptr, + std::string *relativePath = nullptr); static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, diff --git a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.cpp b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.cpp index e92b24a1..dec070f1 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.cpp @@ -72,7 +72,7 @@ MmapedFile::MmapedFile(const std::string &path, size_t size, bool fileType) if (ioctl(m_fd, ASHMEM_SET_NAME, m_name.c_str()) != 0) { MMKVError("fail to set ashmem name:%s, %s", m_name.c_str(), strerror(errno)); } else if (ioctl(m_fd, ASHMEM_SET_SIZE, size) != 0) { - MMKVError("fail to set ashmem:%s, size %d, %s", m_name.c_str(), size, + MMKVError("fail to set ashmem:%s, size %zu, %s", m_name.c_str(), size, strerror(errno)); } else { m_segmentSize = static_cast(size); @@ -154,7 +154,7 @@ bool mkPath(char *path) { if (stat(path, &sb) != 0) { if (errno != ENOENT || mkdir(path, 0777) != 0) { - MMKVWarning("%s", path); + MMKVWarning("%s : %s", path, strerror(errno)); return false; } } else if (!S_ISDIR(sb.st_mode)) { @@ -168,6 +168,36 @@ bool mkPath(char *path) { return true; } +bool createFile(const std::string &filePath) { + bool ret = false; + + // try create at once + auto fd = open(filePath.c_str(), O_RDWR | O_CREAT, S_IRWXU); + if (fd >= 0) { + close(fd); + ret = true; + } else { + // create parent dir + char *path = strdup(filePath.c_str()); + auto ptr = strrchr(path, '/'); + if (ptr) { + *ptr = '\0'; + } + if (mkPath(path)) { + // try again + fd = open(filePath.c_str(), O_RDWR | O_CREAT, S_IRWXU); + if (fd >= 0) { + close(fd); + ret = true; + } else { + MMKVWarning("fail to create file %s, %s", filePath.c_str(), strerror(errno)); + } + } + free(path); + } + return ret; +} + bool removeFile(const string &nsFilePath) { int ret = unlink(nsFilePath.c_str()); if (ret != 0) { diff --git a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h index b5786eb1..f620cbe1 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h +++ b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h @@ -72,5 +72,6 @@ extern bool isFileExist(const std::string &nsFilePath); extern bool removeFile(const std::string &nsFilePath); extern MMBuffer *readWholeFile(const char *path); extern bool zeroFillFile(int fd, size_t startPos, size_t size); +extern bool createFile(const std::string &filePath); #endif //MMKV_MMAPEDFILE_H diff --git a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp index 2964f47a..6545102c 100644 --- a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp @@ -71,7 +71,7 @@ extern "C" JNIEXPORT JNICALL jint JNI_OnLoad(JavaVM *vm, void *reserved) { } extern "C" JNIEXPORT JNICALL void -Java_com_tencent_mmkv_MMKV_initialize(JNIEnv *env, jobject obj, jstring rootDir) { +Java_com_tencent_mmkv_MMKV_jniInitialize(JNIEnv *env, jobject obj, jstring rootDir) { if (!rootDir) { return; } @@ -173,21 +173,33 @@ MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) { } extern "C" JNIEXPORT JNICALL jlong Java_com_tencent_mmkv_MMKV_getMMKVWithID( - JNIEnv *env, jobject obj, jstring mmapID, jint mode, jstring cryptKey) { + JNIEnv *env, jobject obj, jstring mmapID, jint mode, jstring cryptKey, jstring relativePath) { MMKV *kv = nullptr; if (!mmapID) { return (jlong) kv; } string str = jstring2string(env, mmapID); - if (cryptKey != nullptr) { + bool done = false; + if (cryptKey) { string crypt = jstring2string(env, cryptKey); if (crypt.length() > 0) { - kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, &crypt); + if (relativePath) { + string path = jstring2string(env, relativePath); + kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, &crypt, &path); + } else { + kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, &crypt, nullptr); + } + done = true; } } - if (!kv) { - kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, nullptr); + if (!done) { + if (relativePath) { + string path = jstring2string(env, relativePath); + kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, nullptr, &path); + } else { + kv = MMKV::mmkvWithID(str, DEFAULT_MMAP_SIZE, (MMKVMode) mode, nullptr, nullptr); + } } return (jlong) kv; @@ -201,7 +213,7 @@ extern "C" JNIEXPORT JNICALL jlong Java_com_tencent_mmkv_MMKV_getMMKVWithIDAndSi } string str = jstring2string(env, mmapID); - if (cryptKey != nullptr) { + if (cryptKey) { string crypt = jstring2string(env, cryptKey); if (crypt.length() > 0) { kv = MMKV::mmkvWithID(str, size, (MMKVMode) mode, &crypt); @@ -219,7 +231,7 @@ extern "C" JNIEXPORT JNICALL jlong Java_com_tencent_mmkv_MMKV_getDefaultMMKV(JNI jstring cryptKey) { MMKV *kv = nullptr; - if (cryptKey != nullptr) { + if (cryptKey) { string crypt = jstring2string(env, cryptKey); if (crypt.length() > 0) { kv = MMKV::defaultMMKV((MMKVMode) mode, &crypt); @@ -240,7 +252,7 @@ extern "C" JNIEXPORT JNICALL jlong Java_com_tencent_mmkv_MMKV_getMMKVWithAshmemF } string id = jstring2string(env, mmapID); - if (cryptKey != nullptr) { + if (cryptKey) { string crypt = jstring2string(env, cryptKey); if (crypt.length() > 0) { kv = MMKV::mmkvWithAshmemFD(id, fd, metaFD, &crypt); diff --git a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java index 94decd0e..b726cc36 100644 --- a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java +++ b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java @@ -53,10 +53,19 @@ public class MMKV implements SharedPreferences, SharedPreferences.Editor { } // call on program start - static private String rootDir = null; public static String initialize(Context context) { - rootDir = context.getFilesDir().getAbsolutePath() + "/mmkv"; - initialize(rootDir); + String root = context.getFilesDir().getAbsolutePath() + "/mmkv"; + return initialize(root); + } + + static private String rootDir = null; + public static String initialize(String rootDir) { + MMKV.rootDir = rootDir; + jniInitialize(MMKV.rootDir); + return rootDir; + } + + public static String getRootDir() { return rootDir; } @@ -74,7 +83,7 @@ public static MMKV mmkvWithID(String mmapID) { throw new IllegalStateException("You should Call MMKV.initialize() first."); } - long handle = getMMKVWithID(mmapID, SINGLE_PROCESS_MODE, null); + long handle = getMMKVWithID(mmapID, SINGLE_PROCESS_MODE, null, null); return new MMKV(handle); } @@ -83,7 +92,7 @@ public static MMKV mmkvWithID(String mmapID, int mode) { throw new IllegalStateException("You should Call MMKV.initialize() first."); } - long handle = getMMKVWithID(mmapID, mode, null); + long handle = getMMKVWithID(mmapID, mode, null, null); return new MMKV(handle); } @@ -93,7 +102,34 @@ public static MMKV mmkvWithID(String mmapID, int mode, String cryptKey) { throw new IllegalStateException("You should Call MMKV.initialize() first."); } - long handle = getMMKVWithID(mmapID, mode, cryptKey); + long handle = getMMKVWithID(mmapID, mode, cryptKey, null); + return new MMKV(handle); + } + + @Nullable + public static MMKV mmkvWithID(String mmapID, String relativePath) { + if (rootDir == null) { + throw new IllegalStateException("You should Call MMKV.initialize() first."); + } + + long handle = getMMKVWithID(mmapID, SINGLE_PROCESS_MODE, null, relativePath); + if (handle == 0) { + return null; + } + return new MMKV(handle); + } + + // cryptKey's length <= 16 + @Nullable + public static MMKV mmkvWithID(String mmapID, int mode, String cryptKey, String relativePath) { + if (rootDir == null) { + throw new IllegalStateException("You should Call MMKV.initialize() first."); + } + + long handle = getMMKVWithID(mmapID, mode, cryptKey, relativePath); + if (handle == 0) { + return null; + } return new MMKV(handle); } @@ -589,9 +625,10 @@ private MMKV(long handle) { nativeHandle = handle; } - private static native void initialize(String rootDir); + private static native void jniInitialize(String rootDir); - private native static long getMMKVWithID(String mmapID, int mode, String cryptKey); + private native static long + getMMKVWithID(String mmapID, int mode, String cryptKey, String relativePath); private native static long getMMKVWithIDAndSize(String mmapID, int size, int mode, String cryptKey); diff --git a/Android/MMKV/mmkvdemo/build.gradle b/Android/MMKV/mmkvdemo/build.gradle index 9bfb29cd..9b5454e7 100644 --- a/Android/MMKV/mmkvdemo/build.gradle +++ b/Android/MMKV/mmkvdemo/build.gradle @@ -62,8 +62,8 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') -// implementation project(':mmkv') - implementation 'com.tencent:mmkv:1.0.15' + implementation project(':mmkv') +// implementation 'com.tencent:mmkv:1.0.15' // implementation 'com.tencent:mmkv-static:1.0.15' implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' diff --git a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java index 8ec6f5a9..b0e50b11 100644 --- a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java +++ b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java @@ -37,6 +37,8 @@ import com.tencent.mmkv.MMKVHandler; import com.tencent.mmkv.MMKVRecoverStrategic; +import org.jetbrains.annotations.Nullable; + import static com.tencent.mmkvdemo.BenchMarkBaseService.AshmemMMKV_ID; import static com.tencent.mmkvdemo.BenchMarkBaseService.AshmemMMKV_Size; @@ -48,7 +50,10 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - String rootDir = "mmkv root: " + MMKV.initialize(this); + // set root dir + // String rootDir = "mmkv root: " + MMKV.initialize(this); + String dir = getFilesDir().getAbsolutePath() + "/mmkv_2"; + String rootDir = "mmkv root: " + MMKV.initialize(dir); Log.i("MMKV", rootDir); MMKV.registerHandler(this); @@ -102,8 +107,11 @@ public void onClick(View v) { } }); - MMKV kv = testMMKV("test/AES", "Tencent MMKV", false); - kv.close(); + String otherDir = getFilesDir().getAbsolutePath() + "/mmkv_3"; + MMKV kv = testMMKV("test/AES", "Tencent MMKV", false, otherDir); + if (kv != null) { + kv.close(); + } testAshmem(); testReKey(); @@ -134,9 +142,13 @@ private void testInterProcessLogic() { Log.d("mmkv", "" + value); } - private MMKV testMMKV(String mmapID, String cryptKey, boolean decodeOnly) { + @Nullable + private MMKV testMMKV(String mmapID, String cryptKey, boolean decodeOnly, String relativePath) { //MMKV kv = MMKV.defaultMMKV(); - MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, cryptKey); + MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, cryptKey, relativePath); + if (kv == null) { + return null; + } if (!decodeOnly) { kv.encode("bool", true); @@ -238,19 +250,19 @@ private void testImportSharedPreferences() { private void testReKey() { final String mmapID = "testAES_reKey"; - MMKV kv = testMMKV(mmapID, null, false); + MMKV kv = testMMKV(mmapID, null, false, null); kv.reKey("Key_seq_1"); kv.clearMemoryCache(); - testMMKV(mmapID, "Key_seq_1", true); + testMMKV(mmapID, "Key_seq_1", true, null); kv.reKey("Key_seq_2"); kv.clearMemoryCache(); - testMMKV(mmapID, "Key_seq_2", true); + testMMKV(mmapID, "Key_seq_2", true, null); kv.reKey(null); kv.clearMemoryCache(); - testMMKV(mmapID, null, true); + testMMKV(mmapID, null, true, null); } private void interProcessBaselineTest(String cmd) { diff --git a/iOS/MMKV/MMKV/MMKV.h b/iOS/MMKV/MMKV/MMKV.h index 81442bd6..284af02e 100644 --- a/iOS/MMKV/MMKV/MMKV.h +++ b/iOS/MMKV/MMKV/MMKV.h @@ -45,7 +45,8 @@ NS_ASSUME_NONNULL_BEGIN // if you want a per-user mmkv, you could merge user-id within mmapID // cryptKey: 16 byte at most // relativePath: custom path of the file, `NSDocumentDirectory/mmkv` by default -+ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath:)); ++ (nullable instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(nullable NSData *)cryptKey relativePath:(nullable NSString *)path NS_SWIFT_NAME(init(mmapID:cryptKey:relativePath +:)); // default to `NSDocumentDirectory/mmkv` + (NSString *)mmkvBasePath; diff --git a/iOS/MMKV/MMKV/MMKVLog.h b/iOS/MMKV/MMKV/MMKVLog.h index 272d72a2..0998b95b 100644 --- a/iOS/MMKV/MMKV/MMKVLog.h +++ b/iOS/MMKV/MMKV/MMKVLog.h @@ -35,20 +35,20 @@ #ifndef NDEBUG #define MMKVDebug(format, ...) NSLog(@"[D] %s-%d " format, __func__, __LINE__, ##__VA_ARGS__) #else -#define MMKVDebug(format, ...) \ - {} +#define MMKVDebug(format, ...) \ + {} #endif // NDEBUG #else -#define MMKVError(format, ...) \ - {} -#define MMKVWarning(format, ...) \ - {} -#define MMKVInfo(format, ...) \ - {} -#define MMKVDebug(format, ...) \ - {} +#define MMKVError(format, ...) \ + {} +#define MMKVWarning(format, ...) \ + {} +#define MMKVInfo(format, ...) \ + {} +#define MMKVDebug(format, ...) \ + {} #endif // ENABLE_MMKV_LOG diff --git a/iOS/MMKV/MMKV/MiniPBCoder.mm b/iOS/MMKV/MMKV/MiniPBCoder.mm index 12f50e03..8fb6795a 100644 --- a/iOS/MMKV/MMKV/MiniPBCoder.mm +++ b/iOS/MMKV/MMKV/MiniPBCoder.mm @@ -246,7 +246,7 @@ - (id)decodeOneObject:(id)obj ofClass:(Class)cls { if (!cls) { cls = [(NSObject *) obj class]; } - + if (cls == [NSString class]) { return m_inputData->readString(); } else if (cls == [NSMutableString class]) { From 6d54cedd2149f5ad568de83fa72ef3d325bf0c50 Mon Sep 17 00:00:00 2001 From: guoling Date: Sat, 29 Dec 2018 20:35:06 +0800 Subject: [PATCH 46/57] getValueSizeForKey for Android --- Android/MMKV/mmkv/src/main/cpp/MMKV.cpp | 9 +++++++++ Android/MMKV/mmkv/src/main/cpp/MMKV.h | 2 ++ Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp | 12 ++++++++++++ .../mmkv/src/main/java/com/tencent/mmkv/MMKV.java | 8 ++++++++ .../main/java/com/tencent/mmkvdemo/MainActivity.java | 5 ++++- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp index 8c63f710..e0273850 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp @@ -1204,6 +1204,15 @@ bool MMKV::getVectorForKey(const std::string &key, std::vector &res return false; } +size_t MMKV::getValueSizeForKey(const std::string &key) { + if (key.empty()) { + return 0; + } + SCOPEDLOCK(m_lock); + auto &data = getDataForKey(key); + return data.length(); +} + #pragma mark - enumerate bool MMKV::containsKey(const std::string &key) { diff --git a/Android/MMKV/mmkv/src/main/cpp/MMKV.h b/Android/MMKV/mmkv/src/main/cpp/MMKV.h index 3789f1f0..517641db 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MMKV.h +++ b/Android/MMKV/mmkv/src/main/cpp/MMKV.h @@ -191,6 +191,8 @@ class MMKV { bool getVectorForKey(const std::string &key, std::vector &result); + size_t getValueSizeForKey(const std::string &key); + bool containsKey(const std::string &key); size_t count(); diff --git a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp index 6545102c..e5159c85 100644 --- a/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp @@ -679,3 +679,15 @@ extern "C" JNIEXPORT void JNICALL Java_com_tencent_mmkv_MMKV_close(JNIEnv *env, env->SetLongField(instance, g_fileID, 0); } } + +extern "C" JNIEXPORT jint JNICALL Java_com_tencent_mmkv_MMKV_valueSize(JNIEnv *env, + jobject instance, + jlong handle, + jstring oKey) { + MMKV *kv = reinterpret_cast(handle); + if (kv && oKey) { + string key = jstring2string(env, oKey); + return kv->getValueSizeForKey(key); + } + return 0; +} \ No newline at end of file diff --git a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java index b726cc36..1d7a1ca3 100644 --- a/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java +++ b/Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java @@ -382,6 +382,12 @@ public T decodeParcelable(String key, Class tClass, T return defaultValue; } + // return the actual size consumption of the key's value + // Note: might be a little bigger than value's length + public int getValueSize(String key) { + return valueSize(nativeHandle, key); + } + public boolean containsKey(String key) { return containsKey(nativeHandle, key); } @@ -677,4 +683,6 @@ private MMKV(long handle) { private native long totalSize(long handle); private native void removeValueForKey(long handle, String key); + + private native int valueSize(long handle, String key); } diff --git a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java index b0e50b11..df71e6fd 100644 --- a/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java +++ b/Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java @@ -184,7 +184,10 @@ private MMKV testMMKV(String mmapID, String cryptKey, boolean decodeOnly, String byte[] bytes = {'m', 'm', 'k', 'v'}; kv.encode("bytes", bytes); } - Log.i("MMKV", "bytes: " + new String(kv.decodeBytes("bytes"))); + byte[] bytes = kv.decodeBytes("bytes"); + Log.i("MMKV", "bytes: " + new String(bytes)); + Log.i("MMKV", "bytes length = " + bytes.length + + ", value size consumption = " + kv.getValueSize("bytes")); if (!decodeOnly) { TestParcelable testParcelable = new TestParcelable(1024, "Hi Parcelable"); From 44f72aeba164dddde9f97d2d8d0d7e2d2f259edb Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 2 Jan 2019 16:44:22 +0800 Subject: [PATCH 47/57] readme for win32 --- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ba1498e0..d6eeed6a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![license](https://img.shields.io/badge/license-BSD_3-brightgreen.svg?style=flat)](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/MMKV/pulls) -[![Release Version](https://img.shields.io/badge/release-1.0.14-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) +[![Release Version](https://img.shields.io/badge/release-1.0.15-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) [![Platform](https://img.shields.io/badge/Platform-%20iOS%20%7C%20Android-brightgreen.svg)](https://github.com/Tencent/MMKV/wiki/home) 中文版本请参看[这里](./readme_cn.md) @@ -43,8 +43,8 @@ BOOL bValue = [mmkv getBoolForKey:@"bool"]; [mmkv setInt32:-1024 forKey:@"int32"]; int32_t iValue = [mmkv getInt32ForKey:@"int32"]; -[mmkv setObject:@"hello, mmkv" forKey:@"string"]; -NSString *str = [mmkv getObjectOfClass:NSString.class forKey:@"string"]; +[mmkv setString:@"hello, mmkv" forKey:@"string"]; +NSString *str = [mmkv getStringForKey:@"string"]; ``` Full tutorials can be found [here](https://github.com/Tencent/MMKV/wiki/iOS_tutorial). @@ -53,8 +53,8 @@ Full tutorials can be found [here](https://github.com/Tencent/MMKV/wiki/iOS_tuto Writing random `int` for 10000 times, we get this chart: ![](https://github.com/Tencent/MMKV/wiki/assets/profile_mini.jpg) For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/iOS_benchmark). - -# MMKV for Windows + +# MMKV for Android ## Features @@ -68,6 +68,72 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc * **About 60K in binary size**: MMKV adds about 60K per architecture on App size, and much less when zipped (apk). +## Getting Started + +### Installation Via Maven +Add the following lines to `build.gradle` on your app module: + +```gradle +dependencies { + implementation 'com.tencent:mmkv:1.0.15' + // replace "1.0.15" with any available version +} +``` + +For other installation options, see [Android Setup](https://github.com/Tencent/MMKV/wiki/android_setup). + +### Quick Tutorial +You can use MMKV as you go. All changes are saved immediately, no `sync`, no `apply` calls needed. +Setup MMKV on App startup, say your `MainActivity`, add these lines: + +```Java +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String rootDir = MMKV.initialize(this); + System.out.println("mmkv root: " + rootDir); + //…… +} +``` + +MMKV has a global instance, that can be used directly: + +```Java +import com.tencent.mmkv.MMKV; + +MMKV kv = MMKV.defaultMMKV(); + +kv.encode("bool", true); +boolean bValue = kv.decodeBool("bool"); + +kv.encode("int", Integer.MIN_VALUE); +int iValue = kv.decodeInt("int"); + +kv.encode("string", "Hello from mmkv"); +String str = kv.decodeString("string"); +``` + +MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Android Tutorial](https://github.com/Tencent/MMKV/wiki/android_tutorial). + +## Performance +Writing random `int` for 1000 times, we get this chart: +![](https://github.com/Tencent/MMKV/wiki/assets/profile_android_mini.jpg) +For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark). + +# MMKV for Windows + +## Features + +* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of Windows to achieve best performance. + * **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes. + +* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls needed. + +* **Small**. + * **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy. + * **About 60K in binary size**: MMKV adds about 60K per architecture on App size, and much less when zipped. + + ## Getting Started ### Installation Via Source @@ -120,19 +186,18 @@ MMKV also supports **Multi-Process Access**. Full tutorials can be found here [A Writing random `int` for 1000 times, we get this chart: ![](https://github.com/Tencent/MMKV/wiki/assets/profile_android_mini.jpg) For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark). - ## License -MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT). +MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](./LICENSE.TXT). ## Change Log Check out the [CHANGELOG.md](./CHANGELOG.md) for details of change history. ## Contributing -If you are interested in contributing, check out the [CONTRIBUTING.md](https://github.com/Tencent/MMKV/blob/master/CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). +If you are interested in contributing, check out the [CONTRIBUTING.md](./CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). -To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](https://github.com/Tencent/MMKV/blob/master/CODE_OF_CONDUCT.md). +To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](./CODE_OF_CONDUCT.md). ## FAQ & Feedback Check out the [FAQ](https://github.com/Tencent/MMKV/wiki/FAQ) first. Should there be any questions, don't hesitate to create [issues](https://github.com/Tencent/MMKV/issues). From be2731ffa8194609a0c2b8fdf7d3071f815bbd95 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 2 Jan 2019 17:13:03 +0800 Subject: [PATCH 48/57] more robust for 3rd integration --- README.md | 2 +- Win32/MMKV/MMKV.h | 4 ++++ Win32/MMKV/MMKV.vcxproj | 2 +- Win32/MMKV/MMKV.vcxproj.filters | 38 ++++++++++++++++----------------- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index d6eeed6a..b96d25b9 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc * **Small**. * **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy. - * **About 60K in binary size**: MMKV adds about 60K per architecture on App size, and much less when zipped. + * **About 10K in binary size**: MMKV adds about 10K on application size, and much less when zipped. ## Getting Started diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 1d3f6d2f..fb0930dc 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -21,6 +21,10 @@ #ifndef MMKV_MMKV_H #define MMKV_MMKV_H +#ifndef _WINDOWS_ +#include +#endif // !_WINDOWS_ + #include "InterProcessLock.h" #include "MMBuffer.h" #include "MMKVMetaInfo.hpp" diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index bcea5d56..1a110cb8 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -120,7 +120,7 @@ - Use + NotUsing Level3 MaxSpeed true diff --git a/Win32/MMKV/MMKV.vcxproj.filters b/Win32/MMKV/MMKV.vcxproj.filters index 69eb3db4..009e8e5e 100644 --- a/Win32/MMKV/MMKV.vcxproj.filters +++ b/Win32/MMKV/MMKV.vcxproj.filters @@ -78,6 +78,24 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -132,24 +150,4 @@ Source Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - \ No newline at end of file From f5d8e9d4e4c6f48b306232167ab022d583b542a7 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 3 Jan 2019 11:42:28 +0800 Subject: [PATCH 49/57] protect from meta file not valid --- Android/MMKV/mmkv/src/main/cpp/MMKV.cpp | 20 ++++++++++++-------- Android/MMKV/mmkv/src/main/cpp/MmapedFile.h | 5 +++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp index e0273850..4cb2f752 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp +++ b/Android/MMKV/mmkv/src/main/cpp/MMKV.cpp @@ -295,7 +295,9 @@ void MMKV::loadFromFile() { return; } - m_metaInfo.read(m_metaFile.getMemory()); + if (m_metaFile.isFileValid()) { + m_metaInfo.read(m_metaFile.getMemory()); + } m_fd = open(m_path.c_str(), O_RDWR | O_CREAT, S_IRWXU); if (m_fd < 0) { @@ -379,7 +381,9 @@ void MMKV::loadFromFile() { } void MMKV::loadFromAshmem() { - m_metaInfo.read(m_metaFile.getMemory()); + if (m_metaFile.isFileValid()) { + m_metaInfo.read(m_metaFile.getMemory()); + } if (m_fd < 0 || !m_ashmemFile) { MMKVError("ashmem file invalid %s, fd:%d", m_path.c_str(), m_fd); @@ -973,6 +977,10 @@ bool MMKV::isFileValid() { // assuming m_ptr & m_size is set bool MMKV::checkFileCRCValid() { if (m_ptr && m_ptr != MAP_FAILED) { + if (!m_metaFile.isFileValid()) { + MMKVError("Meta file not valid %s", m_mmapID.c_str()); + return false; + } constexpr int offset = pbFixed32Size(0); m_crcDigest = (uint32_t) crc32(0, (const uint8_t *) m_ptr + offset, (uint32_t) m_actualSize); @@ -995,16 +1003,11 @@ void MMKV::recaculateCRCDigest() { } void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSequence) { - if (!ptr) { + if (!ptr || !m_metaFile.isFileValid()) { return; } m_crcDigest = (uint32_t) crc32(m_crcDigest, ptr, (uint32_t) length); - void *crcPtr = m_metaFile.getMemory(); - if (crcPtr == nullptr || crcPtr == MAP_FAILED) { - return; - } - m_metaInfo.m_crcDigest = m_crcDigest; if (increaseSequence) { m_metaInfo.m_sequence++; @@ -1012,6 +1015,7 @@ void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSeque if (m_metaInfo.m_version == 0) { m_metaInfo.m_version = 1; } + auto crcPtr = m_metaFile.getMemory(); m_metaInfo.write(crcPtr); } diff --git a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h index f620cbe1..9339b1c2 100644 --- a/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h +++ b/Android/MMKV/mmkv/src/main/cpp/MmapedFile.h @@ -23,6 +23,7 @@ #include #include +#include #define ASHMEM_NAME_LEN 256 #define ASHMEM_NAME_DEF "/dev/ashmem" @@ -63,6 +64,10 @@ class MmapedFile { std::string &getName() { return m_name; } int getFd() { return m_fd; } + + bool isFileValid() { + return m_fd >= 0 && m_segmentSize > 0 && m_segmentPtr && m_segmentPtr != MAP_FAILED; + } }; class MMBuffer; From a8349177bfc63ee87898dc540f549484b0b6cf16 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 3 Jan 2019 15:33:42 +0800 Subject: [PATCH 50/57] copy header to $(OutDir)\include\MMKV --- Win32/MMKV/MMKV.vcxproj | 4 ++-- Win32/Win32Demo/Win32Demo.cpp | 2 +- Win32/Win32Demo/Win32Demo.vcxproj | 12 ++++-------- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 2 +- Win32/Win32DemoProcess/Win32DemoProcess.vcxproj | 4 ++-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 1a110cb8..6bc61d36 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -97,7 +97,7 @@ true - for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y %%f "$(OutDir)" + for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y /i %%f "$(OutDir)\include\MMKV\" Copying Header Files @@ -138,7 +138,7 @@ true - for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y %%f "$(OutDir)" + for %%f in ("$(ProjectDir)MMKV.h", "$(ProjectDir)InterProcessLock.h", "$(ProjectDir)MmapedFile.h", "$(ProjectDir)MMKVMetaInfo.hpp", "$(ProjectDir)ThreadLock.h", "$(ProjectDir)MMBuffer.h") do xcopy /y /i %%f "$(OutDir)\include\MMKV\" Copying Header Files diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 16d3e4ac..58cf80ee 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -20,7 +20,7 @@ #include "pch.h" -#include "MMKV.h" +#include #include #include diff --git a/Win32/Win32Demo/Win32Demo.vcxproj b/Win32/Win32Demo/Win32Demo.vcxproj index fca69126..959de5d4 100644 --- a/Win32/Win32Demo/Win32Demo.vcxproj +++ b/Win32/Win32Demo/Win32Demo.vcxproj @@ -91,7 +91,7 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h - ..\MMKV;%(AdditionalIncludeDirectories) + $(OutDir)include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -100,9 +100,7 @@ ..\$(IntDir);%(AdditionalLibraryDirectories) MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) - - xcopy /y /d "..\$(IntDir)MMKV.lib" "$(OutDir)" - + @@ -134,7 +132,7 @@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h - ..\MMKV;%(AdditionalIncludeDirectories) + $(OutDir)include;%(AdditionalIncludeDirectories) MultiThreaded @@ -145,9 +143,7 @@ ..\$(IntDir);%(AdditionalLibraryDirectories) MMKV.lib;Shlwapi.lib;%(AdditionalDependencies) - - xcopy /y /d "..\$(IntDir)MMKV.lib" "$(OutDir)" - + diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index 32e07482..3f2cbf34 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -20,7 +20,7 @@ #include "pch.h" -#include "MMKV.h" +#include #include #include #include diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj index e40a60eb..e9f4bfdf 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj +++ b/Win32/Win32DemoProcess/Win32DemoProcess.vcxproj @@ -91,7 +91,7 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h - ..\MMKV + $(OutDir)include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -131,7 +131,7 @@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h - ..\MMKV + $(OutDir)include;%(AdditionalIncludeDirectories) MultiThreaded From c9f26f4a0788fb3fab9e21e78b3aa36d677fe31c Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 3 Jan 2019 18:03:00 +0800 Subject: [PATCH 51/57] remove ForKey --- Win32/MMKV/MMKV.cpp | 24 ++++++++++++------------ Win32/MMKV/MMKV.h | 24 ++++++++++++------------ Win32/Win32Demo/Win32Demo.cpp | 22 +++++++++++----------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index e3c5d072..8427f90c 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -849,7 +849,7 @@ void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSeque // set & get -bool MMKV::setStringForKey(const std::string &value, const std::string &key) { +bool MMKV::set(const std::string &value, const std::string &key) { if (key.empty()) { return false; } @@ -857,7 +857,7 @@ bool MMKV::setStringForKey(const std::string &value, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::setBytesForKey(const MMBuffer &value, const std::string &key) { +bool MMKV::set(const MMBuffer &value, const std::string &key) { if (key.empty()) { return false; } @@ -957,7 +957,7 @@ bool MMKV::set(const std::vector &v, const std::string &key) { return setDataForKey(std::move(data), key); } -bool MMKV::getStringForKey(const std::string &key, std::string &result) { +bool MMKV::getString(const std::string &key, std::string &result) { if (key.empty()) { return false; } @@ -970,7 +970,7 @@ bool MMKV::getStringForKey(const std::string &key, std::string &result) { return false; } -MMBuffer MMKV::getBytesForKey(const std::string &key) { +MMBuffer MMKV::getBytes(const std::string &key) { if (key.empty()) { return MMBuffer(0); } @@ -982,7 +982,7 @@ MMBuffer MMKV::getBytesForKey(const std::string &key) { return MMBuffer(0); } -bool MMKV::getBoolForKey(const std::string &key, bool defaultValue) { +bool MMKV::getBool(const std::string &key, bool defaultValue) { if (key.empty()) { return defaultValue; } @@ -995,7 +995,7 @@ bool MMKV::getBoolForKey(const std::string &key, bool defaultValue) { return defaultValue; } -int32_t MMKV::getInt32ForKey(const std::string &key, int32_t defaultValue) { +int32_t MMKV::getInt32(const std::string &key, int32_t defaultValue) { if (key.empty()) { return defaultValue; } @@ -1008,7 +1008,7 @@ int32_t MMKV::getInt32ForKey(const std::string &key, int32_t defaultValue) { return defaultValue; } -uint32_t MMKV::getUInt32ForKey(const std::string &key, uint32_t defaultValue) { +uint32_t MMKV::getUInt32(const std::string &key, uint32_t defaultValue) { if (key.empty()) { return defaultValue; } @@ -1021,7 +1021,7 @@ uint32_t MMKV::getUInt32ForKey(const std::string &key, uint32_t defaultValue) { return defaultValue; } -int64_t MMKV::getInt64ForKey(const std::string &key, int64_t defaultValue) { +int64_t MMKV::getInt64(const std::string &key, int64_t defaultValue) { if (key.empty()) { return defaultValue; } @@ -1034,7 +1034,7 @@ int64_t MMKV::getInt64ForKey(const std::string &key, int64_t defaultValue) { return defaultValue; } -uint64_t MMKV::getUInt64ForKey(const std::string &key, uint64_t defaultValue) { +uint64_t MMKV::getUInt64(const std::string &key, uint64_t defaultValue) { if (key.empty()) { return defaultValue; } @@ -1047,7 +1047,7 @@ uint64_t MMKV::getUInt64ForKey(const std::string &key, uint64_t defaultValue) { return defaultValue; } -float MMKV::getFloatForKey(const std::string &key, float defaultValue) { +float MMKV::getFloat(const std::string &key, float defaultValue) { if (key.empty()) { return defaultValue; } @@ -1060,7 +1060,7 @@ float MMKV::getFloatForKey(const std::string &key, float defaultValue) { return defaultValue; } -double MMKV::getDoubleForKey(const std::string &key, double defaultValue) { +double MMKV::getDouble(const std::string &key, double defaultValue) { if (key.empty()) { return defaultValue; } @@ -1073,7 +1073,7 @@ double MMKV::getDoubleForKey(const std::string &key, double defaultValue) { return defaultValue; } -bool MMKV::getVectorForKey(const std::string &key, std::vector &result) { +bool MMKV::getVector(const std::string &key, std::vector &result) { if (key.empty()) { return false; } diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index fb0930dc..146f435d 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -170,29 +170,29 @@ class MMKV { bool set(const std::vector &vector, const std::string &key); - bool setStringForKey(const std::string &value, const std::string &key); + bool set(const std::string &value, const std::string &key); - bool setBytesForKey(const mmkv::MMBuffer &value, const std::string &key); + bool set(const mmkv::MMBuffer &value, const std::string &key); - bool getStringForKey(const std::string &key, std::string &result); + bool getString(const std::string &key, std::string &result); - mmkv::MMBuffer getBytesForKey(const std::string &key); + mmkv::MMBuffer getBytes(const std::string &key); - bool getBoolForKey(const std::string &key, bool defaultValue = false); + bool getBool(const std::string &key, bool defaultValue = false); - int32_t getInt32ForKey(const std::string &key, int32_t defaultValue = 0); + int32_t getInt32(const std::string &key, int32_t defaultValue = 0); - uint32_t getUInt32ForKey(const std::string &key, uint32_t defaultValue = 0); + uint32_t getUInt32(const std::string &key, uint32_t defaultValue = 0); - int64_t getInt64ForKey(const std::string &key, int64_t defaultValue = 0); + int64_t getInt64(const std::string &key, int64_t defaultValue = 0); - uint64_t getUInt64ForKey(const std::string &key, uint64_t defaultValue = 0); + uint64_t getUInt64(const std::string &key, uint64_t defaultValue = 0); - float getFloatForKey(const std::string &key, float defaultValue = 0); + float getFloat(const std::string &key, float defaultValue = 0); - double getDoubleForKey(const std::string &key, double defaultValue = 0); + double getDouble(const std::string &key, double defaultValue = 0); - bool getVectorForKey(const std::string &key, std::vector &result); + bool getVector(const std::string &key, std::vector &result); bool containsKey(const std::string &key); diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 58cf80ee..2a18f5a5 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -44,43 +44,43 @@ void functionalTest(MMKV *mmkv, bool decodeOnly) { if (!decodeOnly) { mmkv->set(true, "bool"); } - cout << "bool = " << mmkv->getBoolForKey("bool") << endl; + cout << "bool = " << mmkv->getBool("bool") << endl; if (!decodeOnly) { mmkv->set(1024, "int32"); } - cout << "int32 = " << mmkv->getInt32ForKey("int32") << endl; + cout << "int32 = " << mmkv->getInt32("int32") << endl; if (!decodeOnly) { mmkv->set(numeric_limits::max(), "uint32"); } - cout << "uint32 = " << mmkv->getUInt32ForKey("uint32") << endl; + cout << "uint32 = " << mmkv->getUInt32("uint32") << endl; if (!decodeOnly) { mmkv->set(numeric_limits::min(), "int64"); } - cout << "int64 = " << mmkv->getInt64ForKey("int64") << endl; + cout << "int64 = " << mmkv->getInt64("int64") << endl; if (!decodeOnly) { mmkv->set(numeric_limits::max(), "uint64"); } - cout << "uint64 = " << mmkv->getUInt64ForKey("uint64") << endl; + cout << "uint64 = " << mmkv->getUInt64("uint64") << endl; if (!decodeOnly) { mmkv->set(3.14f, "float"); } - cout << "float = " << mmkv->getFloatForKey("float") << endl; + cout << "float = " << mmkv->getFloat("float") << endl; if (!decodeOnly) { mmkv->set(numeric_limits::max(), "double"); } - cout << "double = " << mmkv->getDoubleForKey("double") << endl; + cout << "double = " << mmkv->getDouble("double") << endl; if (!decodeOnly) { - mmkv->setStringForKey("Hello, MMKV-΢ for Win32 ", "string"); + mmkv->set("Hello, MMKV-΢ for Win32 ", "string"); } string result; - mmkv->getStringForKey("string", result); + mmkv->getString("string", result); cout << "string = " << result << endl; } @@ -101,7 +101,7 @@ DWORD WINAPI threadFunction(LPVOID lpParam) { auto startIndex = segmentCount * threadIndex; for (auto index = startIndex; index < startIndex + segmentCount; index++) { mmkv->set(index, arrIntKeys[index]); - mmkv->setStringForKey("str-" + index, arrStringKeys[index]); + mmkv->set("str-" + index, arrStringKeys[index]); } mmkv->lock(); @@ -126,7 +126,7 @@ void brutleTest() { auto mmkv = MMKV::mmkvWithID(MMKV_ID); for (size_t i = 0; i < keyCount; i++) { mmkv->set(i, arrIntKeys[i]); - mmkv->setStringForKey("str-" + i, arrStringKeys[i]); + mmkv->set("str-" + i, arrStringKeys[i]); } } From 8abbf4d7e90d4cc163cf2dd21c45754e4880c9d4 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 3 Jan 2019 20:53:49 +0800 Subject: [PATCH 52/57] remove unnecessary size --- Win32/MMKV/MMKV.cpp | 6 +++--- Win32/MMKV/MMKV.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 8427f90c..36048e8a 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -112,7 +112,7 @@ MMKV::~MMKV() { } MMKV *MMKV::defaultMMKV(MMKVMode mode, string *cryptKey) { - return mmkvWithID(DEFAULT_MMAP_ID, mode, DEFAULT_MMAP_SIZE, cryptKey); + return mmkvWithID(DEFAULT_MMAP_ID, mode, cryptKey); } void initialize() { @@ -132,7 +132,7 @@ void MMKV::initializeMMKV(const std::wstring &rootDir) { MMKVInfo("root dir: %ws", g_rootDir.c_str()); } -MMKV *MMKV::mmkvWithID(const std::string &mmapID, MMKVMode mode, int size, string *cryptKey) { +MMKV *MMKV::mmkvWithID(const std::string &mmapID, MMKVMode mode, string *cryptKey) { if (mmapID.empty()) { return nullptr; } @@ -143,7 +143,7 @@ MMKV *MMKV::mmkvWithID(const std::string &mmapID, MMKVMode mode, int size, strin MMKV *kv = itr->second; return kv; } - auto kv = new MMKV(mmapID, mode, size, cryptKey); + auto kv = new MMKV(mmapID, mode, DEFAULT_MMAP_SIZE, cryptKey); (*g_instanceDic)[mmapID] = kv; return kv; } diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 146f435d..16b1c029 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -134,7 +134,6 @@ class MMKV { // if you want a per-user mmkv, you could merge user-id within mmapID static MMKV *mmkvWithID(const std::string &mmapID, MMKVMode mode = MMKV_SINGLE_PROCESS, - int size = mmkv::DEFAULT_MMAP_SIZE, std::string *cryptKey = nullptr); static void onExit(); From 2c9e71d9d40f8f59241208178b44f04e45ea51d8 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 3 Jan 2019 21:37:43 +0800 Subject: [PATCH 53/57] add const char* support & avoid unexpected type conversion --- Win32/MMKV/MMKV.cpp | 7 +++++++ Win32/MMKV/MMKV.h | 7 ++++++- Win32/Win32Demo/Win32Demo.cpp | 6 +++--- Win32/Win32DemoProcess/Win32DemoProcess.cpp | 8 ++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Win32/MMKV/MMKV.cpp b/Win32/MMKV/MMKV.cpp index 36048e8a..5bf476a2 100644 --- a/Win32/MMKV/MMKV.cpp +++ b/Win32/MMKV/MMKV.cpp @@ -849,6 +849,13 @@ void MMKV::updateCRCDigest(const uint8_t *ptr, size_t length, bool increaseSeque // set & get +bool MMKV::set(const char *value, const std::string &key) { + if (!value) { + return false; + } + return set(string(value), key); +} + bool MMKV::set(const std::string &value, const std::string &key) { if (key.empty()) { return false; diff --git a/Win32/MMKV/MMKV.h b/Win32/MMKV/MMKV.h index 16b1c029..50b64716 100644 --- a/Win32/MMKV/MMKV.h +++ b/Win32/MMKV/MMKV.h @@ -119,10 +119,13 @@ class MMKV { void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey); + // avoid unexpected type conversion (pointer to bool, etc) + template + bool set(T value, const std::string &key) = delete; + // just forbid it for possibly misuse MMKV(const MMKV &other) = delete; MMKV &operator=(const MMKV &other) = delete; - public: // call this before getting any MMKV instance static void initializeMMKV(const std::wstring &rootDir); @@ -169,6 +172,8 @@ class MMKV { bool set(const std::vector &vector, const std::string &key); + bool set(const char *value, const std::string &key); + bool set(const std::string &value, const std::string &key); bool set(const mmkv::MMBuffer &value, const std::string &key); diff --git a/Win32/Win32Demo/Win32Demo.cpp b/Win32/Win32Demo/Win32Demo.cpp index 2a18f5a5..476952db 100644 --- a/Win32/Win32Demo/Win32Demo.cpp +++ b/Win32/Win32Demo/Win32Demo.cpp @@ -77,7 +77,7 @@ void functionalTest(MMKV *mmkv, bool decodeOnly) { cout << "double = " << mmkv->getDouble("double") << endl; if (!decodeOnly) { - mmkv->set("Hello, MMKV-΢ for Win32 ", "string"); + mmkv->set("Hello, MMKV-΢ for Win32", "string"); } string result; mmkv->getString("string", result); @@ -101,7 +101,7 @@ DWORD WINAPI threadFunction(LPVOID lpParam) { auto startIndex = segmentCount * threadIndex; for (auto index = startIndex; index < startIndex + segmentCount; index++) { mmkv->set(index, arrIntKeys[index]); - mmkv->set("str-" + index, arrStringKeys[index]); + mmkv->set("str-" + to_string(index), arrStringKeys[index]); } mmkv->lock(); @@ -126,7 +126,7 @@ void brutleTest() { auto mmkv = MMKV::mmkvWithID(MMKV_ID); for (size_t i = 0; i < keyCount; i++) { mmkv->set(i, arrIntKeys[i]); - mmkv->set("str-" + i, arrStringKeys[i]); + mmkv->set("str-" + to_string(i), arrStringKeys[i]); } } diff --git a/Win32/Win32DemoProcess/Win32DemoProcess.cpp b/Win32/Win32DemoProcess/Win32DemoProcess.cpp index 3f2cbf34..5d8fe3cb 100644 --- a/Win32/Win32DemoProcess/Win32DemoProcess.cpp +++ b/Win32/Win32DemoProcess/Win32DemoProcess.cpp @@ -53,10 +53,10 @@ void brutleTest(DWORD processID) { auto mmkv = MMKV::mmkvWithID(MMKV_ID, MMKV_MULTI_PROCESS); for (size_t i = 0; i < keyCount; i++) { mmkv->set(i, arrIntKeys[i]); - //mmkv->setStringForKey("str-" + i, arrStringKeys[i]); - //mmkv->getInt32ForKey(arrIntKeys[i]); - //string result; - //mmkv->getStringForKey(arrStringKeys[i], result); + mmkv->set("str-" + to_string(i), arrStringKeys[i]); + mmkv->getInt32(arrIntKeys[i]); + string result; + mmkv->getString(arrStringKeys[i], result); } auto finish = hclock::now(); From d596214add324122e4d3cad5ae0c1f07411297e2 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 4 Jan 2019 11:51:22 +0800 Subject: [PATCH 54/57] pdb --- Win32/MMKV/MMKV.vcxproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Win32/MMKV/MMKV.vcxproj b/Win32/MMKV/MMKV.vcxproj index 6bc61d36..f03c152f 100644 --- a/Win32/MMKV/MMKV.vcxproj +++ b/Win32/MMKV/MMKV.vcxproj @@ -43,14 +43,14 @@ StaticLibrary true Unicode - v140 + v141 StaticLibrary false true Unicode - v140 + v141 @@ -91,6 +91,7 @@ WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;MMKV_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true MultiThreadedDebug + $(OutDir)$(ProjectName).pdb Windows @@ -130,6 +131,7 @@ true MultiThreaded pch.h + $(OutDir)$(ProjectName).pdb Windows @@ -214,4 +216,4 @@ - \ No newline at end of file + From e02d5d9607083d7a94f304620e9e977c7166b538 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 4 Jan 2019 14:38:25 +0800 Subject: [PATCH 55/57] add acknowledgment & license of zlib --- LICENSE.TXT | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/LICENSE.TXT b/LICENSE.TXT index bcdae5df..096acfb2 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -150,6 +150,33 @@ limitations under the License. +Open Source Software Licensed Under the zlib License: +The below software in this distribution may have been modified by THL A29 Limited (“Tencent Modifications”). All Tencent Modifications are Copyright (C) 2018 THL A29 Limited. +---------------------------------------------------------------------------------------- +1. zlib v1.2.11 +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + +Terms of the zlib License: +-------------------------------------------------------------------- + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + + Terms of the BSD 3-Clause License: -------------------------------------------------------------------- From cc6af01504c5bd1566e942d81903906896c25144 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 4 Jan 2019 21:21:13 +0800 Subject: [PATCH 56/57] update readme for windows --- README.md | 60 +++++++++++++++++++++++++---------------------- readme_cn.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 94 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index b96d25b9..60cc715d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ [![license](https://img.shields.io/badge/license-BSD_3-brightgreen.svg?style=flat)](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/MMKV/pulls) -[![Release Version](https://img.shields.io/badge/release-1.0.15-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) +[![Release Version](https://img.shields.io/badge/release-1.0.16-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) [![Platform](https://img.shields.io/badge/Platform-%20iOS%20%7C%20Android-brightgreen.svg)](https://github.com/Tencent/MMKV/wiki/home) 中文版本请参看[这里](./readme_cn.md) -MMKV is an **efficient**, **small**, **easy-to-use** mobile key-value storage framework used in the WeChat application. It's currently available on **iOS**, **macOS** and **Android**. +MMKV is an **efficient**, **small**, **easy-to-use** mobile key-value storage framework used in the WeChat application. It's currently available on **iOS**, **macOS**, **Android** and **Windows**. # MMKV for iOS/macOS @@ -75,8 +75,8 @@ Add the following lines to `build.gradle` on your app module: ```gradle dependencies { - implementation 'com.tencent:mmkv:1.0.15' - // replace "1.0.15" with any available version + implementation 'com.tencent:mmkv:1.0.16' + // replace "1.0.16" with any available version } ``` @@ -137,27 +137,36 @@ For more benchmark data, please refer to [our benchmark](https://github.com/Tenc ## Getting Started ### Installation Via Source -* Clone or Download source from GitHub; -* Add `Win32/MMKV/MMKV.vcxproj` to your solution; -* Add MMKV to your project's dependencies; -* Add `$(OutDir)` to your project's `C/C++` -> `General` -> `Additional Include Directories`; -* Add `$(OutDir)` to your project's `Linker` -> `General` -> `Additional Library Directories`; -* Add `MMKV.lib` to your project's `Linker` -> `Input` -> `Additional Dependencies`; -* MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or wise versa. -* MMKV is developed with Visual Studio 2017, change the `Platform Toolset` if you use a different version of Visual Studio. +1. Getting source code from git repository: + + ``` + git clone http://git.code.oa.com/wechat-team/mmkv.git + ``` + +2. Add `Win32/MMKV/MMKV.vcxproj` to your solution; +3. Add `MMKV` project to your project's dependencies; +4. Add `$(OutDir)include` to your project's `C/C++` -> `General` -> `Additional Include Directories`; +5. Add `$(OutDir)` to your project's `Linker` -> `General` -> `Additional Library Directories`; +6. Add `MMKV.lib` to your project's `Linker` -> `Input` -> `Additional Dependencies`; +7. Add `#include ` to your source file and we are done. + + +note: + +1. MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or wise versa. +2. MMKV is developed with Visual Studio 2017, change the `Platform Toolset` if you use a different version of Visual Studio. -For other installation options, see [Android Setup](https://github.com/Tencent/MMKV/wiki/android_setup). +For other installation options, see [Windows Setup](https://github.com/Tencent/MMKV/wiki/windows_setup). ### Quick Tutorial You can use MMKV as you go. All changes are saved immediately, no `sync`, no `save` calls needed. Setup MMKV on App startup, say in your `main()`, add these lines: ```C++ -#include "MMKV.h" -using namespace std; +#include int main() { - wstring rootDir = getYourAppDocumentDir(); + std::wstring rootDir = getYourAppDocumentDir(); MMKV::initializeMMKV(rootDir); //... } @@ -169,23 +178,18 @@ MMKV has a global instance, that can be used directly: auto mmkv = MMKV::defaultMMKV(); mmkv->set(true, "bool"); -cout << "bool = " << mmkv->getBoolForKey("bool") << endl; +std::cout << "bool = " << mmkv->getBool("bool") << std::endl; mmkv->set(1024, "int32"); -cout << "int32 = " << mmkv->getInt32ForKey("int32") << endl; +std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl; -mmkv->setStringForKey("Hello, MMKV for Win32 ", "string"); -string result; -mmkv->getStringForKey("string", result); -cout << "string = " << result << endl; +mmkv->set("Hello, MMKV for Win32", "string"); +std::string result; +mmkv->getString("string", result); +std::cout << "string = " << result << std::endl; ``` -MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Android Tutorial](https://github.com/Tencent/MMKV/wiki/android_tutorial). - -## Performance -Writing random `int` for 1000 times, we get this chart: -![](https://github.com/Tencent/MMKV/wiki/assets/profile_android_mini.jpg) -For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark). +MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Windows Tutorial](https://github.com/Tencent/MMKV/wiki/windows_tutorial). ## License MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](./LICENSE.TXT). diff --git a/readme_cn.md b/readme_cn.md index 5fac214a..a3a489b9 100644 --- a/readme_cn.md +++ b/readme_cn.md @@ -1,5 +1,5 @@ # MMKV——基于 mmap 的高性能通用 key-value 组件 -MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今,在 iOS 微信上使用已有近 3 年,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS 平台,一并开源。 +MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今在微信上使用,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS / Windows 平台,一并开源。 ## MMKV 源起 @@ -59,8 +59,8 @@ NSString *str = [mmkv getStringForKey:@"string"]; ```gradle dependencies { - implementation 'com.tencent:mmkv:1.0.15' - // replace "1.0.15" with any available version + implementation 'com.tencent:mmkv:1.0.16' + // replace "1.0.16" with any available version } ``` @@ -70,7 +70,7 @@ dependencies { MMKV 的使用非常简单,所有变更立马生效,无需调用 `sync`、`apply`。 在 App 启动时初始化 MMKV,设定 MMKV 的根目录(files/mmkv/),例如在 MainActivity 里: -``` +```Java protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -104,6 +104,64 @@ MMKV 支持**多进程访问**,更详细的用法参考 [Android Tutorial](htt ![](https://github.com/Tencent/MMKV/wiki/assets/profile_android_mini.jpg) 更详细的性能对比参考 [Android Benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark_cn)。 +## Windows 指南 +### 安装引入 +推荐使用子工程: + + 1. 获取 MMKV 源码: + + ``` + git clone http://git.code.oa.com/wechat-team/mmkv.git + ``` + + 2. 添加工程 `Win32/MMKV/MMKV.vcxproj` 到你的项目里; + 3. 设置你的主工程依赖于 `MMKV` 工程; + 4. 添加目录 `$(OutDir)include` 到你主工程的 `C/C++` -> `常规` -> `附加包含目录`; + 5. 添加目录 `$(OutDir)` 到你主工程的 `链接器` -> `常规` -> `附加库目录`; + 6. 添加 `MMKV.lib` 到你主工程的 `链接器` -> `输入` -> `附加依赖项`; + 7. 添加头文件 `#include `,就可以愉快地开始你的 MMKV 之旅了。 + +注意: + +1. MMKV 默认使用 `MT/MTd` 运行时库来编译,如果你发现主工程的配置不一样,请修改 MMKV 的配置再编译; +2. MMKV 使用 Visual Studio 2017 开发,如果你在使用其他版本的 Visual Studio,请修改 MMKV 的`工具集`与主工程一致,再编译. + +更多安装指引参考 [Windows Setup](https://github.com/Tencent/MMKV/wiki/windows_setup_cn)。 + +### 快速上手 +MMKV 的使用非常简单,所有变更立马生效,无需调用 `save`、`sync`。 +在 App 启动时初始化 MMKV,设定 MMKV 的根目录,例如在 main() 里: + + +```C++ +#include + +int main() { + std::wstring rootDir = getYourAppDocumentDir(); + MMKV::initializeMMKV(rootDir); + //... +} +``` + +MMKV 提供一个全局的实例,可以直接使用: + +```C++ +auto mmkv = MMKV::defaultMMKV(); + +mmkv->set(true, "bool"); +std::cout << "bool = " << mmkv->getBool("bool") << std::endl; + +mmkv->set(1024, "int32"); +std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl; + +mmkv->set("Hello, MMKV for Win32", "string"); +std::string result; +mmkv->getString("string", result); +std::cout << "string = " << result << std::endl; +``` + +MMKV 支持**多进程访问**,更详细的用法参考 [Windows Tutorial](https://github.com/Tencent/MMKV/wiki/windows_tutorial_cn)。 + ## License MMKV 以 BSD 3-Clause 证书开源,详情参见 [LICENSE.TXT](./LICENSE.TXT)。 From 1d3bfb6d78d24e5ae13001e6a414d4c04177d882 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 4 Jan 2019 21:44:30 +0800 Subject: [PATCH 57/57] prepare for v1.0.16 --- Android/MMKV/gradle.properties | 2 +- Android/MMKV/mmkvdemo/build.gradle | 6 +++--- CHANGELOG.md | 19 +++++++++++++++++++ MMKV.podspec | 2 +- iOS/MMKV/MMKV/Resources/Info.plist | 2 +- 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Android/MMKV/gradle.properties b/Android/MMKV/gradle.properties index 489d64f9..5d349269 100644 --- a/Android/MMKV/gradle.properties +++ b/Android/MMKV/gradle.properties @@ -12,6 +12,6 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME_PREFIX=1.0.15 +VERSION_NAME_PREFIX=1.0.16 #VERSION_NAME_SUFFIX=-SNAPSHOT VERSION_NAME_SUFFIX= \ No newline at end of file diff --git a/Android/MMKV/mmkvdemo/build.gradle b/Android/MMKV/mmkvdemo/build.gradle index 9b5454e7..ffb863cd 100644 --- a/Android/MMKV/mmkvdemo/build.gradle +++ b/Android/MMKV/mmkvdemo/build.gradle @@ -62,9 +62,9 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation project(':mmkv') -// implementation 'com.tencent:mmkv:1.0.15' -// implementation 'com.tencent:mmkv-static:1.0.15' +// implementation project(':mmkv') + implementation 'com.tencent:mmkv:1.0.16' +// implementation 'com.tencent:mmkv-static:1.0.16' implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' diff --git a/CHANGELOG.md b/CHANGELOG.md index 36367792..cc04ed21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # MMKV Change Log +## v1.0.16 / 2019-01-04 +### iOS / macOS +What's new + +* Customizing root folder of MMKV is supproted now. +* Customizing folder for specific MMKV is supprted now. +* Add method `getValueSizeForKey:` to get value's size of a key. + +### Android +What's new + +* Customizing root folder of MMKV is supproted now. +* Customizing folder for specific MMKV is supprted now. +* Add method `getValueSizeForKey()` to get value's size of a key. + + +### Win32 +MMKV for Windows is released now. Most things actually work! + ## v1.0.15 / 2018-12-13 ### iOS / macOS What's new diff --git a/MMKV.podspec b/MMKV.podspec index fdcc8faf..68315922 100644 --- a/MMKV.podspec +++ b/MMKV.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKV" - s.version = "1.0.15" + s.version = "1.0.16" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.description = <<-DESC diff --git a/iOS/MMKV/MMKV/Resources/Info.plist b/iOS/MMKV/MMKV/Resources/Info.plist index 910e8276..12ecdc0f 100644 --- a/iOS/MMKV/MMKV/Resources/Info.plist +++ b/iOS/MMKV/MMKV/Resources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.15 + 1.0.16 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass