File indexing completed on 2024-04-14 14:12:13

0001 /***************************************************************************
0002     File                 : endianfstream.hh
0003     --------------------------------------------------------------------
0004     Copyright            : (C) 2008 Alex Kargovsky
0005                            Email (use @ for *)  : kargovsky*yumr.phys.msu.su
0006     Description          : Endianless file stream class
0007 
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #ifndef ENDIAN_FSTREAM_H
0030 #define ENDIAN_FSTREAM_H
0031 
0032 #include <fstream>
0033 #include "OriginObj.h"
0034 
0035 namespace std
0036 {
0037     class iendianfstream : public ifstream
0038     {
0039     public:
0040         iendianfstream(const char *_Filename, ios_base::openmode _Mode = ios_base::in)
0041             :   ifstream(_Filename, _Mode)
0042         {
0043             short word = 0x4321;
0044             bigEndian = (*(char*)& word) != 0x21;
0045         };
0046 
0047         iendianfstream& operator>>(bool& value)
0048         {
0049             char c;
0050             get(c);
0051             value = (c != 0);
0052             return *this;
0053         }
0054 
0055         iendianfstream& operator>>(char& value)
0056         {
0057             get(value);
0058             return *this;
0059         }
0060 
0061         iendianfstream& operator>>(unsigned char& value)
0062         {
0063             get(reinterpret_cast<char&>(value));
0064             return *this;
0065         }
0066 
0067         iendianfstream& operator>>(short& value)
0068         {
0069             read(reinterpret_cast<char*>(&value), sizeof(value));
0070             if(bigEndian)
0071                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0072 
0073             return *this;
0074         }
0075 
0076         iendianfstream& operator>>(unsigned short& value)
0077         {
0078             read(reinterpret_cast<char*>(&value), sizeof(value));
0079             if(bigEndian)
0080                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0081 
0082             return *this;
0083         }
0084 
0085         iendianfstream& operator>>(int& value)
0086         {
0087             read(reinterpret_cast<char*>(&value), sizeof(value));
0088             if(bigEndian)
0089                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0090 
0091             return *this;
0092         }
0093 
0094         iendianfstream& operator>>(unsigned int& value)
0095         {
0096             read(reinterpret_cast<char*>(&value), sizeof(value));
0097             if(bigEndian)
0098                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0099 
0100             return *this;
0101         }
0102 
0103         iendianfstream& operator>>(long& value)
0104         {
0105             read(reinterpret_cast<char*>(&value), sizeof(value));
0106             if(bigEndian)
0107                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0108 
0109             return *this;
0110         }
0111 
0112         iendianfstream& operator>>(unsigned long& value)
0113         {
0114             read(reinterpret_cast<char*>(&value), sizeof(value));
0115             if(bigEndian)
0116                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0117 
0118             return *this;
0119         }
0120 
0121         iendianfstream& operator>>(float& value)
0122         {
0123             read(reinterpret_cast<char*>(&value), sizeof(value));
0124             if(bigEndian)
0125                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0126 
0127             return *this;
0128         }
0129 
0130         iendianfstream& operator>>(double& value)
0131         {
0132             read(reinterpret_cast<char*>(&value), sizeof(value));
0133             if(bigEndian)
0134                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0135 
0136             return *this;
0137         }
0138 
0139         iendianfstream& operator>>(long double& value)
0140         {
0141             read(reinterpret_cast<char*>(&value), sizeof(value));
0142             if(bigEndian)
0143                 swap_bytes(reinterpret_cast<unsigned char*>(&value), sizeof(value));
0144 
0145             return *this;
0146         }
0147 
0148         iendianfstream& operator>>(string& value)
0149         {
0150             read(reinterpret_cast<char*>(&value[0]), value.size());
0151             string::size_type pos = value.find_first_of('\0');
0152             if(pos != string::npos)
0153                 value.resize(pos);
0154 
0155             return *this;
0156         }
0157 
0158         iendianfstream& operator>>(Origin::Color& value)
0159         {
0160             unsigned char color[4];
0161             read(reinterpret_cast<char*>(&color), sizeof(color));
0162             switch(color[3])
0163             {
0164             case 0:
0165                 if(color[0] < 0x64)
0166                 {
0167                     value.type = Origin::Color::Regular;
0168                     value.regular = color[0];
0169                 }
0170                 else
0171                 {
0172                     switch(color[2])
0173                     {
0174                     case 0:
0175                         value.type = Origin::Color::Indexing;
0176                         break;
0177                     case 0x40:
0178                         value.type = Origin::Color::Mapping;
0179                         break;
0180                     case 0x80:
0181                         value.type = Origin::Color::RGB;
0182                         break;
0183                     }
0184 
0185                     value.column = color[0] - 0x64;
0186                 }
0187                 
0188                 break;
0189             case 1:
0190                 value.type = Origin::Color::Custom;
0191                 for(int i = 0; i < 3; ++i)
0192                     value.custom[i] = color[i];
0193                 break;
0194             case 0x20:
0195                 value.type = Origin::Color::Increment;
0196                 value.starting = color[1];
0197                 break;
0198             case 0xFF:
0199                 if(color[0] == 0xFC)
0200                     value.type = Origin::Color::None;
0201                 else if(color[0] == 0xF7)
0202                     value.type = Origin::Color::Automatic;
0203 
0204                 break;
0205 
0206             default:
0207                 value.type = Origin::Color::Regular;
0208                 value.regular = color[0];
0209                 break;
0210 
0211             }
0212 
0213             return *this;
0214         }
0215 
0216     private:
0217         bool bigEndian;
0218         void swap_bytes(unsigned char* data, int size)
0219         {
0220             int i = 0;
0221             int j = size - 1;
0222             while(i < j)
0223             {
0224                 std::swap(data[i], data[j]);
0225                 ++i, --j;
0226             }
0227         }
0228     };
0229 }
0230 
0231 #endif // ENDIAN_FSTREAM_H