MMBuffer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Tencent is pleased to support the open source community by making
  3. * MMKV available.
  4. *
  5. * Copyright (C) 2018 THL A29 Limited, a Tencent company.
  6. * All rights reserved.
  7. *
  8. * Licensed under the BSD 3-Clause License (the "License"); you may not use
  9. * this file except in compliance with the License. You may obtain a copy of
  10. * the License at
  11. *
  12. * https://opensource.org/licenses/BSD-3-Clause
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. #include "MMBuffer.h"
  21. #include <cerrno>
  22. #include <cstdlib>
  23. #include <cstring>
  24. #include <utility>
  25. #include <stdexcept>
  26. #ifdef MMKV_APPLE
  27. # if __has_feature(objc_arc)
  28. # error This file must be compiled with MRC. Use -fno-objc-arc flag.
  29. # endif
  30. #endif
  31. using namespace std;
  32. namespace mmkv {
  33. MMBuffer::MMBuffer(size_t length) {
  34. if (length > SmallBufferSize()) {
  35. type = MMBufferType_Normal;
  36. isNoCopy = MMBufferCopy;
  37. size = length;
  38. ptr = malloc(size);
  39. if (!ptr) {
  40. throw std::runtime_error(strerror(errno));
  41. }
  42. #ifdef MMKV_APPLE
  43. m_data = nil;
  44. #endif
  45. } else {
  46. type = MMBufferType_Small;
  47. paddedSize = static_cast<uint8_t>(length);
  48. }
  49. }
  50. MMBuffer::MMBuffer(void *source, size_t length, MMBufferCopyFlag flag) : isNoCopy(flag) {
  51. if (isNoCopy == MMBufferCopy) {
  52. if (length > SmallBufferSize()) {
  53. type = MMBufferType_Normal;
  54. size = length;
  55. ptr = malloc(size);
  56. if (!ptr) {
  57. throw std::runtime_error(strerror(errno));
  58. }
  59. memcpy(ptr, source, size);
  60. #ifdef MMKV_APPLE
  61. m_data = nil;
  62. #endif
  63. } else {
  64. type = MMBufferType_Small;
  65. paddedSize = static_cast<uint8_t>(length);
  66. memcpy(paddedBuffer, source, length);
  67. }
  68. } else {
  69. type = MMBufferType_Normal;
  70. size = length;
  71. ptr = source;
  72. #ifdef MMKV_APPLE
  73. m_data = nil;
  74. #endif
  75. }
  76. }
  77. #ifdef MMKV_APPLE
  78. MMBuffer::MMBuffer(NSData *data, MMBufferCopyFlag flag)
  79. : type(MMBufferType_Normal), ptr((void *) data.bytes), size(data.length), isNoCopy(flag) {
  80. if (isNoCopy == MMBufferCopy) {
  81. m_data = [data retain];
  82. } else {
  83. m_data = data;
  84. }
  85. }
  86. #endif
  87. MMBuffer::MMBuffer(MMBuffer &&other) noexcept : type(other.type) {
  88. if (type == MMBufferType_Normal) {
  89. size = other.size;
  90. ptr = other.ptr;
  91. isNoCopy = other.isNoCopy;
  92. #ifdef MMKV_APPLE
  93. m_data = other.m_data;
  94. #endif
  95. other.detach();
  96. } else {
  97. paddedSize = other.paddedSize;
  98. memcpy(paddedBuffer, other.paddedBuffer, paddedSize);
  99. }
  100. }
  101. MMBuffer &MMBuffer::operator=(MMBuffer &&other) noexcept {
  102. if (type == MMBufferType_Normal) {
  103. if (other.type == MMBufferType_Normal) {
  104. std::swap(isNoCopy, other.isNoCopy);
  105. std::swap(size, other.size);
  106. std::swap(ptr, other.ptr);
  107. #ifdef MMKV_APPLE
  108. std::swap(m_data, other.m_data);
  109. #endif
  110. } else {
  111. type = MMBufferType_Small;
  112. if (isNoCopy == MMBufferCopy) {
  113. #ifdef MMKV_APPLE
  114. if (m_data) {
  115. [m_data release];
  116. } else if (ptr) {
  117. free(ptr);
  118. }
  119. #else
  120. if (ptr) {
  121. free(ptr);
  122. }
  123. #endif
  124. }
  125. paddedSize = other.paddedSize;
  126. memcpy(paddedBuffer, other.paddedBuffer, paddedSize);
  127. }
  128. } else {
  129. if (other.type == MMBufferType_Normal) {
  130. type = MMBufferType_Normal;
  131. isNoCopy = other.isNoCopy;
  132. size = other.size;
  133. ptr = other.ptr;
  134. #ifdef MMKV_APPLE
  135. m_data = other.m_data;
  136. #endif
  137. other.detach();
  138. } else {
  139. uint8_t tmp[SmallBufferSize()];
  140. memcpy(tmp, other.paddedBuffer, other.paddedSize);
  141. memcpy(other.paddedBuffer, paddedBuffer, paddedSize);
  142. memcpy(paddedBuffer, tmp, other.paddedSize);
  143. std::swap(paddedSize, other.paddedSize);
  144. }
  145. }
  146. return *this;
  147. }
  148. MMBuffer::~MMBuffer() {
  149. if (isStoredOnStack()) {
  150. return;
  151. }
  152. #ifdef MMKV_APPLE
  153. if (m_data) {
  154. if (isNoCopy == MMBufferCopy) {
  155. [m_data release];
  156. }
  157. return;
  158. }
  159. #endif
  160. if (isNoCopy == MMBufferCopy && ptr) {
  161. free(ptr);
  162. }
  163. }
  164. void MMBuffer::detach() {
  165. // type = MMBufferType_Small;
  166. // paddedSize = 0;
  167. auto memsetPtr = (size_t *) &type;
  168. *memsetPtr = 0;
  169. }
  170. } // namespace mmkv