MiniPBCoder.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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 "MiniPBCoder.h"
  21. #include "CodedInputData.h"
  22. #include "CodedInputDataCrypt.h"
  23. #include "CodedOutputData.h"
  24. #include "PBEncodeItem.hpp"
  25. #ifdef MMKV_APPLE
  26. # if __has_feature(objc_arc)
  27. # error This file must be compiled with MRC. Use -fno-objc-arc flag.
  28. # endif
  29. #endif // MMKV_APPLE
  30. using namespace std;
  31. namespace mmkv {
  32. MiniPBCoder::MiniPBCoder() : m_encodeItems(new std::vector<PBEncodeItem>()) {
  33. }
  34. MiniPBCoder::MiniPBCoder(const MMBuffer *inputBuffer, AESCrypt *crypter) : MiniPBCoder() {
  35. m_inputBuffer = inputBuffer;
  36. #ifndef MMKV_DISABLE_CRYPT
  37. if (crypter) {
  38. m_inputDataDecrpt = new CodedInputDataCrypt(m_inputBuffer->getPtr(), m_inputBuffer->length(), *crypter);
  39. } else {
  40. m_inputData = new CodedInputData(m_inputBuffer->getPtr(), m_inputBuffer->length());
  41. }
  42. #else
  43. m_inputData = new CodedInputData(m_inputBuffer->getPtr(), m_inputBuffer->length());
  44. #endif // MMKV_DISABLE_CRYPT
  45. }
  46. MiniPBCoder::~MiniPBCoder() {
  47. delete m_inputData;
  48. #ifndef MMKV_DISABLE_CRYPT
  49. delete m_inputDataDecrpt;
  50. #endif
  51. delete m_outputBuffer;
  52. delete m_outputData;
  53. delete m_encodeItems;
  54. }
  55. // encode
  56. // write object using prepared m_encodeItems[]
  57. void MiniPBCoder::writeRootObject() {
  58. for (size_t index = 0, total = m_encodeItems->size(); index < total; index++) {
  59. PBEncodeItem *encodeItem = &(*m_encodeItems)[index];
  60. switch (encodeItem->type) {
  61. case PBEncodeItemType_Data: {
  62. m_outputData->writeData(*(encodeItem->value.bufferValue));
  63. break;
  64. }
  65. case PBEncodeItemType_Container: {
  66. m_outputData->writeUInt32(encodeItem->valueSize);
  67. break;
  68. }
  69. #ifndef MMKV_APPLE
  70. case PBEncodeItemType_String: {
  71. m_outputData->writeString(*(encodeItem->value.strValue));
  72. break;
  73. }
  74. #else
  75. case PBEncodeItemType_NSString: {
  76. m_outputData->writeUInt32(encodeItem->valueSize);
  77. if (encodeItem->valueSize > 0 && encodeItem->value.tmpObjectValue != nullptr) {
  78. auto obj = (__bridge NSData *) encodeItem->value.tmpObjectValue;
  79. MMBuffer buffer(obj, MMBufferNoCopy);
  80. m_outputData->writeRawData(buffer);
  81. }
  82. break;
  83. }
  84. case PBEncodeItemType_NSData: {
  85. m_outputData->writeUInt32(encodeItem->valueSize);
  86. if (encodeItem->valueSize > 0 && encodeItem->value.objectValue != nullptr) {
  87. auto obj = (__bridge NSData *) encodeItem->value.objectValue;
  88. MMBuffer buffer(obj, MMBufferNoCopy);
  89. m_outputData->writeRawData(buffer);
  90. }
  91. break;
  92. }
  93. case PBEncodeItemType_NSDate: {
  94. NSDate *oDate = (__bridge NSDate *) encodeItem->value.objectValue;
  95. m_outputData->writeDouble(oDate.timeIntervalSince1970);
  96. break;
  97. }
  98. #endif // MMKV_APPLE
  99. case PBEncodeItemType_None: {
  100. MMKVError("%d", encodeItem->type);
  101. break;
  102. }
  103. }
  104. }
  105. }
  106. size_t MiniPBCoder::prepareObjectForEncode(const MMBuffer &buffer) {
  107. m_encodeItems->push_back(PBEncodeItem());
  108. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  109. size_t index = m_encodeItems->size() - 1;
  110. {
  111. encodeItem->type = PBEncodeItemType_Data;
  112. encodeItem->value.bufferValue = &buffer;
  113. encodeItem->valueSize = static_cast<uint32_t>(buffer.length());
  114. }
  115. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  116. return index;
  117. }
  118. size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) {
  119. m_encodeItems->push_back(PBEncodeItem());
  120. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  121. size_t index = m_encodeItems->size() - 1;
  122. {
  123. encodeItem->type = PBEncodeItemType_Container;
  124. encodeItem->value.bufferValue = nullptr;
  125. for (const auto &itr : vec) {
  126. const auto &key = itr.first;
  127. const auto &value = itr.second;
  128. # ifdef MMKV_APPLE
  129. if (key.length <= 0) {
  130. # else
  131. if (key.length() <= 0) {
  132. # endif
  133. continue;
  134. }
  135. size_t keyIndex = prepareObjectForEncode(key);
  136. if (keyIndex < m_encodeItems->size()) {
  137. size_t valueIndex = prepareObjectForEncode(value);
  138. if (valueIndex < m_encodeItems->size()) {
  139. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[keyIndex].compiledSize;
  140. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[valueIndex].compiledSize;
  141. } else {
  142. m_encodeItems->pop_back(); // pop key
  143. }
  144. }
  145. }
  146. encodeItem = &(*m_encodeItems)[index];
  147. }
  148. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  149. return index;
  150. }
  151. MMBuffer MiniPBCoder::writePreparedItems(size_t index) {
  152. PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr;
  153. if (oItem && oItem->compiledSize > 0) {
  154. m_outputBuffer = new MMBuffer(oItem->compiledSize);
  155. m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length());
  156. writeRootObject();
  157. }
  158. return std::move(*m_outputBuffer);
  159. }
  160. MMBuffer MiniPBCoder::encodeDataWithObject(const MMBuffer &obj) {
  161. try {
  162. auto valueSize = static_cast<uint32_t>(obj.length());
  163. auto compiledSize = pbRawVarint32Size(valueSize) + valueSize;
  164. MMBuffer result(compiledSize);
  165. CodedOutputData output(result.getPtr(), result.length());
  166. output.writeData(obj);
  167. return result;
  168. } catch (const std::exception &exception) {
  169. MMKVError("%s", exception.what());
  170. return MMBuffer();
  171. }
  172. }
  173. #ifndef MMKV_APPLE
  174. size_t MiniPBCoder::prepareObjectForEncode(const string &str) {
  175. m_encodeItems->push_back(PBEncodeItem());
  176. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  177. size_t index = m_encodeItems->size() - 1;
  178. {
  179. encodeItem->type = PBEncodeItemType_String;
  180. encodeItem->value.strValue = &str;
  181. encodeItem->valueSize = static_cast<int32_t>(str.size());
  182. }
  183. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  184. return index;
  185. }
  186. size_t MiniPBCoder::prepareObjectForEncode(const vector<string> &v) {
  187. m_encodeItems->push_back(PBEncodeItem());
  188. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  189. size_t index = m_encodeItems->size() - 1;
  190. {
  191. encodeItem->type = PBEncodeItemType_Container;
  192. encodeItem->value.bufferValue = nullptr;
  193. for (const auto &str : v) {
  194. size_t itemIndex = prepareObjectForEncode(str);
  195. if (itemIndex < m_encodeItems->size()) {
  196. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[itemIndex].compiledSize;
  197. }
  198. }
  199. encodeItem = &(*m_encodeItems)[index];
  200. }
  201. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  202. return index;
  203. }
  204. vector<string> MiniPBCoder::decodeOneVector() {
  205. vector<string> v;
  206. m_inputData->readInt32();
  207. while (!m_inputData->isAtEnd()) {
  208. auto value = m_inputData->readString();
  209. v.push_back(std::move(value));
  210. }
  211. return v;
  212. }
  213. void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) {
  214. auto block = [position, this](MMKVMap &dictionary) {
  215. if (position) {
  216. m_inputData->seek(position);
  217. } else {
  218. m_inputData->readInt32();
  219. }
  220. while (!m_inputData->isAtEnd()) {
  221. KeyValueHolder kvHolder;
  222. const auto &key = m_inputData->readString(kvHolder);
  223. if (key.length() > 0) {
  224. m_inputData->readData(kvHolder);
  225. if (kvHolder.valueSize > 0) {
  226. dictionary[key] = std::move(kvHolder);
  227. } else {
  228. auto itr = dictionary.find(key);
  229. if (itr != dictionary.end()) {
  230. dictionary.erase(itr);
  231. }
  232. }
  233. }
  234. }
  235. };
  236. if (greedy) {
  237. try {
  238. block(dic);
  239. } catch (std::exception &exception) {
  240. MMKVError("%s", exception.what());
  241. }
  242. } else {
  243. try {
  244. MMKVMap tmpDic;
  245. block(tmpDic);
  246. dic.swap(tmpDic);
  247. } catch (std::exception &exception) {
  248. MMKVError("%s", exception.what());
  249. }
  250. }
  251. }
  252. # ifndef MMKV_DISABLE_CRYPT
  253. void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) {
  254. auto block = [position, this](MMKVMapCrypt &dictionary) {
  255. if (position) {
  256. m_inputDataDecrpt->seek(position);
  257. } else {
  258. m_inputDataDecrpt->readInt32();
  259. }
  260. while (!m_inputDataDecrpt->isAtEnd()) {
  261. KeyValueHolderCrypt kvHolder;
  262. const auto &key = m_inputDataDecrpt->readString(kvHolder);
  263. if (key.length() > 0) {
  264. m_inputDataDecrpt->readData(kvHolder);
  265. if (kvHolder.realValueSize() > 0) {
  266. dictionary[key] = std::move(kvHolder);
  267. } else {
  268. auto itr = dictionary.find(key);
  269. if (itr != dictionary.end()) {
  270. dictionary.erase(itr);
  271. }
  272. }
  273. }
  274. }
  275. };
  276. if (greedy) {
  277. try {
  278. block(dic);
  279. } catch (std::exception &exception) {
  280. MMKVError("%s", exception.what());
  281. }
  282. } else {
  283. try {
  284. MMKVMapCrypt tmpDic;
  285. block(tmpDic);
  286. dic.swap(tmpDic);
  287. } catch (std::exception &exception) {
  288. MMKVError("%s", exception.what());
  289. }
  290. }
  291. }
  292. # endif // MMKV_DISABLE_CRYPT
  293. vector<string> MiniPBCoder::decodeVector(const MMBuffer &oData) {
  294. MiniPBCoder oCoder(&oData);
  295. return oCoder.decodeOneVector();
  296. }
  297. #endif // MMKV_APPLE
  298. void MiniPBCoder::decodeMap(MMKVMap &dic, const MMBuffer &oData, size_t position) {
  299. MiniPBCoder oCoder(&oData);
  300. oCoder.decodeOneMap(dic, position, false);
  301. }
  302. void MiniPBCoder::greedyDecodeMap(MMKVMap &dic, const MMBuffer &oData, size_t position) {
  303. MiniPBCoder oCoder(&oData);
  304. oCoder.decodeOneMap(dic, position, true);
  305. }
  306. #ifndef MMKV_DISABLE_CRYPT
  307. void MiniPBCoder::decodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position) {
  308. MiniPBCoder oCoder(&oData, crypter);
  309. oCoder.decodeOneMap(dic, position, false);
  310. }
  311. void MiniPBCoder::greedyDecodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position) {
  312. MiniPBCoder oCoder(&oData, crypter);
  313. oCoder.decodeOneMap(dic, position, true);
  314. }
  315. #endif
  316. } // namespace mmkv