MiniPBCoder.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. #ifndef MMKV_DISABLE_CRYPT
  119. size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) {
  120. m_encodeItems->push_back(PBEncodeItem());
  121. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  122. size_t index = m_encodeItems->size() - 1;
  123. {
  124. encodeItem->type = PBEncodeItemType_Container;
  125. encodeItem->value.bufferValue = nullptr;
  126. for (const auto &itr : vec) {
  127. const auto &key = itr.first;
  128. const auto &value = itr.second;
  129. # ifdef MMKV_APPLE
  130. if (key.length <= 0) {
  131. # else
  132. if (key.length() <= 0) {
  133. # endif
  134. continue;
  135. }
  136. size_t keyIndex = prepareObjectForEncode(key);
  137. if (keyIndex < m_encodeItems->size()) {
  138. size_t valueIndex = prepareObjectForEncode(value);
  139. if (valueIndex < m_encodeItems->size()) {
  140. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[keyIndex].compiledSize;
  141. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[valueIndex].compiledSize;
  142. } else {
  143. m_encodeItems->pop_back(); // pop key
  144. }
  145. }
  146. }
  147. encodeItem = &(*m_encodeItems)[index];
  148. }
  149. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  150. return index;
  151. }
  152. #endif // MMKV_DISABLE_CRYPT
  153. MMBuffer MiniPBCoder::writePreparedItems(size_t index) {
  154. PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr;
  155. if (oItem && oItem->compiledSize > 0) {
  156. m_outputBuffer = new MMBuffer(oItem->compiledSize);
  157. m_outputData = new CodedOutputData(m_outputBuffer->getPtr(), m_outputBuffer->length());
  158. writeRootObject();
  159. }
  160. return std::move(*m_outputBuffer);
  161. }
  162. MMBuffer MiniPBCoder::encodeDataWithObject(const MMBuffer &obj) {
  163. try {
  164. auto valueSize = static_cast<uint32_t>(obj.length());
  165. auto compiledSize = pbRawVarint32Size(valueSize) + valueSize;
  166. MMBuffer result(compiledSize);
  167. CodedOutputData output(result.getPtr(), result.length());
  168. output.writeData(obj);
  169. return result;
  170. } catch (const std::exception &exception) {
  171. MMKVError("%s", exception.what());
  172. return MMBuffer();
  173. }
  174. }
  175. #ifndef MMKV_APPLE
  176. size_t MiniPBCoder::prepareObjectForEncode(const string &str) {
  177. m_encodeItems->push_back(PBEncodeItem());
  178. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  179. size_t index = m_encodeItems->size() - 1;
  180. {
  181. encodeItem->type = PBEncodeItemType_String;
  182. encodeItem->value.strValue = &str;
  183. encodeItem->valueSize = static_cast<int32_t>(str.size());
  184. }
  185. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  186. return index;
  187. }
  188. size_t MiniPBCoder::prepareObjectForEncode(const vector<string> &v) {
  189. m_encodeItems->push_back(PBEncodeItem());
  190. PBEncodeItem *encodeItem = &(m_encodeItems->back());
  191. size_t index = m_encodeItems->size() - 1;
  192. {
  193. encodeItem->type = PBEncodeItemType_Container;
  194. encodeItem->value.bufferValue = nullptr;
  195. for (const auto &str : v) {
  196. size_t itemIndex = prepareObjectForEncode(str);
  197. if (itemIndex < m_encodeItems->size()) {
  198. (*m_encodeItems)[index].valueSize += (*m_encodeItems)[itemIndex].compiledSize;
  199. }
  200. }
  201. encodeItem = &(*m_encodeItems)[index];
  202. }
  203. encodeItem->compiledSize = pbRawVarint32Size(encodeItem->valueSize) + encodeItem->valueSize;
  204. return index;
  205. }
  206. vector<string> MiniPBCoder::decodeOneVector() {
  207. vector<string> v;
  208. m_inputData->readInt32();
  209. while (!m_inputData->isAtEnd()) {
  210. auto value = m_inputData->readString();
  211. v.push_back(move(value));
  212. }
  213. return v;
  214. }
  215. void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) {
  216. auto block = [position, this](MMKVMap &dictionary) {
  217. if (position) {
  218. m_inputData->seek(position);
  219. } else {
  220. m_inputData->readInt32();
  221. }
  222. while (!m_inputData->isAtEnd()) {
  223. KeyValueHolder kvHolder;
  224. const auto &key = m_inputData->readString(kvHolder);
  225. if (key.length() > 0) {
  226. m_inputData->readData(kvHolder);
  227. if (kvHolder.valueSize > 0) {
  228. dictionary[key] = move(kvHolder);
  229. } else {
  230. auto itr = dictionary.find(key);
  231. if (itr != dictionary.end()) {
  232. dictionary.erase(itr);
  233. }
  234. }
  235. }
  236. }
  237. };
  238. if (greedy) {
  239. try {
  240. block(dic);
  241. } catch (std::exception &exception) {
  242. MMKVError("%s", exception.what());
  243. }
  244. } else {
  245. try {
  246. MMKVMap tmpDic;
  247. block(tmpDic);
  248. dic.swap(tmpDic);
  249. } catch (std::exception &exception) {
  250. MMKVError("%s", exception.what());
  251. }
  252. }
  253. }
  254. # ifndef MMKV_DISABLE_CRYPT
  255. void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) {
  256. auto block = [position, this](MMKVMapCrypt &dictionary) {
  257. if (position) {
  258. m_inputDataDecrpt->seek(position);
  259. } else {
  260. m_inputDataDecrpt->readInt32();
  261. }
  262. while (!m_inputDataDecrpt->isAtEnd()) {
  263. KeyValueHolderCrypt kvHolder;
  264. const auto &key = m_inputDataDecrpt->readString(kvHolder);
  265. if (key.length() > 0) {
  266. m_inputDataDecrpt->readData(kvHolder);
  267. if (kvHolder.realValueSize() > 0) {
  268. dictionary[key] = move(kvHolder);
  269. } else {
  270. auto itr = dictionary.find(key);
  271. if (itr != dictionary.end()) {
  272. dictionary.erase(itr);
  273. }
  274. }
  275. }
  276. }
  277. };
  278. if (greedy) {
  279. try {
  280. block(dic);
  281. } catch (std::exception &exception) {
  282. MMKVError("%s", exception.what());
  283. }
  284. } else {
  285. try {
  286. MMKVMapCrypt tmpDic;
  287. block(tmpDic);
  288. dic.swap(tmpDic);
  289. } catch (std::exception &exception) {
  290. MMKVError("%s", exception.what());
  291. }
  292. }
  293. }
  294. # endif // MMKV_DISABLE_CRYPT
  295. vector<string> MiniPBCoder::decodeVector(const MMBuffer &oData) {
  296. MiniPBCoder oCoder(&oData);
  297. return oCoder.decodeOneVector();
  298. }
  299. #endif // MMKV_APPLE
  300. void MiniPBCoder::decodeMap(MMKVMap &dic, const MMBuffer &oData, size_t position) {
  301. MiniPBCoder oCoder(&oData);
  302. oCoder.decodeOneMap(dic, position, false);
  303. }
  304. void MiniPBCoder::greedyDecodeMap(MMKVMap &dic, const MMBuffer &oData, size_t position) {
  305. MiniPBCoder oCoder(&oData);
  306. oCoder.decodeOneMap(dic, position, true);
  307. }
  308. #ifndef MMKV_DISABLE_CRYPT
  309. void MiniPBCoder::decodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position) {
  310. MiniPBCoder oCoder(&oData, crypter);
  311. oCoder.decodeOneMap(dic, position, false);
  312. }
  313. void MiniPBCoder::greedyDecodeMap(MMKVMapCrypt &dic, const MMBuffer &oData, AESCrypt *crypter, size_t position) {
  314. MiniPBCoder oCoder(&oData, crypter);
  315. oCoder.decodeOneMap(dic, position, true);
  316. }
  317. #endif
  318. } // namespace mmkv