module.cpp revision c6db1b3396384186aab5b685fe1fd540e17b3a62
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20// SOFTWARE.
21//
22
23#include <type_traits>
24#include <algorithm>
25
26#include "core/module.hpp"
27
28using namespace clover;
29
30namespace {
31   template<typename T, typename = void>
32   struct __serializer;
33
34   /// Serialize the specified object.
35   template<typename T>
36   void
37   __proc(compat::ostream &os, const T &x) {
38      __serializer<T>::proc(os, x);
39   }
40
41   /// Deserialize the specified object.
42   template<typename T>
43   void
44   __proc(compat::istream &is, T &x) {
45      __serializer<T>::proc(is, x);
46   }
47
48   template<typename T>
49   T
50   __proc(compat::istream &is) {
51      T x;
52      __serializer<T>::proc(is, x);
53      return x;
54   }
55
56   /// (De)serialize a scalar value.
57   template<typename T>
58   struct __serializer<T, typename std::enable_if<
59                             std::is_scalar<T>::value>::type> {
60      static void
61      proc(compat::ostream &os, const T &x) {
62         os.write(reinterpret_cast<const char *>(&x), sizeof(x));
63      }
64
65      static void
66      proc(compat::istream &is, T &x) {
67         is.read(reinterpret_cast<char *>(&x), sizeof(x));
68      }
69   };
70
71   /// (De)serialize a vector.
72   template<typename T>
73   struct __serializer<compat::vector<T>> {
74      static void
75      proc(compat::ostream &os, const compat::vector<T> &v) {
76         __proc<uint32_t>(os, v.size());
77
78         for (size_t i = 0; i < v.size(); i++)
79            __proc<T>(os, v[i]);
80      }
81
82      static void
83      proc(compat::istream &is, compat::vector<T> &v) {
84         v.reserve(__proc<uint32_t>(is));
85
86         for (size_t i = 0; i < v.size(); i++)
87            new(&v[i]) T(__proc<T>(is));
88      }
89   };
90
91   /// (De)serialize a module::section.
92   template<>
93   struct __serializer<module::section> {
94      template<typename S, typename QT>
95      static void
96      proc(S &s, QT &x) {
97         __proc(s, x.type);
98         __proc(s, x.size);
99         __proc(s, x.data);
100      }
101   };
102
103   /// (De)serialize a module::argument.
104   template<>
105   struct __serializer<module::argument> {
106      template<typename S, typename QT>
107      static void
108      proc(S &s, QT &x) {
109         __proc(s, x.type);
110         __proc(s, x.size);
111      }
112   };
113
114   /// (De)serialize a module::symbol.
115   template<>
116   struct __serializer<module::symbol> {
117      template<typename S, typename QT>
118      static void
119      proc(S &s, QT &x) {
120         __proc(s, x.section);
121         __proc(s, x.offset);
122         __proc(s, x.args);
123      }
124   };
125
126   /// (De)serialize a module.
127   template<>
128   struct __serializer<module> {
129      template<typename S, typename QT>
130      static void
131      proc(S &s, QT &x) {
132         __proc(s, x.syms);
133         __proc(s, x.secs);
134      }
135   };
136};
137
138namespace clover {
139   void
140   module::serialize(compat::ostream &os) const {
141      __proc(os, *this);
142   }
143
144   module
145   module::deserialize(compat::istream &is) {
146      return __proc<module>(is);
147   }
148
149   const module::symbol &
150   module::sym(compat::string name) const {
151      auto it = std::find_if(syms.begin(), syms.end(), [&](const symbol &x) {
152            return compat::string(x.name) == name;
153         });
154
155      if (it == syms.end())
156         throw noent_error();
157
158      return *it;
159   }
160
161   const module::section &
162   module::sec(typename section::type type) const {
163      auto it = std::find_if(secs.begin(), secs.end(), [&](const section &x) {
164            return x.type == type;
165         });
166
167      if (it == secs.end())
168         throw noent_error();
169
170      return *it;
171   }
172}
173