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 28 using namespace clover; 29 30 namespace { 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 138 namespace 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