DOSBox-X
|
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__