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