basic_xml_oarchive.ipp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // basic_xml_oarchive.ipp:
  3. // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org for updates, documentation, and revision history.
  8. #include <algorithm>
  9. #include <cstddef> // NULL
  10. #include <cstring>
  11. #if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__)
  12. namespace std{
  13. using ::strlen;
  14. } // namespace std
  15. #endif
  16. #include <boost/archive/basic_xml_archive.hpp>
  17. #include <boost/archive/basic_xml_oarchive.hpp>
  18. #include <boost/archive/xml_archive_exception.hpp>
  19. #include <boost/detail/no_exceptions_support.hpp>
  20. namespace boost {
  21. namespace archive {
  22. namespace detail {
  23. template<class CharType>
  24. struct XML_name {
  25. void operator()(CharType t) const{
  26. const unsigned char lookup_table[] = {
  27. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  28. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  29. 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -.
  30. 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 0-9
  31. 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A-
  32. 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _
  33. 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a-
  34. 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // -z
  35. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  36. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  37. };
  38. if((unsigned)t > 127)
  39. return;
  40. if(0 == lookup_table[(unsigned)t])
  41. boost::serialization::throw_exception(
  42. xml_archive_exception(
  43. xml_archive_exception::xml_archive_tag_name_error
  44. )
  45. );
  46. }
  47. };
  48. } // namespace detail
  49. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  50. // implemenations of functions common to both types of xml output
  51. template<class Archive>
  52. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  53. basic_xml_oarchive<Archive>::write_attribute(
  54. const char *attribute_name,
  55. int t,
  56. const char *conjunction
  57. ){
  58. this->This()->put(' ');
  59. this->This()->put(attribute_name);
  60. this->This()->put(conjunction);
  61. this->This()->save(t);
  62. this->This()->put('"');
  63. }
  64. template<class Archive>
  65. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  66. basic_xml_oarchive<Archive>::write_attribute(
  67. const char *attribute_name,
  68. const char *key
  69. ){
  70. this->This()->put(' ');
  71. this->This()->put(attribute_name);
  72. this->This()->put("=\"");
  73. this->This()->save(key);
  74. this->This()->put('"');
  75. }
  76. template<class Archive>
  77. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  78. basic_xml_oarchive<Archive>::indent(){
  79. int i;
  80. for(i = depth; i-- > 0;)
  81. this->This()->put('\t');
  82. }
  83. template<class Archive>
  84. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  85. basic_xml_oarchive<Archive>::save_start(const char *name)
  86. {
  87. if(NULL == name)
  88. return;
  89. // be sure name has no invalid characters
  90. std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
  91. end_preamble();
  92. if(depth > 0){
  93. this->This()->put('\n');
  94. indent();
  95. }
  96. ++depth;
  97. this->This()->put('<');
  98. this->This()->save(name);
  99. pending_preamble = true;
  100. indent_next = false;
  101. }
  102. template<class Archive>
  103. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  104. basic_xml_oarchive<Archive>::save_end(const char *name)
  105. {
  106. if(NULL == name)
  107. return;
  108. // be sure name has no invalid characters
  109. std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
  110. end_preamble();
  111. --depth;
  112. if(indent_next){
  113. this->This()->put('\n');
  114. indent();
  115. }
  116. indent_next = true;
  117. this->This()->put("</");
  118. this->This()->save(name);
  119. this->This()->put('>');
  120. if(0 == depth)
  121. this->This()->put('\n');
  122. }
  123. template<class Archive>
  124. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  125. basic_xml_oarchive<Archive>::end_preamble(){
  126. if(pending_preamble){
  127. this->This()->put('>');
  128. pending_preamble = false;
  129. }
  130. }
  131. #if 0
  132. template<class Archive>
  133. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  134. basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int)
  135. {
  136. int i = t.t; // extra .t is for borland
  137. write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_");
  138. }
  139. template<class Archive>
  140. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  141. basic_xml_oarchive<Archive>::save_override(
  142. const object_reference_type & t,
  143. int
  144. ){
  145. int i = t.t; // extra .t is for borland
  146. write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_");
  147. }
  148. template<class Archive>
  149. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  150. basic_xml_oarchive<Archive>::save_override(const version_type & t, int)
  151. {
  152. int i = t.t; // extra .t is for borland
  153. write_attribute(BOOST_ARCHIVE_XML_VERSION(), i);
  154. }
  155. #endif
  156. template<class Archive>
  157. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  158. basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int)
  159. {
  160. // borland doesn't do conversion of STRONG_TYPEDEFs very well
  161. const unsigned int i = t;
  162. write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_");
  163. }
  164. template<class Archive>
  165. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  166. basic_xml_oarchive<Archive>::save_override(
  167. const object_reference_type & t,
  168. int
  169. ){
  170. const unsigned int i = t;
  171. write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_");
  172. }
  173. template<class Archive>
  174. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  175. basic_xml_oarchive<Archive>::save_override(const version_type & t, int)
  176. {
  177. const unsigned int i = t;
  178. write_attribute(BOOST_ARCHIVE_XML_VERSION(), i);
  179. }
  180. template<class Archive>
  181. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  182. basic_xml_oarchive<Archive>::save_override(const class_id_type & t, int)
  183. {
  184. write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t);
  185. }
  186. template<class Archive>
  187. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  188. basic_xml_oarchive<Archive>::save_override(
  189. const class_id_reference_type & t,
  190. int
  191. ){
  192. write_attribute(BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(), t);
  193. }
  194. template<class Archive>
  195. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  196. basic_xml_oarchive<Archive>::save_override(
  197. const class_id_optional_type & t,
  198. int
  199. ){
  200. write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t);
  201. }
  202. template<class Archive>
  203. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  204. basic_xml_oarchive<Archive>::save_override(const class_name_type & t, int)
  205. {
  206. const char * key = t;
  207. if(NULL == key)
  208. return;
  209. write_attribute(BOOST_ARCHIVE_XML_CLASS_NAME(), key);
  210. }
  211. template<class Archive>
  212. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  213. basic_xml_oarchive<Archive>::save_override(const tracking_type & t, int)
  214. {
  215. write_attribute(BOOST_ARCHIVE_XML_TRACKING(), t.t);
  216. }
  217. template<class Archive>
  218. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  219. basic_xml_oarchive<Archive>::init(){
  220. // xml header
  221. this->This()->put("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n");
  222. this->This()->put("<!DOCTYPE boost_serialization>\n");
  223. // xml document wrapper - outer root
  224. this->This()->put("<boost_serialization");
  225. write_attribute("signature", BOOST_ARCHIVE_SIGNATURE());
  226. write_attribute("version", BOOST_ARCHIVE_VERSION());
  227. this->This()->put(">\n");
  228. }
  229. template<class Archive>
  230. BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
  231. basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) :
  232. detail::common_oarchive<Archive>(flags),
  233. depth(0),
  234. indent_next(false),
  235. pending_preamble(false)
  236. {
  237. }
  238. template<class Archive>
  239. BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
  240. basic_xml_oarchive<Archive>::~basic_xml_oarchive(){
  241. if(0 == (this->get_flags() & no_header)){
  242. BOOST_TRY{
  243. this->This()->put("</boost_serialization>\n");
  244. }
  245. BOOST_CATCH(...){}
  246. BOOST_CATCH_END
  247. }
  248. }
  249. } // namespace archive
  250. } // namespace boost