Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/libc/internals/_PDCLIB_io.h
2 views
1
/* PDCLib I/O support <_PDCLIB_io.h>
2
3
This file is part of the Public Domain C Library (PDCLib).
4
Permission is granted to use, modify, and / or redistribute at will.
5
*/
6
7
#ifndef __PDCLIB_IO_H
8
#define __PDCLIB_IO_H __PDCLIB_IO_H
9
10
#include "_PDCLIB_int.h"
11
#include "_PDCLIB_threadconfig.h"
12
13
/* Flags for representing mode (see fopen()). Note these must fit the same
14
status field as the _IO?BF flags in <stdio.h> and the internal flags below.
15
*/
16
#define _PDCLIB_FREAD 8u
17
#define _PDCLIB_FWRITE 16u
18
#define _PDCLIB_FAPPEND 32u
19
#define _PDCLIB_FRW 64u
20
#define _PDCLIB_FBIN 128u
21
22
/* Internal flags, made to fit the same status field as the flags above. */
23
/* -------------------------------------------------------------------------- */
24
/* free() the buffer memory on closing (false for user-supplied buffer) */
25
#define _PDCLIB_FREEBUFFER 512u
26
/* stream has encountered error / EOF */
27
#define _PDCLIB_ERRORFLAG 1024u
28
#define _PDCLIB_EOFFLAG 2048u
29
/* stream is wide-oriented */
30
#define _PDCLIB_WIDESTREAM 4096u
31
/* stream is byte-oriented */
32
#define _PDCLIB_BYTESTREAM 8192u
33
/* file associated with stream should be remove()d on closing (tmpfile()) */
34
#define _PDCLIB_DELONCLOSE 16384u
35
/* stream handle should not be free()d on close (stdin, stdout, stderr) */
36
#define _PDCLIB_STATIC 32768u
37
38
union _PDCLIB_fd
39
{
40
#if defined(_PDCLIB_OSFD_T)
41
_PDCLIB_OSFD_T osfd;
42
#endif
43
void * pointer;
44
_PDCLIB_uintptr_t uval;
45
_PDCLIB_intptr_t sval;
46
};
47
48
/******************************************************************************/
49
/* Internal functions */
50
/******************************************************************************/
51
52
/* The worker for all printf() type of functions. The pointer spec should point
53
to the introducing '%' of a conversion specifier. The status structure is to
54
be that of the current printf() function, of which the members n, s, stream
55
and arg will be preserved; i will be updated; and all others will be trashed
56
by the function.
57
Returns the number of characters parsed as a conversion specifier (0 if none
58
parsed); returns -1 if the underlying I/O callback returns failure.
59
*/
60
int _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );
61
62
/* The worker for all scanf() type of functions. The pointer spec should point
63
to the introducing '%' of a conversion specifier. The status structure is to
64
be that of the current scanf() function, of which the member stream will be
65
preserved; n, i, and s will be updated; and all others will be trashed by
66
the function.
67
Returns a pointer to the first character not parsed as conversion specifier,
68
or NULL in case of error.
69
FIXME: Should distinguish between matching and input error
70
*/
71
const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status );
72
73
/* Parsing any fopen() style filemode string into a number of flags. */
74
unsigned int _PDCLIB_filemode( const char * mode );
75
76
/* Sanity checking and preparing of read buffer, should be called first thing
77
by any stdio read-data function.
78
Returns 0 on success, EOF on error.
79
On error, EOF / error flags and errno are set appropriately.
80
*/
81
int _PDCLIB_prepread( _PDCLIB_file_t * stream );
82
83
/* Sanity checking, should be called first thing by any stdio write-data
84
function.
85
Returns 0 on success, EOF on error.
86
On error, error flags and errno are set appropriately.
87
*/
88
int _PDCLIB_prepwrite( _PDCLIB_file_t * stream );
89
90
/* Closing all streams on program exit */
91
void _PDCLIB_closeall( void );
92
93
/* Writes a stream's buffer.
94
Returns 0 on success, EOF on write error.
95
Sets stream error flags and errno appropriately on error.
96
*/
97
int _PDCLIB_flushbuffer( _PDCLIB_file_t * stream );
98
99
/* Fills a stream's buffer.
100
Returns 0 on success, EOF on read error / EOF.
101
Sets stream EOF / error flags and errno appropriately on error.
102
*/
103
int _PDCLIB_fillbuffer( _PDCLIB_file_t * stream );
104
105
/* Repositions within a file. Returns new offset on success,
106
-1 / errno on error.
107
*/
108
_PDCLIB_int_fast64_t _PDCLIB_seek( _PDCLIB_file_t * stream,
109
_PDCLIB_int_fast64_t offset, int whence );
110
111
/* File backend I/O operations
112
*
113
* PDCLib will call through to these methods as needed to implement the stdio
114
* functions.
115
*/
116
struct _PDCLIB_fileops
117
{
118
/*! Read length bytes from the file into buf; returning the number of bytes
119
* actually read in *numBytesRead.
120
*
121
* Returns true if bytes were read successfully; on end of file, returns
122
* true with *numBytesRead == 0.
123
*
124
* On error, returns false and sets errno appropriately. *numBytesRead is
125
* ignored in this situation.
126
*/
127
_PDCLIB_bool (*read)( _PDCLIB_fd_t self,
128
void * buf,
129
_PDCLIB_size_t length,
130
_PDCLIB_size_t * numBytesRead );
131
132
/*! Write length bytes to the file from buf; returning the number of bytes
133
* actually written in *numBytesWritten
134
*
135
* Returns true if bytes were written successfully. On error, returns false
136
* and setss errno appropriately (as with read, *numBytesWritten is
137
* ignored)
138
*/
139
_PDCLIB_bool (*write)( _PDCLIB_fd_t self, const void * buf,
140
_PDCLIB_size_t length, _PDCLIB_size_t * numBytesWritten );
141
142
/* Seek to the file offset specified by offset, from location whence, which
143
* may be one of the standard constants SEEK_SET/SEEK_CUR/SEEK_END
144
*/
145
_PDCLIB_bool (*seek)( _PDCLIB_fd_t self, _PDCLIB_int_fast64_t offset,
146
int whence, _PDCLIB_int_fast64_t *newPos );
147
148
void (*close)( _PDCLIB_fd_t self );
149
150
/*! Behaves as read does, except for wide characters. Both length and
151
* *numCharsRead represent counts of characters, not bytes.
152
*
153
* This function is optional; if missing, PDCLib will buffer the character
154
* data as bytes and perform translation directly into the user's buffers.
155
* It is useful if your backend can directly take wide characters (for
156
* example, the Windows console)
157
*/
158
_PDCLIB_bool (*wread)( _PDCLIB_fd_t self, _PDCLIB_wchar_t * buf,
159
_PDCLIB_size_t length, _PDCLIB_size_t * numCharsRead );
160
161
/* Behaves as write does, except for wide characters. As with wread, both
162
* length and *numCharsWritten are character counts.
163
*
164
* This function is also optional; if missing, PDCLib will buffer the
165
* character data as bytes and do translation directly from the user's
166
* buffers. You only need to implement this if your backend can directly
167
* take wide characters (for example, the Windows console)
168
*/
169
_PDCLIB_bool (*wwrite)( _PDCLIB_fd_t self, const _PDCLIB_wchar_t * buf,
170
_PDCLIB_size_t length, _PDCLIB_size_t * numCharsWritten );
171
};
172
173
/* struct _PDCLIB_file structure */
174
struct _PDCLIB_file
175
{
176
const _PDCLIB_fileops_t * ops;
177
_PDCLIB_fd_t handle; /* OS file handle */
178
_PDCLIB_MTX_T lock; /* file lock */
179
char * buffer; /* Pointer to buffer memory */
180
_PDCLIB_size_t bufsize; /* Size of buffer */
181
_PDCLIB_size_t bufidx; /* Index of current position in buffer */
182
_PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */
183
#ifdef _PDCLIB_NEED_EOL_TRANSLATION
184
_PDCLIB_size_t bufnlexp; /* Current position of buffer newline expansion */
185
#endif
186
_PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */
187
unsigned char * ungetbuf; /* ungetc() buffer */
188
unsigned int status; /* Status flags; see above */
189
/* multibyte parsing status to be added later */
190
_PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */
191
char * filename; /* Name the current stream has been opened with */
192
_PDCLIB_file_t * next; /* Pointer to next struct (internal) */
193
};
194
195
static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n,
196
int stopchar,
197
_PDCLIB_file_t * stream )
198
{
199
_PDCLIB_size_t i = 0;
200
int c;
201
while ( stream->ungetidx > 0 && i != n )
202
{
203
c = (unsigned char)
204
( out[ i++ ] = stream->ungetbuf[ --(stream->ungetidx) ] );
205
if( c == stopchar )
206
return i;
207
}
208
209
while ( i != n )
210
{
211
while ( stream->bufidx != stream->bufend && i != n)
212
{
213
c = (unsigned char) stream->buffer[ stream->bufidx++ ];
214
#ifdef _PDCLIB_NEED_EOL_TRANSLATION
215
if ( !( stream->status & _PDCLIB_FBIN ) && c == '\r' )
216
{
217
if ( stream->bufidx == stream->bufend )
218
break;
219
220
if ( stream->buffer[ stream->bufidx ] == '\n' )
221
{
222
c = '\n';
223
stream->bufidx++;
224
}
225
}
226
#endif
227
out[ i++ ] = c;
228
229
if( c == stopchar )
230
return i;
231
}
232
233
if ( i != n )
234
{
235
if( _PDCLIB_fillbuffer( stream ) == -1 )
236
{
237
break;
238
}
239
}
240
}
241
242
#ifdef _PDCLIB_NEED_EOL_TRANSLATION
243
if ( i != n && stream->bufidx != stream->bufend )
244
{
245
// we must have EOF'd immediately after a \r
246
out[ i++ ] = stream->buffer[ stream->bufidx++ ];
247
}
248
#endif
249
250
return i;
251
}
252
253
/* Unlocked functions - internal names
254
*
255
* We can't use the functions using their "normal" names internally because that
256
* would cause namespace leakage. Therefore, we use them by prefixed internal
257
* names
258
*/
259
void _PDCLIB_flockfile(struct _PDCLIB_file *file) _PDCLIB_nothrow;
260
int _PDCLIB_ftrylockfile(struct _PDCLIB_file *file) _PDCLIB_nothrow;
261
void _PDCLIB_funlockfile(struct _PDCLIB_file *file) _PDCLIB_nothrow;
262
263
int _PDCLIB_getc_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
264
int _PDCLIB_getchar_unlocked(void) _PDCLIB_nothrow;
265
int _PDCLIB_putc_unlocked(int c, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
266
int _PDCLIB_putchar_unlocked(int c) _PDCLIB_nothrow;
267
void _PDCLIB_clearerr_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
268
int _PDCLIB_feof_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
269
int _PDCLIB_ferror_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
270
int _PDCLIB_fflush_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
271
int _PDCLIB_fgetc_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
272
int _PDCLIB_fputc_unlocked(int c, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
273
_PDCLIB_size_t _PDCLIB_fread_unlocked(void *ptr, _PDCLIB_size_t size, _PDCLIB_size_t n, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
274
_PDCLIB_size_t _PDCLIB_fwrite_unlocked(const void *ptr, _PDCLIB_size_t size, _PDCLIB_size_t n, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
275
char *_PDCLIB_fgets_unlocked(char *s, int n, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
276
int _PDCLIB_fputs_unlocked(const char *s, struct _PDCLIB_file *stream) _PDCLIB_nothrow;
277
int _PDCLIB_fgetpos_unlocked( struct _PDCLIB_file * _PDCLIB_restrict stream, _PDCLIB_fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow;
278
int _PDCLIB_fsetpos_unlocked( struct _PDCLIB_file * stream, const _PDCLIB_fpos_t * pos ) _PDCLIB_nothrow;
279
long int _PDCLIB_ftell_unlocked( struct _PDCLIB_file * stream ) _PDCLIB_nothrow;
280
int _PDCLIB_fseek_unlocked( struct _PDCLIB_file * stream, long int offset, int whence ) _PDCLIB_nothrow;
281
void _PDCLIB_rewind_unlocked( struct _PDCLIB_file * stream ) _PDCLIB_nothrow;
282
283
int _PDCLIB_puts_unlocked( const char * s ) _PDCLIB_nothrow;
284
int _PDCLIB_ungetc_unlocked( int c, struct _PDCLIB_file * stream ) _PDCLIB_nothrow;
285
286
287
int _PDCLIB_printf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
288
int _PDCLIB_vprintf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
289
int _PDCLIB_fprintf_unlocked( struct _PDCLIB_file * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
290
int _PDCLIB_vfprintf_unlocked( struct _PDCLIB_file * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
291
int _PDCLIB_scanf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
292
int _PDCLIB_vscanf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
293
int _PDCLIB_fscanf_unlocked( struct _PDCLIB_file * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
294
int _PDCLIB_vfscanf_unlocked( struct _PDCLIB_file * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
295
296
#endif
297
298