1 #ifndef __MDFN_STREAM_H 2 #define __MDFN_STREAM_H 3 4 // TODO/WIP 5 6 // TODO?: BufferedStream, no virtual functions, yes inline functions, constructor takes a Stream* argument. 7 8 #include "mednafen.h" 9 #include <errno.h> 10 11 #include <stdio.h> // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT. 12 13 #define MODE_READ 0 14 #define MODE_WRITE 1 15 #define MODE_WRITE_SAFE 2 16 17 class Stream 18 { 19 public: 20 21 Stream(); 22 virtual ~Stream(); 23 24 virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0; 25 virtual void write(const void *data, uint64 count) = 0; 26 27 virtual void seek(int64 offset, int whence) = 0; 28 virtual int64 tell(void) = 0; 29 virtual int64 size(void) = 0; 30 virtual void close(void) = 0; // Flushes(in the case of writeable streams) and closes the stream. 31 // Necessary since this operation can fail(running out of disk space, for instance), 32 // and throw an exception in the destructor would be a Bad Idea(TM). 33 // 34 // Manually calling this function isn't strictly necessary, but recommended when the 35 // stream is writeable; it will be called automatically from the destructor, with any 36 // exceptions thrown caught and logged. 37 38 // 39 // Utility functions(TODO): 40 // get_u8(void)41 INLINE uint8 get_u8(void) 42 { 43 uint8 ret; 44 45 read(&ret, sizeof(ret)); 46 47 return ret; 48 } 49 put_u8(uint8 c)50 INLINE void put_u8(uint8 c) 51 { 52 write(&c, sizeof(c)); 53 } 54 55 56 template<typename T> get_NE(void)57 INLINE T get_NE(void) 58 { 59 T ret; 60 61 read(&ret, sizeof(ret)); 62 63 return ret; 64 } 65 66 template<typename T> put_NE(T c)67 INLINE void put_NE(T c) 68 { 69 write(&c, sizeof(c)); 70 } 71 72 73 template<typename T> get_RE(void)74 INLINE T get_RE(void) 75 { 76 uint8 tmp[sizeof(T)]; 77 T ret = 0; 78 79 read(tmp, sizeof(tmp)); 80 81 for(unsigned i = 0; i < sizeof(T); i++) 82 ret |= (T)tmp[i] << (i * 8); 83 84 return ret; 85 } 86 87 template<typename T> put_RE(T c)88 INLINE void put_RE(T c) 89 { 90 uint8 tmp[sizeof(T)]; 91 92 for(unsigned i = 0; i < sizeof(T); i++) 93 tmp[i] = ((uint8 *)&c)[sizeof(T) - 1 - i]; 94 95 write(tmp, sizeof(tmp)); 96 } 97 98 template<typename T> get_LE(void)99 INLINE T get_LE(void) 100 { 101 #ifdef MSB_FIRST 102 return get_RE<T>(); 103 #else 104 return get_NE<T>(); 105 #endif 106 } 107 108 template<typename T> put_LE(T c)109 INLINE void put_LE(T c) 110 { 111 #ifdef MSB_FIRST 112 return put_RE<T>(c); 113 #else 114 return put_NE<T>(c); 115 #endif 116 } 117 118 template<typename T> get_BE(void)119 INLINE T get_BE(void) 120 { 121 #ifdef MSB_FIRST 122 return get_NE<T>(); 123 #else 124 return get_RE<T>(); 125 #endif 126 } 127 128 template<typename T> put_BE(T c)129 INLINE void put_BE(T c) 130 { 131 #ifdef MSB_FIRST 132 return put_NE<T>(c); 133 #else 134 return put_RE<T>(c); 135 #endif 136 } 137 138 // Reads a line into "str", overwriting its contents; returns the line-end char('\n' or '\r' or '\0'), or -1 on EOF. 139 // The line-end char won't be added to "str". 140 // It's up to the caller to handle extraneous empty lines caused by DOS-format text lines(\r\n). 141 // ("str" is passed by reference for the possibility of improved performance by reusing alloced memory for the std::string, though part 142 // of it would be up to the STL implementation). 143 // Implemented as virtual so that a higher-performance version can be implemented if possible(IE with MemoryStream) 144 virtual int get_line(std::string &str); 145 }; 146 #endif 147