From b7221438afffbcd7e8c096e25f789a33d65d63e9 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 30 Nov 2020 13:04:20 +0800 Subject: [PATCH 01/16] fix compile error on NDK 21.x --- Core/MMKVLog_Android.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/MMKVLog_Android.cpp b/Core/MMKVLog_Android.cpp index ee2435f9..d3df746d 100644 --- a/Core/MMKVLog_Android.cpp +++ b/Core/MMKVLog_Android.cpp @@ -30,8 +30,6 @@ using namespace std; constexpr auto APP_NAME = "MMKV"; -extern const char *_getFileName(const char *path); - static android_LogPriority MMKVLogLevelDesc(MMKVLogLevel level) { switch (level) { case MMKVLogDebug: @@ -47,7 +45,7 @@ static android_LogPriority MMKVLogLevelDesc(MMKVLogLevel level) { } } -void _MMKVLogWithLevel(MMKVLogLevel level, const char *file, const char *func, int line, const char *format, ...) { +void _MMKVLogWithLevel(MMKVLogLevel level, const char *filename, const char *func, int line, const char *format, ...) { if (level >= g_currentLogLevel) { string message; char buffer[16]; @@ -68,8 +66,6 @@ void _MMKVLogWithLevel(MMKVLogLevel level, const char *file, const char *func, i va_end(args); } - auto filename = _getFileName(file); - if (g_logHandler) { g_logHandler(level, filename, line, func, message); } else { From 82b9665fae42e6f82ae9379dcc603a05c1a275cc Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 9 Dec 2020 21:38:28 +0800 Subject: [PATCH 02/16] test cgo --- POSIX/golang/.gitignore | 5 + POSIX/golang/CMakeLists.txt | 77 ++++++ POSIX/golang/go.mod | 3 + POSIX/golang/golang-bridge.cpp | 409 ++++++++++++++++++++++++++++++++ POSIX/golang/golang-bridge.h | 20 ++ POSIX/golang/libmmkv_golang.cpp | 21 ++ POSIX/golang/mmkv.go | 36 +++ POSIX/golang/mmkv_test.go | 33 +++ 8 files changed, 604 insertions(+) create mode 100644 POSIX/golang/.gitignore create mode 100644 POSIX/golang/CMakeLists.txt create mode 100644 POSIX/golang/go.mod create mode 100644 POSIX/golang/golang-bridge.cpp create mode 100644 POSIX/golang/golang-bridge.h create mode 100644 POSIX/golang/libmmkv_golang.cpp create mode 100644 POSIX/golang/mmkv.go create mode 100644 POSIX/golang/mmkv_test.go diff --git a/POSIX/golang/.gitignore b/POSIX/golang/.gitignore new file mode 100644 index 00000000..4b7991f9 --- /dev/null +++ b/POSIX/golang/.gitignore @@ -0,0 +1,5 @@ +Core/ +Makefile +libmmkv.* +*.cbp +Testing/ diff --git a/POSIX/golang/CMakeLists.txt b/POSIX/golang/CMakeLists.txt new file mode 100644 index 00000000..8db39f50 --- /dev/null +++ b/POSIX/golang/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# Tencent is pleased to support the open source community by making +# MMKV available. +# +# Copyright (C) 2020 THL A29 Limited, a Tencent company. +# All rights reserved. +# +# Licensed under the BSD 3-Clause License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://opensource.org/licenses/BSD-3-Clause +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.8.0) + +project(mmkv) + +IF(APPLE) + add_compile_definitions(FORCE_POSIX) +ENDIF() + +add_subdirectory(../../Core Core) + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + mmkv + + # Sets the library as a shared library. + STATIC + + # Provides a relative path to your source file(s). + libmmkv_golang.cpp + ) + +target_include_directories(mmkv PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +#find_library( # Sets the name of the path variable. + # log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + # log + #) + +set_target_properties(mmkv PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + ) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( mmkv + core + pthread + ) diff --git a/POSIX/golang/go.mod b/POSIX/golang/go.mod new file mode 100644 index 00000000..83c189e3 --- /dev/null +++ b/POSIX/golang/go.mod @@ -0,0 +1,3 @@ +module tencent.com/mmkv + +go 1.15 diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp new file mode 100644 index 00000000..64304ad0 --- /dev/null +++ b/POSIX/golang/golang-bridge.cpp @@ -0,0 +1,409 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MMKVPredef.h" + +#ifndef MMKV_DISABLE_FLUTTER + +# include "MMKV.h" +# include +# include + +using namespace mmkv; +using namespace std; + +# define MMKV_EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used)) + +MMKV_EXPORT void mmkvInitialize(const char *rootDir, int32_t logLevel) { + if (!rootDir) { + return; + } + MMKV::initializeMMKV(rootDir, (MMKVLogLevel) logLevel); +} + +MMKV_EXPORT void onExit() { + MMKV::onExit(); +} + +MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath) { + MMKV *kv = nullptr; + if (!mmapID) { + return kv; + } + string str = mmapID; + + bool done = false; + if (cryptKey) { + string crypt = cryptKey; + if (crypt.length() > 0) { + if (rootPath) { + string path = rootPath; + kv = MMKV::mmkvWithID(str, (MMKVMode) mode, &crypt, &path); + } else { + kv = MMKV::mmkvWithID(str, (MMKVMode) mode, &crypt, nullptr); + } + done = true; + } + } + if (!done) { + if (rootPath) { + string path = rootPath; + kv = MMKV::mmkvWithID(str, (MMKVMode) mode, nullptr, &path); + } else { + kv = MMKV::mmkvWithID(str, (MMKVMode) mode, nullptr, nullptr); + } + } + + return kv; +} + +MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey) { + MMKV *kv = nullptr; + + if (cryptKey) { + string crypt = cryptKey; + if (crypt.length() > 0) { + kv = MMKV::defaultMMKV((MMKVMode) mode, &crypt); + } + } + if (!kv) { + kv = MMKV::defaultMMKV((MMKVMode) mode, nullptr); + } + + return kv; +} + +MMKV_EXPORT const char *mmapID(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + return kv->mmapID().c_str(); + } + return nullptr; +} + +MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set((bool) value, key); + } + return false; +} + +MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getBool(key, defaultValue); + } + return defaultValue; +} + +MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set((int32_t) value, key); + } + return false; +} + +MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getInt32(key, defaultValue); + } + return defaultValue; +} + +MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set((int64_t) value, key); + } + return false; +} + +MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getInt64(key, defaultValue); + } + return defaultValue; +} + +MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set((double) value, key); + } + return false; +} + +MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getDouble(key, defaultValue); + } + return defaultValue; +} + +MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + if (oValue) { + auto value = MMBuffer(oValue, static_cast(length), MMBufferNoCopy); + return kv->set(value, key); + } else { + kv->removeValueForKey(key); + return true; + } + } + return false; +} + +MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + auto value = kv->getBytes(key); + if (value.length() > 0) { + if (value.isStoredOnStack()) { + auto result = malloc(value.length()); + if (result) { + memcpy(result, value.getPtr(), value.length()); + *lengthPtr = value.length(); + } + return result; + } else { + void *result = value.getPtr(); + *lengthPtr = value.length(); + value.detach(); + return result; + } + } + } + return nullptr; +} + +# ifndef MMKV_DISABLE_CRYPT + +MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length) { + MMKV *kv = static_cast(handle); + if (kv) { + if (oKey && length > 0) { + string key(oKey, length); + return kv->reKey(key); + } else { + return kv->reKey(string()); + } + } + return false; +} + +MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) { + MMKV *kv = static_cast(handle); + if (kv && lengthPtr) { + auto cryptKey = kv->cryptKey(); + if (cryptKey.length() > 0) { + auto ptr = malloc(cryptKey.length()); + if (ptr) { + memcpy(ptr, cryptKey.data(), cryptKey.length()); + *lengthPtr = cryptKey.length(); + return ptr; + } + } + } + return nullptr; +} + +MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t length) { + MMKV *kv = static_cast(handle); + if (kv) { + if (oKey && length > 0) { + string key(oKey, length); + kv->checkReSetCryptKey(&key); + } else { + kv->checkReSetCryptKey(nullptr); + } + } +} + +# endif // MMKV_DISABLE_CRYPT + +MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + string key(oKey); + auto ret = kv->getValueSize(key, actualSize); + return static_cast(ret); + } + return 0; +} + +MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *pointer, uint32_t size) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + string key(oKey); + return kv->writeValueToBuffer(key, pointer, size); + } + return -1; +} + +MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr) { + MMKV *kv = static_cast(handle); + if (kv) { + auto keys = kv->allKeys(); + if (!keys.empty()) { + auto keyArray = (char **) malloc(keys.size() * sizeof(void *)); + auto sizeArray = (uint32_t *) malloc(keys.size() * sizeof(uint32_t *)); + if (!keyArray || !sizeArray) { + free(keyArray); + free(sizeArray); + return 0; + } + *keyArrayPtr = keyArray; + *sizeArrayPtr = sizeArray; + + for (size_t index = 0; index < keys.size(); index++) { + auto &key = keys[index]; + sizeArray[index] = static_cast(key.length()); + keyArray[index] = (char *) malloc(key.length()); + if (keyArray[index]) { + memcpy(keyArray[index], key.data(), key.length()); + } + } + } + return keys.size(); + } + return 0; +} + +MMKV_EXPORT bool containsKey(void *handle, char *oKey) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + string key(oKey); + return kv->containsKey(key); + } + return false; +} + +MMKV_EXPORT uint64_t count(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + return kv->count(); + } + return 0; +} + +MMKV_EXPORT uint64_t totalSize(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + return kv->totalSize(); + } + return 0; +} + +MMKV_EXPORT uint64_t actualSize(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + return kv->actualSize(); + } + return 0; +} + +MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + string key(oKey); + kv->removeValueForKey(key); + } +} + +MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint32_t *sizeArray, uint64_t count) { + MMKV *kv = static_cast(handle); + if (kv && keyArray && sizeArray && count > 0) { + vector arrKeys; + arrKeys.reserve(count); + for (uint64_t index = 0; index < count; index++) { + if (sizeArray[index] > 0 && keyArray[index]) { + arrKeys.emplace_back(keyArray[index], sizeArray[index]); + } + } + if (!arrKeys.empty()) { + kv->removeValuesForKeys(arrKeys); + } + } +} + +MMKV_EXPORT void clearAll(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + kv->clearAll(); + } +} + +MMKV_EXPORT void mmkvSync(void *handle, bool sync) { + MMKV *kv = static_cast(handle); + if (kv) { + kv->sync((SyncFlag) sync); + } +} + +MMKV_EXPORT void clearMemoryCache(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + kv->clearMemoryCache(); + } +} + +MMKV_EXPORT int32_t pageSize() { + return static_cast(DEFAULT_MMAP_SIZE); +} + +MMKV_EXPORT const char *version() { + return MMKV_VERSION; +} + +MMKV_EXPORT void trim(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + kv->trim(); + } +} + +MMKV_EXPORT void mmkvClose(void *handle) { + MMKV *kv = static_cast(handle); + if (kv) { + kv->close(); + } +} + +MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) { + memcpy(dst, src, size); +} + +#endif // MMKV_DISABLE_FLUTTER diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h new file mode 100644 index 00000000..ac9f571e --- /dev/null +++ b/POSIX/golang/golang-bridge.h @@ -0,0 +1,20 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + diff --git a/POSIX/golang/libmmkv_golang.cpp b/POSIX/golang/libmmkv_golang.cpp new file mode 100644 index 00000000..1d579c1a --- /dev/null +++ b/POSIX/golang/libmmkv_golang.cpp @@ -0,0 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MMKV.h" diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go new file mode 100644 index 00000000..a7ee800c --- /dev/null +++ b/POSIX/golang/mmkv.go @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mmkv + +// #cgo CXXFLAGS: -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 +// #cgo LDFLAGS: -L${SRCDIR} -lmmkv +// #include "golang-bridge.h" +import "C" +import "fmt" + +// Hello returns a greeting for the named person. +func Version() string { + return "v1.2.7" +} + +// init sets initial values for variables used in the function. +func init() { +} diff --git a/POSIX/golang/mmkv_test.go b/POSIX/golang/mmkv_test.go new file mode 100644 index 00000000..14db4859 --- /dev/null +++ b/POSIX/golang/mmkv_test.go @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mmkv + +import ( + "testing" + "regexp" +) + +func TestHelloEmpty(t *testing.T) { + msg := Version() + if msg == "" { + t.Fatalf("Version() == \"\"") + } +} From c0234f87754eaed4cda6ef8ef959e2c0134ebdd1 Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 10 Dec 2020 21:51:30 +0800 Subject: [PATCH 03/16] prepare for golang --- POSIX/golang/CMakeLists.txt | 17 +---- POSIX/golang/golang-bridge.cpp | 10 +-- POSIX/golang/golang-bridge.h | 47 +++++++++++++ POSIX/golang/libmmkv_golang.cpp | 21 ------ POSIX/golang/mmkv.go | 121 ++++++++++++++++++++++++++++++-- POSIX/golang/mmkv_test.go | 4 +- 6 files changed, 169 insertions(+), 51 deletions(-) delete mode 100644 POSIX/golang/libmmkv_golang.cpp diff --git a/POSIX/golang/CMakeLists.txt b/POSIX/golang/CMakeLists.txt index 8db39f50..01410788 100644 --- a/POSIX/golang/CMakeLists.txt +++ b/POSIX/golang/CMakeLists.txt @@ -42,26 +42,13 @@ add_library( # Sets the name of the library. STATIC # Provides a relative path to your source file(s). - libmmkv_golang.cpp + golang-bridge.h + golang-bridge.cpp ) target_include_directories(mmkv PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -# Searches for a specified prebuilt library and stores the path as a -# variable. Because CMake includes system libraries in the search path by -# default, you only need to specify the name of the public NDK library -# you want to add. CMake verifies that the library exists before -# completing its build. - -#find_library( # Sets the name of the path variable. - # log-lib - - # Specifies the name of the NDK library that - # you want CMake to locate. - # log - #) - set_target_properties(mmkv PROPERTIES CXX_STANDARD 17 CXX_EXTENSIONS OFF diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index 64304ad0..54102607 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -18,9 +18,9 @@ * limitations under the License. */ -#include "MMKVPredef.h" +#ifndef CGO -#ifndef MMKV_DISABLE_FLUTTER +#include "MMKVPredef.h" # include "MMKV.h" # include @@ -402,8 +402,4 @@ MMKV_EXPORT void mmkvClose(void *handle) { } } -MMKV_EXPORT void mmkvMemcpy(void *dst, const void *src, uint64_t size) { - memcpy(dst, src, size); -} - -#endif // MMKV_DISABLE_FLUTTER +#endif // CGO diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index ac9f571e..cea7301d 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -18,3 +18,50 @@ * limitations under the License. */ +#ifdef __cplusplus +#include +extern "C" { +#else +#include +#include +#endif + +void mmkvInitialize(const char *rootDir, int32_t logLevel); +void onExit(); +void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath); +void *getDefaultMMKV(int32_t mode, const char *cryptKey); +const char *mmapID(void *handle); +bool encodeBool(void *handle, const char *oKey, bool value); +bool decodeBool(void *handle, const char *oKey, bool defaultValue); +bool encodeInt32(void *handle, const char *oKey, int32_t value); +int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue); +bool encodeInt64(void *handle, const char *oKey, int64_t value); +int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue); +bool encodeDouble(void *handle, const char *oKey, double value); +double decodeDouble(void *handle, const char *oKey, double defaultValue); +bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length); +void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr); +bool reKey(void *handle, char *oKey, uint64_t length); +void *cryptKey(void *handle, uint64_t *lengthPtr); +void checkReSetCryptKey(void *handle, char *oKey, uint64_t length); +uint32_t valueSize(void *handle, char *oKey, bool actualSize); +int32_t writeValueToNB(void *handle, char *oKey, void *pointer, uint32_t size); +uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr); +bool containsKey(void *handle, char *oKey); +uint64_t count(void *handle); +uint64_t totalSize(void *handle); +uint64_t actualSize(void *handle); +void removeValueForKey(void *handle, char *oKey); +void removeValuesForKeys(void *handle, char **keyArray, uint32_t *sizeArray, uint64_t count); +void clearAll(void *handle); +void mmkvSync(void *handle, bool sync); +void clearMemoryCache(void *handle); +int32_t pageSize(); +const char *version(); +void trim(void *handle); +void mmkvClose(void *handle); + + +#ifdef __cplusplus +} +#endif diff --git a/POSIX/golang/libmmkv_golang.cpp b/POSIX/golang/libmmkv_golang.cpp deleted file mode 100644 index 1d579c1a..00000000 --- a/POSIX/golang/libmmkv_golang.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * MMKV available. - * - * Copyright (C) 2020 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MMKV.h" diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index a7ee800c..447a33e8 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -20,17 +20,126 @@ package mmkv -// #cgo CXXFLAGS: -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 -// #cgo LDFLAGS: -L${SRCDIR} -lmmkv +// #cgo CXXFLAGS: -D CGO -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 +// #cgo LDFLAGS: -L. -lmmkv -L./Core -lcore -lz -lpthread // #include "golang-bridge.h" +// #include import "C" -import "fmt" +// import "fmt" +import "unsafe" + +const ( + MMKVLogDebug = iota // not available for release/product build + MMKVLogInfo // default level + MMKVLogWarning + MMKVLogError + MMKVLogNone // special level used to disable all log messages +) + +const ( + MMKV_SINGLE_PROCESS = iota << 1 + MMKV_MULTI_PROCESS = iota << 2 +) + +const ( + OnErrorDiscard = iota + OnErrorRecover +) + +const ( + MMKVCRCCheckFail = iota + MMKVFileLength +) + +type ctorMMKV uintptr + +type MMKV interface { +/* + SetBool(value bool, key string) bool + SetInt32(value int32, key string) bool + SetInt64(value int64, key string) bool + SetUInt32(value uint32, key string) bool + SetUInt64(value uint64, key string) bool + SetFloat32(value float32, key string) bool + SetFloat64(value float64, key string) bool + SetString(value string, key string) bool + + GetBool(key string) bool + GetBoolWithDefault(key string, defaultValue bool) bool + GetInt32(key string) int32 + GetInt32WithDefault(key string, defaultValue int32) int32 + GetUInt32(key string) uint32 + GetUInt32WithDefault(key string, defaultValue uint32) uint32 + GetInt64(key string) int64 + GetInt64WithDefault(key string, defaultValue int64) int64 + GetUInt64(key string) uint64 + GetUInt64WithDefault(key string, defaultValue uint64) uint64 + GetFloat32(key string) float32 + GetFloat32WithDefault(key string, defaultValue float32) float32 + GetFloat64(key string) float64 + GetFloat64WithDefault(key string, defaultValue float64) float64 + GetString(key string) string + + RemoveKey(key string) + RemoveKeys(keys []string) + ClearAll() + + Contains(key string) bool + Count() uint64 + AllKeys() []string*/ + TotalSize() uint64 + ActualSize() uint64 +/* + MMAP_ID() string + + Sync(sync bool) + Trim() + Close() + + ReKey(newKey string) bool + CryptKey() string + */ +} // Hello returns a greeting for the named person. func Version() string { - return "v1.2.7" + version := C.version() + goStr := C.GoString(version) + return goStr +} + +func InitializeMMKV(rootDir string) { + cRootDir := C.CString(rootDir) + C.mmkvInitialize(cRootDir, MMKVLogInfo) + C.free(unsafe.Pointer(cRootDir)) +} + +func InitializeMMKVWithLogLevel(rootDir string, logLevel int) { + cRootDir := C.CString(rootDir) + C.mmkvInitialize(cRootDir, C.int32_t(logLevel)) + C.free(unsafe.Pointer(cRootDir)) +} + +func OnExit() { + C.onExit() +} + +func PageSize() int32 { + return int32(C.pageSize()) +} + +func MMKVWithID(mmapID string) MMKV { + cmmapID := C.CString(mmapID) + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, MMKV_SINGLE_PROCESS, nil, nil)) + C.free(unsafe.Pointer(cmmapID)) + + return MMKV(mmkv) +} + +func (kv ctorMMKV) TotalSize() uint64 { + return uint64(C.totalSize(unsafe.Pointer(kv))) } -// init sets initial values for variables used in the function. -func init() { +func (kv ctorMMKV) ActualSize() uint64 { + return uint64(C.actualSize(unsafe.Pointer(kv))) } diff --git a/POSIX/golang/mmkv_test.go b/POSIX/golang/mmkv_test.go index 14db4859..6bc52953 100644 --- a/POSIX/golang/mmkv_test.go +++ b/POSIX/golang/mmkv_test.go @@ -22,10 +22,10 @@ package mmkv import ( "testing" - "regexp" +// "regexp" ) -func TestHelloEmpty(t *testing.T) { +func TestVersionEmpty(t *testing.T) { msg := Version() if msg == "" { t.Fatalf("Version() == \"\"") From 3201c6f06343bb61aed9332510e166e23f48a1d6 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 11 Dec 2020 15:49:04 +0800 Subject: [PATCH 04/16] most prime types --- POSIX/golang/golang-bridge.cpp | 54 +++++++++++ POSIX/golang/golang-bridge.h | 6 ++ POSIX/golang/mmkv.go | 166 ++++++++++++++++++++++++++++++++- 3 files changed, 221 insertions(+), 5 deletions(-) diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index 54102607..d220b7aa 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -134,6 +134,24 @@ MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultV return defaultValue; } +MMKV_EXPORT bool encodeUInt32(void *handle, const char *oKey, uint32_t value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set(value, key); + } + return false; +} + +MMKV_EXPORT uint32_t decodeUInt32(void *handle, const char *oKey, uint32_t defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getUInt32(key, defaultValue); + } + return defaultValue; +} + MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t value) { MMKV *kv = static_cast(handle); if (kv && oKey) { @@ -152,6 +170,42 @@ MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultV return defaultValue; } +MMKV_EXPORT bool encodeUInt64(void *handle, const char *oKey, uint64_t value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set(value, key); + } + return false; +} + +MMKV_EXPORT uint64_t decodeUInt64(void *handle, const char *oKey, uint64_t defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getUInt64(key, defaultValue); + } + return defaultValue; +} + +MMKV_EXPORT bool encodeFloat(void *handle, const char *oKey, float value) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->set((float) value, key); + } + return false; +} + +MMKV_EXPORT float decodeFloat(void *handle, const char *oKey, float defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey) { + auto key = string(oKey); + return kv->getFloat(key, defaultValue); + } + return defaultValue; +} + MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double value) { MMKV *kv = static_cast(handle); if (kv && oKey) { diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index cea7301d..5f9902fa 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -35,8 +35,14 @@ bool encodeBool(void *handle, const char *oKey, bool value); bool decodeBool(void *handle, const char *oKey, bool defaultValue); bool encodeInt32(void *handle, const char *oKey, int32_t value); int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue); +bool encodeUInt32(void *handle, const char *oKey, uint32_t value); +uint32_t decodeUInt32(void *handle, const char *oKey, uint32_t defaultValue); bool encodeInt64(void *handle, const char *oKey, int64_t value); int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue); +bool encodeUInt64(void *handle, const char *oKey, uint64_t value); +uint64_t decodeUInt64(void *handle, const char *oKey, uint64_t defaultValue); +bool encodeFloat(void *handle, const char *oKey, float value); +float decodeFloat(void *handle, const char *oKey, float defaultValue); bool encodeDouble(void *handle, const char *oKey, double value); double decodeDouble(void *handle, const char *oKey, double defaultValue); bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length); diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 447a33e8..2663742e 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -37,8 +37,8 @@ const ( ) const ( - MMKV_SINGLE_PROCESS = iota << 1 - MMKV_MULTI_PROCESS = iota << 2 + MMKV_SINGLE_PROCESS = 1 << iota + MMKV_MULTI_PROCESS ) const ( @@ -54,7 +54,6 @@ const ( type ctorMMKV uintptr type MMKV interface { -/* SetBool(value bool, key string) bool SetInt32(value int32, key string) bool SetInt64(value int64, key string) bool @@ -79,14 +78,14 @@ type MMKV interface { GetFloat64(key string) float64 GetFloat64WithDefault(key string, defaultValue float64) float64 GetString(key string) string - +/* RemoveKey(key string) RemoveKeys(keys []string) ClearAll() - Contains(key string) bool Count() uint64 AllKeys() []string*/ + Contains(key string) bool TotalSize() uint64 ActualSize() uint64 /* @@ -136,6 +135,163 @@ func MMKVWithID(mmapID string) MMKV { return MMKV(mmkv) } +// TODO: use _GoString_ to avoid string copying +func (kv ctorMMKV) SetBool(value bool, key string) bool { + cKey := C.CString(key) + ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetBool(key string) bool { + return kv.GetBoolWithDefault(key, false) +} + +func (kv ctorMMKV) GetBoolWithDefault(key string, defaultValue bool) bool { + cKey := C.CString(key) + value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return bool(value) +} + +func (kv ctorMMKV) SetInt32(value int32, key string) bool { + cKey := C.CString(key) + ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetInt32(key string) int32 { + return kv.GetInt32WithDefault(key, 0) +} + +func (kv ctorMMKV) GetInt32WithDefault(key string, defaultValue int32) int32 { + cKey := C.CString(key) + value := C.decodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return int32(value) +} + +func (kv ctorMMKV) SetUInt32(value uint32, key string) bool { + cKey := C.CString(key) + ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetUInt32(key string) uint32 { + return kv.GetUInt32WithDefault(key, 0) +} + +func (kv ctorMMKV) GetUInt32WithDefault(key string, defaultValue uint32) uint32 { + cKey := C.CString(key) + value := C.decodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return uint32(value) +} + +func (kv ctorMMKV) SetInt64(value int64, key string) bool { + cKey := C.CString(key) + ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetInt64(key string) int64 { + return kv.GetInt64WithDefault(key, 0) +} + +func (kv ctorMMKV) GetInt64WithDefault(key string, defaultValue int64) int64 { + cKey := C.CString(key) + value := C.decodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return int64(value) +} + +func (kv ctorMMKV) SetUInt64(value uint64, key string) bool { + cKey := C.CString(key) + ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetUInt64(key string) uint64 { + return kv.GetUInt64WithDefault(key, 0) +} + +func (kv ctorMMKV) GetUInt64WithDefault(key string, defaultValue uint64) uint64 { + cKey := C.CString(key) + value := C.decodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return uint64(value) +} + +func (kv ctorMMKV) SetFloat32(value float32, key string) bool { + cKey := C.CString(key) + ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetFloat32(key string) float32 { + return kv.GetFloat32WithDefault(key, 0) +} + +func (kv ctorMMKV) GetFloat32WithDefault(key string, defaultValue float32) float32 { + cKey := C.CString(key) + value := C.decodeFloat(unsafe.Pointer(kv), cKey, C.float(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return float32(value) +} + +func (kv ctorMMKV) SetFloat64(value float64, key string) bool { + cKey := C.CString(key) + ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) GetFloat64(key string) float64 { + return kv.GetFloat64WithDefault(key, 0) +} + +func (kv ctorMMKV) GetFloat64WithDefault(key string, defaultValue float64) float64 { + cKey := C.CString(key) + value := C.decodeDouble(unsafe.Pointer(kv), cKey, C.double(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return float64(value) +} + +func (kv ctorMMKV) SetString(value string, key string) bool { + cKey := C.CString(key) + cValue := C.CString(value) + + ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))); + + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return bool(ret) +} + +func (kv ctorMMKV) GetString(key string) string { + cKey := C.CString(key) + var length uint64 + + cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) + value := C.GoString((*C.char)(cValue)) + + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return value +} + +func (kv ctorMMKV) Contains(key string) bool { + cKey := C.CString(key) + ret := C.containsKey(unsafe.Pointer(kv), cKey); + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + func (kv ctorMMKV) TotalSize() uint64 { return uint64(C.totalSize(unsafe.Pointer(kv))) } From 7f522d18ee68638eaf19f2a3e85ff19c5e2546d2 Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 11 Dec 2020 17:59:34 +0800 Subject: [PATCH 05/16] bytes --- POSIX/golang/mmkv.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 2663742e..e46fe33b 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -62,6 +62,7 @@ type MMKV interface { SetFloat32(value float32, key string) bool SetFloat64(value float64, key string) bool SetString(value string, key string) bool + SetBytes(value []byte, key string) bool GetBool(key string) bool GetBoolWithDefault(key string, defaultValue bool) bool @@ -78,6 +79,7 @@ type MMKV interface { GetFloat64(key string) float64 GetFloat64WithDefault(key string, defaultValue float64) float64 GetString(key string) string + GetBytes(key string) []byte /* RemoveKey(key string) RemoveKeys(keys []string) @@ -285,6 +287,29 @@ func (kv ctorMMKV) GetString(key string) string { return value } +func (kv ctorMMKV) SetBytes(value []byte, key string) bool { + cKey := C.CString(key) + cValue := C.CBytes(value) + + ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))); + + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return bool(ret) +} + +func (kv ctorMMKV) GetBytes(key string) []byte { + cKey := C.CString(key) + var length uint64 + + cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) + value := C.GoBytes(unsafe.Pointer(cValue), C.int(length)) + + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return value +} + func (kv ctorMMKV) Contains(key string) bool { cKey := C.CString(key) ret := C.containsKey(unsafe.Pointer(kv), cKey); From 24d34704781c1a93507cbba9fa7de75824f51bfa Mon Sep 17 00:00:00 2001 From: guoling Date: Fri, 11 Dec 2020 21:26:35 +0800 Subject: [PATCH 06/16] golang almost done --- POSIX/golang/golang-bridge.cpp | 25 +---- POSIX/golang/golang-bridge.h | 13 +-- POSIX/golang/mmkv.go | 168 +++++++++++++++++++++++++++++++-- 3 files changed, 169 insertions(+), 37 deletions(-) diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index d220b7aa..52f2b616 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -20,7 +20,7 @@ #ifndef CGO -#include "MMKVPredef.h" +# include "MMKVPredef.h" # include "MMKV.h" # include @@ -265,7 +265,7 @@ MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPt # ifndef MMKV_DISABLE_CRYPT -MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length) { +MMKV_EXPORT bool reKey(void *handle, char *oKey, uint32_t length) { MMKV *kv = static_cast(handle); if (kv) { if (oKey && length > 0) { @@ -278,7 +278,7 @@ MMKV_EXPORT bool reKey(void *handle, char *oKey, uint64_t length) { return false; } -MMKV_EXPORT void *cryptKey(void *handle, uint64_t *lengthPtr) { +MMKV_EXPORT void *cryptKey(void *handle, uint32_t *lengthPtr) { MMKV *kv = static_cast(handle); if (kv && lengthPtr) { auto cryptKey = kv->cryptKey(); @@ -308,25 +308,6 @@ MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t length) { # endif // MMKV_DISABLE_CRYPT -MMKV_EXPORT uint32_t valueSize(void *handle, char *oKey, bool actualSize) { - MMKV *kv = static_cast(handle); - if (kv && oKey) { - string key(oKey); - auto ret = kv->getValueSize(key, actualSize); - return static_cast(ret); - } - return 0; -} - -MMKV_EXPORT int32_t writeValueToNB(void *handle, char *oKey, void *pointer, uint32_t size) { - MMKV *kv = static_cast(handle); - if (kv && oKey) { - string key(oKey); - return kv->writeValueToBuffer(key, pointer, size); - } - return -1; -} - MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr) { MMKV *kv = static_cast(handle); if (kv) { diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index 5f9902fa..7e9f3016 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -19,11 +19,11 @@ */ #ifdef __cplusplus -#include +# include extern "C" { #else -#include -#include +# include +# include #endif void mmkvInitialize(const char *rootDir, int32_t logLevel); @@ -47,11 +47,9 @@ bool encodeDouble(void *handle, const char *oKey, double value); double decodeDouble(void *handle, const char *oKey, double defaultValue); bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length); void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr); -bool reKey(void *handle, char *oKey, uint64_t length); -void *cryptKey(void *handle, uint64_t *lengthPtr); +bool reKey(void *handle, char *oKey, uint32_t length); +void *cryptKey(void *handle, uint32_t *lengthPtr); void checkReSetCryptKey(void *handle, char *oKey, uint64_t length); -uint32_t valueSize(void *handle, char *oKey, bool actualSize); -int32_t writeValueToNB(void *handle, char *oKey, void *pointer, uint32_t size); uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr); bool containsKey(void *handle, char *oKey); uint64_t count(void *handle); @@ -67,7 +65,6 @@ const char *version(); void trim(void *handle); void mmkvClose(void *handle); - #ifdef __cplusplus } #endif diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index e46fe33b..33817a08 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -22,10 +22,36 @@ package mmkv // #cgo CXXFLAGS: -D CGO -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 // #cgo LDFLAGS: -L. -lmmkv -L./Core -lcore -lz -lpthread -// #include "golang-bridge.h" -// #include +/* +#include "golang-bridge.h" +#include + +typedef void* voidptr_t; + +static void setStringArray(char **array, char *str, size_t n) { + array[n] = str; +} + +static char *getStringArray(char **array, size_t n) { + return array[n]; +} + +static void setSizeArray(uint32_t *array, uint32_t value, size_t n) { + array[n] = value; +} + +static uint32_t getSizeArray(uint32_t *array, size_t n) { + return array[n]; +} + +static void freeStringArray(char **a, size_t size) { + size_t i; + for (i = 0; i < size; i++) { + free(a[i]); + } +} +*/ import "C" -// import "fmt" import "unsafe" const ( @@ -80,26 +106,26 @@ type MMKV interface { GetFloat64WithDefault(key string, defaultValue float64) float64 GetString(key string) string GetBytes(key string) []byte -/* + RemoveKey(key string) RemoveKeys(keys []string) ClearAll() Count() uint64 - AllKeys() []string*/ + AllKeys() []string Contains(key string) bool TotalSize() uint64 ActualSize() uint64 -/* + MMAP_ID() string Sync(sync bool) + ClearMemoryCache() Trim() Close() ReKey(newKey string) bool CryptKey() string - */ } // Hello returns a greeting for the named person. @@ -129,6 +155,23 @@ func PageSize() int32 { return int32(C.pageSize()) } +func DefaultMMKV() MMKV { + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, nil)) + return MMKV(mmkv) +} + +func DefaultMMKVWithMode(mode int) MMKV { + mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), nil)) + return MMKV(mmkv) +} + +func DefaultMMKVWithModeAndCryptKey(mode int, cryptKey string) MMKV { + cCryptKey := C.CString(cryptKey) + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, cCryptKey)) + C.free(unsafe.Pointer(cCryptKey)) + return MMKV(mmkv) +} + func MMKVWithID(mmapID string) MMKV { cmmapID := C.CString(mmapID) mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, MMKV_SINGLE_PROCESS, nil, nil)) @@ -137,6 +180,26 @@ func MMKVWithID(mmapID string) MMKV { return MMKV(mmkv) } +func MMKVWithIDAndMode(mmapID string, mode int) MMKV { + cmmapID := C.CString(mmapID) + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), nil, nil)) + C.free(unsafe.Pointer(cmmapID)) + + return MMKV(mmkv) +} + +func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey string) MMKV { + cmmapID := C.CString(mmapID) + cCryptKey := C.CString(cryptKey) + + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), cCryptKey, nil)) + + C.free(unsafe.Pointer(cmmapID)) + C.free(unsafe.Pointer(cCryptKey)) + + return MMKV(mmkv) +} + // TODO: use _GoString_ to avoid string copying func (kv ctorMMKV) SetBool(value bool, key string) bool { cKey := C.CString(key) @@ -310,6 +373,54 @@ func (kv ctorMMKV) GetBytes(key string) []byte { return value } +func (kv ctorMMKV) RemoveKey(key string) { + cKey := C.CString(key) + C.removeValueForKey(unsafe.Pointer(kv), cKey); + C.free(unsafe.Pointer(cKey)) +} + +func (kv ctorMMKV) RemoveKeys(keys []string) { + keyArray := (**C.char)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) + sizeArray := (*C.uint32_t)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) + + for index, key := range keys { + C.setStringArray(keyArray, C.CString(key), C.size_t(index)) + C.setSizeArray(sizeArray, C.uint32_t(len(key)), C.size_t(index)) + } + C.removeValuesForKeys(unsafe.Pointer(kv), keyArray, sizeArray, C.uint64_t(len(keys))) + + C.freeStringArray(keyArray, C.size_t(len(keys))) + C.free(unsafe.Pointer(keyArray)) + C.free(unsafe.Pointer(sizeArray)) +} + +func (kv ctorMMKV) Count() uint64 { + return uint64(C.count(unsafe.Pointer(kv))) +} + +func (kv ctorMMKV) AllKeys() []string { + var keyArray **C.char + var sizeArray *C.uint32_t + + cCount := C.allKeys(unsafe.Pointer(kv), &keyArray, &sizeArray) + count := uint64(cCount) + if count == 0 { + return []string{} + } + + result := make([]string, count) + for index := uint64(0); index < count; index++ { + cStr := C.getStringArray(keyArray, C.size_t(index)) + cLen := C.getSizeArray(sizeArray, C.size_t(index)) + result[index] = C.GoStringN(cStr, C.int(cLen)) + } + + C.freeStringArray(keyArray, C.size_t(cCount)) + C.free(unsafe.Pointer(keyArray)) + C.free(unsafe.Pointer(sizeArray)) + return result +} + func (kv ctorMMKV) Contains(key string) bool { cKey := C.CString(key) ret := C.containsKey(unsafe.Pointer(kv), cKey); @@ -317,6 +428,10 @@ func (kv ctorMMKV) Contains(key string) bool { return bool(ret) } +func (kv ctorMMKV) ClearAll() { + C.clearAll(unsafe.Pointer(kv)) +} + func (kv ctorMMKV) TotalSize() uint64 { return uint64(C.totalSize(unsafe.Pointer(kv))) } @@ -324,3 +439,42 @@ func (kv ctorMMKV) TotalSize() uint64 { func (kv ctorMMKV) ActualSize() uint64 { return uint64(C.actualSize(unsafe.Pointer(kv))) } + +func (kv ctorMMKV) MMAP_ID() string { + cStr := C.mmapID(unsafe.Pointer(kv)) + return C.GoString(cStr) +} + +func (kv ctorMMKV) Sync(sync bool) { + C.mmkvSync(unsafe.Pointer(kv), C.bool(sync)) +} + +func (kv ctorMMKV) ClearMemoryCache() { + C.clearMemoryCache(unsafe.Pointer(kv)) +} + +func (kv ctorMMKV) Trim() { + C.trim(unsafe.Pointer(kv)) +} + +func (kv ctorMMKV) Close() { + C.mmkvClose(unsafe.Pointer(kv)) +} + +func (kv ctorMMKV) ReKey(newKey string) bool { + cKey := C.CString(newKey) + ret := C.reKey(unsafe.Pointer(kv), cKey, C.uint32_t(len(newKey))) + C.free(unsafe.Pointer(cKey)) + return bool(ret) +} + +func (kv ctorMMKV) CryptKey() string { + var cLen C.uint32_t + cStr := C.cryptKey(unsafe.Pointer(kv), &cLen) + if cStr == nil || cLen == 0 { + return "" + } + result := C.GoStringN((*C.char)(cStr), C.int(cLen)) + C.free(unsafe.Pointer(cStr)) + return result +} From 6ef5b8ebcd10d72d5809564647fabd2fbc741dd8 Mon Sep 17 00:00:00 2001 From: lingol Date: Sat, 12 Dec 2020 18:54:16 +0800 Subject: [PATCH 07/16] opt with not copying key --- POSIX/golang/golang-bridge.cpp | 19 +++++++++++++++++ POSIX/golang/golang-bridge.h | 11 +++++++++- POSIX/golang/mmkv.go | 37 +++++++++++++++++++++------------- POSIX/golang/test/demo.go | 14 +++++++++++++ POSIX/golang/test/go.mod | 7 +++++++ 5 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 POSIX/golang/test/demo.go create mode 100644 POSIX/golang/test/go.mod diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index 52f2b616..e1975021 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -25,6 +25,7 @@ # include "MMKV.h" # include # include +#include "golang-bridge.h" using namespace mmkv; using namespace std; @@ -116,6 +117,24 @@ MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool defaultValue) { return defaultValue; } +MMKV_EXPORT bool encodeBool2(void *handle, GoStringWrap oKey, bool value) { + MMKV *kv = static_cast(handle); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); + return kv->set((bool) value, key); + } + return false; +} + +MMKV_EXPORT bool decodeBool2(void *handle, GoStringWrap oKey, bool defaultValue) { + MMKV *kv = static_cast(handle); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); + return kv->getBool(key, defaultValue); + } + return defaultValue; +} + MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t value) { MMKV *kv = static_cast(handle); if (kv && oKey) { diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index 7e9f3016..866eb819 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -19,13 +19,18 @@ */ #ifdef __cplusplus -# include +# include extern "C" { #else # include # include #endif +typedef struct { + const char *ptr; + size_t length; +} GoStringWrap; + void mmkvInitialize(const char *rootDir, int32_t logLevel); void onExit(); void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath); @@ -33,6 +38,10 @@ void *getDefaultMMKV(int32_t mode, const char *cryptKey); const char *mmapID(void *handle); bool encodeBool(void *handle, const char *oKey, bool value); bool decodeBool(void *handle, const char *oKey, bool defaultValue); + +bool encodeBool2(void *handle, GoStringWrap oKey, bool value); +bool decodeBool2(void *handle, GoStringWrap oKey, bool defaultValue); + bool encodeInt32(void *handle, const char *oKey, int32_t value); int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue); bool encodeUInt32(void *handle, const char *oKey, uint32_t value); diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 33817a08..41b7fb03 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -28,6 +28,11 @@ package mmkv typedef void* voidptr_t; +GoStringWrap wrapGoString(_GoString_ str) { + GoStringWrap wrap = { _GoStringPtr(str), _GoStringLen(str) }; + return wrap; +} + static void setStringArray(char **array, char *str, size_t n) { array[n] = str; } @@ -202,9 +207,11 @@ func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey string) MMKV // TODO: use _GoString_ to avoid string copying func (kv ctorMMKV) SetBool(value bool, key string) bool { - cKey := C.CString(key) - ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)); - C.free(unsafe.Pointer(cKey)) + //cKey := C.CString(key) + //ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)) + //C.free(unsafe.Pointer(cKey)) + cKey := C.wrapGoString(key) + ret := C.encodeBool2(unsafe.Pointer(kv), cKey, C.bool(value)) return bool(ret) } @@ -213,15 +220,17 @@ func (kv ctorMMKV) GetBool(key string) bool { } func (kv ctorMMKV) GetBoolWithDefault(key string, defaultValue bool) bool { - cKey := C.CString(key) - value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) - C.free(unsafe.Pointer(cKey)) + //cKey := C.CString(key) + //value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) + //C.free(unsafe.Pointer(cKey)) + cKey := C.wrapGoString(key) + value := C.decodeBool2(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) return bool(value) } func (kv ctorMMKV) SetInt32(value int32, key string) bool { cKey := C.CString(key) - ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)); + ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -239,7 +248,7 @@ func (kv ctorMMKV) GetInt32WithDefault(key string, defaultValue int32) int32 { func (kv ctorMMKV) SetUInt32(value uint32, key string) bool { cKey := C.CString(key) - ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)); + ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -257,7 +266,7 @@ func (kv ctorMMKV) GetUInt32WithDefault(key string, defaultValue uint32) uint32 func (kv ctorMMKV) SetInt64(value int64, key string) bool { cKey := C.CString(key) - ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)); + ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -275,7 +284,7 @@ func (kv ctorMMKV) GetInt64WithDefault(key string, defaultValue int64) int64 { func (kv ctorMMKV) SetUInt64(value uint64, key string) bool { cKey := C.CString(key) - ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)); + ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -293,7 +302,7 @@ func (kv ctorMMKV) GetUInt64WithDefault(key string, defaultValue uint64) uint64 func (kv ctorMMKV) SetFloat32(value float32, key string) bool { cKey := C.CString(key) - ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)); + ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -311,7 +320,7 @@ func (kv ctorMMKV) GetFloat32WithDefault(key string, defaultValue float32) float func (kv ctorMMKV) SetFloat64(value float64, key string) bool { cKey := C.CString(key) - ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)); + ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)) C.free(unsafe.Pointer(cKey)) return bool(ret) } @@ -354,7 +363,7 @@ func (kv ctorMMKV) SetBytes(value []byte, key string) bool { cKey := C.CString(key) cValue := C.CBytes(value) - ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))); + ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) C.free(unsafe.Pointer(cKey)) C.free(unsafe.Pointer(cValue)) @@ -423,7 +432,7 @@ func (kv ctorMMKV) AllKeys() []string { func (kv ctorMMKV) Contains(key string) bool { cKey := C.CString(key) - ret := C.containsKey(unsafe.Pointer(kv), cKey); + ret := C.containsKey(unsafe.Pointer(kv), cKey) C.free(unsafe.Pointer(cKey)) return bool(ret) } diff --git a/POSIX/golang/test/demo.go b/POSIX/golang/test/demo.go new file mode 100644 index 00000000..2f41fde3 --- /dev/null +++ b/POSIX/golang/test/demo.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "tencent.com/mmkv" +) + +func main() { + mmkv.InitializeMMKV("/tmp/mmkv") + + kv := mmkv.MMKVWithID("test") + kv.SetBool(true, "bool") + fmt.Println("bool =", kv.GetBool("bool")) +} diff --git a/POSIX/golang/test/go.mod b/POSIX/golang/test/go.mod new file mode 100644 index 00000000..912f6c22 --- /dev/null +++ b/POSIX/golang/test/go.mod @@ -0,0 +1,7 @@ +module mmkv_test + +go 1.15 + +replace tencent.com/mmkv => ../../golang + +require tencent.com/mmkv v0.0.0-00010101000000-000000000000 // indirect From 8e9c5a800c4a7c2475935c6141cd493f91a9da90 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 14 Dec 2020 11:45:21 +0800 Subject: [PATCH 08/16] complete test --- POSIX/golang/test/demo.go | 14 ---- POSIX/golang/test/main.go | 143 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 14 deletions(-) delete mode 100644 POSIX/golang/test/demo.go create mode 100644 POSIX/golang/test/main.go diff --git a/POSIX/golang/test/demo.go b/POSIX/golang/test/demo.go deleted file mode 100644 index 2f41fde3..00000000 --- a/POSIX/golang/test/demo.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "fmt" - "tencent.com/mmkv" -) - -func main() { - mmkv.InitializeMMKV("/tmp/mmkv") - - kv := mmkv.MMKVWithID("test") - kv.SetBool(true, "bool") - fmt.Println("bool =", kv.GetBool("bool")) -} diff --git a/POSIX/golang/test/main.go b/POSIX/golang/test/main.go new file mode 100644 index 00000000..ad9f9bc3 --- /dev/null +++ b/POSIX/golang/test/main.go @@ -0,0 +1,143 @@ +package main + +import ( + "fmt" + //"log" + "math" + + "tencent.com/mmkv" +) + +func main() { + mmkv.InitializeMMKV("/tmp/mmkv") + + functionalTest() + testReKey() +} + +func functionalTest() { + kv := mmkv.DefaultMMKV() + fmt.Println("actual size:", kv.ActualSize()) + fmt.Println("total size:", kv.TotalSize()) + + kv.SetBool(true, "bool") + fmt.Println("bool =", kv.GetBool("bool")) + + kv.SetInt32(math.MinInt32, "int32") + fmt.Println("int32 =", kv.GetInt32("int32")) + + kv.SetUInt32(math.MaxUint32, "uint32") + fmt.Println("uint32 =", kv.GetUInt32("uint32")) + + kv.SetInt64(math.MinInt64, "int64") + fmt.Println("int64 =", kv.GetInt64("int64")) + + kv.SetUInt64(math.MaxUint64, "uint64") + fmt.Println("uint64 =", kv.GetUInt64("uint64")) + + kv.SetFloat32(math.MaxFloat32, "float32") + fmt.Println("float32 =", kv.GetFloat32("float32")) + + kv.SetFloat64(math.MaxFloat64, "float64") + fmt.Println("float64 =", kv.GetFloat64("float64")) + + kv.SetString("Hello world, from MMKV!", "string") + fmt.Println("string =", kv.GetString("string")) + + kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + fmt.Println("bytes =", string(kv.GetBytes("bytes"))) + + fmt.Println("contains \"bool\"? ", kv.Contains("bool")) + kv.RemoveKey("bool") + fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) + + kv.RemoveKeys([]string {"int32", "int64"}) + fmt.Println("count =", kv.Count(), ", all keys:", kv.AllKeys()) + + kv.Trim() + kv.ClearMemoryCache() + fmt.Println("all keys:", kv.AllKeys()) + kv.ClearAll() + fmt.Println("all keys:", kv.AllKeys()) + kv.Sync(true) + kv.Close() +} + +func testMMKV(mmapID string, cryptKey string, decodeOnly bool) mmkv.MMKV { + kv := mmkv.MMKVWithIDAndModeAndCryptKey(mmapID, mmkv.MMKV_SINGLE_PROCESS, cryptKey) + + if !decodeOnly { + kv.SetBool(true, "bool") + } + fmt.Println("bool =", kv.GetBool("bool")) + + if !decodeOnly { + kv.SetInt32(math.MinInt32, "int32") + } + fmt.Println("int32 =", kv.GetInt32("int32")) + + if !decodeOnly { + kv.SetUInt32(math.MaxUint32, "uint32") + } + fmt.Println("uint32 =", kv.GetUInt32("uint32")) + + if !decodeOnly { + kv.SetInt64(math.MinInt64, "int64") + } + fmt.Println("int64 =", kv.GetInt64("int64")) + + if !decodeOnly { + kv.SetUInt64(math.MaxUint64, "uint64") + } + fmt.Println("uint64 =", kv.GetUInt64("uint64")) + + if !decodeOnly { + kv.SetFloat32(math.MaxFloat32, "float32") + } + fmt.Println("float32 =", kv.GetFloat32("float32")) + + if !decodeOnly { + kv.SetFloat64(math.MaxFloat64, "float64") + } + fmt.Println("float64 =", kv.GetFloat64("float64")) + + if !decodeOnly { + kv.SetString("Hello world, from MMKV!", "string") + } + fmt.Println("string =", kv.GetString("string")) + + if !decodeOnly { + kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + } + fmt.Println("bytes =", string(kv.GetBytes("bytes"))) + + fmt.Println("contains \"bool\"? ", kv.Contains("bool")) + kv.RemoveKey("bool") + fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) + + kv.RemoveKeys([]string {"int32", "int64"}) + fmt.Println("all keys:", kv.AllKeys()) + + return kv +} + +func testReKey() { + mmapID := "testAES_reKey1" + kv := testMMKV(mmapID, "", false) + if kv == nil { + return + } + + kv.ReKey("Key_seq_1") + kv.ClearMemoryCache() + testMMKV(mmapID, "Key_seq_1", true) + + kv.ReKey("Key_seq_2") + kv.ClearMemoryCache() + testMMKV(mmapID, "Key_seq_2", true) + + kv.ReKey("") + kv.ClearMemoryCache() + testMMKV(mmapID, "", true) +} + From 0656bc81b4719bc1307ad12e777e9ba1436195c9 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 14 Dec 2020 12:01:28 +0800 Subject: [PATCH 09/16] go fmt --- POSIX/golang/mmkv.go | 478 +++++++++++++++++++------------------- POSIX/golang/mmkv_test.go | 12 +- POSIX/golang/test/main.go | 225 +++++++++--------- 3 files changed, 357 insertions(+), 358 deletions(-) diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 41b7fb03..844c7ee6 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -60,430 +60,430 @@ import "C" import "unsafe" const ( - MMKVLogDebug = iota // not available for release/product build - MMKVLogInfo // default level - MMKVLogWarning - MMKVLogError - MMKVLogNone // special level used to disable all log messages + MMKVLogDebug = iota // not available for release/product build + MMKVLogInfo // default level + MMKVLogWarning + MMKVLogError + MMKVLogNone // special level used to disable all log messages ) const ( - MMKV_SINGLE_PROCESS = 1 << iota - MMKV_MULTI_PROCESS + MMKV_SINGLE_PROCESS = 1 << iota + MMKV_MULTI_PROCESS ) const ( - OnErrorDiscard = iota - OnErrorRecover + OnErrorDiscard = iota + OnErrorRecover ) const ( - MMKVCRCCheckFail = iota - MMKVFileLength + MMKVCRCCheckFail = iota + MMKVFileLength ) type ctorMMKV uintptr type MMKV interface { - SetBool(value bool, key string) bool - SetInt32(value int32, key string) bool - SetInt64(value int64, key string) bool - SetUInt32(value uint32, key string) bool - SetUInt64(value uint64, key string) bool - SetFloat32(value float32, key string) bool - SetFloat64(value float64, key string) bool - SetString(value string, key string) bool - SetBytes(value []byte, key string) bool - - GetBool(key string) bool - GetBoolWithDefault(key string, defaultValue bool) bool - GetInt32(key string) int32 - GetInt32WithDefault(key string, defaultValue int32) int32 - GetUInt32(key string) uint32 - GetUInt32WithDefault(key string, defaultValue uint32) uint32 - GetInt64(key string) int64 - GetInt64WithDefault(key string, defaultValue int64) int64 - GetUInt64(key string) uint64 - GetUInt64WithDefault(key string, defaultValue uint64) uint64 - GetFloat32(key string) float32 - GetFloat32WithDefault(key string, defaultValue float32) float32 - GetFloat64(key string) float64 - GetFloat64WithDefault(key string, defaultValue float64) float64 - GetString(key string) string - GetBytes(key string) []byte - - RemoveKey(key string) - RemoveKeys(keys []string) - ClearAll() - - Count() uint64 - AllKeys() []string - Contains(key string) bool - TotalSize() uint64 - ActualSize() uint64 - - MMAP_ID() string - - Sync(sync bool) - ClearMemoryCache() - Trim() - Close() - - ReKey(newKey string) bool - CryptKey() string + SetBool(value bool, key string) bool + SetInt32(value int32, key string) bool + SetInt64(value int64, key string) bool + SetUInt32(value uint32, key string) bool + SetUInt64(value uint64, key string) bool + SetFloat32(value float32, key string) bool + SetFloat64(value float64, key string) bool + SetString(value string, key string) bool + SetBytes(value []byte, key string) bool + + GetBool(key string) bool + GetBoolWithDefault(key string, defaultValue bool) bool + GetInt32(key string) int32 + GetInt32WithDefault(key string, defaultValue int32) int32 + GetUInt32(key string) uint32 + GetUInt32WithDefault(key string, defaultValue uint32) uint32 + GetInt64(key string) int64 + GetInt64WithDefault(key string, defaultValue int64) int64 + GetUInt64(key string) uint64 + GetUInt64WithDefault(key string, defaultValue uint64) uint64 + GetFloat32(key string) float32 + GetFloat32WithDefault(key string, defaultValue float32) float32 + GetFloat64(key string) float64 + GetFloat64WithDefault(key string, defaultValue float64) float64 + GetString(key string) string + GetBytes(key string) []byte + + RemoveKey(key string) + RemoveKeys(keys []string) + ClearAll() + + Count() uint64 + AllKeys() []string + Contains(key string) bool + TotalSize() uint64 + ActualSize() uint64 + + MMAP_ID() string + + Sync(sync bool) + ClearMemoryCache() + Trim() + Close() + + ReKey(newKey string) bool + CryptKey() string } // Hello returns a greeting for the named person. func Version() string { - version := C.version() - goStr := C.GoString(version) - return goStr + version := C.version() + goStr := C.GoString(version) + return goStr } func InitializeMMKV(rootDir string) { - cRootDir := C.CString(rootDir) - C.mmkvInitialize(cRootDir, MMKVLogInfo) - C.free(unsafe.Pointer(cRootDir)) + cRootDir := C.CString(rootDir) + C.mmkvInitialize(cRootDir, MMKVLogInfo) + C.free(unsafe.Pointer(cRootDir)) } func InitializeMMKVWithLogLevel(rootDir string, logLevel int) { - cRootDir := C.CString(rootDir) - C.mmkvInitialize(cRootDir, C.int32_t(logLevel)) - C.free(unsafe.Pointer(cRootDir)) + cRootDir := C.CString(rootDir) + C.mmkvInitialize(cRootDir, C.int32_t(logLevel)) + C.free(unsafe.Pointer(cRootDir)) } func OnExit() { - C.onExit() + C.onExit() } func PageSize() int32 { - return int32(C.pageSize()) + return int32(C.pageSize()) } func DefaultMMKV() MMKV { - mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, nil)) - return MMKV(mmkv) + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, nil)) + return MMKV(mmkv) } func DefaultMMKVWithMode(mode int) MMKV { - mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), nil)) - return MMKV(mmkv) + mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), nil)) + return MMKV(mmkv) } func DefaultMMKVWithModeAndCryptKey(mode int, cryptKey string) MMKV { - cCryptKey := C.CString(cryptKey) - mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, cCryptKey)) - C.free(unsafe.Pointer(cCryptKey)) - return MMKV(mmkv) + cCryptKey := C.CString(cryptKey) + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, cCryptKey)) + C.free(unsafe.Pointer(cCryptKey)) + return MMKV(mmkv) } func MMKVWithID(mmapID string) MMKV { - cmmapID := C.CString(mmapID) - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, MMKV_SINGLE_PROCESS, nil, nil)) - C.free(unsafe.Pointer(cmmapID)) + cmmapID := C.CString(mmapID) + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, MMKV_SINGLE_PROCESS, nil, nil)) + C.free(unsafe.Pointer(cmmapID)) - return MMKV(mmkv) + return MMKV(mmkv) } func MMKVWithIDAndMode(mmapID string, mode int) MMKV { - cmmapID := C.CString(mmapID) - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), nil, nil)) - C.free(unsafe.Pointer(cmmapID)) + cmmapID := C.CString(mmapID) + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), nil, nil)) + C.free(unsafe.Pointer(cmmapID)) - return MMKV(mmkv) + return MMKV(mmkv) } func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey string) MMKV { - cmmapID := C.CString(mmapID) - cCryptKey := C.CString(cryptKey) + cmmapID := C.CString(mmapID) + cCryptKey := C.CString(cryptKey) - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), cCryptKey, nil)) + mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), cCryptKey, nil)) - C.free(unsafe.Pointer(cmmapID)) - C.free(unsafe.Pointer(cCryptKey)) + C.free(unsafe.Pointer(cmmapID)) + C.free(unsafe.Pointer(cCryptKey)) - return MMKV(mmkv) + return MMKV(mmkv) } // TODO: use _GoString_ to avoid string copying func (kv ctorMMKV) SetBool(value bool, key string) bool { - //cKey := C.CString(key) - //ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)) - //C.free(unsafe.Pointer(cKey)) - cKey := C.wrapGoString(key) - ret := C.encodeBool2(unsafe.Pointer(kv), cKey, C.bool(value)) - return bool(ret) + //cKey := C.CString(key) + //ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)) + //C.free(unsafe.Pointer(cKey)) + cKey := C.wrapGoString(key) + ret := C.encodeBool2(unsafe.Pointer(kv), cKey, C.bool(value)) + return bool(ret) } func (kv ctorMMKV) GetBool(key string) bool { - return kv.GetBoolWithDefault(key, false) + return kv.GetBoolWithDefault(key, false) } func (kv ctorMMKV) GetBoolWithDefault(key string, defaultValue bool) bool { - //cKey := C.CString(key) - //value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) - //C.free(unsafe.Pointer(cKey)) - cKey := C.wrapGoString(key) - value := C.decodeBool2(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) - return bool(value) + //cKey := C.CString(key) + //value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) + //C.free(unsafe.Pointer(cKey)) + cKey := C.wrapGoString(key) + value := C.decodeBool2(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) + return bool(value) } func (kv ctorMMKV) SetInt32(value int32, key string) bool { - cKey := C.CString(key) - ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetInt32(key string) int32 { - return kv.GetInt32WithDefault(key, 0) + return kv.GetInt32WithDefault(key, 0) } func (kv ctorMMKV) GetInt32WithDefault(key string, defaultValue int32) int32 { - cKey := C.CString(key) - value := C.decodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return int32(value) + cKey := C.CString(key) + value := C.decodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return int32(value) } func (kv ctorMMKV) SetUInt32(value uint32, key string) bool { - cKey := C.CString(key) - ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetUInt32(key string) uint32 { - return kv.GetUInt32WithDefault(key, 0) + return kv.GetUInt32WithDefault(key, 0) } func (kv ctorMMKV) GetUInt32WithDefault(key string, defaultValue uint32) uint32 { - cKey := C.CString(key) - value := C.decodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return uint32(value) + cKey := C.CString(key) + value := C.decodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return uint32(value) } func (kv ctorMMKV) SetInt64(value int64, key string) bool { - cKey := C.CString(key) - ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetInt64(key string) int64 { - return kv.GetInt64WithDefault(key, 0) + return kv.GetInt64WithDefault(key, 0) } func (kv ctorMMKV) GetInt64WithDefault(key string, defaultValue int64) int64 { - cKey := C.CString(key) - value := C.decodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return int64(value) + cKey := C.CString(key) + value := C.decodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return int64(value) } func (kv ctorMMKV) SetUInt64(value uint64, key string) bool { - cKey := C.CString(key) - ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetUInt64(key string) uint64 { - return kv.GetUInt64WithDefault(key, 0) + return kv.GetUInt64WithDefault(key, 0) } func (kv ctorMMKV) GetUInt64WithDefault(key string, defaultValue uint64) uint64 { - cKey := C.CString(key) - value := C.decodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return uint64(value) + cKey := C.CString(key) + value := C.decodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return uint64(value) } func (kv ctorMMKV) SetFloat32(value float32, key string) bool { - cKey := C.CString(key) - ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetFloat32(key string) float32 { - return kv.GetFloat32WithDefault(key, 0) + return kv.GetFloat32WithDefault(key, 0) } func (kv ctorMMKV) GetFloat32WithDefault(key string, defaultValue float32) float32 { - cKey := C.CString(key) - value := C.decodeFloat(unsafe.Pointer(kv), cKey, C.float(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return float32(value) + cKey := C.CString(key) + value := C.decodeFloat(unsafe.Pointer(kv), cKey, C.float(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return float32(value) } func (kv ctorMMKV) SetFloat64(value float64, key string) bool { - cKey := C.CString(key) - ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) GetFloat64(key string) float64 { - return kv.GetFloat64WithDefault(key, 0) + return kv.GetFloat64WithDefault(key, 0) } func (kv ctorMMKV) GetFloat64WithDefault(key string, defaultValue float64) float64 { - cKey := C.CString(key) - value := C.decodeDouble(unsafe.Pointer(kv), cKey, C.double(defaultValue)) - C.free(unsafe.Pointer(cKey)) - return float64(value) + cKey := C.CString(key) + value := C.decodeDouble(unsafe.Pointer(kv), cKey, C.double(defaultValue)) + C.free(unsafe.Pointer(cKey)) + return float64(value) } func (kv ctorMMKV) SetString(value string, key string) bool { - cKey := C.CString(key) - cValue := C.CString(value) + cKey := C.CString(key) + cValue := C.CString(value) - ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))); + ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) - return bool(ret) + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return bool(ret) } func (kv ctorMMKV) GetString(key string) string { - cKey := C.CString(key) - var length uint64 + cKey := C.CString(key) + var length uint64 - cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) - value := C.GoString((*C.char)(cValue)) + cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) + value := C.GoString((*C.char)(cValue)) - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) - return value + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return value } func (kv ctorMMKV) SetBytes(value []byte, key string) bool { - cKey := C.CString(key) - cValue := C.CBytes(value) + cKey := C.CString(key) + cValue := C.CBytes(value) - ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) + ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) - return bool(ret) + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return bool(ret) } func (kv ctorMMKV) GetBytes(key string) []byte { - cKey := C.CString(key) - var length uint64 + cKey := C.CString(key) + var length uint64 - cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) - value := C.GoBytes(unsafe.Pointer(cValue), C.int(length)) + cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) + value := C.GoBytes(unsafe.Pointer(cValue), C.int(length)) - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) - return value + C.free(unsafe.Pointer(cKey)) + C.free(unsafe.Pointer(cValue)) + return value } func (kv ctorMMKV) RemoveKey(key string) { - cKey := C.CString(key) - C.removeValueForKey(unsafe.Pointer(kv), cKey); - C.free(unsafe.Pointer(cKey)) + cKey := C.CString(key) + C.removeValueForKey(unsafe.Pointer(kv), cKey) + C.free(unsafe.Pointer(cKey)) } func (kv ctorMMKV) RemoveKeys(keys []string) { - keyArray := (**C.char)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) - sizeArray := (*C.uint32_t)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) + keyArray := (**C.char)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) + sizeArray := (*C.uint32_t)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) - for index, key := range keys { - C.setStringArray(keyArray, C.CString(key), C.size_t(index)) - C.setSizeArray(sizeArray, C.uint32_t(len(key)), C.size_t(index)) - } - C.removeValuesForKeys(unsafe.Pointer(kv), keyArray, sizeArray, C.uint64_t(len(keys))) + for index, key := range keys { + C.setStringArray(keyArray, C.CString(key), C.size_t(index)) + C.setSizeArray(sizeArray, C.uint32_t(len(key)), C.size_t(index)) + } + C.removeValuesForKeys(unsafe.Pointer(kv), keyArray, sizeArray, C.uint64_t(len(keys))) - C.freeStringArray(keyArray, C.size_t(len(keys))) - C.free(unsafe.Pointer(keyArray)) - C.free(unsafe.Pointer(sizeArray)) + C.freeStringArray(keyArray, C.size_t(len(keys))) + C.free(unsafe.Pointer(keyArray)) + C.free(unsafe.Pointer(sizeArray)) } func (kv ctorMMKV) Count() uint64 { - return uint64(C.count(unsafe.Pointer(kv))) + return uint64(C.count(unsafe.Pointer(kv))) } func (kv ctorMMKV) AllKeys() []string { - var keyArray **C.char - var sizeArray *C.uint32_t + var keyArray **C.char + var sizeArray *C.uint32_t - cCount := C.allKeys(unsafe.Pointer(kv), &keyArray, &sizeArray) - count := uint64(cCount) - if count == 0 { - return []string{} - } + cCount := C.allKeys(unsafe.Pointer(kv), &keyArray, &sizeArray) + count := uint64(cCount) + if count == 0 { + return []string{} + } - result := make([]string, count) - for index := uint64(0); index < count; index++ { - cStr := C.getStringArray(keyArray, C.size_t(index)) - cLen := C.getSizeArray(sizeArray, C.size_t(index)) - result[index] = C.GoStringN(cStr, C.int(cLen)) - } + result := make([]string, count) + for index := uint64(0); index < count; index++ { + cStr := C.getStringArray(keyArray, C.size_t(index)) + cLen := C.getSizeArray(sizeArray, C.size_t(index)) + result[index] = C.GoStringN(cStr, C.int(cLen)) + } - C.freeStringArray(keyArray, C.size_t(cCount)) - C.free(unsafe.Pointer(keyArray)) - C.free(unsafe.Pointer(sizeArray)) - return result + C.freeStringArray(keyArray, C.size_t(cCount)) + C.free(unsafe.Pointer(keyArray)) + C.free(unsafe.Pointer(sizeArray)) + return result } func (kv ctorMMKV) Contains(key string) bool { - cKey := C.CString(key) - ret := C.containsKey(unsafe.Pointer(kv), cKey) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(key) + ret := C.containsKey(unsafe.Pointer(kv), cKey) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) ClearAll() { - C.clearAll(unsafe.Pointer(kv)) + C.clearAll(unsafe.Pointer(kv)) } func (kv ctorMMKV) TotalSize() uint64 { - return uint64(C.totalSize(unsafe.Pointer(kv))) + return uint64(C.totalSize(unsafe.Pointer(kv))) } func (kv ctorMMKV) ActualSize() uint64 { - return uint64(C.actualSize(unsafe.Pointer(kv))) + return uint64(C.actualSize(unsafe.Pointer(kv))) } func (kv ctorMMKV) MMAP_ID() string { - cStr := C.mmapID(unsafe.Pointer(kv)) - return C.GoString(cStr) + cStr := C.mmapID(unsafe.Pointer(kv)) + return C.GoString(cStr) } func (kv ctorMMKV) Sync(sync bool) { - C.mmkvSync(unsafe.Pointer(kv), C.bool(sync)) + C.mmkvSync(unsafe.Pointer(kv), C.bool(sync)) } func (kv ctorMMKV) ClearMemoryCache() { - C.clearMemoryCache(unsafe.Pointer(kv)) + C.clearMemoryCache(unsafe.Pointer(kv)) } func (kv ctorMMKV) Trim() { - C.trim(unsafe.Pointer(kv)) + C.trim(unsafe.Pointer(kv)) } func (kv ctorMMKV) Close() { - C.mmkvClose(unsafe.Pointer(kv)) + C.mmkvClose(unsafe.Pointer(kv)) } func (kv ctorMMKV) ReKey(newKey string) bool { - cKey := C.CString(newKey) - ret := C.reKey(unsafe.Pointer(kv), cKey, C.uint32_t(len(newKey))) - C.free(unsafe.Pointer(cKey)) - return bool(ret) + cKey := C.CString(newKey) + ret := C.reKey(unsafe.Pointer(kv), cKey, C.uint32_t(len(newKey))) + C.free(unsafe.Pointer(cKey)) + return bool(ret) } func (kv ctorMMKV) CryptKey() string { - var cLen C.uint32_t - cStr := C.cryptKey(unsafe.Pointer(kv), &cLen) - if cStr == nil || cLen == 0 { - return "" - } - result := C.GoStringN((*C.char)(cStr), C.int(cLen)) - C.free(unsafe.Pointer(cStr)) - return result + var cLen C.uint32_t + cStr := C.cryptKey(unsafe.Pointer(kv), &cLen) + if cStr == nil || cLen == 0 { + return "" + } + result := C.GoStringN((*C.char)(cStr), C.int(cLen)) + C.free(unsafe.Pointer(cStr)) + return result } diff --git a/POSIX/golang/mmkv_test.go b/POSIX/golang/mmkv_test.go index 6bc52953..b84e0973 100644 --- a/POSIX/golang/mmkv_test.go +++ b/POSIX/golang/mmkv_test.go @@ -21,13 +21,13 @@ package mmkv import ( - "testing" -// "regexp" + "testing" + // "regexp" ) func TestVersionEmpty(t *testing.T) { - msg := Version() - if msg == "" { - t.Fatalf("Version() == \"\"") - } + msg := Version() + if msg == "" { + t.Fatalf("Version() == \"\"") + } } diff --git a/POSIX/golang/test/main.go b/POSIX/golang/test/main.go index ad9f9bc3..69c77e1d 100644 --- a/POSIX/golang/test/main.go +++ b/POSIX/golang/test/main.go @@ -1,143 +1,142 @@ package main import ( - "fmt" - //"log" - "math" + "fmt" + //"log" + "math" - "tencent.com/mmkv" + "tencent.com/mmkv" ) func main() { - mmkv.InitializeMMKV("/tmp/mmkv") + mmkv.InitializeMMKV("/tmp/mmkv") - functionalTest() - testReKey() + functionalTest() + testReKey() } func functionalTest() { - kv := mmkv.DefaultMMKV() - fmt.Println("actual size:", kv.ActualSize()) - fmt.Println("total size:", kv.TotalSize()) + kv := mmkv.DefaultMMKV() + fmt.Println("actual size:", kv.ActualSize()) + fmt.Println("total size:", kv.TotalSize()) - kv.SetBool(true, "bool") - fmt.Println("bool =", kv.GetBool("bool")) + kv.SetBool(true, "bool") + fmt.Println("bool =", kv.GetBool("bool")) - kv.SetInt32(math.MinInt32, "int32") - fmt.Println("int32 =", kv.GetInt32("int32")) + kv.SetInt32(math.MinInt32, "int32") + fmt.Println("int32 =", kv.GetInt32("int32")) - kv.SetUInt32(math.MaxUint32, "uint32") - fmt.Println("uint32 =", kv.GetUInt32("uint32")) + kv.SetUInt32(math.MaxUint32, "uint32") + fmt.Println("uint32 =", kv.GetUInt32("uint32")) - kv.SetInt64(math.MinInt64, "int64") - fmt.Println("int64 =", kv.GetInt64("int64")) + kv.SetInt64(math.MinInt64, "int64") + fmt.Println("int64 =", kv.GetInt64("int64")) - kv.SetUInt64(math.MaxUint64, "uint64") - fmt.Println("uint64 =", kv.GetUInt64("uint64")) + kv.SetUInt64(math.MaxUint64, "uint64") + fmt.Println("uint64 =", kv.GetUInt64("uint64")) - kv.SetFloat32(math.MaxFloat32, "float32") - fmt.Println("float32 =", kv.GetFloat32("float32")) + kv.SetFloat32(math.MaxFloat32, "float32") + fmt.Println("float32 =", kv.GetFloat32("float32")) - kv.SetFloat64(math.MaxFloat64, "float64") - fmt.Println("float64 =", kv.GetFloat64("float64")) + kv.SetFloat64(math.MaxFloat64, "float64") + fmt.Println("float64 =", kv.GetFloat64("float64")) - kv.SetString("Hello world, from MMKV!", "string") - fmt.Println("string =", kv.GetString("string")) + kv.SetString("Hello world, from MMKV!", "string") + fmt.Println("string =", kv.GetString("string")) - kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") - fmt.Println("bytes =", string(kv.GetBytes("bytes"))) + kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + fmt.Println("bytes =", string(kv.GetBytes("bytes"))) - fmt.Println("contains \"bool\"? ", kv.Contains("bool")) - kv.RemoveKey("bool") - fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) + fmt.Println("contains \"bool\"? ", kv.Contains("bool")) + kv.RemoveKey("bool") + fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) - kv.RemoveKeys([]string {"int32", "int64"}) - fmt.Println("count =", kv.Count(), ", all keys:", kv.AllKeys()) + kv.RemoveKeys([]string{"int32", "int64"}) + fmt.Println("count =", kv.Count(), ", all keys:", kv.AllKeys()) - kv.Trim() - kv.ClearMemoryCache() - fmt.Println("all keys:", kv.AllKeys()) - kv.ClearAll() - fmt.Println("all keys:", kv.AllKeys()) - kv.Sync(true) - kv.Close() + kv.Trim() + kv.ClearMemoryCache() + fmt.Println("all keys:", kv.AllKeys()) + kv.ClearAll() + fmt.Println("all keys:", kv.AllKeys()) + kv.Sync(true) + kv.Close() } func testMMKV(mmapID string, cryptKey string, decodeOnly bool) mmkv.MMKV { - kv := mmkv.MMKVWithIDAndModeAndCryptKey(mmapID, mmkv.MMKV_SINGLE_PROCESS, cryptKey) - - if !decodeOnly { - kv.SetBool(true, "bool") - } - fmt.Println("bool =", kv.GetBool("bool")) - - if !decodeOnly { - kv.SetInt32(math.MinInt32, "int32") - } - fmt.Println("int32 =", kv.GetInt32("int32")) - - if !decodeOnly { - kv.SetUInt32(math.MaxUint32, "uint32") - } - fmt.Println("uint32 =", kv.GetUInt32("uint32")) - - if !decodeOnly { - kv.SetInt64(math.MinInt64, "int64") - } - fmt.Println("int64 =", kv.GetInt64("int64")) - - if !decodeOnly { - kv.SetUInt64(math.MaxUint64, "uint64") - } - fmt.Println("uint64 =", kv.GetUInt64("uint64")) - - if !decodeOnly { - kv.SetFloat32(math.MaxFloat32, "float32") - } - fmt.Println("float32 =", kv.GetFloat32("float32")) - - if !decodeOnly { - kv.SetFloat64(math.MaxFloat64, "float64") - } - fmt.Println("float64 =", kv.GetFloat64("float64")) - - if !decodeOnly { - kv.SetString("Hello world, from MMKV!", "string") - } - fmt.Println("string =", kv.GetString("string")) - - if !decodeOnly { - kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") - } - fmt.Println("bytes =", string(kv.GetBytes("bytes"))) - - fmt.Println("contains \"bool\"? ", kv.Contains("bool")) - kv.RemoveKey("bool") - fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) - - kv.RemoveKeys([]string {"int32", "int64"}) - fmt.Println("all keys:", kv.AllKeys()) - - return kv + kv := mmkv.MMKVWithIDAndModeAndCryptKey(mmapID, mmkv.MMKV_SINGLE_PROCESS, cryptKey) + + if !decodeOnly { + kv.SetBool(true, "bool") + } + fmt.Println("bool =", kv.GetBool("bool")) + + if !decodeOnly { + kv.SetInt32(math.MinInt32, "int32") + } + fmt.Println("int32 =", kv.GetInt32("int32")) + + if !decodeOnly { + kv.SetUInt32(math.MaxUint32, "uint32") + } + fmt.Println("uint32 =", kv.GetUInt32("uint32")) + + if !decodeOnly { + kv.SetInt64(math.MinInt64, "int64") + } + fmt.Println("int64 =", kv.GetInt64("int64")) + + if !decodeOnly { + kv.SetUInt64(math.MaxUint64, "uint64") + } + fmt.Println("uint64 =", kv.GetUInt64("uint64")) + + if !decodeOnly { + kv.SetFloat32(math.MaxFloat32, "float32") + } + fmt.Println("float32 =", kv.GetFloat32("float32")) + + if !decodeOnly { + kv.SetFloat64(math.MaxFloat64, "float64") + } + fmt.Println("float64 =", kv.GetFloat64("float64")) + + if !decodeOnly { + kv.SetString("Hello world, from MMKV!", "string") + } + fmt.Println("string =", kv.GetString("string")) + + if !decodeOnly { + kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + } + fmt.Println("bytes =", string(kv.GetBytes("bytes"))) + + fmt.Println("contains \"bool\"? ", kv.Contains("bool")) + kv.RemoveKey("bool") + fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) + + kv.RemoveKeys([]string{"int32", "int64"}) + fmt.Println("all keys:", kv.AllKeys()) + + return kv } func testReKey() { - mmapID := "testAES_reKey1" - kv := testMMKV(mmapID, "", false) - if kv == nil { - return - } - - kv.ReKey("Key_seq_1") - kv.ClearMemoryCache() - testMMKV(mmapID, "Key_seq_1", true) - - kv.ReKey("Key_seq_2") - kv.ClearMemoryCache() - testMMKV(mmapID, "Key_seq_2", true) - - kv.ReKey("") - kv.ClearMemoryCache() - testMMKV(mmapID, "", true) + mmapID := "testAES_reKey1" + kv := testMMKV(mmapID, "", false) + if kv == nil { + return + } + + kv.ReKey("Key_seq_1") + kv.ClearMemoryCache() + testMMKV(mmapID, "Key_seq_1", true) + + kv.ReKey("Key_seq_2") + kv.ClearMemoryCache() + testMMKV(mmapID, "Key_seq_2", true) + + kv.ReKey("") + kv.ClearMemoryCache() + testMMKV(mmapID, "", true) } - From 9b5ed1c7871fa5248878d5cfa53b83f2e9c5bb45 Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 14 Dec 2020 17:43:28 +0800 Subject: [PATCH 10/16] golang support almost done --- POSIX/golang/golang-bridge.cpp | 202 +++++++++++++++----------------- POSIX/golang/golang-bridge.h | 86 ++++++++------ POSIX/golang/mmkv.go | 203 ++++++++++----------------------- POSIX/golang/test/main.go | 8 +- 4 files changed, 205 insertions(+), 294 deletions(-) diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index e1975021..7a59e6c2 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -23,39 +23,39 @@ # include "MMKVPredef.h" # include "MMKV.h" +# include "golang-bridge.h" # include # include -#include "golang-bridge.h" using namespace mmkv; using namespace std; # define MMKV_EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used)) -MMKV_EXPORT void mmkvInitialize(const char *rootDir, int32_t logLevel) { - if (!rootDir) { +MMKV_EXPORT void mmkvInitialize(GoStringWrap rootDir, int32_t logLevel) { + if (!rootDir.ptr) { return; } - MMKV::initializeMMKV(rootDir, (MMKVLogLevel) logLevel); + MMKV::initializeMMKV(string(rootDir.ptr, rootDir.length), (MMKVLogLevel) logLevel); } MMKV_EXPORT void onExit() { MMKV::onExit(); } -MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath) { +MMKV_EXPORT void *getMMKVWithID(GoStringWrap mmapID, int32_t mode, GoStringWrap cryptKey, GoStringWrap rootPath) { MMKV *kv = nullptr; - if (!mmapID) { + if (!mmapID.ptr) { return kv; } - string str = mmapID; + auto str = string(mmapID.ptr, mmapID.length); bool done = false; - if (cryptKey) { - string crypt = cryptKey; + if (cryptKey.ptr) { + auto crypt = string(cryptKey.ptr, cryptKey.length); if (crypt.length() > 0) { - if (rootPath) { - string path = rootPath; + if (rootPath.ptr) { + auto path = string(rootPath.ptr, rootPath.length); kv = MMKV::mmkvWithID(str, (MMKVMode) mode, &crypt, &path); } else { kv = MMKV::mmkvWithID(str, (MMKVMode) mode, &crypt, nullptr); @@ -64,8 +64,8 @@ MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cr } } if (!done) { - if (rootPath) { - string path = rootPath; + if (rootPath.ptr) { + auto path = string(rootPath.ptr, rootPath.length); kv = MMKV::mmkvWithID(str, (MMKVMode) mode, nullptr, &path); } else { kv = MMKV::mmkvWithID(str, (MMKVMode) mode, nullptr, nullptr); @@ -75,11 +75,11 @@ MMKV_EXPORT void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cr return kv; } -MMKV_EXPORT void *getDefaultMMKV(int32_t mode, const char *cryptKey) { +MMKV_EXPORT void *getDefaultMMKV(int32_t mode, GoStringWrap cryptKey) { MMKV *kv = nullptr; - if (cryptKey) { - string crypt = cryptKey; + if (cryptKey.ptr) { + auto crypt = string(cryptKey.ptr, cryptKey.length); if (crypt.length() > 0) { kv = MMKV::defaultMMKV((MMKVMode) mode, &crypt); } @@ -99,25 +99,7 @@ MMKV_EXPORT const char *mmapID(void *handle) { return nullptr; } -MMKV_EXPORT bool encodeBool(void *handle, const char *oKey, bool value) { - MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); - return kv->set((bool) value, key); - } - return false; -} - -MMKV_EXPORT bool decodeBool(void *handle, const char *oKey, bool defaultValue) { - MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); - return kv->getBool(key, defaultValue); - } - return defaultValue; -} - -MMKV_EXPORT bool encodeBool2(void *handle, GoStringWrap oKey, bool value) { +MMKV_EXPORT bool encodeBool(void *handle, GoStringWrap oKey, bool value) { MMKV *kv = static_cast(handle); if (kv && oKey.ptr) { auto key = string(oKey.ptr, oKey.length); @@ -126,7 +108,7 @@ MMKV_EXPORT bool encodeBool2(void *handle, GoStringWrap oKey, bool value) { return false; } -MMKV_EXPORT bool decodeBool2(void *handle, GoStringWrap oKey, bool defaultValue) { +MMKV_EXPORT bool decodeBool(void *handle, GoStringWrap oKey, bool defaultValue) { MMKV *kv = static_cast(handle); if (kv && oKey.ptr) { auto key = string(oKey.ptr, oKey.length); @@ -135,120 +117,120 @@ MMKV_EXPORT bool decodeBool2(void *handle, GoStringWrap oKey, bool defaultValue) return defaultValue; } -MMKV_EXPORT bool encodeInt32(void *handle, const char *oKey, int32_t value) { +MMKV_EXPORT bool encodeInt32(void *handle, GoStringWrap oKey, int32_t value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set((int32_t) value, key); } return false; } -MMKV_EXPORT int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue) { +MMKV_EXPORT int32_t decodeInt32(void *handle, GoStringWrap oKey, int32_t defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getInt32(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeUInt32(void *handle, const char *oKey, uint32_t value) { +MMKV_EXPORT bool encodeUInt32(void *handle, GoStringWrap oKey, uint32_t value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set(value, key); } return false; } -MMKV_EXPORT uint32_t decodeUInt32(void *handle, const char *oKey, uint32_t defaultValue) { +MMKV_EXPORT uint32_t decodeUInt32(void *handle, GoStringWrap oKey, uint32_t defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getUInt32(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeInt64(void *handle, const char *oKey, int64_t value) { +MMKV_EXPORT bool encodeInt64(void *handle, GoStringWrap oKey, int64_t value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set((int64_t) value, key); } return false; } -MMKV_EXPORT int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue) { +MMKV_EXPORT int64_t decodeInt64(void *handle, GoStringWrap oKey, int64_t defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getInt64(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeUInt64(void *handle, const char *oKey, uint64_t value) { +MMKV_EXPORT bool encodeUInt64(void *handle, GoStringWrap oKey, uint64_t value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set(value, key); } return false; } -MMKV_EXPORT uint64_t decodeUInt64(void *handle, const char *oKey, uint64_t defaultValue) { +MMKV_EXPORT uint64_t decodeUInt64(void *handle, GoStringWrap oKey, uint64_t defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getUInt64(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeFloat(void *handle, const char *oKey, float value) { +MMKV_EXPORT bool encodeFloat(void *handle, GoStringWrap oKey, float value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set((float) value, key); } return false; } -MMKV_EXPORT float decodeFloat(void *handle, const char *oKey, float defaultValue) { +MMKV_EXPORT float decodeFloat(void *handle, GoStringWrap oKey, float defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getFloat(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeDouble(void *handle, const char *oKey, double value) { +MMKV_EXPORT bool encodeDouble(void *handle, GoStringWrap oKey, double value) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->set((double) value, key); } return false; } -MMKV_EXPORT double decodeDouble(void *handle, const char *oKey, double defaultValue) { +MMKV_EXPORT double decodeDouble(void *handle, GoStringWrap oKey, double defaultValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->getDouble(key, defaultValue); } return defaultValue; } -MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length) { +MMKV_EXPORT bool encodeBytes(void *handle, GoStringWrap oKey, GoStringWrap oValue) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); - if (oValue) { - auto value = MMBuffer(oValue, static_cast(length), MMBufferNoCopy); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); + if (oValue.ptr) { + auto value = MMBuffer((void *) oValue.ptr, oValue.length, MMBufferNoCopy); return kv->set(value, key); } else { kv->removeValueForKey(key); @@ -258,10 +240,10 @@ MMKV_EXPORT bool encodeBytes(void *handle, const char *oKey, void *oValue, uint6 return false; } -MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr) { +MMKV_EXPORT void *decodeBytes(void *handle, GoStringWrap oKey, uint64_t *lengthPtr) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - auto key = string(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); auto value = kv->getBytes(key); if (value.length() > 0) { if (value.isStoredOnStack()) { @@ -284,11 +266,11 @@ MMKV_EXPORT void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPt # ifndef MMKV_DISABLE_CRYPT -MMKV_EXPORT bool reKey(void *handle, char *oKey, uint32_t length) { +MMKV_EXPORT bool reKey(void *handle, GoStringWrap oKey) { MMKV *kv = static_cast(handle); if (kv) { - if (oKey && length > 0) { - string key(oKey, length); + if (oKey.ptr && oKey.length > 0) { + string key(oKey.ptr, oKey.length); return kv->reKey(key); } else { return kv->reKey(string()); @@ -313,11 +295,11 @@ MMKV_EXPORT void *cryptKey(void *handle, uint32_t *lengthPtr) { return nullptr; } -MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t length) { +MMKV_EXPORT void checkReSetCryptKey(void *handle, GoStringWrap oKey) { MMKV *kv = static_cast(handle); if (kv) { - if (oKey && length > 0) { - string key(oKey, length); + if (oKey.ptr && oKey.length > 0) { + string key(oKey.ptr, oKey.length); kv->checkReSetCryptKey(&key); } else { kv->checkReSetCryptKey(nullptr); @@ -327,39 +309,36 @@ MMKV_EXPORT void checkReSetCryptKey(void *handle, char *oKey, uint64_t length) { # endif // MMKV_DISABLE_CRYPT -MMKV_EXPORT uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr) { +MMKV_EXPORT GoStringWrap *allKeys(void *handle, uint64_t *lengthPtr) { MMKV *kv = static_cast(handle); if (kv) { auto keys = kv->allKeys(); if (!keys.empty()) { - auto keyArray = (char **) malloc(keys.size() * sizeof(void *)); - auto sizeArray = (uint32_t *) malloc(keys.size() * sizeof(uint32_t *)); - if (!keyArray || !sizeArray) { - free(keyArray); - free(sizeArray); - return 0; + auto keyArray = (GoStringWrap *) calloc(keys.size(), sizeof(GoStringWrap)); + if (!keyArray) { + return nullptr; } - *keyArrayPtr = keyArray; - *sizeArrayPtr = sizeArray; for (size_t index = 0; index < keys.size(); index++) { auto &key = keys[index]; - sizeArray[index] = static_cast(key.length()); - keyArray[index] = (char *) malloc(key.length()); - if (keyArray[index]) { - memcpy(keyArray[index], key.data(), key.length()); + auto &stringWrap = keyArray[index]; + stringWrap.length = static_cast(key.length()); + stringWrap.ptr = (char *) malloc(key.length()); + if (stringWrap.ptr) { + memcpy((void *) stringWrap.ptr, key.data(), key.length()); } } + *lengthPtr = keys.size(); + return keyArray; } - return keys.size(); } - return 0; + return nullptr; } -MMKV_EXPORT bool containsKey(void *handle, char *oKey) { +MMKV_EXPORT bool containsKey(void *handle, GoStringWrap oKey) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - string key(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); return kv->containsKey(key); } return false; @@ -389,22 +368,23 @@ MMKV_EXPORT uint64_t actualSize(void *handle) { return 0; } -MMKV_EXPORT void removeValueForKey(void *handle, char *oKey) { +MMKV_EXPORT void removeValueForKey(void *handle, GoStringWrap oKey) { MMKV *kv = static_cast(handle); - if (kv && oKey) { - string key(oKey); + if (kv && oKey.ptr) { + auto key = string(oKey.ptr, oKey.length); kv->removeValueForKey(key); } } -MMKV_EXPORT void removeValuesForKeys(void *handle, char **keyArray, uint32_t *sizeArray, uint64_t count) { +MMKV_EXPORT void removeValuesForKeys(void *handle, GoStringWrap *keyArray, uint64_t count) { MMKV *kv = static_cast(handle); - if (kv && keyArray && sizeArray && count > 0) { + if (kv && keyArray && count > 0) { vector arrKeys; arrKeys.reserve(count); for (uint64_t index = 0; index < count; index++) { - if (sizeArray[index] > 0 && keyArray[index]) { - arrKeys.emplace_back(keyArray[index], sizeArray[index]); + auto &stringWrap = keyArray[index]; + if (stringWrap.ptr && stringWrap.length > 0) { + arrKeys.emplace_back(stringWrap.ptr, stringWrap.length); } } if (!arrKeys.empty()) { diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index 866eb819..a19daab9 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -26,54 +26,72 @@ extern "C" { # include #endif -typedef struct { +struct GoStringWrap { const char *ptr; - size_t length; -} GoStringWrap; + int64_t length; +}; +typedef struct GoStringWrap GoStringWrap_t; -void mmkvInitialize(const char *rootDir, int32_t logLevel); +struct GoSliceWrap { + void *array; + int64_t length; + int64_t capacity; +}; +typedef struct GoSliceWrap GoSliceWrap_t; + +void mmkvInitialize(GoStringWrap_t rootDir, int32_t logLevel); void onExit(); -void *getMMKVWithID(const char *mmapID, int32_t mode, const char *cryptKey, const char *rootPath); -void *getDefaultMMKV(int32_t mode, const char *cryptKey); + +void *getMMKVWithID(GoStringWrap_t mmapID, int32_t mode, GoStringWrap_t cryptKey, GoStringWrap_t rootPath); +void *getDefaultMMKV(int32_t mode, GoStringWrap_t cryptKey); const char *mmapID(void *handle); -bool encodeBool(void *handle, const char *oKey, bool value); -bool decodeBool(void *handle, const char *oKey, bool defaultValue); - -bool encodeBool2(void *handle, GoStringWrap oKey, bool value); -bool decodeBool2(void *handle, GoStringWrap oKey, bool defaultValue); - -bool encodeInt32(void *handle, const char *oKey, int32_t value); -int32_t decodeInt32(void *handle, const char *oKey, int32_t defaultValue); -bool encodeUInt32(void *handle, const char *oKey, uint32_t value); -uint32_t decodeUInt32(void *handle, const char *oKey, uint32_t defaultValue); -bool encodeInt64(void *handle, const char *oKey, int64_t value); -int64_t decodeInt64(void *handle, const char *oKey, int64_t defaultValue); -bool encodeUInt64(void *handle, const char *oKey, uint64_t value); -uint64_t decodeUInt64(void *handle, const char *oKey, uint64_t defaultValue); -bool encodeFloat(void *handle, const char *oKey, float value); -float decodeFloat(void *handle, const char *oKey, float defaultValue); -bool encodeDouble(void *handle, const char *oKey, double value); -double decodeDouble(void *handle, const char *oKey, double defaultValue); -bool encodeBytes(void *handle, const char *oKey, void *oValue, uint64_t length); -void *decodeBytes(void *handle, const char *oKey, uint64_t *lengthPtr); -bool reKey(void *handle, char *oKey, uint32_t length); + +bool encodeBool(void *handle, GoStringWrap_t oKey, bool value); +bool decodeBool(void *handle, GoStringWrap_t oKey, bool defaultValue); + +bool encodeInt32(void *handle, GoStringWrap_t oKey, int32_t value); +int32_t decodeInt32(void *handle, GoStringWrap_t oKey, int32_t defaultValue); + +bool encodeUInt32(void *handle, GoStringWrap_t oKey, uint32_t value); +uint32_t decodeUInt32(void *handle, GoStringWrap_t oKey, uint32_t defaultValue); + +bool encodeInt64(void *handle, GoStringWrap_t oKey, int64_t value); +int64_t decodeInt64(void *handle, GoStringWrap_t oKey, int64_t defaultValue); + +bool encodeUInt64(void *handle, GoStringWrap_t oKey, uint64_t value); +uint64_t decodeUInt64(void *handle, GoStringWrap_t oKey, uint64_t defaultValue); + +bool encodeFloat(void *handle, GoStringWrap_t oKey, float value); +float decodeFloat(void *handle, GoStringWrap_t oKey, float defaultValue); + +bool encodeDouble(void *handle, GoStringWrap_t oKey, double value); +double decodeDouble(void *handle, GoStringWrap_t oKey, double defaultValue); + +bool encodeBytes(void *handle, GoStringWrap_t oKey, GoStringWrap_t oValue); +void *decodeBytes(void *handle, GoStringWrap_t oKey, uint64_t *lengthPtr); + +bool reKey(void *handle, GoStringWrap_t oKey); void *cryptKey(void *handle, uint32_t *lengthPtr); -void checkReSetCryptKey(void *handle, char *oKey, uint64_t length); -uint64_t allKeys(void *handle, char ***keyArrayPtr, uint32_t **sizeArrayPtr); -bool containsKey(void *handle, char *oKey); +void checkReSetCryptKey(void *handle, GoStringWrap_t oKey); + +GoStringWrap_t *allKeys(void *handle, uint64_t *lengthPtr); +bool containsKey(void *handle, GoStringWrap_t oKey); uint64_t count(void *handle); uint64_t totalSize(void *handle); uint64_t actualSize(void *handle); -void removeValueForKey(void *handle, char *oKey); -void removeValuesForKeys(void *handle, char **keyArray, uint32_t *sizeArray, uint64_t count); + +void removeValueForKey(void *handle, GoStringWrap_t oKey); +void removeValuesForKeys(void *handle, GoStringWrap_t *keyArray, uint64_t count); void clearAll(void *handle); + void mmkvSync(void *handle, bool sync); void clearMemoryCache(void *handle); -int32_t pageSize(); -const char *version(); void trim(void *handle); void mmkvClose(void *handle); +int32_t pageSize(); +const char *version(); + #ifdef __cplusplus } #endif diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 844c7ee6..c9480b2b 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -28,31 +28,24 @@ package mmkv typedef void* voidptr_t; -GoStringWrap wrapGoString(_GoString_ str) { - GoStringWrap wrap = { _GoStringPtr(str), _GoStringLen(str) }; +static GoStringWrap_t wrapGoString(_GoString_ str) { + GoStringWrap_t wrap = { _GoStringPtr(str), _GoStringLen(str) }; return wrap; } -static void setStringArray(char **array, char *str, size_t n) { - array[n] = str; +static GoStringWrap_t GoStringWrapNil() { + GoStringWrap_t result = { 0, 0 }; + return result; } -static char *getStringArray(char **array, size_t n) { - return array[n]; -} - -static void setSizeArray(uint32_t *array, uint32_t value, size_t n) { - array[n] = value; -} - -static uint32_t getSizeArray(uint32_t *array, size_t n) { - return array[n]; +static GoStringWrap_t wrapGoByteSlice(const void *ptr, size_t len) { + GoStringWrap_t wrap = { ptr, len }; + return wrap; } -static void freeStringArray(char **a, size_t size) { - size_t i; - for (i = 0; i < size; i++) { - free(a[i]); +static void freeStringArray(GoStringWrap_t *a, size_t size) { + for (size_t i = 0; i < size; i++) { + free((void*) a[i].ptr); } } */ @@ -141,15 +134,11 @@ func Version() string { } func InitializeMMKV(rootDir string) { - cRootDir := C.CString(rootDir) - C.mmkvInitialize(cRootDir, MMKVLogInfo) - C.free(unsafe.Pointer(cRootDir)) + C.mmkvInitialize(C.wrapGoString(rootDir), MMKVLogInfo) } func InitializeMMKVWithLogLevel(rootDir string, logLevel int) { - cRootDir := C.CString(rootDir) - C.mmkvInitialize(cRootDir, C.int32_t(logLevel)) - C.free(unsafe.Pointer(cRootDir)) + C.mmkvInitialize(C.wrapGoString(rootDir), C.int32_t(logLevel)) } func OnExit() { @@ -161,57 +150,40 @@ func PageSize() int32 { } func DefaultMMKV() MMKV { - mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, nil)) + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, C.GoStringWrapNil())) return MMKV(mmkv) } func DefaultMMKVWithMode(mode int) MMKV { - mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), nil)) + mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), C.GoStringWrapNil())) return MMKV(mmkv) } func DefaultMMKVWithModeAndCryptKey(mode int, cryptKey string) MMKV { - cCryptKey := C.CString(cryptKey) - mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, cCryptKey)) - C.free(unsafe.Pointer(cCryptKey)) + mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, C.wrapGoString(cryptKey))) return MMKV(mmkv) } func MMKVWithID(mmapID string) MMKV { - cmmapID := C.CString(mmapID) - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, MMKV_SINGLE_PROCESS, nil, nil)) - C.free(unsafe.Pointer(cmmapID)) - + cStrNull := C.GoStringWrapNil() + mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), MMKV_SINGLE_PROCESS, cStrNull, cStrNull)) return MMKV(mmkv) } func MMKVWithIDAndMode(mmapID string, mode int) MMKV { - cmmapID := C.CString(mmapID) - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), nil, nil)) - C.free(unsafe.Pointer(cmmapID)) - + cStrNull := C.GoStringWrapNil() + mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), C.int(mode), cStrNull, cStrNull)) return MMKV(mmkv) } func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey string) MMKV { - cmmapID := C.CString(mmapID) - cCryptKey := C.CString(cryptKey) - - mmkv := ctorMMKV(C.getMMKVWithID(cmmapID, C.int(mode), cCryptKey, nil)) - - C.free(unsafe.Pointer(cmmapID)) - C.free(unsafe.Pointer(cCryptKey)) - + cStrNull := C.GoStringWrapNil() + mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), C.int(mode), C.wrapGoString(cryptKey), cStrNull)) return MMKV(mmkv) } -// TODO: use _GoString_ to avoid string copying func (kv ctorMMKV) SetBool(value bool, key string) bool { - //cKey := C.CString(key) - //ret := C.encodeBool(unsafe.Pointer(kv), cKey, C.bool(value)) - //C.free(unsafe.Pointer(cKey)) - cKey := C.wrapGoString(key) - ret := C.encodeBool2(unsafe.Pointer(kv), cKey, C.bool(value)) + ret := C.encodeBool(unsafe.Pointer(kv), C.wrapGoString(key), C.bool(value)) return bool(ret) } @@ -220,18 +192,12 @@ func (kv ctorMMKV) GetBool(key string) bool { } func (kv ctorMMKV) GetBoolWithDefault(key string, defaultValue bool) bool { - //cKey := C.CString(key) - //value := C.decodeBool(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) - //C.free(unsafe.Pointer(cKey)) - cKey := C.wrapGoString(key) - value := C.decodeBool2(unsafe.Pointer(kv), cKey, C.bool(defaultValue)) + value := C.decodeBool(unsafe.Pointer(kv), C.wrapGoString(key), C.bool(defaultValue)) return bool(value) } func (kv ctorMMKV) SetInt32(value int32, key string) bool { - cKey := C.CString(key) - ret := C.encodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeInt32(unsafe.Pointer(kv), C.wrapGoString(key), C.int32_t(value)) return bool(ret) } @@ -240,16 +206,12 @@ func (kv ctorMMKV) GetInt32(key string) int32 { } func (kv ctorMMKV) GetInt32WithDefault(key string, defaultValue int32) int32 { - cKey := C.CString(key) - value := C.decodeInt32(unsafe.Pointer(kv), cKey, C.int32_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeInt32(unsafe.Pointer(kv), C.wrapGoString(key), C.int32_t(defaultValue)) return int32(value) } func (kv ctorMMKV) SetUInt32(value uint32, key string) bool { - cKey := C.CString(key) - ret := C.encodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeUInt32(unsafe.Pointer(kv), C.wrapGoString(key), C.uint32_t(value)) return bool(ret) } @@ -258,16 +220,12 @@ func (kv ctorMMKV) GetUInt32(key string) uint32 { } func (kv ctorMMKV) GetUInt32WithDefault(key string, defaultValue uint32) uint32 { - cKey := C.CString(key) - value := C.decodeUInt32(unsafe.Pointer(kv), cKey, C.uint32_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeUInt32(unsafe.Pointer(kv), C.wrapGoString(key), C.uint32_t(defaultValue)) return uint32(value) } func (kv ctorMMKV) SetInt64(value int64, key string) bool { - cKey := C.CString(key) - ret := C.encodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeInt64(unsafe.Pointer(kv), C.wrapGoString(key), C.int64_t(value)) return bool(ret) } @@ -276,16 +234,12 @@ func (kv ctorMMKV) GetInt64(key string) int64 { } func (kv ctorMMKV) GetInt64WithDefault(key string, defaultValue int64) int64 { - cKey := C.CString(key) - value := C.decodeInt64(unsafe.Pointer(kv), cKey, C.int64_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeInt64(unsafe.Pointer(kv), C.wrapGoString(key), C.int64_t(defaultValue)) return int64(value) } func (kv ctorMMKV) SetUInt64(value uint64, key string) bool { - cKey := C.CString(key) - ret := C.encodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeUInt64(unsafe.Pointer(kv), C.wrapGoString(key), C.uint64_t(value)) return bool(ret) } @@ -294,16 +248,12 @@ func (kv ctorMMKV) GetUInt64(key string) uint64 { } func (kv ctorMMKV) GetUInt64WithDefault(key string, defaultValue uint64) uint64 { - cKey := C.CString(key) - value := C.decodeUInt64(unsafe.Pointer(kv), cKey, C.uint64_t(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeUInt64(unsafe.Pointer(kv), C.wrapGoString(key), C.uint64_t(defaultValue)) return uint64(value) } func (kv ctorMMKV) SetFloat32(value float32, key string) bool { - cKey := C.CString(key) - ret := C.encodeFloat(unsafe.Pointer(kv), cKey, C.float(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeFloat(unsafe.Pointer(kv), C.wrapGoString(key), C.float(value)) return bool(ret) } @@ -312,16 +262,12 @@ func (kv ctorMMKV) GetFloat32(key string) float32 { } func (kv ctorMMKV) GetFloat32WithDefault(key string, defaultValue float32) float32 { - cKey := C.CString(key) - value := C.decodeFloat(unsafe.Pointer(kv), cKey, C.float(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeFloat(unsafe.Pointer(kv), C.wrapGoString(key), C.float(defaultValue)) return float32(value) } func (kv ctorMMKV) SetFloat64(value float64, key string) bool { - cKey := C.CString(key) - ret := C.encodeDouble(unsafe.Pointer(kv), cKey, C.double(value)) - C.free(unsafe.Pointer(cKey)) + ret := C.encodeDouble(unsafe.Pointer(kv), C.wrapGoString(key), C.double(value)) return bool(ret) } @@ -330,77 +276,49 @@ func (kv ctorMMKV) GetFloat64(key string) float64 { } func (kv ctorMMKV) GetFloat64WithDefault(key string, defaultValue float64) float64 { - cKey := C.CString(key) - value := C.decodeDouble(unsafe.Pointer(kv), cKey, C.double(defaultValue)) - C.free(unsafe.Pointer(cKey)) + value := C.decodeDouble(unsafe.Pointer(kv), C.wrapGoString(key), C.double(defaultValue)) return float64(value) } func (kv ctorMMKV) SetString(value string, key string) bool { - cKey := C.CString(key) - cValue := C.CString(value) - - ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) - - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) + cValue := C.wrapGoString(value) + ret := C.encodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), cValue) return bool(ret) } func (kv ctorMMKV) GetString(key string) string { - cKey := C.CString(key) var length uint64 - cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) - value := C.GoString((*C.char)(cValue)) + cValue := C.decodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), (*C.uint64_t)(&length)) + value := C.GoStringN((*C.char)(cValue), C.int(length)) - C.free(unsafe.Pointer(cKey)) C.free(unsafe.Pointer(cValue)) return value } func (kv ctorMMKV) SetBytes(value []byte, key string) bool { - cKey := C.CString(key) - cValue := C.CBytes(value) - - ret := C.encodeBytes(unsafe.Pointer(kv), cKey, unsafe.Pointer(cValue), C.uint64_t(len(value))) - - C.free(unsafe.Pointer(cKey)) - C.free(unsafe.Pointer(cValue)) + cValue := C.wrapGoByteSlice(unsafe.Pointer(&value[0]), C.size_t(len(value))) + ret := C.encodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), cValue) return bool(ret) } func (kv ctorMMKV) GetBytes(key string) []byte { - cKey := C.CString(key) var length uint64 - cValue := C.decodeBytes(unsafe.Pointer(kv), cKey, (*C.uint64_t)(&length)) + cValue := C.decodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), (*C.uint64_t)(&length)) value := C.GoBytes(unsafe.Pointer(cValue), C.int(length)) - C.free(unsafe.Pointer(cKey)) C.free(unsafe.Pointer(cValue)) return value } func (kv ctorMMKV) RemoveKey(key string) { - cKey := C.CString(key) - C.removeValueForKey(unsafe.Pointer(kv), cKey) - C.free(unsafe.Pointer(cKey)) + C.removeValueForKey(unsafe.Pointer(kv), C.wrapGoString(key)) } func (kv ctorMMKV) RemoveKeys(keys []string) { - keyArray := (**C.char)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) - sizeArray := (*C.uint32_t)(C.calloc(C.size_t(len(keys)), C.sizeof_voidptr_t)) - - for index, key := range keys { - C.setStringArray(keyArray, C.CString(key), C.size_t(index)) - C.setSizeArray(sizeArray, C.uint32_t(len(key)), C.size_t(index)) - } - C.removeValuesForKeys(unsafe.Pointer(kv), keyArray, sizeArray, C.uint64_t(len(keys))) - - C.freeStringArray(keyArray, C.size_t(len(keys))) - C.free(unsafe.Pointer(keyArray)) - C.free(unsafe.Pointer(sizeArray)) + keyArray := (*C.struct_GoStringWrap)(unsafe.Pointer(&keys[0])) + C.removeValuesForKeys(unsafe.Pointer(kv), keyArray, C.uint64_t(len(keys))) } func (kv ctorMMKV) Count() uint64 { @@ -408,32 +326,29 @@ func (kv ctorMMKV) Count() uint64 { } func (kv ctorMMKV) AllKeys() []string { - var keyArray **C.char - var sizeArray *C.uint32_t - - cCount := C.allKeys(unsafe.Pointer(kv), &keyArray, &sizeArray) - count := uint64(cCount) - if count == 0 { + count := uint64(0) + keyArray := C.allKeys(unsafe.Pointer(kv), (*C.uint64_t)(&count)) + if keyArray == nil || count == 0 { return []string{} } + // turn C array into go slice with offset(0), length(count) & capacity(count) + keys := (*[1 << 30]C.struct_GoStringWrap)(unsafe.Pointer(keyArray))[0:count:count] + // Actually the keys IS a go string slice, but we need to COPY the elements for the caller to use. + // Too bad go doesn't has destructors, hence we can't simply TRANSFER ownership of C memory. result := make([]string, count) for index := uint64(0); index < count; index++ { - cStr := C.getStringArray(keyArray, C.size_t(index)) - cLen := C.getSizeArray(sizeArray, C.size_t(index)) - result[index] = C.GoStringN(cStr, C.int(cLen)) + key := keys[index] + result[index] = C.GoStringN(key.ptr, C.int(key.length)) } - C.freeStringArray(keyArray, C.size_t(cCount)) + C.freeStringArray(keyArray, C.size_t(count)) C.free(unsafe.Pointer(keyArray)) - C.free(unsafe.Pointer(sizeArray)) return result } func (kv ctorMMKV) Contains(key string) bool { - cKey := C.CString(key) - ret := C.containsKey(unsafe.Pointer(kv), cKey) - C.free(unsafe.Pointer(cKey)) + ret := C.containsKey(unsafe.Pointer(kv), C.wrapGoString(key)) return bool(ret) } @@ -471,9 +386,7 @@ func (kv ctorMMKV) Close() { } func (kv ctorMMKV) ReKey(newKey string) bool { - cKey := C.CString(newKey) - ret := C.reKey(unsafe.Pointer(kv), cKey, C.uint32_t(len(newKey))) - C.free(unsafe.Pointer(cKey)) + ret := C.reKey(unsafe.Pointer(kv), C.wrapGoString(newKey)) return bool(ret) } diff --git a/POSIX/golang/test/main.go b/POSIX/golang/test/main.go index 69c77e1d..823f4ea8 100644 --- a/POSIX/golang/test/main.go +++ b/POSIX/golang/test/main.go @@ -41,10 +41,10 @@ func functionalTest() { kv.SetFloat64(math.MaxFloat64, "float64") fmt.Println("float64 =", kv.GetFloat64("float64")) - kv.SetString("Hello world, from MMKV!", "string") + kv.SetString("Hello world, 你好 from MMKV!", "string") fmt.Println("string =", kv.GetString("string")) - kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + kv.SetBytes([]byte("Hello world, 你好 from MMKV 以及 bytes!"), "bytes") fmt.Println("bytes =", string(kv.GetBytes("bytes"))) fmt.Println("contains \"bool\"? ", kv.Contains("bool")) @@ -102,12 +102,12 @@ func testMMKV(mmapID string, cryptKey string, decodeOnly bool) mmkv.MMKV { fmt.Println("float64 =", kv.GetFloat64("float64")) if !decodeOnly { - kv.SetString("Hello world, from MMKV!", "string") + kv.SetString("Hello world, 你好 from MMKV!", "string") } fmt.Println("string =", kv.GetString("string")) if !decodeOnly { - kv.SetBytes([]byte("Hello world, from MMKV with bytes!"), "bytes") + kv.SetBytes([]byte("Hello world, 你好 from MMKV 以及 bytes!"), "bytes") } fmt.Println("bytes =", string(kv.GetBytes("bytes"))) From c4c541830f5dccf8f4128de86fcfa2cf9310c7ac Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 14 Dec 2020 22:11:20 +0800 Subject: [PATCH 11/16] add doc for golang --- POSIX/golang/mmkv.go | 70 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index c9480b2b..cddead15 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -18,6 +18,7 @@ * limitations under the License. */ +// MMKV is a cross-platform key-value storage framework developed by WeChat. package mmkv // #cgo CXXFLAGS: -D CGO -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 @@ -79,50 +80,92 @@ type ctorMMKV uintptr type MMKV interface { SetBool(value bool, key string) bool - SetInt32(value int32, key string) bool - SetInt64(value int64, key string) bool - SetUInt32(value uint32, key string) bool - SetUInt64(value uint64, key string) bool - SetFloat32(value float32, key string) bool - SetFloat64(value float64, key string) bool - SetString(value string, key string) bool - SetBytes(value []byte, key string) bool - GetBool(key string) bool GetBoolWithDefault(key string, defaultValue bool) bool + + SetInt32(value int32, key string) bool GetInt32(key string) int32 GetInt32WithDefault(key string, defaultValue int32) int32 - GetUInt32(key string) uint32 - GetUInt32WithDefault(key string, defaultValue uint32) uint32 + + SetInt64(value int64, key string) bool GetInt64(key string) int64 GetInt64WithDefault(key string, defaultValue int64) int64 + + SetUInt32(value uint32, key string) bool + GetUInt32(key string) uint32 + GetUInt32WithDefault(key string, defaultValue uint32) uint32 + + SetUInt64(value uint64, key string) bool GetUInt64(key string) uint64 GetUInt64WithDefault(key string, defaultValue uint64) uint64 + + SetFloat32(value float32, key string) bool GetFloat32(key string) float32 GetFloat32WithDefault(key string, defaultValue float32) float32 + + SetFloat64(value float64, key string) bool GetFloat64(key string) float64 GetFloat64WithDefault(key string, defaultValue float64) float64 + + // string value should be utf-8 encoded + SetString(value string, key string) bool GetString(key string) string + + SetBytes(value []byte, key string) bool GetBytes(key string) []byte RemoveKey(key string) RemoveKeys(keys []string) + + // clear all key-values ClearAll() + // return count of keys Count() uint64 + AllKeys() []string Contains(key string) bool + + // total size of the file TotalSize() uint64 + + // actual used size of the file ActualSize() uint64 + // the mmapID of the instance MMAP_ID() string + /* Synchronize memory to file. You don't need to call this, really, I mean it. Unless you worry about running out of battery. + * Pass true to perform synchronous write. + * Pass false to perform asynchronous write, return immediately. + */ Sync(sync bool) + // Clear all caches (on memory warning). ClearMemoryCache() + + /* Trim the file size to minimal. + * MMKV's size won't reduce after deleting key-values. + * Call this method after lots of deleting if you care about disk usage. + * Note that clearAll() has the similar effect. + */ Trim() + + // Close the instance when it's no longer needed in the near future. + // Any subsequent call to the instance is undefined behavior. Close() + /* Change encryption key for the MMKV instance. + * The cryptKey is 16 bytes limited. + * You can transfer a plain-text MMKV into encrypted by setting an non-null, non-empty cryptKey. + * Or vice versa by passing cryptKey with null. See also checkReSetCryptKey(). + */ ReKey(newKey string) bool + + // Just reset the cryptKey (will not encrypt or decrypt anything). + // Usually you should call this method after other process reKey() the multi-process mmkv. + CheckReSetCryptKey(key string) + + // See also reKey(). CryptKey() string } @@ -390,6 +433,11 @@ func (kv ctorMMKV) ReKey(newKey string) bool { return bool(ret) } +func (kv ctorMMKV) CheckReSetCryptKey(key string) { + ret := C.checkReSetCryptKey(unsafe.Pointer(kv), C.wrapGoString(key)) + return bool(ret) +} + func (kv ctorMMKV) CryptKey() string { var cLen C.uint32_t cStr := C.cryptKey(unsafe.Pointer(kv), &cLen) From 80b90c8b1ca2e51f945a139079aa89f568e95bcc Mon Sep 17 00:00:00 2001 From: guoling Date: Mon, 14 Dec 2020 22:26:45 +0800 Subject: [PATCH 12/16] add more doc --- POSIX/golang/mmkv.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index cddead15..e9518d93 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -169,56 +169,73 @@ type MMKV interface { CryptKey() string } -// Hello returns a greeting for the named person. +// return the version of MMKV func Version() string { version := C.version() goStr := C.GoString(version) return goStr } +/* MMKV must be initialized before any usage. + * Generally speaking you should do this inside main(): +func main() { + mmkv.InitializeMMKV("/path/to/my/working/dir") + // other logic +} +*/ func InitializeMMKV(rootDir string) { C.mmkvInitialize(C.wrapGoString(rootDir), MMKVLogInfo) } +// Same as the function InitializeMMKV() above, except that you can customize MMKV's log level by passing logLevel. +// You can even turnoff logging by passing MMKVLogNone, which we don't recommend doing. func InitializeMMKVWithLogLevel(rootDir string, logLevel int) { C.mmkvInitialize(C.wrapGoString(rootDir), C.int32_t(logLevel)) } +// Call before App exists, it's just fine not calling it on most case (except when the device shutdown suddenly). func OnExit() { C.onExit() } +// return the page size of memory func PageSize() int32 { return int32(C.pageSize()) } +// a generic purpose instance in single-process mode. func DefaultMMKV() MMKV { mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, C.GoStringWrapNil())) return MMKV(mmkv) } +// a generic purpose instance in single-process or multi-process mode. func DefaultMMKVWithMode(mode int) MMKV { mmkv := ctorMMKV(C.getDefaultMMKV(C.int(mode), C.GoStringWrapNil())) return MMKV(mmkv) } +// an encrypted generic purpose instance in single-process or multi-process mode. func DefaultMMKVWithModeAndCryptKey(mode int, cryptKey string) MMKV { mmkv := ctorMMKV(C.getDefaultMMKV(MMKV_SINGLE_PROCESS, C.wrapGoString(cryptKey))) return MMKV(mmkv) } +// an instance with specific location ${MMKV Root}/mmapID, in single-process mode. func MMKVWithID(mmapID string) MMKV { cStrNull := C.GoStringWrapNil() mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), MMKV_SINGLE_PROCESS, cStrNull, cStrNull)) return MMKV(mmkv) } +// an instance with specific location ${MMKV Root}/mmapID, in single-process or multi-process mode. func MMKVWithIDAndMode(mmapID string, mode int) MMKV { cStrNull := C.GoStringWrapNil() mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), C.int(mode), cStrNull, cStrNull)) return MMKV(mmkv) } +// an encrypted instance with specific location ${MMKV Root}/mmapID, in single-process or multi-process mode. func MMKVWithIDAndModeAndCryptKey(mmapID string, mode int, cryptKey string) MMKV { cStrNull := C.GoStringWrapNil() mmkv := ctorMMKV(C.getMMKVWithID(C.wrapGoString(mmapID), C.int(mode), C.wrapGoString(cryptKey), cStrNull)) From e6e8e2467ecb94ae9850df8582674225444f97f2 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 15 Dec 2020 21:43:20 +0800 Subject: [PATCH 13/16] add MMBuffer & callback --- POSIX/golang/callback.go | 119 +++++++++++++++++++++++++++++++++ POSIX/golang/golang-bridge.cpp | 50 ++++++++++++++ POSIX/golang/golang-bridge.h | 4 ++ POSIX/golang/mmkv.go | 53 ++++++++++++--- POSIX/golang/test/main.go | 52 ++++++++++++++ 5 files changed, 267 insertions(+), 11 deletions(-) create mode 100644 POSIX/golang/callback.go diff --git a/POSIX/golang/callback.go b/POSIX/golang/callback.go new file mode 100644 index 00000000..a2dbf51e --- /dev/null +++ b/POSIX/golang/callback.go @@ -0,0 +1,119 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// MMKV is a cross-platform key-value storage framework developed by WeChat. +package mmkv + +/* +#include "golang-bridge.h" +#include +*/ +import "C" + +// the callback type of Logger +type LogHandler func(level int, file string, line int, function string, message string) + +var gLogHandler LogHandler + +// register a log callback +func RegisterLogHandler(logHandler LogHandler) { + gLogHandler = logHandler + + C.setWantsLogRedirect(C.bool(true)) +} + +// unregister a log callback +func UnRegisterLogHandler() { + gLogHandler = nil + + C.setWantsLogRedirect(C.bool(false)) +} + +//export myLogHandler +func myLogHandler(level int, file string, line int, function string, message string) { + if gLogHandler != nil { + gLogHandler(level, file, line, function, message) + } +} + +const ( + OnErrorDiscard = iota // When there's an error, MMKV will discard everything by default. + OnErrorRecover // When there's an error, MMKV will try to recover as much data as possible. +) + +const ( + MMKVCRCCheckFail = iota + MMKVFileLength +) + +// the callback type of error handler +// error is either MMKVCRCCheckFail or MMKVFileLength +// return OnErrorDiscard (default) or OnErrorRecover +type ErrorHandler func(mmapID string, error int) int + +var gErrorHandler ErrorHandler + +// register a error callback +func RegisterErrorHandler(errorHandler ErrorHandler) { + gErrorHandler = errorHandler + + C.setWantsErrorHandle(C.bool(true)) +} + +// unregister a error callback +func UnRegisterErrorHandler() { + gErrorHandler = nil + + C.setWantsErrorHandle(C.bool(false)) +} + +//export myErrorHandler +func myErrorHandler(mmapID string, error int) int { + if gErrorHandler != nil { + return gErrorHandler(mmapID, error) + } + return OnErrorDiscard +} + +// the type of content change handler +type ContentChangeHandler func(mmapID string) + +var gContentChangeHandler ContentChangeHandler + +// register a content change callback +func RegisterContentChangeHandler(contentChangeHandler ContentChangeHandler) { + gContentChangeHandler = contentChangeHandler + + C.setWantsContentChangeHandle(C.bool(true)) +} + +// unregister a content change callback +func UnRegisterContentChangeHandler() { + gContentChangeHandler = nil + + C.setWantsContentChangeHandle(C.bool(false)) +} + +//export myContentChangeHandler +func myContentChangeHandler(mmapID string) { + if gContentChangeHandler != nil { + gContentChangeHandler(mmapID) + } +} diff --git a/POSIX/golang/golang-bridge.cpp b/POSIX/golang/golang-bridge.cpp index 7a59e6c2..26d7e525 100644 --- a/POSIX/golang/golang-bridge.cpp +++ b/POSIX/golang/golang-bridge.cpp @@ -436,4 +436,54 @@ MMKV_EXPORT void mmkvClose(void *handle) { } } +extern "C" void myLogHandler(int64_t level, GoStringWrap file, int64_t line, GoStringWrap function, GoStringWrap message); + +void cLogHandler(MMKVLogLevel level, const char *file, int line, const char *function, const std::string &message) { + GoStringWrap oFile { file, static_cast(strlen(file)) }; + GoStringWrap oFunction { function, static_cast(strlen(function)) }; + GoStringWrap oMessage { message.data(), static_cast(message.length()) }; + + myLogHandler(level, oFile, line, oFunction, oMessage); +} + +void setWantsLogRedirect(bool redirect) { + if (redirect) { + MMKV::registerLogHandler(&cLogHandler); + } else { + MMKV::unRegisterLogHandler(); + } +} + +extern "C" int64_t myErrorHandler(GoStringWrap mmapID, int64_t error); + +static MMKVRecoverStrategic cErrorHandler(const std::string &mmapID, MMKVErrorType errorType) { + GoStringWrap oID { mmapID.data(), static_cast(mmapID.length()) }; + + return static_cast(myErrorHandler(oID, static_cast(errorType))); +} + +void setWantsErrorHandle(bool errorHandle) { + if (errorHandle) { + MMKV::registerErrorHandler(&cErrorHandler); + } else { + MMKV::unRegisterErrorHandler(); + } +} + +extern "C" void myContentChangeHandler(GoStringWrap mmapID); + +static void cContentChangeHandler(const std::string &mmapID) { + GoStringWrap oID { mmapID.data(), static_cast(mmapID.length()) }; + + myContentChangeHandler(oID); +} + +void setWantsContentChangeHandle(bool errorHandle) { + if (errorHandle) { + MMKV::registerContentChangeHandler(&cContentChangeHandler); + } else { + MMKV::unRegisterContentChangeHandler(); + } +} + #endif // CGO diff --git a/POSIX/golang/golang-bridge.h b/POSIX/golang/golang-bridge.h index a19daab9..bd227faf 100644 --- a/POSIX/golang/golang-bridge.h +++ b/POSIX/golang/golang-bridge.h @@ -92,6 +92,10 @@ void mmkvClose(void *handle); int32_t pageSize(); const char *version(); +void setWantsLogRedirect(bool redirect); +void setWantsErrorHandle(bool errorHandle); +void setWantsContentChangeHandle(bool contentChange); + #ifdef __cplusplus } #endif diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index e9518d93..568efd2f 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -66,17 +66,30 @@ const ( MMKV_MULTI_PROCESS ) -const ( - OnErrorDiscard = iota - OnErrorRecover -) +// a wrapper of native C memory, efficient for simple usage +// must call MMBuffer.Destroy() after no longer usage +type MMBuffer struct { + ptr uintptr + length int +} -const ( - MMKVCRCCheckFail = iota - MMKVFileLength -) +// get byte slice view of underlying memory +// the slice is valid as long as MMBuffer.Destroy() not called +func (buffer MMBuffer) ByteSliceView() []byte { + bytes := (*[1 << 30]byte)(unsafe.Pointer(buffer.ptr))[0:buffer.length:buffer.length] + return bytes +} -type ctorMMKV uintptr +// get string view of underlying memory +// the string is valid as long as MMBuffer.Destroy() not called +func (buffer MMBuffer) StringView() string { + return *((*string)(unsafe.Pointer(&buffer))) +} + +// must call Destroy() after no longer usage +func (buffer MMBuffer) Destroy() { + C.free(unsafe.Pointer(buffer.ptr)) +} type MMKV interface { SetBool(value bool, key string) bool @@ -110,9 +123,13 @@ type MMKV interface { // string value should be utf-8 encoded SetString(value string, key string) bool GetString(key string) string + // get C memory directly (without memcpy), much more efferent for large value + GetStringBuffer(key string) MMBuffer SetBytes(value []byte, key string) bool GetBytes(key string) []byte + // get C memory directly (without memcpy), much more efferent for large value + GetBytesBuffer(key string) MMBuffer RemoveKey(key string) RemoveKeys(keys []string) @@ -169,6 +186,8 @@ type MMKV interface { CryptKey() string } +type ctorMMKV uintptr + // return the version of MMKV func Version() string { version := C.version() @@ -356,6 +375,10 @@ func (kv ctorMMKV) GetString(key string) string { return value } +func (kv ctorMMKV) GetStringBuffer(key string) MMBuffer { + return kv.GetBytesBuffer(key) +} + func (kv ctorMMKV) SetBytes(value []byte, key string) bool { cValue := C.wrapGoByteSlice(unsafe.Pointer(&value[0]), C.size_t(len(value))) ret := C.encodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), cValue) @@ -372,6 +395,15 @@ func (kv ctorMMKV) GetBytes(key string) []byte { return value } +func (kv ctorMMKV) GetBytesBuffer(key string) MMBuffer { + var length uint64 + + cValue := C.decodeBytes(unsafe.Pointer(kv), C.wrapGoString(key), (*C.uint64_t)(&length)) + value := MMBuffer{uintptr(cValue), int(length)} + + return value +} + func (kv ctorMMKV) RemoveKey(key string) { C.removeValueForKey(unsafe.Pointer(kv), C.wrapGoString(key)) } @@ -451,8 +483,7 @@ func (kv ctorMMKV) ReKey(newKey string) bool { } func (kv ctorMMKV) CheckReSetCryptKey(key string) { - ret := C.checkReSetCryptKey(unsafe.Pointer(kv), C.wrapGoString(key)) - return bool(ret) + C.checkReSetCryptKey(unsafe.Pointer(kv), C.wrapGoString(key)) } func (kv ctorMMKV) CryptKey() string { diff --git a/POSIX/golang/test/main.go b/POSIX/golang/test/main.go index 823f4ea8..55d1628d 100644 --- a/POSIX/golang/test/main.go +++ b/POSIX/golang/test/main.go @@ -11,6 +11,13 @@ import ( func main() { mmkv.InitializeMMKV("/tmp/mmkv") + // you can set log redirecting + mmkv.RegisterLogHandler(logHandler) + // you can set error handler + mmkv.RegisterErrorHandler(errorHandler) + // you can get notify content change by other process (not in realtime) + mmkv.RegisterContentChangeHandler(contentChangeNotify) + functionalTest() testReKey() } @@ -44,9 +51,21 @@ func functionalTest() { kv.SetString("Hello world, 你好 from MMKV!", "string") fmt.Println("string =", kv.GetString("string")) + // much more efficient + buffer := kv.GetStringBuffer("string") + fmt.Println("string(buffer) =", buffer.StringView()) + // must call Destroy() after usage + buffer.Destroy() + kv.SetBytes([]byte("Hello world, 你好 from MMKV 以及 bytes!"), "bytes") fmt.Println("bytes =", string(kv.GetBytes("bytes"))) + // much more efficient + buffer = kv.GetBytesBuffer("bytes") + fmt.Println("bytes(buffer) =", string(buffer.ByteSliceView())) + // must call Destroy() after usage + buffer.Destroy() + fmt.Println("contains \"bool\"? ", kv.Contains("bool")) kv.RemoveKey("bool") fmt.Println("after remove, contains \"bool\"? ", kv.Contains("bool")) @@ -140,3 +159,36 @@ func testReKey() { kv.ClearMemoryCache() testMMKV(mmapID, "", true) } + +func logHandler(level int, file string, line int, function string, message string) { + var levelStr string + switch level { + case mmkv.MMKVLogDebug: + levelStr = "[D]" + case mmkv.MMKVLogInfo: + levelStr = "[I]" + case mmkv.MMKVLogWarning: + levelStr = "[W]" + case mmkv.MMKVLogError: + levelStr = "[E]" + default: + levelStr = "[N]" + } + fmt.Printf("Redirect %v <%v:%v::%v> %v\n", levelStr, file, line, function, message) +} + +func errorHandler(mmapID string, error int) int { + var errorDesc string + if error == mmkv.MMKVCRCCheckFail { + errorDesc = "CRC-Error" + } else { + errorDesc = "File-Length-Error" + } + fmt.Println(mmapID, "has error type:", errorDesc) + + return mmkv.OnErrorRecover +} + +func contentChangeNotify(mmapID string) { + fmt.Println(mmapID, "content changed by other process") +} \ No newline at end of file From 3bcd82d41e4cd7d56a88ae002f1f8fabbfb0a4a3 Mon Sep 17 00:00:00 2001 From: guoling Date: Tue, 15 Dec 2020 21:45:27 +0800 Subject: [PATCH 14/16] add doc --- POSIX/golang/test/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/POSIX/golang/test/main.go b/POSIX/golang/test/main.go index 55d1628d..20c4b42e 100644 --- a/POSIX/golang/test/main.go +++ b/POSIX/golang/test/main.go @@ -9,6 +9,7 @@ import ( ) func main() { + // init MMKV with root dir mmkv.InitializeMMKV("/tmp/mmkv") // you can set log redirecting From 40c6dafa8c809e776caa8a90b4e10268afc73b18 Mon Sep 17 00:00:00 2001 From: guoling Date: Wed, 16 Dec 2020 20:47:30 +0800 Subject: [PATCH 15/16] add make install --- POSIX/golang/.gitignore | 2 ++ POSIX/golang/CMakeLists.txt | 9 +++++++++ POSIX/golang/mmkv.go | 2 +- POSIX/golang/test/go.mod | 4 ++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/POSIX/golang/.gitignore b/POSIX/golang/.gitignore index 4b7991f9..0b37e262 100644 --- a/POSIX/golang/.gitignore +++ b/POSIX/golang/.gitignore @@ -3,3 +3,5 @@ Makefile libmmkv.* *.cbp Testing/ +tencent.com/ +install_manifest.txt diff --git a/POSIX/golang/CMakeLists.txt b/POSIX/golang/CMakeLists.txt index 01410788..0f7e7bc2 100644 --- a/POSIX/golang/CMakeLists.txt +++ b/POSIX/golang/CMakeLists.txt @@ -62,3 +62,12 @@ target_link_libraries( mmkv core pthread ) + +# Install source file & library to tencent.com/mmkv dir + +install(FILES mmkv.go callback.go go.mod mmkv_test.go golang-bridge.h golang-bridge.cpp + DESTINATION "tencent.com/mmkv") + +install(FILES libmmkv.a Core/libcore.a + DESTINATION "tencent.com/mmkv/lib") + diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 568efd2f..4f34e852 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -22,7 +22,7 @@ package mmkv // #cgo CXXFLAGS: -D CGO -D FORCE_POSIX -I ${SRCDIR}/../../Core -std=c++17 -// #cgo LDFLAGS: -L. -lmmkv -L./Core -lcore -lz -lpthread +// #cgo LDFLAGS: -L./lib -lmmkv -lcore -lz -lpthread /* #include "golang-bridge.h" #include diff --git a/POSIX/golang/test/go.mod b/POSIX/golang/test/go.mod index 912f6c22..e940a62e 100644 --- a/POSIX/golang/test/go.mod +++ b/POSIX/golang/test/go.mod @@ -2,6 +2,6 @@ module mmkv_test go 1.15 -replace tencent.com/mmkv => ../../golang +replace tencent.com/mmkv => ../tencent.com/mmkv -require tencent.com/mmkv v0.0.0-00010101000000-000000000000 // indirect +require tencent.com/mmkv v0.0.0-00010101000000-000000000000 From d8416b5b4f6cf71322a86cced4b03b9f9cac605e Mon Sep 17 00:00:00 2001 From: guoling Date: Thu, 17 Dec 2020 16:21:27 +0800 Subject: [PATCH 16/16] add Pointer() & Length() for MMBuffer --- Android/MMKV/build.gradle | 2 +- POSIX/golang/mmkv.go | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Android/MMKV/build.gradle b/Android/MMKV/build.gradle index 8411b9f5..6206b3c1 100644 --- a/Android/MMKV/build.gradle +++ b/Android/MMKV/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.4.10' + ext.kotlin_version = '1.4.21' repositories { google() diff --git a/POSIX/golang/mmkv.go b/POSIX/golang/mmkv.go index 4f34e852..29ec76b8 100644 --- a/POSIX/golang/mmkv.go +++ b/POSIX/golang/mmkv.go @@ -73,6 +73,16 @@ type MMBuffer struct { length int } +// the address of underlying memory +func (buffer MMBuffer) Pointer() uintptr { + return buffer.ptr +} + +// the size of underlying memory +func (buffer MMBuffer) Length() int { + return buffer.length +} + // get byte slice view of underlying memory // the slice is valid as long as MMBuffer.Destroy() not called func (buffer MMBuffer) ByteSliceView() []byte {