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

Revision 542, 8.5 KB checked in by Eoin, 12 years ago (diff)

Updating HaliteWindow? serialization.

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