Home | History | Annotate | Download | only in core
      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