source: trunk/src/global/txml_oarchive.hpp @ 573

Revision 573, 8.3 KB checked in by Eoin, 11 years ago (diff)

Disabled libtorrent and serialization warnings over which I've no control.

Line 
1
2#pragma once
3
4#include <stack>
5
6#include <boost/mpl/assert.hpp>
7#include <boost/format.hpp>
8#include <boost/lexical_cast.hpp>
9#include <boost/filesystem/path.hpp>
10
11//#include <boost/archive/xml_oarchive.hpp>
12
13#pragma warning (push)
14#pragma warning (disable : 4099)
15#       include <boost/serialization/version.hpp>
16#       include <boost/serialization/vector.hpp>
17#       include <boost/serialization/map.hpp>
18#       include <boost/serialization/split_free.hpp>
19
20#       include <boost/archive/impl/basic_text_oprimitive.ipp>
21#       include <boost/archive/impl/xml_oarchive_impl.ipp>
22#       include <boost/archive/impl/basic_xml_oarchive.ipp>
23#       include <boost/archive/impl/archive_pointer_oserializer.ipp>
24#pragma warning (pop)
25
26#include "global/string_conv.hpp"
27#include "txml.hpp"
28
29#define foreach BOOST_FOREACH
30
31#ifndef TXML_ARCHIVE_LOGGING
32#       define TXML_LOG(s)
33#else
34#       include "../halEvent.hpp"
35#       define TXML_LOG(msg) \
36        hal::event_log.post(boost::shared_ptr<hal::EventDetail>( \
37                        new hal::EventMsg(msg, hal::event_logger::xml_dev)))
38#endif
39
40namespace 
41{
42
43struct o_stringstream_holder
44{
45        std::stringstream stream_ ;
46};
47
48}
49
50namespace hal { namespace xml
51{
52
53namespace serial = boost::serialization;
54namespace arc = boost::archive;
55
56class txml_oarchive : 
57        private o_stringstream_holder,
58        public arc::basic_text_oprimitive<std::ostream>,
59        public arc::detail::common_oarchive<txml_oarchive>
60{
61        typedef arc::detail::common_oarchive<txml_oarchive> detail_common_oarchive;
62
63public:
64
65    txml_oarchive(std::ostream& os, unsigned int flags = 0) :
66                basic_text_oprimitive<std::ostream>(stream_, 0 != (flags & arc::no_codecvt)),
67                common_oarchive(flags),
68                os_(os),
69                current_node_(0)
70    {
71                xml_.link_end_child(new xml::declaration("1.0", "", "")); 
72               
73                if (!current_node_)
74                {
75                        current_node_ = new xml::element("serial");
76                        xml_.link_end_child(current_node_);
77                }
78
79                if(0 == (flags & arc::no_header))
80                        init();
81        }
82
83    ~txml_oarchive()
84        {
85#ifdef TXML_ARCHIVE_LOGGING
86                xml_.save_file("debug.xml");
87#endif
88                os_ << xml_;
89        }
90
91    template<class T>
92    void save(const T & t)
93        {
94                basic_text_oprimitive<std::ostream>::save(t);
95        }
96           
97        void save(const char *  s)
98        {
99                typedef boost::archive::iterators::xml_escape<
100                        const char * 
101                > xml_escape_translator;
102                std::copy(
103                        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s)),
104                        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s + std::strlen(s))), 
105                        boost::archive::iterators::ostream_iterator<char>(os)
106                );
107        }
108
109    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
110    void save(const wchar_t* ws)
111        {
112                arc::save_iterator(os, ws, ws + std::wcslen(ws));
113        }
114    #endif
115
116    void save(const std::string &s)
117        {
118        //  at least one library doesn't typedef value_type for strings
119        //  so rather than using string directly make a pointer iterator out of it
120                typedef boost::archive::iterators::xml_escape<
121                        const char * 
122                > xml_escape_translator;
123                std::copy(
124                        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data())),
125                        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data()+ s.size())), 
126                        boost::archive::iterators::ostream_iterator<char>(os)
127                );
128        }
129
130    #ifndef BOOST_NO_STD_WSTRING
131    void save(const std::wstring &ws)
132        {
133        //  at least one library doesn't typedef value_type for strings
134        //  so rather than using string directly make a pointer iterator out of it
135        //    save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data()));
136        //              arc::save_iterator(os, ws.data(), ws.data() + ws.size());
137                        os << to_utf8(ws);
138        }
139    #endif
140
141    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
142
143    void save_binary(const void *address, std::size_t count)
144        {
145        this->end_preamble();
146        this->basic_text_oprimitive<std::ostream>::save_binary(
147            address, 
148            count
149        );
150        //this->indent_next = true;
151    }
152
153    void write_attribute(
154        const char *attribute_name,
155        int t,
156        const char *conjunction = 0)
157        { 
158                assert(attribute_name);
159
160                xml::element* e = dynamic_cast<xml::element*>(current_node_);
161
162                if (true || !conjunction)
163                {
164                        e->set_attribute(attribute_name, t);
165
166                        TXML_LOG(boost::wformat(L" >> write_attribute: %1%, t:%2%") % attribute_name % t);
167                }
168                else
169                {
170                        std::string attr = conjunction;
171                        attr += boost::lexical_cast<std::string>(t);
172                        e->set_attribute(attribute_name, attr);
173                       
174                        TXML_LOG(boost::wformat(L" >> write_attribute: %1%, t:%2%") % attribute_name % from_utf8(attr));
175                }
176        }       
177
178    void write_attribute(const char *attribute_name, const char *key)
179        {
180                assert(attribute_name);
181                assert(key);
182
183                xml::element* e = dynamic_cast<xml::element*>(current_node_);
184                e->set_attribute(attribute_name, key);
185
186                TXML_LOG(boost::wformat(L" >> write_attribute: %1%, key:%2%") % attribute_name % key);
187        }
188
189    void save_start(const char *name)
190        {
191                if (name)
192                {
193                        TXML_LOG(boost::wformat(L" >> save_start: %1%") % name);
194                        node_stack_.push(current_node_);
195
196                        boost::filesystem::path branch(name);
197
198                        std::string leaf = branch.filename();
199                        branch = branch.parent_path();
200
201                        foreach(std::string elem, branch)
202                        {
203                                TXML_LOG(boost::wformat(L" >> >> %1%") % from_utf8(elem));
204
205                                if (elem == ".")
206                                {}
207                                else if (elem == "..")
208                                {
209                                        current_node_ = current_node_->parent();
210                                }
211                                else
212                                {
213                                        xml::node* child_node = current_node_->first_child(elem);
214                                       
215                                        if (!child_node)
216                                        {
217                                                child_node = new xml::element(elem);
218                                                current_node_->link_end_child(child_node);
219                                        }
220                                       
221                                        current_node_ = child_node;
222                                }
223                        }
224
225                        xml::node* n = new xml::element(leaf);
226                        current_node_ = current_node_->link_end_child(n);
227
228                        stream_.str("");
229                }
230        }
231   
232    void save_end(const char *name)
233        {
234                if (name)
235                {
236                        assert(!node_stack_.empty());
237
238                        std::string s = stream_.str();
239
240                        TXML_LOG(boost::wformat(L" >> stringstream: %1%") % from_utf8(s));
241                        xml::text* t = new xml::text(s);
242
243                        current_node_->link_end_child(t);
244
245                        stream_.str("");
246                        stream_ << std::noboolalpha;
247
248                        TXML_LOG(boost::wformat(L" >> save_end: %1%") % name);
249
250                        current_node_ = node_stack_.top();
251                        node_stack_.pop();
252                }               
253        }
254
255        // Anything not an attribute and not a name-value pair is an
256    // error and should be trapped here.
257    template<class T>
258    void save_override(T & t, BOOST_PFTO int)
259    {
260        BOOST_MPL_ASSERT((::boost::serialization::is_wrapper<T>));
261
262        this->detail_common_oarchive::save_override(t, 0);
263        // If your program fails to compile here, its most likely due to
264        // not specifying an nvp wrapper around the variable to
265        // be serialized.
266    }
267
268   // special treatment for name-value pairs.
269
270    template<class T>
271    void save_override( const ::boost::serialization::nvp<T> & t, int)
272    {
273                save_start(t.name());
274                this->detail_common_oarchive::save_override(t.const_value(), 0);
275        save_end(t.name());
276    }
277
278        void init()
279        {
280                // xml header
281                write_attribute("signature", arc::ARCHIVE_SIGNATURE());
282                write_attribute("version", arc::ARCHIVE_VERSION());
283        }
284
285        // specific overrides for attributes - not name value pairs so we
286    // want to trap them before the above "fall through"
287
288        void save_override(const arc::object_id_type & t, int i)
289        { 
290                write_attribute(arc::OBJECT_ID(), t);
291        }
292
293    void save_override(const arc::object_reference_type & t, int)
294        {
295                write_attribute(arc::OBJECT_REFERENCE(), t);
296        }
297   
298        void save_override(const arc::version_type & t, int i)
299        { 
300                write_attribute(arc::VERSION(), t);
301        }
302   
303        void save_override(const arc::class_id_type & t, int i)
304        { 
305                write_attribute(arc::CLASS_ID(), t);
306        }
307   
308        void save_override(const arc::class_id_optional_type & t, int i)
309        { 
310                write_attribute(arc::CLASS_ID(), t); 
311        }
312   
313        void save_override(const arc::class_id_reference_type & t, int i)
314        { 
315                write_attribute(arc::CLASS_ID_REFERENCE(), t); 
316        }
317   
318        void save_override(const arc::class_name_type & t, int i)
319        { 
320                const char * key = t;
321                if(NULL == key)
322                        return;
323
324                write_attribute(arc::CLASS_NAME(), key);
325        }
326   
327        void save_override(const arc::tracking_type & t, int i)
328        { 
329                write_attribute(arc::TRACKING(), t.t); 
330        }
331
332        xml::document xml_;
333        xml::node* current_node_;
334        std::stack<xml::node*> node_stack_;
335
336        std::ostream& os_;
337};
338
339} }
340
341//BOOST_SERIALIZATION_REGISTER_ARCHIVE(xml::txml_oarchive)
Note: See TracBrowser for help on using the repository browser.