File indexing completed on 2024-05-12 03:46:59

0001 /*
0002     File                 : endianfstream.hh
0003     Description          : Endianless file stream class
0004     --------------------------------------------------------------------
0005     SPDX-FileCopyrightText: 2008 Alex Kargovsky <kargovsky@yumr.phys.msu.su>
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #ifndef ENDIAN_FSTREAM_H
0010 #define ENDIAN_FSTREAM_H
0011 
0012 #include "OriginObj.h"
0013 
0014 #include <fstream>
0015 
0016 namespace endianfstream {
0017 class ORIGIN_EXPORT iendianfstream : public std::ifstream
0018 {
0019 public:
0020     iendianfstream(const char *_Filename, std::ios_base::openmode _Mode = std::ios_base::in)
0021         : std::ifstream(_Filename, _Mode)
0022     {
0023         short word = 0x4321;
0024         bigEndian = (*(char *)&word) != 0x21;
0025     };
0026 
0027     iendianfstream &operator>>(bool &value)
0028     {
0029         char c;
0030         get(c);
0031         value = (c != 0);
0032         return *this;
0033     }
0034 
0035     iendianfstream &operator>>(char &value)
0036     {
0037         get(value);
0038         return *this;
0039     }
0040 
0041     iendianfstream &operator>>(unsigned char &value)
0042     {
0043         get(reinterpret_cast<char &>(value));
0044         return *this;
0045     }
0046 
0047     iendianfstream &operator>>(short &value)
0048     {
0049         read(reinterpret_cast<char *>(&value), sizeof(value));
0050         if (bigEndian)
0051             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0052 
0053         return *this;
0054     }
0055 
0056     iendianfstream &operator>>(unsigned short &value)
0057     {
0058         read(reinterpret_cast<char *>(&value), sizeof(value));
0059         if (bigEndian)
0060             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0061 
0062         return *this;
0063     }
0064 
0065     iendianfstream &operator>>(int &value)
0066     {
0067         read(reinterpret_cast<char *>(&value), sizeof(value));
0068         if (bigEndian)
0069             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0070 
0071         return *this;
0072     }
0073 
0074     iendianfstream &operator>>(unsigned int &value)
0075     {
0076         read(reinterpret_cast<char *>(&value), sizeof(value));
0077         if (bigEndian)
0078             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0079 
0080         return *this;
0081     }
0082 
0083     iendianfstream &operator>>(long &value)
0084     {
0085         read(reinterpret_cast<char *>(&value), sizeof(value));
0086         if (bigEndian)
0087             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0088 
0089         return *this;
0090     }
0091 
0092     iendianfstream &operator>>(unsigned long &value)
0093     {
0094         read(reinterpret_cast<char *>(&value), sizeof(value));
0095         if (bigEndian)
0096             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0097 
0098         return *this;
0099     }
0100 
0101     iendianfstream &operator>>(float &value)
0102     {
0103         read(reinterpret_cast<char *>(&value), sizeof(value));
0104         if (bigEndian)
0105             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0106 
0107         return *this;
0108     }
0109 
0110     iendianfstream &operator>>(double &value)
0111     {
0112         read(reinterpret_cast<char *>(&value), sizeof(value));
0113         if (bigEndian)
0114             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0115 
0116         return *this;
0117     }
0118 
0119     iendianfstream &operator>>(long double &value)
0120     {
0121         read(reinterpret_cast<char *>(&value), sizeof(value));
0122         if (bigEndian)
0123             swap_bytes(reinterpret_cast<unsigned char *>(&value), sizeof(value));
0124 
0125         return *this;
0126     }
0127 
0128     iendianfstream &operator>>(std::string &value)
0129     {
0130         read(reinterpret_cast<char *>(&value[0]), value.size());
0131         std::string::size_type pos = value.find_first_of('\0');
0132         if (pos != std::string::npos)
0133             value.resize(pos);
0134 
0135         return *this;
0136     }
0137 
0138     iendianfstream &operator>>(Origin::Color &value)
0139     {
0140         unsigned char color[4];
0141         read(reinterpret_cast<char *>(&color), sizeof(color));
0142         switch (color[3]) {
0143         case 0:
0144             if (color[0] < 0x64) {
0145                 value.type = Origin::Color::Regular;
0146                 value.regular = color[0];
0147             } else {
0148                 switch (color[2]) {
0149                 case 0:
0150                     value.type = Origin::Color::Indexing;
0151                     break;
0152                 case 0x40:
0153                     value.type = Origin::Color::Mapping;
0154                     break;
0155                 case 0x80:
0156                     value.type = Origin::Color::RGB;
0157                     break;
0158                 }
0159 
0160                 value.column = color[0] - 0x64;
0161             }
0162 
0163             break;
0164         case 1:
0165             value.type = Origin::Color::Custom;
0166             for (int i = 0; i < 3; ++i)
0167                 value.custom[i] = color[i];
0168             break;
0169         case 0x20:
0170             value.type = Origin::Color::Increment;
0171             value.starting = color[1];
0172             break;
0173         case 0xFF:
0174             if (color[0] == 0xFC)
0175                 value.type = Origin::Color::None;
0176             else if (color[0] == 0xF7)
0177                 value.type = Origin::Color::Automatic;
0178 
0179             break;
0180 
0181         default:
0182             value.type = Origin::Color::Regular;
0183             value.regular = color[0];
0184             break;
0185         }
0186 
0187         return *this;
0188     }
0189 
0190 private:
0191     bool bigEndian;
0192     void swap_bytes(unsigned char *data, int size)
0193     {
0194         int i = 0;
0195         int j = size - 1;
0196         while (i < j) {
0197             std::swap(data[i], data[j]);
0198             ++i, --j;
0199         }
0200     }
0201 };
0202 }
0203 
0204 #endif // ENDIAN_FSTREAM_H