185 lines
4.7 KiB
C++
185 lines
4.7 KiB
C++
/*
|
|
* Tencent is pleased to support the open source community by making
|
|
* MMKV available.
|
|
*
|
|
* Copyright (C) 2018 THL A29 Limited, a Tencent company.
|
|
* All rights reserved.
|
|
*
|
|
* Licensed under the BSD 3-Clause License (the "License"); you may not use
|
|
* this file except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* https://opensource.org/licenses/BSD-3-Clause
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "MMBuffer.h"
|
|
#include <cerrno>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <utility>
|
|
|
|
#ifdef MMKV_APPLE
|
|
# if __has_feature(objc_arc)
|
|
# error This file must be compiled with MRC. Use -fno-objc-arc flag.
|
|
# endif
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
namespace mmkv {
|
|
|
|
MMBuffer::MMBuffer(size_t length) {
|
|
if (length > SmallBufferSize()) {
|
|
type = MMBufferType_Normal;
|
|
isNoCopy = MMBufferCopy;
|
|
size = length;
|
|
ptr = malloc(size);
|
|
if (!ptr) {
|
|
throw std::runtime_error(strerror(errno));
|
|
}
|
|
#ifdef MMKV_APPLE
|
|
m_data = nil;
|
|
#endif
|
|
} else {
|
|
type = MMBufferType_Small;
|
|
paddedSize = static_cast<uint8_t>(length);
|
|
}
|
|
}
|
|
|
|
MMBuffer::MMBuffer(void *source, size_t length, MMBufferCopyFlag flag) : isNoCopy(flag) {
|
|
if (isNoCopy == MMBufferCopy) {
|
|
if (length > SmallBufferSize()) {
|
|
type = MMBufferType_Normal;
|
|
size = length;
|
|
ptr = malloc(size);
|
|
if (!ptr) {
|
|
throw std::runtime_error(strerror(errno));
|
|
}
|
|
memcpy(ptr, source, size);
|
|
#ifdef MMKV_APPLE
|
|
m_data = nil;
|
|
#endif
|
|
} else {
|
|
type = MMBufferType_Small;
|
|
paddedSize = static_cast<uint8_t>(length);
|
|
memcpy(paddedBuffer, source, length);
|
|
}
|
|
} else {
|
|
type = MMBufferType_Normal;
|
|
size = length;
|
|
ptr = source;
|
|
#ifdef MMKV_APPLE
|
|
m_data = nil;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef MMKV_APPLE
|
|
MMBuffer::MMBuffer(NSData *data, MMBufferCopyFlag flag)
|
|
: type(MMBufferType_Normal), ptr((void *) data.bytes), size(data.length), isNoCopy(flag) {
|
|
if (isNoCopy == MMBufferCopy) {
|
|
m_data = [data retain];
|
|
} else {
|
|
m_data = data;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
MMBuffer::MMBuffer(MMBuffer &&other) noexcept : type(other.type) {
|
|
if (type == MMBufferType_Normal) {
|
|
size = other.size;
|
|
ptr = other.ptr;
|
|
isNoCopy = other.isNoCopy;
|
|
#ifdef MMKV_APPLE
|
|
m_data = other.m_data;
|
|
#endif
|
|
other.detach();
|
|
} else {
|
|
paddedSize = other.paddedSize;
|
|
memcpy(paddedBuffer, other.paddedBuffer, paddedSize);
|
|
}
|
|
}
|
|
|
|
MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept {
|
|
if (type == MMBufferType_Normal) {
|
|
if (other.type == MMBufferType_Normal) {
|
|
std::swap(isNoCopy, other.isNoCopy);
|
|
std::swap(size, other.size);
|
|
std::swap(ptr, other.ptr);
|
|
#ifdef MMKV_APPLE
|
|
std::swap(m_data, other.m_data);
|
|
#endif
|
|
} else {
|
|
type = MMBufferType_Small;
|
|
if (isNoCopy == MMBufferCopy) {
|
|
#ifdef MMKV_APPLE
|
|
if (m_data) {
|
|
[m_data release];
|
|
} else if (ptr) {
|
|
free(ptr);
|
|
}
|
|
#else
|
|
if (ptr) {
|
|
free(ptr);
|
|
}
|
|
#endif
|
|
}
|
|
paddedSize = other.paddedSize;
|
|
memcpy(paddedBuffer, other.paddedBuffer, paddedSize);
|
|
}
|
|
} else {
|
|
if (other.type == MMBufferType_Normal) {
|
|
type = MMBufferType_Normal;
|
|
isNoCopy = other.isNoCopy;
|
|
size = other.size;
|
|
ptr = other.ptr;
|
|
#ifdef MMKV_APPLE
|
|
m_data = other.m_data;
|
|
#endif
|
|
other.detach();
|
|
} else {
|
|
uint8_t tmp[SmallBufferSize()];
|
|
memcpy(tmp, other.paddedBuffer, other.paddedSize);
|
|
memcpy(other.paddedBuffer, paddedBuffer, paddedSize);
|
|
memcpy(paddedBuffer, tmp, other.paddedSize);
|
|
std::swap(paddedSize, other.paddedSize);
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
MMBuffer::~MMBuffer() {
|
|
if (type == MMBufferType_Small) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MMKV_APPLE
|
|
if (m_data) {
|
|
if (isNoCopy == MMBufferCopy) {
|
|
[m_data release];
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (isNoCopy == MMBufferCopy && ptr) {
|
|
free(ptr);
|
|
}
|
|
}
|
|
|
|
void MMBuffer::detach() {
|
|
// type = MMBufferType_Small;
|
|
// paddedSize = 0;
|
|
auto memsetPtr = (size_t *) &type;
|
|
*memsetPtr = 0;
|
|
}
|
|
|
|
} // namespace mmkv
|