Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

stream.h

Go to the documentation of this file.
00001 /*
00002     Ishtar - A network transparent read/write interface with
00003     probing and enumeration support.
00004     network part : convenient cross-platform packaging for tcp/ip networking
00005     Copyright (C) 2003-2005 Stephane Magnenat <nct@ysagoon.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 */
00021 
00022 #ifndef __ISHTAR_STREAM_H
00023 #define __ISHTAR_STREAM_H
00024 
00025 #include <algorithm>
00026 
00055 
00056 namespace Ishtar
00057 {
00059     typedef signed char Int8;
00061     typedef unsigned char UInt8;
00063     typedef signed short Int16;
00065     typedef unsigned short UInt16;
00067     typedef signed int Int32;
00069     typedef unsigned int UInt32;
00071     typedef size_t Size;
00072     
00074     struct EndianDiscoverer
00075     {
00077         bool isLittleEndian;
00079         bool isInvertedDouble;
00080         
00082         EndianDiscoverer();
00083     };
00084     
00086     extern EndianDiscoverer endianDiscoverer;
00087     
00089     template<typename T> void swapBytesIfRequired(T &v)
00090     {
00091         // we save files in little endian as most user architecture are little endian
00092         if (!endianDiscoverer.isLittleEndian)
00093         {
00094             UInt8 *data = reinterpret_cast<UInt8 *>(&v);
00095             Size size = sizeof(T);
00096             for(Size p = 0; p < (size>>1); p++)
00097                 std::swap(data[p], data[size-1-p]);
00098         }
00099     }
00100     
00101     // Endian safe read and write
00102     // ==========================
00103     
00105     class OutputStream
00106     {
00107     public:
00109         virtual ~OutputStream() { }
00110     
00112         virtual void write(const void *data, const Size size) = 0;
00113     
00115         virtual void flush(void) = 0;
00116     
00118         template<typename T> void writeEndianIndependant(const T &v)
00119         {
00120             T swapedValue = v;
00121             swapBytesIfRequired(swapedValue);
00122             write(&swapedValue, sizeof(T));
00123         }
00124     
00126         inline void writeInt8(const Int8 v) { this->write(&v, 1); }
00128         inline void writeUInt8(const UInt8 v) { this->write(&v, 1); }
00130         inline void writeInt16(const Int16 v) { this->writeEndianIndependant(v); }
00132         inline void writeUInt16(const UInt16 v) { this->writeEndianIndependant(v); }
00134         inline void writeInt32(const Int32 v) { this->writeEndianIndependant(v); }
00136         inline void writeUInt32(const UInt32 v) { this->writeEndianIndependant(v); }
00138         inline void writeFloat(const float v) { this->writeEndianIndependant(v); }
00140         inline void writeDouble(const double v)
00141         {
00142             double value = v;
00143             // arm inverted double forces us to do this
00144             if (endianDiscoverer.isInvertedDouble)
00145             {
00146                 UInt32 *ptr = reinterpret_cast<UInt32 *>(&value);
00147                 UInt32 tempValue = *ptr;
00148                 *ptr = *(ptr+1);
00149                 *(ptr+1) = tempValue;
00150             }
00151             this->writeEndianIndependant(value);
00152         }
00153     };
00154     
00156     class InputStream
00157     {
00158     public:
00160         virtual ~InputStream() { }
00161     
00163         virtual void read(void *data, Size size) = 0;
00164     
00166         template<typename T> T readEndianIndependant()
00167         {
00168             T v;
00169             read(&v, sizeof(T));
00170             swapBytesIfRequired(v);
00171             return v;
00172         }
00173     
00175         inline Int8 readInt8(void) { Int8 i; this->read(&i, 1); return i; }
00177         inline UInt8 readUInt8(void) { UInt8 i; this->read(&i, 1); return i; }
00179         inline Int16 readInt16(void) { return this->readEndianIndependant<Int16>(); }
00181         inline UInt16 readUInt16(void) { return this->readEndianIndependant<UInt16>(); }
00183         inline Int32 readInt32(void) { return this->readEndianIndependant<Int32>(); }
00185         inline UInt32 readUInt32(void) { return this->readEndianIndependant<UInt32>(); }
00187         inline float readFloat(void) { return this->readEndianIndependant<float>(); }
00189         inline double readDouble(void)
00190         {
00191             double value = this->readEndianIndependant<double>();
00192             // arm inverted double forces us to do this
00193             if (endianDiscoverer.isInvertedDouble)
00194             {
00195                 UInt32 *ptr = reinterpret_cast<UInt32 *>(&value);
00196                 UInt32 tempValue = *ptr;
00197                 *ptr = *(ptr+1);
00198                 *(ptr+1) = tempValue;
00199             }
00200             return value;
00201         }
00202     };
00203 }
00204 
00205 #endif

Generated on Mon Oct 24 17:30:54 2005 for libishtarnet by  doxygen 1.4.2