QxArchive.inl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /****************************************************************************
  2. **
  3. ** https://www.qxorm.com/
  4. ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
  5. **
  6. ** This file is part of the QxOrm library
  7. **
  8. ** This software is provided 'as-is', without any express or implied
  9. ** warranty. In no event will the authors be held liable for any
  10. ** damages arising from the use of this software
  11. **
  12. ** Commercial Usage
  13. ** Licensees holding valid commercial QxOrm licenses may use this file in
  14. ** accordance with the commercial license agreement provided with the
  15. ** Software or, alternatively, in accordance with the terms contained in
  16. ** a written agreement between you and Lionel Marty
  17. **
  18. ** GNU General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU
  20. ** General Public License version 3.0 as published by the Free Software
  21. ** Foundation and appearing in the file 'license.gpl3.txt' included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU General Public License version 3.0 requirements will be
  24. ** met : http://www.gnu.org/copyleft/gpl.html
  25. **
  26. ** If you are unsure which license is appropriate for your use, or
  27. ** if you have questions regarding the use of this file, please contact :
  28. ** contact@qxorm.com
  29. **
  30. ****************************************************************************/
  31. #ifdef _QX_ENABLE_BOOST_SERIALIZATION
  32. namespace qx {
  33. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  34. qx_bool QxArchive_ToFile<T, ArchiveInput, ArchiveOutput>::toFile(const T & obj, const QString & sFileName, unsigned int flags /* = boost::archive::no_header */)
  35. {
  36. typedef typename qx::trait::archive_wide_traits<ArchiveOutput>::type_ofstream qx_type_ofstream;
  37. qx_type_ofstream ofile(qPrintable(sFileName), (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc));
  38. if (! ofile.is_open()) { return qx_bool(false, 0, QString("Cannot create or open file '") + sFileName + QString("'")); }
  39. ArchiveOutput oar(ofile, flags);
  40. qx_bool bSerializeOk = false;
  41. const char * sTag = QxClassName<T>::get_xml_tag();
  42. QxBoostSerializeRegisterHelperX::helper(oar);
  43. try { oar << boost::serialization::make_nvp(sTag, obj); bSerializeOk = ofile.good(); }
  44. catch (const boost::archive::archive_exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  45. catch (const std::exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  46. catch (...) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  47. ofile.close();
  48. if (! bSerializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_ToFile<T>::toFile() -> ") + bSerializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  49. qAssert(bSerializeOk);
  50. return bSerializeOk;
  51. }
  52. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  53. qx_bool QxArchive_FromFile<T, ArchiveInput, ArchiveOutput>::fromFile(T & obj, const QString & sFileName, unsigned int flags /* = boost::archive::no_header */)
  54. {
  55. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_ifstream qx_type_ifstream;
  56. qx_type_ifstream ifile(qPrintable(sFileName), (std::ios_base::binary | std::ios_base::in));
  57. if (! ifile.is_open()) { return qx_bool(false, 0, QString("Cannot open file '") + sFileName + QString("'")); }
  58. ArchiveInput iar(ifile, flags);
  59. qx_bool bDeserializeOk = false;
  60. const char * sTag = QxClassName<T>::get_xml_tag();
  61. QxBoostSerializeRegisterHelperX::helper(iar);
  62. try { iar >> boost::serialization::make_nvp(sTag, obj); bDeserializeOk = true; }
  63. catch (const boost::archive::archive_exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  64. catch (const std::exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  65. catch (...) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  66. ifile.close();
  67. if (! bDeserializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_FromFile<T>::fromFile() -> ") + bDeserializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  68. qAssert(bDeserializeOk);
  69. return bDeserializeOk;
  70. }
  71. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  72. qx_bool QxArchive_ToFileCompressed<T, ArchiveInput, ArchiveOutput>::toFileCompressed(const T & obj, const QString & sFileName, unsigned int flags /* = boost::archive::no_header */, int iCompressionLevel /* = -1 */)
  73. {
  74. typedef typename qx::trait::archive_wide_traits<ArchiveOutput>::type_ostringstream qx_type_ostringstream;
  75. qx_type_ostringstream oss(std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
  76. ArchiveOutput oar(oss, flags);
  77. qx_bool bSerializeOk = false;
  78. const char * sTag = QxClassName<T>::get_xml_tag();
  79. QxBoostSerializeRegisterHelperX::helper(oar);
  80. try { oar << boost::serialization::make_nvp(sTag, obj); bSerializeOk = oss.good(); }
  81. catch (const boost::archive::archive_exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  82. catch (const std::exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  83. catch (...) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  84. qAssert(bSerializeOk);
  85. if (! bSerializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_ToFileCompressed<T>::toFileCompressed() -> ") + bSerializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  86. if (! bSerializeOk) { return false; }
  87. oss.seekp(0, std::ios::end);
  88. QByteArray compressed = qCompress((unsigned char *)(oss.str().c_str()), static_cast<int>(oss.tellp()), iCompressionLevel);
  89. if (compressed.isEmpty()) { qAssert(false); return qx_bool(false, 0, QString("Cannot compress archive")); }
  90. typedef typename qx::trait::archive_wide_traits<ArchiveOutput>::type_ofstream qx_type_ofstream;
  91. qx_type_ofstream ofile(qPrintable(sFileName), (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc));
  92. if (! ofile.is_open()) { return qx_bool(false, 0, QString("Cannot create or open compressed file '") + sFileName + QString("'")); }
  93. ofile.write(compressed.constData(), compressed.size());
  94. ofile.close();
  95. return true;
  96. }
  97. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  98. qx_bool QxArchive_FromFileCompressed<T, ArchiveInput, ArchiveOutput>::fromFileCompressed(T & obj, const QString & sFileName, unsigned int flags /* = boost::archive::no_header */)
  99. {
  100. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_ifstream qx_type_ifstream;
  101. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_char qx_type_char;
  102. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_string qx_type_string;
  103. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_istringstream qx_type_istringstream;
  104. qx_type_ifstream ifile(qPrintable(sFileName), (std::ios_base::binary | std::ios_base::in));
  105. if (! ifile.is_open()) { return qx_bool(false, 0, QString("Cannot open compressed file '") + sFileName + QString("'")); }
  106. ifile.seekg(0, std::ios::end);
  107. int iSize = ifile.tellg();
  108. ifile.seekg(0, std::ios::beg);
  109. qx_type_char * buffer = new qx_type_char[iSize];
  110. ifile.read(buffer, iSize);
  111. ifile.close();
  112. QByteArray uncompressed = qUncompress((unsigned char *)(buffer), iSize);
  113. if (uncompressed.isEmpty()) { delete[] buffer; qAssert(false); return qx_bool(false, 0, QString("Cannot uncompress archive")); }
  114. delete[] buffer;
  115. qx_type_string str(uncompressed.constData(), uncompressed.count());
  116. qx_type_istringstream iss(str, (std::ios_base::binary | std::ios_base::in));
  117. ArchiveInput iar(iss, flags);
  118. qx_bool bDeserializeOk = false;
  119. const char * sTag = QxClassName<T>::get_xml_tag();
  120. QxBoostSerializeRegisterHelperX::helper(iar);
  121. try { iar >> boost::serialization::make_nvp(sTag, obj); bDeserializeOk = true; }
  122. catch (const boost::archive::archive_exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  123. catch (const std::exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  124. catch (...) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  125. if (! bDeserializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_FromFileCompressed<T>::fromFileCompressed() -> ") + bDeserializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  126. qAssert(bDeserializeOk);
  127. return bDeserializeOk;
  128. }
  129. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  130. QString QxArchive_ToString<T, ArchiveInput, ArchiveOutput>::toString(const T & obj, unsigned int flags /* = boost::archive::no_header */)
  131. {
  132. typedef typename qx::trait::archive_wide_traits<ArchiveOutput>::type_ostringstream qx_type_ostringstream;
  133. qx_type_ostringstream oss(std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
  134. ArchiveOutput oar(oss, flags);
  135. qx_bool bSerializeOk = false;
  136. const char * sTag = QxClassName<T>::get_xml_tag();
  137. QxBoostSerializeRegisterHelperX::helper(oar);
  138. try { oar << boost::serialization::make_nvp(sTag, obj); bSerializeOk = oss.good(); }
  139. catch (const boost::archive::archive_exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  140. catch (const std::exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  141. catch (...) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  142. if (! bSerializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_ToString<T>::toString() -> ") + bSerializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  143. qAssert(bSerializeOk);
  144. return (bSerializeOk ? qx::trait::archive_wide_traits<ArchiveOutput>::toQString(oss.str()) : QString());
  145. }
  146. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  147. qx_bool QxArchive_FromString<T, ArchiveInput, ArchiveOutput>::fromString(T & obj, const QString & sString, unsigned int flags /* = boost::archive::no_header */)
  148. {
  149. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_string qx_type_string;
  150. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_istringstream qx_type_istringstream;
  151. qx_type_string str;
  152. if (sString.isEmpty()) { return false; }
  153. qx::trait::archive_wide_traits<ArchiveInput>::fromQString(sString, str);
  154. qx_type_istringstream iss(str, (std::ios_base::binary | std::ios_base::in));
  155. ArchiveInput iar(iss, flags);
  156. qx_bool bDeserializeOk = false;
  157. const char * sTag = QxClassName<T>::get_xml_tag();
  158. QxBoostSerializeRegisterHelperX::helper(iar);
  159. try { iar >> boost::serialization::make_nvp(sTag, obj); bDeserializeOk = true; }
  160. catch (const boost::archive::archive_exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  161. catch (const std::exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  162. catch (...) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  163. if (! bDeserializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_FromString<T>::fromString() -> ") + bDeserializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  164. qAssert(bDeserializeOk);
  165. return bDeserializeOk;
  166. }
  167. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  168. QByteArray QxArchive_ToByteArray<T, ArchiveInput, ArchiveOutput>::toByteArray(const T & obj, type_string * owner /* = NULL */, unsigned int flags /* = boost::archive::no_header */)
  169. {
  170. typedef typename qx::trait::archive_wide_traits<ArchiveOutput>::type_ostringstream qx_type_ostringstream;
  171. qx_type_ostringstream oss(std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
  172. ArchiveOutput oar(oss, flags);
  173. qx_bool bSerializeOk = false;
  174. const char * sTag = QxClassName<T>::get_xml_tag();
  175. QxBoostSerializeRegisterHelperX::helper(oar);
  176. try { oar << boost::serialization::make_nvp(sTag, obj); bSerializeOk = oss.good(); }
  177. catch (const boost::archive::archive_exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  178. catch (const std::exception & e) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  179. catch (...) { bSerializeOk.setDesc(QString(QX_STR_SERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  180. if (! bSerializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_ToByteArray<T>::toByteArray() -> ") + bSerializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  181. qAssert(bSerializeOk);
  182. return (bSerializeOk ? qx::trait::archive_wide_traits<ArchiveOutput>::toQByteArray(oss.str(), owner) : QByteArray());
  183. }
  184. template <class T, class ArchiveInput /* = QX_DEFAULT_ARCHIVE_INPUT */, class ArchiveOutput /* = QX_DEFAULT_ARCHIVE_OUTPUT */>
  185. qx_bool QxArchive_FromByteArray<T, ArchiveInput, ArchiveOutput>::fromByteArray(T & obj, const QByteArray & data, unsigned int flags /* = boost::archive::no_header */)
  186. {
  187. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_string qx_type_string;
  188. typedef typename qx::trait::archive_wide_traits<ArchiveInput>::type_istringstream qx_type_istringstream;
  189. qx_type_string str;
  190. if (data.size() <= 0) { return false; }
  191. qx::trait::archive_wide_traits<ArchiveInput>::fromQByteArray(data, str);
  192. qx_type_istringstream iss(str, (std::ios_base::binary | std::ios_base::in));
  193. ArchiveInput iar(iss, flags);
  194. qx_bool bDeserializeOk = false;
  195. const char * sTag = QxClassName<T>::get_xml_tag();
  196. QxBoostSerializeRegisterHelperX::helper(iar);
  197. try { iar >> boost::serialization::make_nvp(sTag, obj); bDeserializeOk = true; }
  198. catch (const boost::archive::archive_exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  199. catch (const std::exception & e) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", e.what())); }
  200. catch (...) { bDeserializeOk.setDesc(QString(QX_STR_DESERIALIZATION_ERROR).replace("%ERR%", "unknown error")); }
  201. if (! bDeserializeOk.getDesc().isEmpty()) { QString sMsg = QString("qx::QxArchive_FromByteArray<T>::fromByteArray() -> ") + bDeserializeOk.getDesc(); qDebug("[QxOrm] %s", qPrintable(sMsg)); }
  202. qAssert(bDeserializeOk);
  203. return bDeserializeOk;
  204. }
  205. } // namespace qx
  206. #endif // _QX_ENABLE_BOOST_SERIALIZATION