1 /******************************************************************************** 2 * * 3 * P e r s i s t e n t S t o r a g e S t r e a m C l a s s e s * 4 * * 5 ********************************************************************************* 6 * Copyright (C) 1997,2021 by Jeroen van der Zijp. All Rights Reserved. * 7 ********************************************************************************* 8 * This library is free software; you can redistribute it and/or modify * 9 * it under the terms of the GNU Lesser General Public License as published by * 10 * the Free Software Foundation; either version 3 of the License, or * 11 * (at your option) any later version. * 12 * * 13 * This library is distributed in the hope that it will be useful, * 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 16 * GNU Lesser General Public License for more details. * 17 * * 18 * You should have received a copy of the GNU Lesser General Public License * 19 * along with this program. If not, see <http://www.gnu.org/licenses/> * 20 ********************************************************************************/ 21 #ifndef FXSTREAM_H 22 #define FXSTREAM_H 23 24 namespace FX { 25 26 27 /// Stream data flow direction 28 enum FXStreamDirection { 29 FXStreamDead=0, /// Unopened stream 30 FXStreamSave=1, /// Saving stuff to stream 31 FXStreamLoad=2 /// Loading stuff from stream 32 }; 33 34 35 /// Stream status codes 36 enum FXStreamStatus { 37 FXStreamOK=0, /// OK 38 FXStreamEnd=1, /// Try read past end of stream 39 FXStreamFull=2, /// Filled up stream buffer or disk full 40 FXStreamNoWrite=3, /// Unable to open for write 41 FXStreamNoRead=4, /// Unable to open for read 42 FXStreamFormat=5, /// Stream format error 43 FXStreamUnknown=6, /// Trying to read unknown class 44 FXStreamAlloc=7, /// Alloc failed 45 FXStreamFailure=8 /// General failure 46 }; 47 48 49 /// Stream seeking 50 enum FXWhence { 51 FXFromStart=0, /// Seek from start position 52 FXFromCurrent=1, /// Seek from current position 53 FXFromEnd=2 /// Seek from end position 54 }; 55 56 57 /** 58 * A stream is a way to serialize data and objects into a byte stream. 59 * Each item of data that is saved or loaded from the stream may be byte-swapped, 60 * thus allowing little-endian machines to read data produced on big endian ones 61 * and vice-versa. 62 * Data is serialized exactly as-is. There are no tags or other markers 63 * inserted into the stream; thus, the stream may be used to save or load arbitrary 64 * binary data. 65 * Objects derived from FXObjects may be serialized also; whenever a reference to an 66 * object is serialized, a table is consulted to determine if the same object has 67 * been encountered previously; if not, the object is added to the table and then 68 * its contents are serialized. If the object has been encountered before, only a 69 * reference to the object is serialized. 70 * When loading back a serialized object, new instances are constructed using 71 * the default constructor, and subsequently the object's contents are loaded. 72 * A special container object may be passed in which is placed in the table 73 * as if it had been encountered before; this will cause only references to this 74 * object to be saved. The container object is typically the top-level document 75 * object which manages all objects contained by it. Additional objects may be 76 * added using addObject(); these will not be actually saved or loaded. 77 */ 78 class FXAPI FXStream { 79 protected: 80 FXHash hash; // Hash table 81 const FXObject *parent; // Parent object 82 FXuchar *begptr; // Begin of buffer 83 FXuchar *endptr; // End of buffer 84 FXuchar *wrptr; // Write pointer 85 FXuchar *rdptr; // Read pointer 86 FXlong pos; // Position 87 FXStreamDirection dir; // Direction of current transfer 88 FXStreamStatus code; // Status code 89 FXuint seq; // Sequence number 90 FXbool owns; // Stream owns buffer 91 FXbool swap; // Swap bytes on readin 92 protected: 93 94 /** 95 * Write at least count bytes from the buffer; 96 * returns number of bytes available to be written. 97 */ 98 virtual FXuval writeBuffer(FXuval count); 99 100 /** 101 * Read at least count bytes into the buffer; 102 * returns number of bytes available to be read. 103 */ 104 virtual FXuval readBuffer(FXuval count); 105 106 private: 107 FXStream(const FXStream&); 108 FXStream &operator=(const FXStream&); 109 public: 110 111 /** 112 * Construct stream with given container object. The container object 113 * is an object that will itself not be saved to or loaded from the stream, 114 * but which may be referenced by other objects. These references will be 115 * properly saved and restored. 116 */ 117 FXStream(const FXObject* cont=NULL); 118 119 /** 120 * Open stream for reading (FXStreamLoad) or for writing (FXStreamSave). 121 * An initial buffer size may be given, which must be at least 16 bytes. 122 * If data is not NULL, it is expected to point to an external data buffer 123 * of length size; otherwise stream will use an internally managed buffer. 124 */ 125 FXbool open(FXStreamDirection save_or_load,FXuchar* data=NULL,FXuval size=8192UL,FXbool owned=false); 126 127 /// Flush buffer 128 virtual FXbool flush(); 129 130 /// Close; return true if OK 131 virtual FXbool close(); 132 133 /// Get available buffer space 134 FXuval getSpace() const; 135 136 /// Set available buffer space 137 void setSpace(FXuval sp); 138 139 /// Set buffer ownership flag setOwned(FXbool owned)140 void setOwned(FXbool owned){ owns=owned; } 141 142 /// Get buffer ownership flag isOwned()143 FXbool isOwned() const { return owns; } 144 145 /// Get status code status()146 FXStreamStatus status() const { return code; } 147 148 /// Return true if at end of file or error eof()149 FXbool eof() const { return code!=FXStreamOK; } 150 151 /// Set status code 152 void setError(FXStreamStatus err); 153 154 /// Obtain stream direction direction()155 FXStreamDirection direction() const { return dir; } 156 157 /// Get parent object container()158 const FXObject* container() const { return parent; } 159 160 /// Get position position()161 FXlong position() const { return pos; } 162 163 /// Move to position relative to head, tail, or current location 164 virtual FXbool position(FXlong offset,FXWhence whence=FXFromStart); 165 166 /** 167 * Change swap bytes flag. 168 */ swapBytes(FXbool s)169 void swapBytes(FXbool s){ swap=s; } 170 171 /** 172 * Get state of the swap bytes flag. 173 */ swapBytes()174 FXbool swapBytes() const { return swap; } 175 176 /** 177 * Set stream to big endian mode if true. Byte swapping will 178 * be enabled if the machine native byte order is not equal to 179 * the desired byte order. 180 */ 181 void setBigEndian(FXbool big); 182 183 /** 184 * Return true if big endian mode. 185 */ 186 FXbool isBigEndian() const; 187 188 /// Save single items to stream 189 FXStream& operator<<(const FXuchar& v); 190 FXStream& operator<<(const FXchar& v){ return *this << reinterpret_cast<const FXuchar&>(v); } 191 FXStream& operator<<(const FXbool& v){ return *this << reinterpret_cast<const FXuchar&>(v); } 192 FXStream& operator<<(const FXushort& v); 193 FXStream& operator<<(const FXshort& v){ return *this << reinterpret_cast<const FXushort&>(v); } 194 FXStream& operator<<(const FXuint& v); 195 FXStream& operator<<(const FXint& v){ return *this << reinterpret_cast<const FXuint&>(v); } 196 FXStream& operator<<(const FXfloat& v){ return *this << reinterpret_cast<const FXuint&>(v); } 197 FXStream& operator<<(const FXdouble& v); 198 FXStream& operator<<(const FXlong& v){ return *this << reinterpret_cast<const FXdouble&>(v); } 199 FXStream& operator<<(const FXulong& v){ return *this << reinterpret_cast<const FXdouble&>(v); } 200 201 /// Save arrays of items to stream 202 FXStream& save(const FXuchar* p,FXuval n); save(const FXchar * p,FXuval n)203 FXStream& save(const FXchar* p,FXuval n){ return save(reinterpret_cast<const FXuchar*>(p),n); } save(const FXbool * p,FXuval n)204 FXStream& save(const FXbool* p,FXuval n){ return save(reinterpret_cast<const FXuchar*>(p),n); } 205 FXStream& save(const FXushort* p,FXuval n); save(const FXshort * p,FXuval n)206 FXStream& save(const FXshort* p,FXuval n){ return save(reinterpret_cast<const FXushort*>(p),n); } 207 FXStream& save(const FXuint* p,FXuval n); save(const FXint * p,FXuval n)208 FXStream& save(const FXint* p,FXuval n){ return save(reinterpret_cast<const FXuint*>(p),n); } save(const FXfloat * p,FXuval n)209 FXStream& save(const FXfloat* p,FXuval n){ return save(reinterpret_cast<const FXuint*>(p),n); } 210 FXStream& save(const FXdouble* p,FXuval n); save(const FXlong * p,FXuval n)211 FXStream& save(const FXlong* p,FXuval n){ return save(reinterpret_cast<const FXdouble*>(p),n); } save(const FXulong * p,FXuval n)212 FXStream& save(const FXulong* p,FXuval n){ return save(reinterpret_cast<const FXdouble*>(p),n); } 213 214 /// Load single items from stream 215 FXStream& operator>>(FXuchar& v); 216 FXStream& operator>>(FXchar& v){ return *this >> reinterpret_cast<FXuchar&>(v); } 217 FXStream& operator>>(FXbool& v){ return *this >> reinterpret_cast<FXuchar&>(v); } 218 FXStream& operator>>(FXushort& v); 219 FXStream& operator>>(FXshort& v){ return *this >> reinterpret_cast<FXushort&>(v); } 220 FXStream& operator>>(FXuint& v); 221 FXStream& operator>>(FXint& v){ return *this >> reinterpret_cast<FXuint&>(v); } 222 FXStream& operator>>(FXfloat& v){ return *this >> reinterpret_cast<FXuint&>(v); } 223 FXStream& operator>>(FXdouble& v); 224 FXStream& operator>>(FXlong& v){ return *this >> reinterpret_cast<FXdouble&>(v); } 225 FXStream& operator>>(FXulong& v){ return *this >> reinterpret_cast<FXdouble&>(v); } 226 227 /// Load arrays of items from stream 228 FXStream& load(FXuchar* p,FXuval n); load(FXchar * p,FXuval n)229 FXStream& load(FXchar* p,FXuval n){ return load(reinterpret_cast<FXuchar*>(p),n); } load(FXbool * p,FXuval n)230 FXStream& load(FXbool* p,FXuval n){ return load(reinterpret_cast<FXuchar*>(p),n); } 231 FXStream& load(FXushort* p,FXuval n); load(FXshort * p,FXuval n)232 FXStream& load(FXshort* p,FXuval n){ return load(reinterpret_cast<FXushort*>(p),n); } 233 FXStream& load(FXuint* p,FXuval n); load(FXint * p,FXuval n)234 FXStream& load(FXint* p,FXuval n){ return load(reinterpret_cast<FXuint*>(p),n); } load(FXfloat * p,FXuval n)235 FXStream& load(FXfloat* p,FXuval n){ return load(reinterpret_cast<FXuint*>(p),n); } 236 FXStream& load(FXdouble* p,FXuval n); load(FXlong * p,FXuval n)237 FXStream& load(FXlong* p,FXuval n){ return load(reinterpret_cast<FXdouble*>(p),n); } load(FXulong * p,FXuval n)238 FXStream& load(FXulong* p,FXuval n){ return load(reinterpret_cast<FXdouble*>(p),n); } 239 240 /// Save object 241 FXStream& saveObject(const FXObject* v); 242 243 /// Load object 244 FXStream& loadObject(FXObject*& v); 245 246 /// Add object without saving or loading 247 FXStream& addObject(const FXObject* v); 248 249 /// Load object 250 template<class TYPE> 251 FXStream& operator>>(TYPE*& obj){ return loadObject(reinterpret_cast<FXObject*&>(obj)); } 252 253 /// Save object 254 template<class TYPE> 255 FXStream& operator<<(const TYPE* obj){ return saveObject(static_cast<const FXObject*>(obj)); } 256 257 /// Destructor 258 virtual ~FXStream(); 259 }; 260 261 } 262 263 #endif 264