FotoSHOCK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
Serialization_internal.hpp
1 /*
2  * Copyright 2012 Lukas Jirkovsky
3  *
4  * This file is part of FotoSHOCKcore.
5  *
6  * FotoSHOCKcore is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, version 3 of the License.
9  *
10  * FotoSHOCKcore is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with FotoSHOCKcore. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef SERIALIZETION_INTERNAL_H
20 #define SERIALIZETION_INTERNAL_H
21 
22 #include <cstring>
23 #include <sstream>
24 #include <cstddef>
25 #include <cassert>
26 #include <stdint.h>
27 #include <arpa/inet.h>
28 #include <boost/type_traits/is_fundamental.hpp>
29 
30 #include "XML.hpp"
31 
32 namespace FotoSHOCKcore {
33 
35 namespace Serialization_internal {
36 
38  template <typename T>
39  class HasSerialize {
40  private:
41  typedef char yes[1];
42  typedef char no[2];
43 
44  template <typename U, U> struct type_check;
45  template <typename C> static yes& test(type_check<xmlNodePtr(T::*)() const, &C::serialize>*);
46  template <typename C> static no& test(...);
47  public:
48  static const bool value = sizeof(test<T>(0)) == sizeof(yes);
49  };
50 
51  template<bool T>
53  public:
54  template<typename C>
55  static xmlNodePtr serialize(C /*value*/) {
56  // TODO: replace by static assert after move to C++11
57  assert("Type doesn't provide the required serialize() function");
58  return NULL;
59  }
60 
61  template<typename C>
62  static C deserialize(const xmlNodePtr /*value*/) {
63  // TODO: replace by static assert after move to C++11
64  assert("Type doesn't provide the required deserialize() function");
65  return C();
66  }
67  };
68 
69  template<>
70  struct CompoundTypeSerializer<true> {
71  public:
72  template<typename T>
73  static xmlNodePtr serialize(T value) {
74  return value.serialize();
75  }
76 
77  // Assume that if the user provided a serialize function, he also provided
78  // a static deserialize function, as these two are closely related.
79  template<typename T>
80  static T deserialize(const xmlNodePtr value) {
81  return T::deserialize(value);
82  }
83  };
84 
86 
95  template <typename T>
96  xmlNodePtr serializeGeneral_impl(T value, boost::true_type) {
97  std::stringstream os;
98  os << value;
99  std::string tmp = os.str();
100  return xmlNewText(BAD_CAST tmp.c_str());
101  }
102 
104 
108  template <typename T>
109  xmlNodePtr serializeGeneral_impl(T value, boost::false_type) {
110  return CompoundTypeSerializer<HasSerialize<T>::value>::serialize(value);
111  }
112 
114 
120  template <typename T>
121  xmlNodePtr serializeGeneral(T value) {
122  return serializeGeneral_impl(value, boost::is_fundamental<T>());
123  }
124 
125  // deserialize functions equivalent to the serializeGeneral and serializeGeneral_impl
126 
128  template <typename T>
129  T deserializeGeneral_impl(const xmlNodePtr value, boost::true_type) {
130  T retVal;
131  std::stringstream is(reinterpret_cast<const char*>(value->content));
132  is >> retVal;
133  return retVal;
134  }
135 
137  template <typename T>
138  T deserializeGeneral_impl(const xmlNodePtr value, boost::false_type) {
139  // ISO C++03 14.2/4:
140  return CompoundTypeSerializer<HasSerialize<T>::value>::template deserialize<T>(value);
141  }
142 
143  template <typename T>
144  T deserializeGeneral(const xmlNodePtr value) {
145  return deserializeGeneral_impl<T>(value, boost::is_fundamental<T>());
146  }
147 
148  // other usefull functions
149 
150  inline uint64_t htonll(uint64_t value) {
151  const int test = 1;
152 
153  // Check the endianness
154  if (*reinterpret_cast<const char*>(&test) == 1) {
155  // create a 0xFFFFFFFF mask in a portable way
156  uint64_t mask = 0; mask = ~mask;
157  const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
158  const uint32_t low_part = htonl(static_cast<uint32_t>(value & mask));
159  return (static_cast<uint64_t>(low_part) << 32) | high_part;
160  }
161  else {
162  return value;
163  }
164  }
165 
166  inline uint64_t ntohll(uint64_t value) {
167  const int test = 1;
168 
169  // Check the endianness
170  if (*reinterpret_cast<const char*>(&test) == 1) {
171  return ( (static_cast<uint64_t>(ntohl(value))) << 32 | ntohl(value>>32) );
172  }
173  else {
174  return value;
175  }
176  }
177 
178 }
179 }
180 
181 #endif
182