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

Revision 541, 8.4 KB checked in by Eoin, 11 years ago (diff)

Updating halConfig 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                std::string signature = read_attribute<std::string>("signature");
141                int version = read_attribute<int>("version");
142
143                TXML_LOG(boost::wformat(L" << siganture: %1%, version: %2%") % from_utf8(signature) % version);
144        }
145
146        template<typename T>
147        T read_attribute(const char* attribute_name, const char* fallback_name=0)
148        {
149                T type;
150
151                TXML_LOG(boost::wformat(L" << attribute_name: %1%") % from_utf8(attribute_name));
152
153                xml::element* e = current_node_->to_element();
154                int result = e->query_value_attribute(attribute_name, &type);
155
156                if (result == xml::TIXML_NO_ATTRIBUTE && fallback_name != 0)
157                {
158                        TXML_LOG(boost::wformat(L" << -- fallback_name: %1%") % from_utf8(fallback_name));
159
160                        result = e->query_value_attribute(fallback_name, &type);
161                }
162
163                assert(result == xml::TIXML_SUCCESS);
164                TXML_LOG(boost::wformat(L" << -- value: %2%") % from_utf8(attribute_name) % type);
165               
166                return type;
167        }       
168
169        template<>
170        std::string read_attribute(const char* attribute_name, const char* fallback_name)
171        {
172                std::string type;
173
174                TXML_LOG(boost::wformat(L" << attribute_name: %1%") % from_utf8(attribute_name));
175
176                xml::element* e = current_node_->to_element();
177                int result = e->query_value_attribute(attribute_name, &type);
178
179                if (result == xml::TIXML_NO_ATTRIBUTE && fallback_name != 0)
180                {
181                        TXML_LOG(boost::wformat(L" << -- fallback_name: %1%") % from_utf8(fallback_name));
182
183                        result = e->query_value_attribute(fallback_name, &type);
184                }
185
186                assert(result == xml::TIXML_SUCCESS);
187
188                TXML_LOG(boost::wformat(L" << -- value: %2%") % from_utf8(attribute_name) % from_utf8(type));
189
190                return type;
191        }       
192
193    bool load_start(const char* name)
194        {
195                if (name)
196                {
197                        xml::node* failsafe_current = 0;
198
199                        TXML_LOG(boost::wformat(L" << load_start: %1%") % from_utf8(name));
200
201                        node_stack_.push(current_node_);
202                        failsafe_current = current_node_;
203
204                        boost::filesystem::path location(name);
205
206                        if (previous_child_node_ &&
207                                        previous_child_branch_ == location.branch_path())
208                        {
209                        //      TXML_LOG(boost::wformat(L" << previous_child: %1%") % previous_child_node_->to_element()->get_text());
210                                failsafe_current = previous_child_node_->next_sibling(location.leaf());
211                                previous_child_node_ = 0;
212                               
213                                if (!failsafe_current) 
214                                        failsafe_current = current_node_->first_child(location.leaf());;
215                        }
216                        else
217                        {
218                                foreach(std::string elem, location)
219                                {
220                                        TXML_LOG(boost::wformat(L" >> >> %1%") % from_utf8(elem));
221
222                                        if (elem == ".")
223                                        {}
224                                        else if (elem == "..")
225                                        {
226                                                failsafe_current = failsafe_current->parent();
227                                        }
228                                        else
229                                        {
230                                                failsafe_current = failsafe_current->first_child(elem);
231                                               
232                                                if (!failsafe_current) return false;
233                                        }
234                                }
235                        }
236
237                //      xml::node* n = new xml::element(leaf);                 
238
239                        if (!failsafe_current) 
240                                return false;
241                        else
242                        {
243                                current_node_ = failsafe_current;
244
245                                previous_child_branch_ = location.branch_path();
246                        }
247                }
248                return true;
249        }
250   
251    void load_end(const char *name)
252        {
253                if (name)
254                {
255                        TXML_LOG(boost::wformat(L" << load_end: %1%") % from_utf8(name));
256
257                        previous_child_node_ = current_node_;
258
259                        current_node_ = node_stack_.top();
260                        node_stack_.pop();
261                }
262        }
263
264        // Anything not an attribute and not a name-value pair is an
265    // error and should be trapped here.
266    template<class T>
267    void load_override(T & t, BOOST_PFTO int)
268    {
269                BOOST_MPL_ASSERT((boost::serialization::is_wrapper<T>));
270
271        this->detail_common_iarchive::load_override(t, 0);
272        // If your program fails to compile here, its most likely due to
273        // not specifying an nvp wrapper around the variable to
274        // be serialized.
275    }
276
277        // special treatment for name-value pairs.
278    template<class T>
279    void load_override(const ::boost::serialization::nvp<T>& t, int)
280        {
281                TXML_LOG(boost::wformat(L" << loading: %1%") % t.name());
282
283                if (load_start(t.name()))
284                {
285                        this->detail_common_iarchive::load_override(t.value(), 0);
286                        load_end(t.name());
287                }
288                else
289                        TXML_LOG(boost::wformat(L" << load_aborted: %1%") % t.name());
290    }
291
292        // specific overrides for attributes - not name value pairs so we
293    // want to trap them before the above "fall through"
294        void load_override(arc::class_id_optional_type&, int)
295        {}
296
297        void load_override(arc::object_id_type& t, int)
298        { 
299                t = read_attribute<arc::object_id_type>(arc::OBJECT_ID(), arc::OBJECT_REFERENCE());             
300        }
301   
302        void load_override(arc::version_type& t, int)
303        { 
304                t = read_attribute<arc::version_type>(arc::VERSION());
305        }
306   
307        void load_override(arc::class_id_type& t, int)
308        { 
309                t = read_attribute<arc::class_id_type>(arc::CLASS_ID(), arc::CLASS_ID_REFERENCE());
310        }
311   
312        void load_override(arc::tracking_type& t, int)
313        { 
314                t = read_attribute<arc::tracking_type>(arc::TRACKING()); 
315        }
316
317        xml::document xml_;
318
319        xml::node* current_node_;
320        xml::node* previous_child_node_;
321        boost::filesystem::path previous_child_branch_;
322
323        std::stack<xml::node*> node_stack_;
324
325        std::istream& is_;
326};
327
328} }
329
330//BOOST_SERIALIZATION_REGISTER_ARCHIVE(xml::txml_iarchive)
Note: See TracBrowser for help on using the repository browser.