module.cpp revision 4a39e5073a7d0cd8243c6f963567a9945265490c
1//
2// Copyright 2012 Francisco Jerez
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20// OTHER DEALINGS IN THE SOFTWARE.
21//
22
23#include <type_traits>
24
25#include "core/module.hpp"
26
27using namespace clover;
28
29namespace {
30   template<typename T, typename = void>
31   struct _serializer;
32
33   /// Serialize the specified object.
34   template<typename T>
35   void
36   _proc(compat::ostream &os, const T &x) {
37      _serializer<T>::proc(os, x);
38   }
39
40   /// Deserialize the specified object.
41   template<typename T>
42   void
43   _proc(compat::istream &is, T &x) {
44      _serializer<T>::proc(is, x);
45   }
46
47   template<typename T>
48   T
49   _proc(compat::istream &is) {
50      T x;
51      _serializer<T>::proc(is, x);
52      return x;
53   }
54
55   /// Calculate the size of the specified object.
56   template<typename T>
57   void
58   _proc(module::size_t &sz, const T &x) {
59      _serializer<T>::proc(sz, x);
60   }
61
62   /// (De)serialize a scalar value.
63   template<typename T>
64   struct _serializer<T, typename std::enable_if<
65                            std::is_scalar<T>::value>::type> {
66      static void
67      proc(compat::ostream &os, const T &x) {
68         os.write(reinterpret_cast<const char *>(&x), sizeof(x));
69      }
70
71      static void
72      proc(compat::istream &is, T &x) {
73         is.read(reinterpret_cast<char *>(&x), sizeof(x));
74      }
75
76      static void
77      proc(module::size_t &sz, const T &x) {
78         sz += sizeof(x);
79      }
80   };
81
82   /// (De)serialize a vector.
83   template<typename T>
84   struct _serializer<compat::vector<T>,
85                      typename std::enable_if<
86                         !std::is_scalar<T>::value>::type> {
87      static void
88      proc(compat::ostream &os, const compat::vector<T> &v) {
89         _proc<uint32_t>(os, v.size());
90
91         for (size_t i = 0; i < v.size(); i++)
92            _proc<T>(os, v[i]);
93      }
94
95      static void
96      proc(compat::istream &is, compat::vector<T> &v) {
97         v.reserve(_proc<uint32_t>(is));
98
99         for (size_t i = 0; i < v.size(); i++)
100            new(&v[i]) T(_proc<T>(is));
101      }
102
103      static void
104      proc(module::size_t &sz, const compat::vector<T> &v) {
105         sz += sizeof(uint32_t);
106
107         for (size_t i = 0; i < v.size(); i++)
108            _proc<T>(sz, v[i]);
109      }
110   };
111
112   template<typename T>
113   struct _serializer<compat::vector<T>,
114                      typename std::enable_if<
115                         std::is_scalar<T>::value>::type> {
116      static void
117      proc(compat::ostream &os, const compat::vector<T> &v) {
118         _proc<uint32_t>(os, v.size());
119         os.write(reinterpret_cast<const char *>(v.begin()),
120                  v.size() * sizeof(T));
121      }
122
123      static void
124      proc(compat::istream &is, compat::vector<T> &v) {
125         v.reserve(_proc<uint32_t>(is));
126         is.read(reinterpret_cast<char *>(v.begin()),
127                 v.size() * sizeof(T));
128      }
129
130      static void
131      proc(module::size_t &sz, const compat::vector<T> &v) {
132         sz += sizeof(uint32_t) + sizeof(T) * v.size();
133      }
134   };
135
136   /// (De)serialize a module::section.
137   template<>
138   struct _serializer<module::section> {
139      template<typename S, typename QT>
140      static void
141      proc(S &s, QT &x) {
142         _proc(s, x.id);
143         _proc(s, x.type);
144         _proc(s, x.size);
145         _proc(s, x.data);
146      }
147   };
148
149   /// (De)serialize a module::argument.
150   template<>
151   struct _serializer<module::argument> {
152      template<typename S, typename QT>
153      static void
154      proc(S &s, QT &x) {
155         _proc(s, x.type);
156         _proc(s, x.size);
157         _proc(s, x.target_size);
158         _proc(s, x.target_align);
159         _proc(s, x.ext_type);
160      }
161   };
162
163   /// (De)serialize a module::symbol.
164   template<>
165   struct _serializer<module::symbol> {
166      template<typename S, typename QT>
167      static void
168      proc(S &s, QT &x) {
169         _proc(s, x.name);
170         _proc(s, x.section);
171         _proc(s, x.offset);
172         _proc(s, x.args);
173      }
174   };
175
176   /// (De)serialize a module.
177   template<>
178   struct _serializer<module> {
179      template<typename S, typename QT>
180      static void
181      proc(S &s, QT &x) {
182         _proc(s, x.syms);
183         _proc(s, x.secs);
184      }
185   };
186};
187
188namespace clover {
189   void
190   module::serialize(compat::ostream &os) const {
191      _proc(os, *this);
192   }
193
194   module
195   module::deserialize(compat::istream &is) {
196      return _proc<module>(is);
197   }
198
199   module::size_t
200   module::size() const {
201      size_t sz = 0;
202      _proc(sz, *this);
203      return sz;
204   }
205}
206