]> pd.if.org Git - pdclib.old/blob - internals/_PDCLIB_io.h
PDCLIB-18: Add _PDCLIB_getchars to _PDCLIB_io.h. Change fread & fgets to go through...
[pdclib.old] / internals / _PDCLIB_io.h
1 #ifndef _PDCLIB_IO_H\r
2 #define _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_int.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 typedef 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 } _PDCLIB_fd_t;\r
46 \r
47 /* Internal functions */\r
48 /* Writes a stream's buffer.\r
49    Returns 0 on success, EOF on write error.\r
50    Sets stream error flags and errno appropriately on error.\r
51 */\r
52 int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream );\r
53 \r
54 /* Fills a stream's buffer.\r
55    Returns 0 on success, EOF on read error / EOF.\r
56    Sets stream EOF / error flags and errno appropriately on error.\r
57 */\r
58 int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream );\r
59 \r
60 /* Repositions within a file. Returns new offset on success,\r
61    -1 / errno on error.\r
62 */\r
63 _PDCLIB_int_fast64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, \r
64                                   _PDCLIB_int_fast64_t offset, int whence );\r
65 \r
66 /* File backend I/O operations\r
67  *\r
68  * PDCLib will call through to these methods as needed to implement the stdio\r
69  * functions.\r
70  */\r
71 typedef struct _PDCLIB_fileops\r
72 {\r
73     /*! Read length bytes from the file into buf; returning the number of bytes\r
74      *  actually read in *numBytesRead.\r
75      *\r
76      *  Returns true if bytes were read successfully; on end of file, returns\r
77      *  true with *numBytesRead == 0.\r
78      *\r
79      *  On error, returns false and sets errno appropriately. *numBytesRead is\r
80      *  ignored in this situation.\r
81      */\r
82     _PDCLIB_bool (*read)( _PDCLIB_fd_t self, \r
83                           void * buf, \r
84                           _PDCLIB_size_t length, \r
85                           _PDCLIB_size_t * numBytesRead );\r
86 \r
87     /*! Write length bytes to the file from buf; returning the number of bytes\r
88      *  actually written in *numBytesWritten\r
89      *\r
90      *  Returns true if bytes were written successfully. On error, returns false\r
91      *  and setss errno appropriately (as with read, *numBytesWritten is \r
92      *  ignored)\r
93      */\r
94     _PDCLIB_bool (*write)( _PDCLIB_fd_t self, const void * buf, \r
95                    _PDCLIB_size_t length, _PDCLIB_size_t * numBytesWritten );\r
96 \r
97     /* Seek to the file offset specified by offset, from location whence, which\r
98      * may be one of the standard constants SEEK_SET/SEEK_CUR/SEEK_END\r
99      */\r
100     _PDCLIB_bool (*seek)( _PDCLIB_fd_t self, _PDCLIB_int_fast64_t offset, \r
101                           int whence, _PDCLIB_int_fast64_t *newPos );\r
102 \r
103     void (*close)( _PDCLIB_fd_t self );\r
104 \r
105     /*! Behaves as read does, except for wide characters. Both length and \r
106      *  *numCharsRead represent counts of characters, not bytes.\r
107      *\r
108      *  This function is optional; if missing, PDCLib will buffer the character\r
109      *  data as bytes and perform translation directly into the user's buffers.\r
110      *  It is useful if your backend can directly take wide characters (for \r
111      *  example, the Windows console)\r
112      */\r
113     _PDCLIB_bool (*wread)( _PDCLIB_fd_t self, _PDCLIB_wchar_t * buf, \r
114                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsRead );\r
115 \r
116     /* Behaves as write does, except for wide characters. As with wread, both\r
117      * length and *numCharsWritten are character counts.\r
118      *\r
119      * This function is also optional; if missing, PDCLib will buffer the \r
120      * character data as bytes and do translation directly from the user's \r
121      * buffers. You only need to implement this if your backend can directly \r
122      * take wide characters (for example, the Windows console)\r
123      */\r
124     _PDCLIB_bool (*wwrite)( _PDCLIB_fd_t self, const _PDCLIB_wchar_t * buf, \r
125                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsWritten );\r
126 } _PDCLIB_fileops_t;\r
127 \r
128 /* Position / status structure for getpos() / fsetpos(). */\r
129 struct _PDCLIB_fpos_t\r
130 {\r
131     _PDCLIB_int_fast64_t offset; /* File position offset */\r
132     int                  status; /* Multibyte parsing state (unused, reserved) */\r
133 };\r
134 \r
135 /* FILE structure */\r
136 struct _PDCLIB_file_t\r
137 {\r
138     const _PDCLIB_fileops_t * ops;\r
139     _PDCLIB_fd_t              handle;   /* OS file handle */\r
140     _PDCLIB_MTX_T             lock;     /* file lock */\r
141     char *                    buffer;   /* Pointer to buffer memory */\r
142     _PDCLIB_size_t            bufsize;  /* Size of buffer */\r
143     _PDCLIB_size_t            bufidx;   /* Index of current position in buffer */\r
144     _PDCLIB_size_t            bufend;   /* Index of last pre-read character in buffer */\r
145     struct _PDCLIB_fpos_t     pos;      /* Offset and multibyte parsing state */\r
146     _PDCLIB_size_t            ungetidx; /* Number of ungetc()'ed characters */\r
147     unsigned char *           ungetbuf; /* ungetc() buffer */\r
148     unsigned int              status;   /* Status flags; see above */\r
149     /* multibyte parsing status to be added later */\r
150     char *                    filename; /* Name the current stream has been opened with */\r
151     struct _PDCLIB_file_t *   next;     /* Pointer to next struct (internal) */\r
152 };\r
153 \r
154 static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n,\r
155                                                int stopchar,\r
156                                                struct _PDCLIB_file_t * stream )\r
157 {\r
158     _PDCLIB_size_t i = 0;\r
159     int c;\r
160     while ( stream->ungetidx > 0 && i != n )\r
161     {\r
162         c = (unsigned char) \r
163                 ( out[ i++ ] = stream->ungetbuf[ --(stream->ungetidx) ] );\r
164         if( c == stopchar )\r
165             return i;\r
166     }\r
167 \r
168     while ( i != n )\r
169     {\r
170         while ( stream->bufidx != stream->bufend && i != n) \r
171         {\r
172             c = (unsigned char) \r
173                 ( out[ i++ ] = stream->buffer[ stream->bufidx++ ] );\r
174             if( c == stopchar )\r
175                 return i;\r
176         }\r
177 \r
178         if ( stream->bufidx == stream->bufend )\r
179         {\r
180             if( _PDCLIB_fillbuffer( stream ) == -1 )\r
181             {\r
182                 return i;\r
183             }\r
184         }\r
185     }\r
186 \r
187     return i;\r
188 }\r
189 \r
190 #endif\r