comparison src/lstream.h @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents fdefd0186b75
children 026c5bf9c134
comparison
equal deleted inserted replaced
770:336a418893b5 771:943eaba38521
1 /* Generic stream implementation -- header file. 1 /* Generic stream implementation -- header file.
2 Copyright (C) 1995 Free Software Foundation, Inc. 2 Copyright (C) 1995 Free Software Foundation, Inc.
3 Copyright (C) 1996 Ben Wing. 3 Copyright (C) 1996, 2001 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
41 41
42 #ifndef EOF 42 #ifndef EOF
43 #define EOF (-1) 43 #define EOF (-1)
44 #endif 44 #endif
45 45
46 /* The have been some arguments over the what the type should be that 46 /* There have been some arguments over the what the type should be that
47 specifies a count of bytes in a data block to be written out or read in, 47 specifies a count of bytes in a data block to be written out or read in,
48 using Lstream_read(), Lstream_write(), and related functions. 48 using Lstream_read(), Lstream_write(), and related functions.
49 Originally it was long, which worked fine; Martin "corrected" these to 49 Originally it was long, which worked fine; Martin "corrected" these to
50 size_t and ssize_t on the grounds that this is theoretically cleaner and 50 size_t and ssize_t on the grounds that this is theoretically cleaner and
51 is in keeping with the C standards. Unfortunately, this practice is 51 is in keeping with the C standards. Unfortunately, this practice is
71 bound to fail in all sorts of horrible ways when a number in the 71 bound to fail in all sorts of horrible ways when a number in the
72 upper-half of the size_t range is passed in -- this number is 72 upper-half of the size_t range is passed in -- this number is
73 unrepresentable as an ssize_t, so code that checks to see how many 73 unrepresentable as an ssize_t, so code that checks to see how many
74 bytes are actually written (which is mandatory if you are dealing 74 bytes are actually written (which is mandatory if you are dealing
75 with certain types of devices) will get completely screwed up. 75 with certain types of devices) will get completely screwed up.
76 76
77 --ben 77 --ben
78 */ 78 */
79
80 typedef enum lstream_buffering 79 typedef enum lstream_buffering
81 { 80 {
82 /* No buffering. */ 81 /* No buffering. */
83 LSTREAM_UNBUFFERED, 82 LSTREAM_UNBUFFERED,
84 /* Buffer until a '\n' character is reached. */ 83 /* Buffer until a '\n' character is reached. */
90 /* Buffer until the stream is closed (only applies to write-only 89 /* Buffer until the stream is closed (only applies to write-only
91 streams). Only one call to the stream writer will be made, 90 streams). Only one call to the stream writer will be made,
92 and that is when the stream is closed. */ 91 and that is when the stream is closed. */
93 LSTREAM_UNLIMITED 92 LSTREAM_UNLIMITED
94 } Lstream_buffering; 93 } Lstream_buffering;
94
95 #if 0
96
97 /* #### not currently implemented; correct EOF handling is quite tricky
98 in the presence of various levels of filtering streams, and simply
99 interpreting 0 as EOF works fairly well as long as the amount of
100 data you're attempting to read is large and you know whether the
101 source stream at the end of the chain is a pipe (or other blocking
102 source) or not. we really should fix this, though. */
103
104 /* Return values from Lstream_read(). We do NOT use the C lib trick
105 of returning 0 to maybe indicate EOF because that is simply too
106 random and error-prone. It is quite legitimate for there to be no
107 data available but no EOF, even when not in the presence of
108 non-blocking I/O. For example, decoding/encoding streams (and in
109 general, any type of filtering stream) may only be able to return
110 data after a certain amount of data on the other end is
111 available. */
112
113 #define LSTREAM_EOF -2
114
115 #endif /* 0 */
116
117 #define LSTREAM_ERROR -1
95 118
96 /* Methods defining how this stream works. Some may be undefined. */ 119 /* Methods defining how this stream works. Some may be undefined. */
97 120
98 /* We do not implement the seek/tell paradigm. I tried to do that, 121 /* We do not implement the seek/tell paradigm. I tried to do that,
99 but getting the semantics right in the presence of buffering is 122 but getting the semantics right in the presence of buffering is
157 by whether a rewind method is present. */ 180 by whether a rewind method is present. */
158 int (*seekable_p) (Lstream *stream); 181 int (*seekable_p) (Lstream *stream);
159 /* Perform any additional operations necessary to flush the 182 /* Perform any additional operations necessary to flush the
160 data in this stream. */ 183 data in this stream. */
161 int (*flusher) (Lstream *stream); 184 int (*flusher) (Lstream *stream);
162 /* Perform any additional operations necessary to close this 185 /* Perform any additional operations necessary to close this stream down.
163 stream down. May be NULL. This function is called when 186 May be NULL. This function is called when Lstream_close() is called
164 Lstream_close() is called or when the stream is garbage- 187 (which will be called automatically on any open streams when they are
165 collected. When this function is called, all pending data 188 garbage-collected or deleted with Lstream_delete()). When this
166 in the stream will already have been written out. */ 189 function is called, all pending data in the stream will already have
190 been written out; however, the closer write more data, e.g. an "end"
191 section at the end of a file. */
167 int (*closer) (Lstream *stream); 192 int (*closer) (Lstream *stream);
193 /* Clean up any remaining data at the time that a stream is
194 garbage-collected or deleted with Lstream_delete(). If the stream was
195 open at this point, the finalizer is called after calling
196 Lstream_close(). Called only once (NOT called at disksave time). */
197 void (*finalizer) (Lstream *stream);
168 /* Mark this object for garbage collection. Same semantics as 198 /* Mark this object for garbage collection. Same semantics as
169 a standard Lisp_Object marker. This function can be NULL. */ 199 a standard Lisp_Object marker. This function can be NULL. */
170 Lisp_Object (*marker) (Lisp_Object lstream); 200 Lisp_Object (*marker) (Lisp_Object lstream);
171 } Lstream_implementation; 201 } Lstream_implementation;
172 202
173 #define DEFINE_LSTREAM_IMPLEMENTATION(name,c_name,size) \ 203 #define DEFINE_LSTREAM_IMPLEMENTATION(name, c_name) \
174 Lstream_implementation c_name[1] = \ 204 Lstream_implementation lstream_##c_name[1] = \
175 { { (name), (size) } } 205 { { (name), sizeof (struct c_name##_stream) } }
206
207 #define DECLARE_LSTREAM(c_name) \
208 extern Lstream_implementation lstream_##c_name[]
176 209
177 #define LSTREAM_FL_IS_OPEN 1 210 #define LSTREAM_FL_IS_OPEN 1
178 #define LSTREAM_FL_READ 2 211 #define LSTREAM_FL_READ 2
179 #define LSTREAM_FL_WRITE 4 212 #define LSTREAM_FL_WRITE 4
180 #define LSTREAM_FL_NO_PARTIAL_CHARS 8 213 #define LSTREAM_FL_NO_PARTIAL_CHARS 8
224 const Lstream_implementation *imp) 257 const Lstream_implementation *imp)
225 { 258 {
226 assert (stream->imp == imp); 259 assert (stream->imp == imp);
227 return stream; 260 return stream;
228 } 261 }
229 # define LSTREAM_TYPE_DATA(lstr, type) \ 262 # define LSTREAM_TYPE_DATA(lstr, type) \
230 ((struct type##_stream *) \ 263 ((struct type##_stream *) \
231 Lstream_data (error_check_lstream_type(lstr, lstream_##type))) 264 Lstream_data (error_check_lstream_type (lstr, lstream_##type)))
232 #else 265 #else
233 # define LSTREAM_TYPE_DATA(lstr, type) \ 266 # define LSTREAM_TYPE_DATA(lstr, type) \
234 ((struct type##_stream *) Lstream_data (lstr)) 267 ((struct type##_stream *) Lstream_data (lstr))
235 #endif 268 #endif
236 269
237 /* Declare that lstream-type TYPE has method M; used in 270 /* Declare that lstream-type TYPE has method M; used in initialization
238 initialization routines */ 271 routines */
239 #define LSTREAM_HAS_METHOD(type, m) \ 272 #define LSTREAM_HAS_METHOD(type, m) \
240 (lstream_##type->m = type##_##m) 273 (lstream_##type->m = type##_##m)
241 274
242 275
243 Lstream *Lstream_new (const Lstream_implementation *imp, 276 Lstream *Lstream_new (const Lstream_implementation *imp,
250 int Lstream_fputc (Lstream *lstr, int c); 283 int Lstream_fputc (Lstream *lstr, int c);
251 int Lstream_fgetc (Lstream *lstr); 284 int Lstream_fgetc (Lstream *lstr);
252 void Lstream_fungetc (Lstream *lstr, int c); 285 void Lstream_fungetc (Lstream *lstr, int c);
253 Bytecount Lstream_read (Lstream *lstr, void *data, 286 Bytecount Lstream_read (Lstream *lstr, void *data,
254 Bytecount size); 287 Bytecount size);
255 Bytecount Lstream_write (Lstream *lstr, const void *data, 288 int Lstream_write (Lstream *lstr, const void *data,
256 Bytecount size); 289 Bytecount size);
257 int Lstream_was_blocked_p (Lstream *lstr); 290 int Lstream_was_blocked_p (Lstream *lstr);
258 void Lstream_unread (Lstream *lstr, const void *data, Bytecount size); 291 void Lstream_unread (Lstream *lstr, const void *data, Bytecount size);
259 int Lstream_rewind (Lstream *lstr); 292 int Lstream_rewind (Lstream *lstr);
260 int Lstream_seekable_p (Lstream *lstr); 293 int Lstream_seekable_p (Lstream *lstr);
261 int Lstream_close (Lstream *lstr); 294 int Lstream_close (Lstream *lstr);
295
262 void Lstream_delete (Lstream *lstr); 296 void Lstream_delete (Lstream *lstr);
263 void Lstream_set_character_mode (Lstream *str); 297 void Lstream_set_character_mode (Lstream *str);
264 298 void Lstream_unset_character_mode (Lstream *lstr);
265 /* Call the function equivalent if the out buffer is full. Otherwise, 299
266 add to the end of the out buffer and, if line buffering is called for 300 /* Lstream_putc: Write out one byte to the stream. This is a macro
267 and the character marks the end of a line, write out the buffer. */ 301 and so it is very efficient. The C argument is only evaluated once
268 302 but the STREAM argument is evaluated more than once. Returns 0 on
269 #define Lstream_putc(stream, c) \ 303 success, -1 on error. */
270 ((stream)->out_buffer_ind >= (stream)->out_buffer_size ? \ 304
271 Lstream_fputc (stream, c) : \ 305 #define Lstream_putc(stream, c) \
272 ((stream)->out_buffer[(stream)->out_buffer_ind++] = \ 306 /* Call the function equivalent if the out buffer is full. Otherwise, \
273 (unsigned char) (c), \ 307 add to the end of the out buffer and, if line buffering is called for \
274 (stream)->byte_count++, \ 308 and the character marks the end of a line, write out the buffer. */ \
275 (stream)->buffering == LSTREAM_LINE_BUFFERED && \ 309 ((stream)->out_buffer_ind >= (stream)->out_buffer_size ? \
276 (stream)->out_buffer[(stream)->out_buffer_ind - 1] == '\n' ? \ 310 Lstream_fputc (stream, c) : \
311 ((stream)->out_buffer[(stream)->out_buffer_ind++] = \
312 (unsigned char) (c), \
313 (stream)->byte_count++, \
314 (stream)->buffering == LSTREAM_LINE_BUFFERED && \
315 (stream)->out_buffer[(stream)->out_buffer_ind - 1] == '\n' ? \
277 Lstream_flush_out (stream) : 0)) 316 Lstream_flush_out (stream) : 0))
278 317
279 /* Retrieve from unget buffer if there are any characters there; 318 /* Lstream_getc: Read one byte from the stream and returns it as an
280 else retrieve from in buffer if there's anything there; 319 unsigned char cast to an int, or EOF on end of file or error. This
281 else call the function equivalent */ 320 is a macro and so it is very efficient. The STREAM argument is
282 #define Lstream_getc(stream) \ 321 evaluated more than once. */
322
323 #define Lstream_getc(stream) \
324 /* Retrieve from unget buffer if there are any characters there; \
325 else retrieve from in buffer if there's anything there; \
326 else call the function equivalent */ \
283 ((stream)->unget_buffer_ind > 0 ? \ 327 ((stream)->unget_buffer_ind > 0 ? \
284 ((stream)->byte_count++, \ 328 ((stream)->byte_count++, \
285 (stream)->unget_buffer[--(stream)->unget_buffer_ind]) : \ 329 (stream)->unget_buffer[--(stream)->unget_buffer_ind]) : \
286 (stream)->in_buffer_ind < (stream)->in_buffer_current ? \ 330 (stream)->in_buffer_ind < (stream)->in_buffer_current ? \
287 ((stream)->byte_count++, \ 331 ((stream)->byte_count++, \
288 (stream)->in_buffer[(stream)->in_buffer_ind++]) : \ 332 (stream)->in_buffer[(stream)->in_buffer_ind++]) : \
289 Lstream_fgetc (stream)) 333 Lstream_fgetc (stream))
290 334
291 /* Add to the end if it won't overflow buffer; otherwise call the 335 /* Lstream_ungetc: Push one byte back onto the input queue, cast to
292 function equivalent */ 336 unsigned char. This will be the next byte read from the stream.
337 Any number of bytes can be pushed back and will be read in the
338 reverse order they were pushed back -- most recent first. (This is
339 necessary for consistency -- if there are a number of bytes that
340 have been unread and I read and unread a byte, it needs to be the
341 first to be read again.) This is a macro and so it is very
342 efficient. The C argument is only evaluated once but the STREAM
343 argument is evaluated more than once.
344 */
345
293 #define Lstream_ungetc(stream, c) \ 346 #define Lstream_ungetc(stream, c) \
347 /* Add to the end if it won't overflow buffer; otherwise call the \
348 function equivalent */ \
294 ((stream)->unget_buffer_ind >= (stream)->unget_buffer_size ? \ 349 ((stream)->unget_buffer_ind >= (stream)->unget_buffer_size ? \
295 Lstream_fungetc (stream, c) : \ 350 Lstream_fungetc (stream, c) : \
296 (void) ((stream)->byte_count--, \ 351 (void) ((stream)->byte_count--, \
297 ((stream)->unget_buffer[(stream)->unget_buffer_ind++] = \ 352 ((stream)->unget_buffer[(stream)->unget_buffer_ind++] = \
298 (unsigned char) (c)))) 353 (unsigned char) (c))))
305 /* working with an Lstream as a stream of Emchars */ 360 /* working with an Lstream as a stream of Emchars */
306 /************************************************************************/ 361 /************************************************************************/
307 362
308 #ifdef MULE 363 #ifdef MULE
309 364
310 #ifndef BYTE_ASCII_P
311 #include "mule-charset.h"
312 #endif
313
314 INLINE_HEADER Emchar Lstream_get_emchar (Lstream *stream); 365 INLINE_HEADER Emchar Lstream_get_emchar (Lstream *stream);
315 INLINE_HEADER Emchar 366 INLINE_HEADER Emchar
316 Lstream_get_emchar (Lstream *stream) 367 Lstream_get_emchar (Lstream *stream)
317 { 368 {
318 int c = Lstream_getc (stream); 369 int c = Lstream_getc (stream);
319 return (c < 0x80 /* c == EOF || BYTE_ASCII_P (c) */ 370 return (c < 0x80 /* c == EOF || BYTE_ASCII_P (c) */
320 ? (Emchar) c 371 ? (Emchar) c
321 : Lstream_get_emchar_1 (stream, c)); 372 : Lstream_get_emchar_1 (stream, c));
322 } 373 }
374
375 /* Write an Emchar to a stream. Return value is 0 for success, -1 for
376 failure. */
323 377
324 INLINE_HEADER int Lstream_put_emchar (Lstream *stream, Emchar ch); 378 INLINE_HEADER int Lstream_put_emchar (Lstream *stream, Emchar ch);
325 INLINE_HEADER int 379 INLINE_HEADER int
326 Lstream_put_emchar (Lstream *stream, Emchar ch) 380 Lstream_put_emchar (Lstream *stream, Emchar ch)
327 { 381 {