source: trunk/src/global/txml_iarchive.hpp @ 780

Revision 780, 9.8 KB checked in by Eoin, 10 years ago (diff)

Archive supports Boost .40. Some 64bit casts added.

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#include <boost/filesystem/operations.hpp>
11
12//#include <boost/archive/xml_iarchive.hpp>
13
14#pragma warning (push)
15#pragma warning (disable : 4099)
16#pragma warning (disable : 4267)
17#       include <boost/serialization/version.hpp>
18#       include <boost/serialization/vector.hpp>
19#       include <boost/serialization/map.hpp>
20#       include <boost/serialization/split_free.hpp>
21
22#       include <boost/archive/impl/basic_text_iprimitive.ipp>
23#       include <boost/archive/impl/xml_iarchive_impl.ipp>
24//#     include <boost/archive/impl/basic_xml_iarchive.ipp>
25#       include <boost/archive/impl/archive_serializer_map.ipp>
26#       include <boost/archive/shared_ptr_helper.hpp>
27#pragma warning (pop)
28
29#include "global/string_conv.hpp"
30#include "txml.hpp"
31
32#define foreach BOOST_FOREACH
33
34#ifndef TXML_ARCHIVE_LOGGING
35#       define TXML_LOG(s)
36#else
37#       include "../halEvent.hpp"
38#       define TXML_LOG(msg) \
39        hal::event_log().post(boost::shared_ptr<hal::EventDetail>( \
40                        new hal::EventMsg(msg, hal::event_logger::xml_dev)))
41#endif
42
43namespace 
44{
45
46struct i_stringstream_holder
47{
48        std::stringstream stream_;
49};
50
51}
52
53namespace hal { namespace xml
54{
55
56namespace serial = boost::serialization;
57namespace arc = boost::archive;
58
59class txml_iarchive : 
60        private i_stringstream_holder,
61        public arc::basic_text_iprimitive<std::istream>,
62        public arc::detail::common_iarchive<txml_iarchive>,
63        public boost::archive::detail::shared_ptr_helper
64{
65        typedef arc::detail::common_iarchive<txml_iarchive> detail_common_iarchive;
66
67public:
68    txml_iarchive(std::istream& is, unsigned int flags = 0) :
69                basic_text_iprimitive<std::istream>(stream_, 0 != (flags & arc::no_codecvt)),
70                detail_common_iarchive(flags),
71                boost_xml_compat_(false),
72                is_(is),               
73                previous_child_node_(0)
74    {
75                is_ >> xml_;
76
77                current_node_ = xml_.root_element();
78                init();
79        }
80
81    ~txml_iarchive()
82        {}
83           
84        template<class T>
85    void load(T& t)
86        {
87                std::string tstring = current_node_->first_child()->value_str();
88
89                TXML_LOG(boost::wformat(L" << basic_text_iprimitive: %1%") % from_utf8(tstring));
90
91                stream_ << tstring;
92        basic_text_iprimitive<std::istream>::load(t);
93
94                stream_.clear();
95                stream_ << std::noboolalpha;
96    }
97
98/*      void load(char* s)
99        {
100                std::string tstring = current_node_->first_child()->value_str();
101
102                std::memcpy(s, tstring.data(), tstring.size());
103                s[tstring.size()] = 0;
104                TXML_LOG(boost::wformat(L" << load char*: %1%") % from_utf8(tstring));
105        }
106
107        void load(wchar_t* t)
108        {
109                TXML_LOG(boost::wformat(L" << load wchar_t*: %1%") % from_utf8(current_node_->first_child()->value_str());
110        }
111*/
112        void load(std::string& s) 
113        {               
114                if (xml::node* child = current_node_->first_child())
115                        s = child->value_str();
116                else
117                        s = "";
118
119                TXML_LOG(boost::wformat(L" << load string: %1%") % from_utf8(s));
120        }
121
122        void load(std::wstring& ws) 
123        {
124                if (xml::node* child = current_node_->first_child())
125                        ws = from_utf8(child->value_str());
126                else
127                        ws = L"";
128
129                TXML_LOG(boost::wformat(L" << load wstring: %1%") % ws);
130        }
131
132        void load_override(arc::class_name_type& t, int) 
133        {   
134                std::string tstring = current_node_->first_child()->value_str();
135
136                TXML_LOG(boost::wformat(L" << load class_name_type: %1%") % from_utf8(tstring));
137
138                char * tptr = t;
139                std::memcpy(tptr, tstring.data(), tstring.size());
140                tptr[tstring.size()] = '\0';
141        }
142
143        void init() 
144        {
145                if (current_node_)
146                {
147                        boost_xml_compat_ = (current_node_->value_str() == "boost_serialization");
148                        TXML_LOG(boost::wformat(L" << boost_serialization compatibility %1%") % (boost_xml_compat_ ? "on" : "off"));
149
150                        std::string signature = read_attribute<std::string>("signature");
151                        int version = read_attribute<int>("version");
152
153                        TXML_LOG(boost::wformat(L" << siganture: %1%, version: %2%") % from_utf8(signature) % version);
154                }
155        }
156
157        template<typename T>
158        T read_attribute(const char* attribute_name, const char* fallback_name=0)
159        {
160                T type = T();
161
162                TXML_LOG(boost::wformat(L" << attribute_name: %1%") % from_utf8(attribute_name));
163
164                xml::element* e = current_node_->to_element();
165                if (!e) return type;
166
167                int result = e->query_value_attribute(attribute_name, &type);
168
169                if (result == xml::TIXML_NO_ATTRIBUTE && fallback_name != 0)
170                {
171                        TXML_LOG(boost::wformat(L" << -- fallback_name: %1%") % from_utf8(fallback_name));
172
173                        result = e->query_value_attribute(fallback_name, &type);
174                }
175
176                assert(result == xml::TIXML_SUCCESS);
177                TXML_LOG(boost::wformat(L" << -- value: %2%") % from_utf8(attribute_name) % type);
178               
179                return type;
180        }       
181
182        template<>
183        std::string read_attribute(const char* attribute_name, const char* fallback_name)
184        {
185                std::string type;
186
187                TXML_LOG(boost::wformat(L" << attribute_name: %1%") % from_utf8(attribute_name));
188
189                xml::element* e = current_node_->to_element();
190                if (!e) return type;
191
192                int result = e->query_value_attribute(attribute_name, &type);
193
194                if (result == xml::TIXML_NO_ATTRIBUTE && fallback_name != 0)
195                {
196                        TXML_LOG(boost::wformat(L" << -- fallback_name: %1%") % from_utf8(fallback_name));
197
198                        result = e->query_value_attribute(fallback_name, &type);
199                }
200
201                assert(result == xml::TIXML_SUCCESS);
202
203                TXML_LOG(boost::wformat(L" << -- value: %2%") % from_utf8(attribute_name) % from_utf8(type));
204
205                return type;
206        }       
207
208    bool load_start(const char* name)
209        {
210                if (name)
211                {
212                        TXML_LOG(boost::wformat(L" << load_start: %1%") % from_utf8(name));
213
214                        xml::node* failsafe_current = current_node_;
215
216                        boost::filesystem::path location(name);
217
218                        if (previous_child_node_ &&
219                                        previous_child_branch_ == location.parent_path())
220                        {
221                        //      TXML_LOG(boost::wformat(L" << previous_child: %1%") % previous_child_node_->to_element()->get_text());
222                                failsafe_current = previous_child_node_->next_sibling(location.filename());
223                                previous_child_node_ = 0;
224                               
225                                if (!failsafe_current) 
226                                        failsafe_current = current_node_->first_child(location.filename());;
227                        }
228                        else
229                        {
230                                foreach(std::string elem, location)
231                                {
232                                        TXML_LOG(boost::wformat(L" >> >> %1%") % from_utf8(elem));
233
234                                        if (elem == ".")
235                                        {}
236                                        else if (elem == "..")
237                                        {
238                                                failsafe_current = failsafe_current->parent();
239                                        }
240                                        else
241                                        {
242                                                failsafe_current = failsafe_current->first_child(elem);
243                                               
244                                                if (!failsafe_current) return false;
245                                        }
246                                }
247                        }
248
249                //      xml::node* n = new xml::element(leaf);                 
250
251                        if (!failsafe_current) 
252                                return false;
253                        else
254                        {
255                                current_node_ = failsafe_current;
256
257                                previous_child_branch_ = location.parent_path();
258                        }
259                }
260                return true;
261        }
262   
263    void load_end(const char *name)
264        {
265                if (name)
266                {
267                        TXML_LOG(boost::wformat(L" << load_end: %1%") % from_utf8(name));
268
269                        previous_child_node_ = current_node_;
270                }
271        }
272
273        // Anything not an attribute and not a name-value pair is an
274    // error and should be trapped here.
275    template<class T>
276    void load_override(T & t, BOOST_PFTO int)
277    {
278                BOOST_MPL_ASSERT((boost::serialization::is_wrapper<T>));
279
280        this->detail_common_iarchive::load_override(t, 0);
281        // If your program fails to compile here, its most likely due to
282        // not specifying an nvp wrapper around the variable to
283        // be serialized.
284    }
285
286        // special treatment for name-value pairs.
287    template<class T>
288    void load_override(const ::boost::serialization::nvp<T>& t, int)
289        {
290                node_stack_.push(current_node_);
291
292                if (t.name()) 
293                {
294                        TXML_LOG(boost::wformat(L" << loading: %1%") % t.name());
295                }
296
297                if (current_node_ && load_start(t.name()))
298                {
299                        this->detail_common_iarchive::load_override(t.value(), 0);
300                        load_end(t.name());
301                }
302                else
303                        TXML_LOG(boost::wformat(L" << load_aborted: %1%") % t.name());
304
305                current_node_ = node_stack_.top();
306                node_stack_.pop();
307    }
308
309        // specific overrides for attributes - not name value pairs so we
310    // want to trap them before the above "fall through"
311        void load_override(arc::class_id_optional_type&, int)
312        {}
313
314        void load_override(arc::object_id_type& t, int)
315        { 
316                if (boost_xml_compat_)
317                {
318#if BOOST_VERSION < 103700
319                        std::string id = read_attribute<std::string>(arc::OBJECT_ID(), arc::OBJECT_REFERENCE());
320#else
321                        std::string id = read_attribute<std::string>(arc::BOOST_ARCHIVE_XML_OBJECT_ID(), arc::BOOST_ARCHIVE_XML_OBJECT_REFERENCE());
322#endif
323
324                        t = boost::lexical_cast<int>(id.substr(1));
325                }
326                else
327#if BOOST_VERSION < 103700
328                        t = read_attribute<arc::object_id_type>(arc::OBJECT_ID(), arc::OBJECT_REFERENCE());     
329#else
330                        t = read_attribute<arc::object_id_type>(arc::BOOST_ARCHIVE_XML_OBJECT_ID(), arc::BOOST_ARCHIVE_XML_OBJECT_REFERENCE()); 
331#endif
332        }
333   
334        void load_override(arc::version_type& t, int)
335        { 
336#if BOOST_VERSION < 103700
337                t = read_attribute<arc::version_type>(arc::VERSION());
338#else
339                t = read_attribute<arc::version_type>(arc::BOOST_ARCHIVE_XML_VERSION());
340#endif
341        }
342   
343        void load_override(arc::class_id_type& t, int)
344        { 
345#if BOOST_VERSION < 103700
346                t = read_attribute<arc::class_id_type>(arc::CLASS_ID(), arc::CLASS_ID_REFERENCE());
347#else
348                t = read_attribute<arc::class_id_type>(arc::BOOST_ARCHIVE_XML_CLASS_ID(), arc::BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE());
349#endif
350        }
351   
352        void load_override(arc::tracking_type& t, int)
353        { 
354#if BOOST_VERSION < 103700
355                t = read_attribute<arc::tracking_type>(arc::TRACKING()); 
356#else
357                t = read_attribute<arc::tracking_type>(arc::BOOST_ARCHIVE_XML_TRACKING()); 
358#endif
359        }
360
361        bool boost_xml_compat_;
362
363        xml::document xml_;
364
365        xml::node* current_node_;
366        xml::node* previous_child_node_;
367        boost::filesystem::path previous_child_branch_;
368
369        std::stack<xml::node*> node_stack_;
370
371        std::istream& is_;
372};
373
374} }
375
376//BOOST_SERIALIZATION_REGISTER_ARCHIVE(xml::txml_iarchive)
Note: See TracBrowser for help on using the repository browser.