1 /* Generic stream implementation -- header file.
2 Copyright (C) 1995 Free Software Foundation, Inc.
3 Copyright (C) 1996 Ben Wing.
5 This file is part of XEmacs.
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
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not in FSF. */
24 /* Written by Ben Wing. */
26 #ifndef INCLUDED_lstream_h_
27 #define INCLUDED_lstream_h_
29 /************************************************************************/
30 /* definition of Lstream object */
31 /************************************************************************/
33 DECLARE_LRECORD (lstream, struct lstream);
34 #define XLSTREAM(x) XRECORD (x, lstream, struct lstream)
35 #define XSETLSTREAM(x, p) XSETRECORD (x, p, lstream)
36 #define LSTREAMP(x) RECORDP (x, lstream)
37 /* #define CHECK_LSTREAM(x) CHECK_RECORD (x, lstream)
38 Lstream pointers should never escape to the Lisp level, so
39 functions should not be doing this. */
45 /* Typedef specifying a count of bytes in a data block to be written
46 out or read in, using Lstream_read(), Lstream_write(), and related
47 functions. This MUST BE SIGNED, since it also is used in functions
48 that return the number of bytes actually read to or written from in
49 an operation, and these functions can return -1 to signal error.
51 Note that the standard Unix read() and write() functions define the
52 count going in as a size_t, which is UNSIGNED, and the count going
53 out as an ssize_t, which is SIGNED. This is a horrible design
54 flaw. Not only is it highly likely to lead to logic errors when a
55 -1 gets interpreted as a large positive number, but operations are
56 bound to fail in all sorts of horrible ways when a number in the
57 upper-half of the size_t range is passed in -- this number is
58 unrepresentable as an ssize_t, so code that checks to see how many
59 bytes are actually written (which is mandatory if you are dealing
60 with certain types of devices) will get completely screwed up.
63 typedef EMACS_INT Lstream_data_count;
65 typedef enum lstream_buffering
69 /* Buffer until a '\n' character is reached. */
70 LSTREAM_LINE_BUFFERED,
71 /* Buffer in standard-size (i.e. 512-byte) blocks. */
72 LSTREAM_BLOCK_BUFFERED,
73 /* Buffer in blocks of a specified size. */
74 LSTREAM_BLOCKN_BUFFERED,
75 /* Buffer until the stream is closed (only applies to write-only
76 streams). Only one call to the stream writer will be made,
77 and that is when the stream is closed. */
81 /* Methods defining how this stream works. Some may be undefined. */
83 /* We do not implement the seek/tell paradigm. I tried to do that,
84 but getting the semantics right in the presence of buffering is
85 extremely tricky and very error-prone and basically not worth it.
86 This is especially the case with complicated streams like
87 decoding streams -- the seek pointer in this case can't be a single
88 integer but has to be a whole complicated structure that records
89 all of the stream's state at the time.
91 Rewind semantics are generally easy to implement, so we do provide
92 a rewind method. Even rewind() may not be available on a stream,
93 however -- e.g. on process output. */
95 typedef struct lstream_implementation
98 Lstream_data_count size; /* Number of additional bytes to be
99 allocated with this stream. Access this
100 data using Lstream_data(). */
101 /* Read some data from the stream's end and store it into DATA, which
102 can hold SIZE bytes. Return the number of bytes read. A return
103 value of 0 means no bytes can be read at this time. This may
104 be because of an EOF, or because there is a granularity greater
105 than one byte that the stream imposes on the returned data, and
106 SIZE is less than this granularity. (This will happen frequently
107 for streams that need to return whole characters, because
108 Lstream_read() calls the reader function repeatedly until it
109 has the number of bytes it wants or until 0 is returned.)
110 The lstream functions do not treat a 0 return as EOF or do
111 anything special; however, the calling function will interpret
112 any 0 it gets back as EOF. This will normally not happen unless
113 the caller calls Lstream_read() with a very small size.
115 This function can be NULL if the stream is output-only. */
116 /* The omniscient mly, blinded by the irresistible thrall of Common
117 Lisp, thinks that it is bogus that the types and implementations
118 of input and output streams are the same. */
119 Lstream_data_count (*reader) (Lstream *stream, unsigned char *data,
120 Lstream_data_count size);
121 /* Send some data to the stream's end. Data to be sent is in DATA
122 and is SIZE bytes. Return the number of bytes sent. This
123 function can send and return fewer bytes than is passed in; in
124 that case, the function will just be called again until there is
125 no data left or 0 is returned. A return value of 0 means that no
126 more data can be currently stored, but there is no error; the
127 data will be squirrelled away until the writer can accept
128 data. (This is useful, e.g., of you're dealing with a
129 non-blocking file descriptor and are getting EWOULDBLOCK errors.)
130 This function can be NULL if the stream is input-only. */
131 Lstream_data_count (*writer) (Lstream *stream, const unsigned char *data,
132 Lstream_data_count size);
133 /* Return non-zero if the last write operation on the stream resulted
134 in an attempt to block (EWOULDBLOCK). If this method does not
135 exists, the implementation returns 0 */
136 int (*was_blocked_p) (Lstream *stream);
137 /* Rewind the stream. If this is NULL, the stream is not seekable. */
138 int (*rewinder) (Lstream *stream);
139 /* Indicate whether this stream is seekable -- i.e. it can be rewound.
140 This method is ignored if the stream does not have a rewind
141 method. If this method is not present, the result is determined
142 by whether a rewind method is present. */
143 int (*seekable_p) (Lstream *stream);
144 /* Perform any additional operations necessary to flush the
145 data in this stream. */
146 int (*flusher) (Lstream *stream);
147 /* Perform any additional operations necessary to close this
148 stream down. May be NULL. This function is called when
149 Lstream_close() is called or when the stream is garbage-
150 collected. When this function is called, all pending data
151 in the stream will already have been written out. */
152 int (*closer) (Lstream *stream);
153 /* Mark this object for garbage collection. Same semantics as
154 a standard Lisp_Object marker. This function can be NULL. */
155 Lisp_Object (*marker) (Lisp_Object lstream);
156 } Lstream_implementation;
158 #define DEFINE_LSTREAM_IMPLEMENTATION(name,c_name,size) \
159 Lstream_implementation c_name[1] = \
160 { { (name), (size) } }
162 #define LSTREAM_FL_IS_OPEN 1
163 #define LSTREAM_FL_READ 2
164 #define LSTREAM_FL_WRITE 4
165 #define LSTREAM_FL_NO_PARTIAL_CHARS 8
166 #define LSTREAM_FL_CLOSE_AT_DISKSAVE 16
170 struct lcrecord_header header;
171 const Lstream_implementation *imp; /* methods for this stream */
172 Lstream_buffering buffering; /* type of buffering in use */
173 Lstream_data_count buffering_size; /* number of bytes buffered */
175 unsigned char *in_buffer; /* holds characters read from stream end */
176 Lstream_data_count in_buffer_size; /* allocated size of buffer */
177 Lstream_data_count in_buffer_current; /* number of characters in buffer */
178 Lstream_data_count in_buffer_ind; /* pointer to next character to
181 unsigned char *out_buffer; /* holds characters to write to stream end */
182 Lstream_data_count out_buffer_size; /* allocated size of buffer */
183 Lstream_data_count out_buffer_ind; /* pointer to next buffer spot to
186 /* The unget buffer is more or less a stack -- things get pushed
187 onto the end and read back from the end. Lstream_read()
188 basically reads backwards from the end to get stuff; Lstream_unread()
189 similarly has to push the data on backwards. */
190 unsigned char *unget_buffer; /* holds characters pushed back onto input */
191 Lstream_data_count unget_buffer_size; /* allocated size of buffer */
192 Lstream_data_count unget_buffer_ind; /* pointer to next buffer spot
193 to write a character */
195 Lstream_data_count byte_count;
200 #define LSTREAM_TYPE_P(lstr, type) \
201 ((lstr)->imp == lstream_##type)
203 #ifdef ERROR_CHECK_TYPECHECK
204 INLINE_HEADER struct lstream *
205 error_check_lstream_type (struct lstream *stream,
206 const Lstream_implementation *imp);
207 INLINE_HEADER struct lstream *
208 error_check_lstream_type (struct lstream *stream,
209 const Lstream_implementation *imp)
211 assert (stream->imp == imp);
214 # define LSTREAM_TYPE_DATA(lstr, type) \
215 ((struct type##_stream *) \
216 Lstream_data (error_check_lstream_type(lstr, lstream_##type)))
218 # define LSTREAM_TYPE_DATA(lstr, type) \
219 ((struct type##_stream *) Lstream_data (lstr))
222 /* Declare that lstream-type TYPE has method M; used in
223 initialization routines */
224 #define LSTREAM_HAS_METHOD(type, m) \
225 (lstream_##type->m = type##_##m)
228 Lstream *Lstream_new (const Lstream_implementation *imp,
230 void Lstream_reopen (Lstream *lstr);
231 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
233 int Lstream_flush (Lstream *lstr);
234 int Lstream_flush_out (Lstream *lstr);
235 int Lstream_fputc (Lstream *lstr, int c);
236 int Lstream_fgetc (Lstream *lstr);
237 void Lstream_fungetc (Lstream *lstr, int c);
238 Lstream_data_count Lstream_read (Lstream *lstr, void *data,
239 Lstream_data_count size);
240 Lstream_data_count Lstream_write (Lstream *lstr, const void *data,
241 Lstream_data_count size);
242 int Lstream_was_blocked_p (Lstream *lstr);
243 void Lstream_unread (Lstream *lstr, const void *data, Lstream_data_count size);
244 int Lstream_rewind (Lstream *lstr);
245 int Lstream_seekable_p (Lstream *lstr);
246 int Lstream_close (Lstream *lstr);
247 void Lstream_delete (Lstream *lstr);
248 void Lstream_set_character_mode (Lstream *str);
250 /* Call the function equivalent if the out buffer is full. Otherwise,
251 add to the end of the out buffer and, if line buffering is called for
252 and the character marks the end of a line, write out the buffer. */
254 #define Lstream_putc(stream, c) \
255 ((stream)->out_buffer_ind >= (stream)->out_buffer_size ? \
256 Lstream_fputc (stream, c) : \
257 ((stream)->out_buffer[(stream)->out_buffer_ind++] = \
258 (unsigned char) (c), \
259 (stream)->byte_count++, \
260 (stream)->buffering == LSTREAM_LINE_BUFFERED && \
261 (stream)->out_buffer[(stream)->out_buffer_ind - 1] == '\n' ? \
262 Lstream_flush_out (stream) : 0))
264 /* Retrieve from unget buffer if there are any characters there;
265 else retrieve from in buffer if there's anything there;
266 else call the function equivalent */
267 #define Lstream_getc(stream) \
268 ((stream)->unget_buffer_ind > 0 ? \
269 ((stream)->byte_count++, \
270 (stream)->unget_buffer[--(stream)->unget_buffer_ind]) : \
271 (stream)->in_buffer_ind < (stream)->in_buffer_current ? \
272 ((stream)->byte_count++, \
273 (stream)->in_buffer[(stream)->in_buffer_ind++]) : \
274 Lstream_fgetc (stream))
276 /* Add to the end if it won't overflow buffer; otherwise call the
277 function equivalent */
278 #define Lstream_ungetc(stream, c) \
279 ((stream)->unget_buffer_ind >= (stream)->unget_buffer_size ? \
280 Lstream_fungetc (stream, c) : \
281 (void) ((stream)->byte_count--, \
282 ((stream)->unget_buffer[(stream)->unget_buffer_ind++] = \
283 (unsigned char) (c))))
285 #define Lstream_data(stream) ((void *) ((stream)->data))
286 #define Lstream_byte_count(stream) ((stream)->byte_count)
289 /************************************************************************/
290 /* working with an Lstream as a stream of Emchars */
291 /************************************************************************/
296 #include "multibyte.h"
300 #include "character.h"
303 INLINE_HEADER Emchar Lstream_get_emchar (Lstream *stream);
305 Lstream_get_emchar (Lstream *stream)
307 int c = Lstream_getc (stream);
308 return (c < 0x80 /* c == EOF || BYTE_ASCII_P (c) */
310 : Lstream_get_emchar_1 (stream, c));
313 INLINE_HEADER int Lstream_put_emchar (Lstream *stream, Emchar ch);
315 Lstream_put_emchar (Lstream *stream, Emchar ch)
317 return CHAR_ASCII_P (ch) ?
318 Lstream_putc (stream, ch) :
319 Lstream_fput_emchar (stream, ch);
322 INLINE_HEADER void Lstream_unget_emchar (Lstream *stream, Emchar ch);
324 Lstream_unget_emchar (Lstream *stream, Emchar ch)
326 if (CHAR_ASCII_P (ch))
327 Lstream_ungetc (stream, ch);
329 Lstream_funget_emchar (stream, ch);
333 # define Lstream_get_emchar(stream) Lstream_getc (stream)
334 # define Lstream_put_emchar(stream, ch) Lstream_putc (stream, ch)
335 # define Lstream_unget_emchar(stream, ch) Lstream_ungetc (stream, ch)
337 #endif /* not MULE */
340 /************************************************************************/
341 /* Lstream implementations */
342 /************************************************************************/
344 /* Flags we can pass to the filedesc and stdio streams. */
346 /* If set, close the descriptor or FILE * when the stream is closed. */
347 #define LSTR_CLOSING 1
349 /* If set, allow quitting out of the actual I/O. */
350 #define LSTR_ALLOW_QUIT 2
352 /* If set and filedesc_stream_set_pty_flushing() has been called
353 on the stream, do not send more than pty_max_bytes on a single
354 line without flushing the data out using the eof_char. */
355 #define LSTR_PTY_FLUSHING 4
357 /* If set, an EWOULDBLOCK error is not treated as an error but
358 simply causes the write function to return 0 as the number
359 of bytes written out. */
360 #define LSTR_BLOCKED_OK 8
362 Lisp_Object make_stdio_input_stream (FILE *stream, int flags);
363 Lisp_Object make_stdio_output_stream (FILE *stream, int flags);
364 Lisp_Object make_filedesc_input_stream (int filedesc, int offset, int count,
366 Lisp_Object make_filedesc_output_stream (int filedesc, int offset, int count,
368 void filedesc_stream_set_pty_flushing (Lstream *stream,
371 int filedesc_stream_fd (Lstream *stream);
372 Lisp_Object make_lisp_string_input_stream (Lisp_Object string,
375 Lisp_Object make_fixed_buffer_input_stream (const void *buf,
376 Lstream_data_count size);
377 Lisp_Object make_fixed_buffer_output_stream (void *buf,
378 Lstream_data_count size);
379 const unsigned char *fixed_buffer_input_stream_ptr (Lstream *stream);
380 unsigned char *fixed_buffer_output_stream_ptr (Lstream *stream);
381 Lisp_Object make_resizing_buffer_output_stream (void);
382 unsigned char *resizing_buffer_stream_ptr (Lstream *stream);
383 Lisp_Object make_dynarr_output_stream (unsigned_char_dynarr *dyn);
384 #define LSTR_SELECTIVE 1
385 #define LSTR_IGNORE_ACCESSIBLE 2
386 Lisp_Object make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start,
387 Bufpos end, int flags);
388 Lisp_Object make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos,
390 Bufpos lisp_buffer_stream_startpos (Lstream *stream);
392 #endif /* INCLUDED_lstream_h_ */