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

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

Fixed problem with log singleton (there were 2 of 'em!)

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                        else
214                        {
215                                foreach(std::string elem, location)
216                                {
217                                        TXML_LOG(boost::wformat(L" >> >> %1%") % from_utf8(elem));
218
219                                        if (elem == ".")
220                                        {}
221                                        else if (elem == "..")
222                                        {
223                                                failsafe_current = failsafe_current->parent();
224                                        }
225                                        else
226                                        {
227                                                failsafe_current = failsafe_current->first_child(elem);
228                                               
229                                                if (!failsafe_current) return false;
230                                        }
231                                }
232                        }
233
234                //      xml::node* n = new xml::element(leaf);                 
235
236                        if (!failsafe_current) 
237                                return false;
238                        else
239                        {
240                                current_node_ = failsafe_current;
241
242                                previous_child_branch_ = location.branch_path();
243                        }
244                }
245                return true;
246        }
247   
248    void load_end(const char *name)
249        {
250                if (name)
251                {
252                        TXML_LOG(boost::wformat(L" << load_end: %1%") % from_utf8(name));
253
254                        previous_child_node_ = current_node_;
255
256                        current_node_ = node_stack_.top();
257                        node_stack_.pop();
258                }
259        }
260
261        // Anything not an attribute and not a name-value pair is an
262    // error and should be trapped here.
263    template<class T>
264    void load_override(T & t, BOOST_PFTO int)
265    {
266                BOOST_MPL_ASSERT((boost::serialization::is_wrapper<T>));
267
268        this->detail_common_iarchive::load_override(t, 0);
269        // If your program fails to compile here, its most likely due to
270        // not specifying an nvp wrapper around the variable to
271        // be serialized.
272    }
273
274        // special treatment for name-value pairs.
275    template<class T>
276    void load_override(const ::boost::serialization::nvp<T>& t, int)
277        {
278                TXML_LOG(boost::wformat(L" << loading: %1%") % t.name());
279
280                if (load_start(t.name()))
281                {
282                        this->detail_common_iarchive::load_override(t.value(), 0);
283                        load_end(t.name());
284                }
285                else
286                        TXML_LOG(boost::wformat(L" << load_aborted: %1%") % t.name());
287    }
288
289        // specific overrides for attributes - not name value pairs so we
290    // want to trap them before the above "fall through"
291        void load_override(arc::class_id_optional_type&, int)
292        {}
293
294        void load_override(arc::object_id_type& t, int)
295        { 
296                t = read_attribute<arc::object_id_type>(arc::OBJECT_ID(), arc::OBJECT_REFERENCE());             
297        }
298   
299        void load_override(arc::version_type& t, int)
300        { 
301                t = read_attribute<arc::version_type>(arc::VERSION());
302        }
303   
304        void load_override(arc::class_id_type& t, int)
305        { 
306                t = read_attribute<arc::class_id_type>(arc::CLASS_ID(), arc::CLASS_ID_REFERENCE());
307        }
308   
309        void load_override(arc::tracking_type& t, int)
310        { 
311                t = read_attribute<arc::tracking_type>(arc::TRACKING()); 
312        }
313
314        xml::document xml_;
315
316        xml::node* current_node_;
317        xml::node* previous_child_node_;
318        boost::filesystem::path previous_child_branch_;
319
320        std::stack<xml::node*> node_stack_;
321
322        std::istream& is_;
323};
324
325} }
326
327//BOOST_SERIALIZATION_REGISTER_ARCHIVE(xml::txml_iarchive)
Note: See TracBrowser for help on using the repository browser.