DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/libs/decoders/archive.h
00001 /*
00002 This is free and unencumbered software released into the public domain.
00003 
00004 Anyone is free to copy, modify, publish, use, compile, sell, or
00005 distribute this software, either in source code form or as a compiled
00006 binary, for any purpose, commercial or non-commercial, and by any
00007 means.
00008 
00009 In jurisdictions that recognize copyright laws, the author or authors
00010 of this software dedicate any and all copyright interest in the
00011 software to the public domain. We make this dedication for the benefit
00012 of the public at large and to the detriment of our heirs and
00013 successors. We intend this dedication to be an overt act of
00014 relinquishment in perpetuity of all present and future rights to this
00015 software under copyright law.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00018 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00021 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00022 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00023 OTHER DEALINGS IN THE SOFTWARE.
00024 
00025 For more information, please refer to <https://unlicense.org>
00026 */
00027 
00028 #ifndef ARCHIVE_H__
00029 #define ARCHIVE_H__
00030 
00031 #include <stdint.h>
00032 #include <string>
00033 #include <cassert>
00034 #include <algorithm>
00035 
00036 #include <vector>
00037 #include <deque>
00038 #include <list>
00039 #include <set>
00040 #include <map>
00041 
00042 #include <exception>
00043 #include <stdexcept>
00044 
00045 namespace EndianSwapper
00046 {
00047     class SwapByteBase
00048     {
00049         public:
00050             static bool ShouldSwap()
00051             {
00052                 static const uint16_t swapTest = 1;
00053                 return (*((char*)&swapTest) == 1);
00054             }
00055 
00056             static void SwapBytes(uint8_t& v1, uint8_t& v2)
00057             {
00058                 uint8_t tmp = v1;
00059                 v1 = v2;
00060                 v2 = tmp;
00061             }
00062     };
00063 
00064     template <class T, int S>
00065         class SwapByte : public SwapByteBase
00066     {
00067         public:
00068             static T Swap(T v)
00069             {
00070                 assert(false); // Shoud not be here...
00071                 return v;
00072             }
00073     };
00074 
00075     template <class T>
00076         class SwapByte<T, 1> : public SwapByteBase
00077         {
00078             public:
00079                 static T Swap(T v)
00080                 {
00081                     return v;
00082                 }
00083         };
00084 
00085     template <class T>
00086         class SwapByte<T, 2> : public SwapByteBase
00087         {
00088             public:
00089                 static T Swap(T v)
00090                 {
00091                     if(ShouldSwap())
00092                         return ((uint16_t)v >> 8) | ((uint16_t)v << 8);
00093                     return v;
00094                 }
00095         };
00096 
00097     template <class T>
00098         class SwapByte<T, 4> : public SwapByteBase
00099         {
00100             public:
00101                 static T Swap(T v)
00102                 {
00103                     if(ShouldSwap())
00104                     {
00105                         return (SwapByte<uint16_t, 2>::Swap((uint32_t)v & 0xffff) << 16) | (SwapByte<uint16_t, 2>::Swap(((uint32_t)v & 0xffff0000) >> 16));
00106                     }
00107                     return v;
00108                 }
00109         };
00110 
00111     template <class T>
00112         class SwapByte<T, 8> : public SwapByteBase
00113         {
00114             public:
00115                 static T Swap(T v)
00116                 {
00117                     if(ShouldSwap())
00118                         return (((uint64_t)SwapByte<uint32_t, 4>::Swap((uint32_t)(v & 0xffffffffull))) << 32) | (SwapByte<uint32_t, 4>::Swap((uint32_t)(v >> 32)));
00119                     return v;
00120                 }
00121         };
00122 
00123     template <>
00124         class SwapByte<float, 4> : public SwapByteBase
00125         {
00126             public:
00127                 static float Swap(float v)
00128                 {
00129                     union { float f; uint8_t c[4]; };
00130                     f = v;
00131                     if(ShouldSwap())
00132                     {
00133                         SwapBytes(c[0], c[3]);
00134                         SwapBytes(c[1], c[2]);
00135                     }
00136                     return f;
00137                 }
00138         };
00139 
00140     template <>
00141         class SwapByte<double, 8> : public SwapByteBase
00142         {
00143             public:
00144                 static double Swap(double v)
00145                 {
00146                     union { double f; uint8_t c[8]; };
00147                     f = v;
00148                     if(ShouldSwap())
00149                     {
00150                         SwapBytes(c[0], c[7]);
00151                         SwapBytes(c[1], c[6]);
00152                         SwapBytes(c[2], c[5]);
00153                         SwapBytes(c[3], c[4]);
00154                     }
00155                     return f;
00156                 }
00157         };
00158 }
00159 
00160 template <class STREAM_TYPE>
00161 class Archive
00162 {
00163     public:
00164         Archive(STREAM_TYPE& stream) : m_stream(stream)
00165         {
00166         }
00167 
00168     public:
00169         template <class T>
00170             const Archive& operator<<(const T& v) const
00171             {
00172                 *this & v;
00173                 return *this;
00174             }
00175 
00176         template <class T>
00177             Archive& operator>>(T& v)
00178             {
00179                 *this & v;
00180                 return *this;
00181             }
00182 
00183     public:
00184         template <class T>
00185             Archive& operator&(T& v)
00186             {
00187                 v.Serialize(*this);
00188                 return *this;
00189             }
00190 
00191         template <class T>
00192             const Archive& operator&(const T& v) const
00193             {
00194                 ((T&)v).Serialize(*this);
00195                 return *this;
00196             }
00197 
00198         template <class T, size_t N>
00199             Archive& operator&(T (&v)[N])
00200             {
00201                 uint32_t len;
00202                 *this & len;
00203                 for(size_t i = 0; i < N; ++i)
00204                     *this & v[i];
00205                 return *this;
00206             }
00207 
00208         template <class T, size_t N>
00209             const Archive& operator&(const T (&v)[N]) const
00210             {
00211                 uint32_t len = N;
00212                 *this & len;
00213                 for(size_t i = 0; i < N; ++i)
00214                     *this & v[i];
00215                 return *this;
00216             }
00217 
00218 #define SERIALIZER_FOR_POD(type) \
00219         Archive& operator&(type& v) \
00220         { \
00221             m_stream.read((char*)&v, sizeof(type)); \
00222             if(!m_stream) { throw std::runtime_error("malformed data"); } \
00223             v = Swap(v); \
00224             return *this; \
00225         } \
00226         const Archive& operator&(type v) const \
00227         { \
00228             v = Swap(v); \
00229             m_stream.write((const char*)&v, sizeof(type)); \
00230             return *this; \
00231         } 
00232 
00233         SERIALIZER_FOR_POD(bool)
00234         SERIALIZER_FOR_POD(char)
00235         SERIALIZER_FOR_POD(unsigned char)
00236         SERIALIZER_FOR_POD(short)
00237         SERIALIZER_FOR_POD(unsigned short)
00238         SERIALIZER_FOR_POD(int)
00239         SERIALIZER_FOR_POD(unsigned int)
00240         SERIALIZER_FOR_POD(long)
00241         SERIALIZER_FOR_POD(unsigned long)
00242         SERIALIZER_FOR_POD(long long)
00243         SERIALIZER_FOR_POD(unsigned long long)
00244         SERIALIZER_FOR_POD(float)
00245         SERIALIZER_FOR_POD(double)
00246 
00247 
00248 #define SERIALIZER_FOR_STL(type) \
00249         template <class T> \
00250         Archive& operator&(type<T>& v) \
00251         { \
00252             uint32_t len; \
00253             *this & len; \
00254             for(uint32_t i = 0; i < len; ++i) \
00255             { \
00256                 T value; \
00257                 *this & value; \
00258                 v.insert(v.end(), value); \
00259             } \
00260             return *this; \
00261         } \
00262         template <class T> \
00263         const Archive& operator&(const type<T>& v) const \
00264         { \
00265             uint32_t len = v.size(); \
00266             *this & len; \
00267             for(typename type<T>::const_iterator it = v.begin(); it != v.end(); ++it) \
00268             *this & *it; \
00269             return *this; \
00270         }
00271 
00272 #define SERIALIZER_FOR_STL2(type) \
00273         template <class T1, class T2> \
00274         Archive& operator&(type<T1, T2>& v) \
00275         { \
00276             uint32_t len; \
00277             *this & len; \
00278             for(uint32_t i = 0; i < len; ++i) \
00279             { \
00280                 std::pair<T1, T2> value; \
00281                 *this & value; \
00282                 v.insert(v.end(), value); \
00283             } \
00284             return *this; \
00285         } \
00286         template <class T1, class T2> \
00287         const Archive& operator&(const type<T1, T2>& v) const \
00288         { \
00289             uint32_t len = v.size(); \
00290             *this & len; \
00291             for(typename type<T1, T2>::const_iterator it = v.begin(); it != v.end(); ++it) \
00292             *this & *it; \
00293             return *this; \
00294         }
00295 
00296         SERIALIZER_FOR_STL(std::vector)
00297         SERIALIZER_FOR_STL(std::deque)
00298         SERIALIZER_FOR_STL(std::list)
00299         SERIALIZER_FOR_STL(std::set)
00300         SERIALIZER_FOR_STL(std::multiset)
00301         SERIALIZER_FOR_STL2(std::map)
00302         SERIALIZER_FOR_STL2(std::multimap)
00303 
00304         template <class T1, class T2>
00305             Archive& operator&(std::pair<T1, T2>& v)
00306             {
00307                 *this & v.first & v.second;
00308                 return *this;
00309             }
00310 
00311         template <class T1, class T2>
00312             const Archive& operator&(const std::pair<T1, T2>& v) const
00313             {
00314                 *this & v.first & v.second;
00315                 return *this;
00316             }
00317 
00318         Archive& operator&(std::string& v)
00319         {
00320             uint32_t len;
00321             *this & len;
00322             v.clear();
00323             char buffer[4096];
00324             uint32_t toRead = len;
00325             while(toRead != 0)
00326             {
00327                                 uint32_t l;
00328                                 
00329 #if defined(_MSC_VER)
00330                 l = min(toRead, (uint32_t)sizeof(buffer));
00331 #else
00332                 l = std::min(toRead, (uint32_t)sizeof(buffer));
00333 #endif
00334                 m_stream.read(buffer, l);
00335                 if(!m_stream)
00336                     throw std::runtime_error("malformed data");
00337                 v += std::string(buffer, l);
00338                 toRead -= l;
00339             }
00340             return *this;
00341         }
00342 
00343         const Archive& operator&(const std::string& v) const
00344         {
00345             uint32_t len = v.length();
00346             *this & len;
00347             m_stream.write(v.c_str(), len);
00348             return *this;
00349         }
00350 
00351     private:
00352         template <class T>
00353             T Swap(const T& v) const
00354             {
00355                 return EndianSwapper::SwapByte<T, sizeof(T)>::Swap(v);
00356             }
00357 
00358     private:
00359         STREAM_TYPE& m_stream;
00360 };
00361 
00362 #endif // ARCHIVE_H__