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