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