Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/mednadisc/Stream.h
2 views
1
#ifndef __MDFN_STREAM_H
2
#define __MDFN_STREAM_H
3
4
// TODO?: BufferedStream, no virtual functions, yes inline functions, constructor takes a Stream* argument.
5
6
#include "emuware/emuware.h"
7
8
#include <errno.h>
9
10
#include <stdio.h> // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT.
11
#include <string.h>
12
13
#include <string>
14
15
class Stream
16
{
17
public:
18
19
Stream();
20
virtual ~Stream();
21
22
enum
23
{
24
ATTRIBUTE_READABLE = 1U << 0,
25
ATTRIBUTE_WRITEABLE = 1U << 1,
26
ATTRIBUTE_SEEKABLE = 1U << 2,
27
ATTRIBUTE_SLOW_SEEK = 1U << 3,
28
ATTRIBUTE_SLOW_SIZE = 1U << 4
29
};
30
virtual uint64 attributes(void) = 0;
31
32
virtual uint8 *map(void) noexcept;
33
// Map the entirety of the stream data into the address space of the process, if possible, and return a pointer.
34
// (the returned pointer must be cached, and returned on any subsequent calls to map() without an unmap()
35
// in-between, to facilitate a sort of "feature-testing", to determine if an alternative like "MemoryStream"
36
// should be used).
37
//
38
// If the mapping fails for whatever reason, return NULL rather than throwing an exception.
39
//
40
// For code using this functionality, ensure usage of map_size() instead of size(), unless you're only using a specific derived
41
// class like MemoryStream() where the value returned by size() won't change unexpectedly due to outside factors.
42
43
virtual uint64 map_size(void) noexcept;
44
// The size of the memory mapping area, point to which returned by map().
45
//
46
// Returns 0 on supported, or if no mapping currently exists.
47
48
virtual void unmap(void) noexcept;
49
// Unmap the stream data from the address space. (Possibly invalidating the pointer returned from map()).
50
// (must automatically be called, if necessary, from the destructor).
51
//
52
// If the data can't be "unmapped" as such because it was never mmap()'d or similar in the first place(such as with MemoryStream),
53
// then this will be a nop.
54
55
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0;
56
virtual void write(const void *data, uint64 count) = 0;
57
58
virtual void truncate(uint64 length) = 0; // Should have ftruncate()-like semantics; but avoid using it to extend files.
59
60
virtual void seek(int64 offset, int whence = SEEK_SET) = 0;
61
inline void rewind(void)
62
{
63
seek(0, SEEK_SET);
64
}
65
virtual uint64 tell(void) = 0;
66
virtual uint64 size(void) = 0; // May implicitly call flush() if the stream is writeable.
67
virtual void flush(void) = 0;
68
virtual void close(void) = 0; // Flushes(in the case of writeable streams) and closes the stream.
69
// Necessary since this operation can fail(running out of disk space, for instance),
70
// and throw an exception in the destructor would be a Bad Idea(TM).
71
//
72
// Manually calling this function isn't strictly necessary, but recommended when the
73
// stream is writeable; it will be called automatically from the destructor, with any
74
// exceptions thrown caught and logged.
75
76
//
77
// Utility functions(TODO):
78
//
79
INLINE uint8 get_u8(void)
80
{
81
uint8 ret;
82
83
read(&ret, sizeof(ret));
84
85
return ret;
86
}
87
88
INLINE void put_u8(uint8 c)
89
{
90
write(&c, sizeof(c));
91
}
92
93
94
template<typename T>
95
INLINE T get_NE(void)
96
{
97
T ret;
98
99
read(&ret, sizeof(ret));
100
101
return ret;
102
}
103
104
105
template<typename T>
106
INLINE T get_RE(void)
107
{
108
uint8 tmp[sizeof(T)];
109
union
110
{
111
T ret;
112
uint8 ret_u8[sizeof(T)];
113
};
114
115
read(tmp, sizeof(tmp));
116
117
for(unsigned i = 0; i < sizeof(T); i++)
118
ret_u8[i] = tmp[sizeof(T) - 1 - i];
119
120
return ret;
121
}
122
123
template<typename T>
124
INLINE void put_NE(T c)
125
{
126
write(&c, sizeof(c));
127
}
128
129
template<typename T>
130
INLINE void put_RE(T c)
131
{
132
uint8 tmp[sizeof(T)];
133
134
for(unsigned i = 0; i < sizeof(T); i++)
135
tmp[i] = ((uint8 *)&c)[sizeof(T) - 1 - i];
136
137
write(tmp, sizeof(tmp));
138
}
139
140
template<typename T>
141
INLINE T get_LE(void)
142
{
143
#ifdef LSB_FIRST
144
return get_NE<T>();
145
#else
146
return get_RE<T>();
147
#endif
148
}
149
150
template<typename T>
151
INLINE void put_LE(T c)
152
{
153
#ifdef LSB_FIRST
154
return put_NE<T>(c);
155
#else
156
return put_RE<T>(c);
157
#endif
158
}
159
160
template<typename T>
161
INLINE T get_BE(void)
162
{
163
#ifndef LSB_FIRST
164
return get_NE<T>();
165
#else
166
return get_RE<T>();
167
#endif
168
}
169
170
template<typename T>
171
INLINE void put_BE(T c)
172
{
173
#ifndef LSB_FIRST
174
return put_NE<T>(c);
175
#else
176
return put_RE<T>(c);
177
#endif
178
}
179
180
INLINE void put_string(const char* str)
181
{
182
write(str, strlen(str));
183
}
184
185
// Reads a line into "str", overwriting its contents; returns the line-end char('\n' or '\r' or '\0'), or 256 on EOF and
186
// data has been read into "str", and -1 on EOF when no data has been read into "str".
187
// The line-end char won't be added to "str".
188
// It's up to the caller to handle extraneous empty lines caused by DOS-format text lines(\r\n).
189
// ("str" is passed by reference for the possibility of improved performance by reusing alloced memory for the std::string, though part
190
// of it would be up to the STL implementation).
191
// Implemented as virtual so that a higher-performance version can be implemented if possible(IE with MemoryStream)
192
virtual int get_line(std::string &str);
193
194
virtual void put_line(const std::string& str);
195
196
virtual void print_format(const char *format, ...) MDFN_FORMATSTR(gnu_printf, 2, 3);
197
198
#if 0
199
int scanf(const char *format, ...) MDFN_FORMATSTR(gnu_scanf, 2, 3);
200
void put_string(const char *str);
201
void put_string(const std::string &str);
202
#endif
203
204
//
205
// Read until end-of-stream(or count), discarding any read data, and returns the amount of data "read".
206
// (Useful for detecting and printing warnings about extra garbage data without needing to call size(),
207
// which can be problematic for some types of Streams).
208
uint64 read_discard(uint64 count = ~(uint64)0);
209
210
//
211
// Reads stream starting at the current stream position(as returned by tell()), into memory allocated with malloc() and realloc(), and
212
// sets *data_out to a pointer to the memory(which the caller will need to free() at some point).
213
//
214
// *data_out is only an output.
215
//
216
// If size_limit is/will be exceeded, an exception will be thrown, and *data_out will not be written to.
217
//
218
// Will return the amount of data read(and the size of the alloced memory).
219
//
220
uint64 alloc_and_read(void** data_out, uint64 size_limit = ~(uint64)0);
221
};
222
223
#endif
224
225