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 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 #include <iostream>
     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(std::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(std::istream &is, T &x) {
     45       _serializer<T>::proc(is, x);
     46    }
     47 
     48    template<typename T>
     49    T
     50    _proc(std::istream &is) {
     51       T x;
     52       _serializer<T>::proc(is, x);
     53       return x;
     54    }
     55 
     56    /// Calculate the size of the specified object.
     57    template<typename T>
     58    void
     59    _proc(module::size_t &sz, const T &x) {
     60       _serializer<T>::proc(sz, x);
     61    }
     62 
     63    /// (De)serialize a scalar value.
     64    template<typename T>
     65    struct _serializer<T, typename std::enable_if<
     66                             std::is_scalar<T>::value>::type> {
     67       static void
     68       proc(std::ostream &os, const T &x) {
     69          os.write(reinterpret_cast<const char *>(&x), sizeof(x));
     70       }
     71 
     72       static void
     73       proc(std::istream &is, T &x) {
     74          is.read(reinterpret_cast<char *>(&x), sizeof(x));
     75       }
     76 
     77       static void
     78       proc(module::size_t &sz, const T &x) {
     79          sz += sizeof(x);
     80       }
     81    };
     82 
     83    /// (De)serialize a vector.
     84    template<typename T>
     85    struct _serializer<std::vector<T>,
     86                       typename std::enable_if<
     87                          !std::is_scalar<T>::value>::type> {
     88       static void
     89       proc(std::ostream &os, const std::vector<T> &v) {
     90          _proc<uint32_t>(os, v.size());
     91 
     92          for (size_t i = 0; i < v.size(); i++)
     93             _proc<T>(os, v[i]);
     94       }
     95 
     96       static void
     97       proc(std::istream &is, std::vector<T> &v) {
     98          v.resize(_proc<uint32_t>(is));
     99 
    100          for (size_t i = 0; i < v.size(); i++)
    101             new(&v[i]) T(_proc<T>(is));
    102       }
    103 
    104       static void
    105       proc(module::size_t &sz, const std::vector<T> &v) {
    106          sz += sizeof(uint32_t);
    107 
    108          for (size_t i = 0; i < v.size(); i++)
    109             _proc<T>(sz, v[i]);
    110       }
    111    };
    112 
    113    template<typename T>
    114    struct _serializer<std::vector<T>,
    115                       typename std::enable_if<
    116                          std::is_scalar<T>::value>::type> {
    117       static void
    118       proc(std::ostream &os, const std::vector<T> &v) {
    119          _proc<uint32_t>(os, v.size());
    120          os.write(reinterpret_cast<const char *>(&v[0]),
    121                   v.size() * sizeof(T));
    122       }
    123 
    124       static void
    125       proc(std::istream &is, std::vector<T> &v) {
    126          v.resize(_proc<uint32_t>(is));
    127          is.read(reinterpret_cast<char *>(&v[0]),
    128                  v.size() * sizeof(T));
    129       }
    130 
    131       static void
    132       proc(module::size_t &sz, const std::vector<T> &v) {
    133          sz += sizeof(uint32_t) + sizeof(T) * v.size();
    134       }
    135    };
    136 
    137    /// (De)serialize a string.
    138    template<>
    139    struct _serializer<std::string> {
    140       static void
    141       proc(std::ostream &os, const std::string &s) {
    142          _proc<uint32_t>(os, s.size());
    143          os.write(&s[0], s.size() * sizeof(std::string::value_type));
    144       }
    145 
    146       static void
    147       proc(std::istream &is, std::string &s) {
    148          s.resize(_proc<uint32_t>(is));
    149          is.read(&s[0], s.size() * sizeof(std::string::value_type));
    150       }
    151 
    152       static void
    153       proc(module::size_t &sz, const std::string &s) {
    154          sz += sizeof(uint32_t) + sizeof(std::string::value_type) * s.size();
    155       }
    156    };
    157 
    158    /// (De)serialize a module::section.
    159    template<>
    160    struct _serializer<module::section> {
    161       template<typename S, typename QT>
    162       static void
    163       proc(S &s, QT &x) {
    164          _proc(s, x.id);
    165          _proc(s, x.type);
    166          _proc(s, x.size);
    167          _proc(s, x.data);
    168       }
    169    };
    170 
    171    /// (De)serialize a module::argument.
    172    template<>
    173    struct _serializer<module::argument> {
    174       template<typename S, typename QT>
    175       static void
    176       proc(S &s, QT &x) {
    177          _proc(s, x.type);
    178          _proc(s, x.size);
    179          _proc(s, x.target_size);
    180          _proc(s, x.target_align);
    181          _proc(s, x.ext_type);
    182          _proc(s, x.semantic);
    183       }
    184    };
    185 
    186    /// (De)serialize a module::symbol.
    187    template<>
    188    struct _serializer<module::symbol> {
    189       template<typename S, typename QT>
    190       static void
    191       proc(S &s, QT &x) {
    192          _proc(s, x.name);
    193          _proc(s, x.section);
    194          _proc(s, x.offset);
    195          _proc(s, x.args);
    196       }
    197    };
    198 
    199    /// (De)serialize a module.
    200    template<>
    201    struct _serializer<module> {
    202       template<typename S, typename QT>
    203       static void
    204       proc(S &s, QT &x) {
    205          _proc(s, x.syms);
    206          _proc(s, x.secs);
    207       }
    208    };
    209 };
    210 
    211 namespace clover {
    212    void
    213    module::serialize(std::ostream &os) const {
    214       _proc(os, *this);
    215    }
    216 
    217    module
    218    module::deserialize(std::istream &is) {
    219       return _proc<module>(is);
    220    }
    221 
    222    module::size_t
    223    module::size() const {
    224       size_t sz = 0;
    225       _proc(sz, *this);
    226       return sz;
    227    }
    228 }
    229