summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/ioprocs.h
blob: 9e2c29d2a1422d51f1af3683e0538d010013d206 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************

    ioprocs.h

    I/O interfaces

***************************************************************************/
#ifndef MAME_LIB_UTIL_IOPROCS_H
#define MAME_LIB_UTIL_IOPROCS_H

#pragma once

#include "utilfwd.h"

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <system_error>
#include <tuple>
#include <utility>


// FIXME: make a proper place for OSD forward declarations
class osd_file;


namespace util {

/// \defgroup ioprocs Generic I/O interfaces
/// \{

/// \brief Interface to an input stream
///
/// Represents a stream producing a sequence of bytes with no further
/// structure.
/// \sa write_stream read_write_stream random_read
class read_stream
{
public:
	using ptr = std::unique_ptr<read_stream>;

	virtual ~read_stream() = default;

	/// \brief Read from the current position in the stream
	///
	/// Reads up to the specified number of bytes from the stream into
	/// the supplied buffer.  May read less than the requested number of
	/// bytes if the end of the stream is reached or an error occurs.
	/// If the stream supports seeking, reading starts at the current
	/// position in the stream, and the current position is incremented
	/// by the number of bytes read.
	/// \param [out] buffer Destination buffer.  Must be large enough to
	///   hold the requested number of bytes.
	/// \param [in] length Maximum number of bytes to read.
	/// \param [out] actual Number of bytes actually read.  Will always
	///   be less than or equal to the requested length.
	/// \return An error condition if reading stopped due to an error.
	virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};


/// \brief Interface to an output stream
///
/// Represents a stream that accepts a sequence of bytes with no further
/// structure.
/// \sa read_stream read_write_stream random_write
class write_stream
{
public:
	using ptr = std::unique_ptr<write_stream>;

	virtual ~write_stream() = default;

	/// \brief Finish writing data
	///
	/// Performs any tasks necessary to finish writing data to the
	/// stream and guarantee that the written data can be read in its
	/// entirety.  Further writes may not be possible.
	/// \return An error condition if the operation fails.
	virtual std::error_condition finalize() noexcept = 0;

	/// \brief Flush application-side caches
	///
	/// Flushes any caches to the underlying stream.  Success does not
	/// guarantee that data has reached persistent storage.
	/// \return An error condition if flushing caches fails.
	virtual std::error_condition flush() noexcept = 0;

	/// \brief Write at the current position in the stream
	///
	/// Writes up to the specified number of bytes from the supplied
	/// buffer to the stream.  May write less than the requested number
	/// of bytes if an error occurs.  If the stream supports seeking,
	/// writing starts at the current position in the stream, and the
	/// current position is incremented by the number of bytes written.
	/// \param [in] buffer Buffer containing the data to write.  Must
	///   contain at least the specified number of bytes.
	/// \param [in] length Number of bytes to write.
	/// \param [out] actual Number of bytes actually written.  Will
	///   always be less than or equal to the requested length.
	/// \return An error condition if writing stopped due to an error.
	virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};


/// \brief Interface to an I/O stream
///
/// Represents an object that acts as both a source of and sink for byte
/// sequences.
/// \sa read_stream write_stream random_read_write
class read_write_stream : public virtual read_stream, public virtual write_stream
{
public:
	using ptr = std::unique_ptr<read_write_stream>;
};


/// \brief Interface to a byte sequence that supports seeking
///
/// Provides an interface for controlling the position within a byte
/// sequence that supports seeking.
/// \sa random_read random_write random_read_write
class random_access
{
public:
	virtual ~random_access() = default;

	/// \brief Set the position in the stream
	///
	/// Sets the position for the next read or write operation.  It may
	/// be possible to set the position beyond the end of the stream.
	/// \param [in] offset The offset in bytes, relative to the position
	///   specified by the whence parameter.
	/// \param [in] whence One of SEEK_SET, SEEK_CUR or SEEK_END, to
	///   interpret the offset parameter relative to the beginning of
	///   the stream, the current position in the stream, or the end of
	///   the stream, respectively.
	/// \return An error condition of the operation failed.
	virtual std::error_condition seek(std::int64_t offset, int whence) noexcept = 0;

	/// \brief Get the current position in the stream
	///
	/// Gets the position in the stream for the next read or write
	/// operation.  The position may be beyond the end of the stream.
	/// \param [out] result The position in bytes relative to the
	///   beginning of the stream.  Not valid if the operation fails.
	/// \return An error condition if the operation failed.
	virtual std::error_condition tell(std::uint64_t &result) noexcept = 0;

	/// \brief Get the length of the stream
	///
	/// Gets the current length of the stream.
	/// \param [out] result The length of the stream in bytes.  Not
	///   valid if the operation fails.
	/// \return An error condtion if the operation failed.
	virtual std::error_condition length(std::uint64_t &result) noexcept = 0;
};


/// \brief Interface to a random-access byte input sequence
///
/// Provides an interface for reading from arbitrary positions within a
/// byte sequence.  No further structure is provided.
/// \sa read_stream random_write random_read_write
class random_read : public virtual read_stream, public virtual random_access
{
public:
	using ptr = std::unique_ptr<random_read>;

	/// \brief Read from specified position
	///
	/// Reads up to the specified number of bytes into the supplied
	/// buffer.  If seeking is supported, reading starts at the
	/// specified position and the current position is unaffected.  May
	/// read less than the requested number of bytes if the end of the
	/// stream is encountered or an error occurs.
	/// \param [in] offset The position to start reading from, specified
	///   as a number of bytes from the beginning of the stream.
	/// \param [out] buffer Destination buffer.  Must be large enough to
	///   hold the requested number of bytes.
	/// \param [in] length Maximum number of bytes to read.
	/// \param [out] actual Number of bytes actually read.  Will always
	///   be less than or equal to the requested length.
	/// \return An error condition if seeking failed or reading stopped
	///   due to an error.
	virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};


/// \brief Interface to a random-access byte output sequence
///
/// Provides an interface for writing to arbitrary positions within a
/// byte sequence.  No further structure is provided.
/// \sa write_stream random_read random_read_write
class random_write : public virtual write_stream, public virtual random_access
{
public:
	using ptr = std::unique_ptr<random_write>;

	/// \brief Write at specified position
	///
	/// Writes up to the specified number of bytes from the supplied
	/// buffer.  If seeking is supported, writing starts at the
	/// specified position and the current position is unaffected.   May
	/// write less than the requested number of bytes if an error
	/// occurs.
	/// \param [in] offset The position to start writing at, specified
	///   as a number of bytes from the beginning of the stream.
	/// \param [in] buffer Buffer containing the data to write.  Must
	///   contain at least the specified number of bytes.
	/// \param [in] length Number of bytes to write.
	/// \param [out] actual Number of bytes actually written.  Will
	///   always be less than or equal to the requested length.
	/// \return An error condition if seeking failed or writing stopped
	///   due to an error.
	virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};


/// \brief Interface to a random-access read/write byte sequence
///
/// Provides an interface for reading from and writing to arbitrary
/// positions within a byte sequence.  No further structure is provided.
/// \sa random_read random_write read_write_stream
class random_read_write : public read_write_stream, public virtual random_read, public virtual random_write
{
public:
	using ptr = std::unique_ptr<random_read_write>;
};


/// \brief Read from the current position in the stream
///
/// Reads up to the specified number of bytes from the stream into the
/// supplied buffer, continuing if interrupted by asynchronous signals.
/// May read less than the requested number of bytes if the end of the
/// stream is reached or an error occurs.  If the stream supports
/// seeking, reading starts at the current position in the stream, and
/// the current position is incremented by the number of bytes read.
/// The operation may not be atomic if it is interrupted before the
/// requested number of bytes is read.
/// \param [in] stream The stream to read from.
/// \param [out] buffer Destination buffer.  Must be large enough to
///   hold the requested number of bytes.
/// \param [in] length Maximum number of bytes to read.
/// \return A pair containing an error condition if reading stopped due
///   to an error, and the actual number of bytes read.
std::pair<std::error_condition, std::size_t> read(read_stream &stream, void *buffer, std::size_t length) noexcept;

/// \brief Allocate memory and read from the current position in the
///   stream
///
/// Allocates the specified number of bytes and then reads up to that
/// number of bytes from the stream into the newly allocated buffer,
/// continuing if interrupted by asynchronous signals.  May read less
/// than the requested number of bytes if the end of the stream is
/// reached or an error occurs.  If the stream supports seeking,
/// reading starts at the current position in the stream, and the
/// current position is incremented by the number of bytes read.  The
/// operation may not be atomic if it is interrupted before the
/// requested number of bytes is read.  No data will be read if
/// allocation fails.
/// \param [in] stream The stream to read from.
///   hold the requested number of bytes.
/// \param [in] length Maximum number of bytes to read.
/// \return A tuple containing an error condition if allocation failed
///   or reading stopped due to an error, the allocated buffer, and the
///   actual number of bytes read.
std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read(read_stream &stream, std::size_t length) noexcept;

/// \brief Read from the specified position
///
/// Reads up to the specified number of bytes from the stream into the
/// supplied buffer, continuing if interrupted by asynchronous signals.
/// May read less than the requested number of bytes if the end of the
/// stream is reached or an error occurs.  If seeking is supported,
/// reading starts at the specified position and the current position is
/// unaffected.  The operation may not be atomic if it is interrupted
/// before the requested number of bytes is read.
/// \param [in] stream The stream to read from.
/// \param [in] offset The position to start reading from, specified as
///   a number of bytes from the beginning of the stream.
/// \param [out] buffer Destination buffer.  Must be large enough to
///   hold the requested number of bytes.
/// \param [in] length Maximum number of bytes to read.
/// \return A pair containing an error condition if reading stopped due
///   to an error, and the actual number of bytes read.
std::pair<std::error_condition, std::size_t> read_at(random_read &stream, std::uint64_t offset, void *buffer, std::size_t length) noexcept;

/// \brief Allocate memory and read from the specified position
///
/// Allocates the specified number of bytes and then reads up to that
/// number of bytes from the stream into the newly allocated buffer,
/// continuing if interrupted by asynchronous signals.  May read less
/// than the requested number of bytes if the end of the stream is
/// reached or an error occurs.  If seeking is supported, reading
/// starts at the specified position and the current position is
/// unaffected.  The operation may not be atomic if it is interrupted
/// before the requested number of bytes is read.  No data will be read
/// if allocation fails.
/// \param [in] stream The stream to read from.
/// \param [in] offset The position to start reading from, specified as
///   a number of bytes from the beginning of the stream.
/// \param [out] buffer Destination buffer.  Must be large enough to
///   hold the requested number of bytes.
/// \param [in] length Maximum number of bytes to read.
/// \return A tuple containing an error condition if allocation failed
///   or reading stopped due to an error, the allocated buffer, and the
///   actual number of bytes read.
std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read_at(random_read &stream, std::uint64_t offset, std::size_t length) noexcept;

/// \brief Write at the current position in the stream
///
/// Writes up to the specified number of bytes from the supplied
/// buffer to the stream, continuing if interrupted by asynchronous
/// signals.  May write less than the requested number of bytes if an
/// error occurs.  If the stream supports seeking, writing starts at the
/// current position in the stream, and the current position is
/// incremented by the number of bytes written.  The operation may not
/// be atomic if it is interrupted before the requested number of bytes
/// is written.
/// \param [in] stream The stream to write to.
/// \param [in] buffer Buffer containing the data to write.  Must
///   contain at least the specified number of bytes.
/// \param [in] length Number of bytes to write.
/// \return A pair containing an error condition if writing stopped due
///   to an error, and the actual number of bytes written.
std::pair<std::error_condition, std::size_t> write(write_stream &stream, void const *buffer, std::size_t length) noexcept;

/// \brief Write at specified position
///
/// Writes up to the specified number of bytes from the supplied buffer,
/// continuing if interrupted by asynchronous signals.  If seeking is
/// supported, writing starts at the specified position and the current
/// position is unaffected.   May write less than the requested number
/// of bytes if an error occurs.  The operation may not be atomic if it
/// is interrupted before the requested number of bytes is written.
/// \param [in] stream The stream to write to.
/// \param [in] offset The position to start writing at, specified as a
///   number of bytes from the beginning of the stream.
/// \param [in] buffer Buffer containing the data to write.  Must
///   contain at least the specified number of bytes.
/// \param [in] length Number of bytes to write.
/// \return A pair containing an error condition if writing stopped due
///   to an error, and the actual number of bytes written.
std::pair<std::error_condition, std::size_t> write_at(random_write &stream, std::uint64_t offset, void const *buffer, std::size_t length) noexcept;

/// \}


random_read::ptr ram_read(void const *data, std::size_t size) noexcept;
random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept;
random_read::ptr ram_read_copy(void const *data, std::size_t size) noexcept;
random_read::ptr ram_read_copy(void const *data, std::size_t size, std::uint8_t filler) noexcept;

random_read::ptr stdio_read(FILE *file) noexcept;
random_read::ptr stdio_read(FILE *file, std::uint8_t filler) noexcept;
random_read::ptr stdio_read_noclose(FILE *file) noexcept;
random_read::ptr stdio_read_noclose(FILE *file, std::uint8_t filler) noexcept;

random_read_write::ptr stdio_read_write(FILE *file) noexcept;
random_read_write::ptr stdio_read_write(FILE *file, std::uint8_t filler) noexcept;
random_read_write::ptr stdio_read_write_noclose(FILE *file) noexcept;
random_read_write::ptr stdio_read_write_noclose(FILE *file, std::uint8_t filler) noexcept;

random_read::ptr osd_file_read(std::unique_ptr<osd_file> &&file) noexcept;
random_read::ptr osd_file_read(osd_file &file) noexcept;

random_read_write::ptr osd_file_read_write(std::unique_ptr<osd_file> &&file) noexcept;
random_read_write::ptr osd_file_read_write(osd_file &file) noexcept;

} // namespace util

#endif // MAME_LIB_UTIL_IOPROCS_H