Mercurial > hg > xemacs-beta
comparison src/lstream.h @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 8de8e3f6228a |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* Generic stream implementation -- header file. | |
2 Copyright (C) 1995 Free Software Foundation, Inc. | |
3 Copyright (C) 1996 Ben Wing. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
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 | |
10 later version. | |
11 | |
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 | |
15 for more details. | |
16 | |
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. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
24 /* Written by Ben Wing. */ | |
25 | |
26 #ifndef _XEMACS_LSTREAM_H_ | |
27 #define _XEMACS_LSTREAM_H_ | |
28 | |
29 /************************************************************************/ | |
30 /* definition of Lstream object */ | |
31 /************************************************************************/ | |
32 | |
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. */ | |
40 | |
41 #ifndef EOF | |
42 #define EOF (-1) | |
43 #endif | |
44 | |
45 typedef enum lstream_buffering | |
46 { | |
47 /* No buffering. */ | |
48 LSTREAM_UNBUFFERED, | |
49 /* Buffer until a '\n' character is reached. */ | |
50 LSTREAM_LINE_BUFFERED, | |
51 /* Buffer in standard-size (i.e. 512-byte) blocks. */ | |
52 LSTREAM_BLOCK_BUFFERED, | |
53 /* Buffer in blocks of a specified size. */ | |
54 LSTREAM_BLOCKN_BUFFERED, | |
55 /* Buffer until the stream is closed (only applies to write-only | |
56 streams). Only one call to the stream writer will be made, | |
57 and that is when the stream is closed. */ | |
58 LSTREAM_UNLIMITED | |
59 } Lstream_buffering; | |
60 | |
61 /* Methods defining how this stream works. Some may be undefined. */ | |
62 | |
63 /* We do not implement the seek/tell paradigm. I tried to do that, | |
64 but getting the semantics right in the presence of buffering is | |
65 extremely tricky and very error-prone and basically not worth it. | |
66 This is especially the case with complicated streams like | |
67 decoding streams -- the seek pointer in this case can't be a single | |
68 integer but has to be a whole complicated structure that records | |
69 all of the stream's state at the time. | |
70 | |
71 Rewind semantics are generally easy to implement, so we do provide | |
72 a rewind method. Even rewind() may not be available on a stream, | |
73 however -- e.g. on process output. */ | |
74 | |
75 typedef struct lstream_implementation | |
76 { | |
77 CONST char *name; | |
78 size_t size; /* Number of additional bytes to be allocated with this | |
79 stream. Access this data using Lstream_data(). */ | |
80 /* Read some data from the stream's end and store it into DATA, which | |
81 can hold SIZE bytes. Return the number of bytes read. A return | |
82 value of 0 means no bytes can be read at this time. This may | |
83 be because of an EOF, or because there is a granularity greater | |
84 than one byte that the stream imposes on the returned data, and | |
85 SIZE is less than this granularity. (This will happen frequently | |
86 for streams that need to return whole characters, because | |
87 Lstream_read() calls the reader function repeatedly until it | |
88 has the number of bytes it wants or until 0 is returned.) | |
89 The lstream functions do not treat a 0 return as EOF or do | |
90 anything special; however, the calling function will interpret | |
91 any 0 it gets back as EOF. This will normally not happen unless | |
92 the caller calls Lstream_read() with a very small size. | |
93 | |
94 This function can be NULL if the stream is output-only. */ | |
95 /* The omniscient mly, blinded by the irresistable thrall of Common | |
96 Lisp, thinks that it is bogus that the types and implementations | |
97 of input and output streams are the same. */ | |
98 ssize_t (*reader) (Lstream *stream, unsigned char *data, size_t size); | |
99 /* Send some data to the stream's end. Data to be sent is in DATA | |
100 and is SIZE bytes. Return the number of bytes sent. This | |
101 function can send and return fewer bytes than is passed in; in | |
102 that case, the function will just be called again until there is | |
103 no data left or 0 is returned. A return value of 0 means that no | |
104 more data can be currently stored, but there is no error; the | |
105 data will be squirrelled away until the writer can accept | |
106 data. (This is useful, e.g., of you're dealing with a | |
107 non-blocking file descriptor and are getting EWOULDBLOCK errors.) | |
108 This function can be NULL if the stream is input-only. */ | |
109 ssize_t (*writer) (Lstream *stream, CONST unsigned char *data, size_t size); | |
110 /* Return non-zero if the last write operation on the stream resulted | |
111 in an attempt to block (EWOULDBLOCK). If this method does not | |
112 exists, the implementation returns 0 */ | |
113 int (*was_blocked_p) (Lstream *stream); | |
114 /* Rewind the stream. If this is NULL, the stream is not seekable. */ | |
115 int (*rewinder) (Lstream *stream); | |
116 /* Indicate whether this stream is seekable -- i.e. it can be rewound. | |
117 This method is ignored if the stream does not have a rewind | |
118 method. If this method is not present, the result is determined | |
119 by whether a rewind method is present. */ | |
120 int (*seekable_p) (Lstream *stream); | |
121 /* Perform any additional operations necessary to flush the | |
122 data in this stream. */ | |
123 int (*flusher) (Lstream *stream); | |
124 /* Perform any additional operations necessary to close this | |
125 stream down. May be NULL. This function is called when | |
126 Lstream_close() is called or when the stream is garbage- | |
127 collected. When this function is called, all pending data | |
128 in the stream will already have been written out. */ | |
129 int (*closer) (Lstream *stream); | |
130 /* Mark this object for garbage collection. Same semantics as | |
131 a standard Lisp_Object marker. This function can be NULL. */ | |
132 Lisp_Object (*marker) (Lisp_Object lstream); | |
133 } Lstream_implementation; | |
134 | |
135 #define DEFINE_LSTREAM_IMPLEMENTATION(name,c_name,size) \ | |
136 Lstream_implementation c_name[1] = \ | |
137 { { (name), (size) } } | |
138 | |
139 #define LSTREAM_FL_IS_OPEN 1 | |
140 #define LSTREAM_FL_READ 2 | |
141 #define LSTREAM_FL_WRITE 4 | |
142 #define LSTREAM_FL_NO_PARTIAL_CHARS 8 | |
143 #define LSTREAM_FL_CLOSE_AT_DISKSAVE 16 | |
144 | |
145 struct lstream | |
146 { | |
147 struct lcrecord_header header; | |
148 CONST Lstream_implementation *imp; /* methods for this stream */ | |
149 Lstream_buffering buffering; /* type of buffering in use */ | |
150 size_t buffering_size; /* number of bytes buffered */ | |
151 | |
152 unsigned char *in_buffer; /* holds characters read from stream end */ | |
153 size_t in_buffer_size; /* allocated size of buffer */ | |
154 size_t in_buffer_current; /* number of characters in buffer */ | |
155 size_t in_buffer_ind; /* pointer to next character to take from buffer */ | |
156 | |
157 unsigned char *out_buffer; /* holds characters to write to stream end */ | |
158 size_t out_buffer_size; /* allocated size of buffer */ | |
159 size_t out_buffer_ind; /* pointer to next buffer spot to write a character */ | |
160 | |
161 /* The unget buffer is more or less a stack -- things get pushed | |
162 onto the end and read back from the end. Lstream_read() | |
163 basically reads backwards from the end to get stuff; Lstream_unread() | |
164 similarly has to push the data on backwards. */ | |
165 unsigned char *unget_buffer; /* holds characters pushed back onto input */ | |
166 size_t unget_buffer_size; /* allocated size of buffer */ | |
167 size_t unget_buffer_ind; /* pointer to next buffer spot to write a character */ | |
168 | |
169 size_t byte_count; | |
170 long flags; /* Align pointer for 64 bit machines (kny) */ | |
171 char data[1]; | |
172 }; | |
173 | |
174 #define LSTREAM_TYPE_P(lstr, type) \ | |
175 ((lstr)->imp == lstream_##type) | |
176 | |
177 #ifdef ERROR_CHECK_TYPECHECK | |
178 INLINE struct lstream * | |
179 error_check_lstream_type (struct lstream *stream, | |
180 CONST Lstream_implementation *imp); | |
181 INLINE struct lstream * | |
182 error_check_lstream_type (struct lstream *stream, | |
183 CONST Lstream_implementation *imp) | |
184 { | |
185 assert (stream->imp == imp); | |
186 return stream; | |
187 } | |
188 # define LSTREAM_TYPE_DATA(lstr, type) \ | |
189 ((struct type##_stream *) \ | |
190 Lstream_data (error_check_lstream_type(lstr, lstream_##type))) | |
191 #else | |
192 # define LSTREAM_TYPE_DATA(lstr, type) \ | |
193 ((struct type##_stream *) Lstream_data (lstr)) | |
194 #endif | |
195 | |
196 /* Declare that lstream-type TYPE has method M; used in | |
197 initialization routines */ | |
198 #define LSTREAM_HAS_METHOD(type, m) \ | |
199 (lstream_##type->m = type##_##m) | |
200 | |
201 | |
202 Lstream *Lstream_new (CONST Lstream_implementation *imp, | |
203 CONST char *mode); | |
204 void Lstream_reopen (Lstream *lstr); | |
205 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering, | |
206 int buffering_size); | |
207 int Lstream_flush (Lstream *lstr); | |
208 int Lstream_flush_out (Lstream *lstr); | |
209 int Lstream_fputc (Lstream *lstr, int c); | |
210 int Lstream_fgetc (Lstream *lstr); | |
211 void Lstream_fungetc (Lstream *lstr, int c); | |
212 ssize_t Lstream_read (Lstream *lstr, void *data, size_t size); | |
213 ssize_t Lstream_write (Lstream *lstr, CONST void *data, size_t size); | |
214 int Lstream_was_blocked_p (Lstream *lstr); | |
215 void Lstream_unread (Lstream *lstr, CONST void *data, size_t size); | |
216 int Lstream_rewind (Lstream *lstr); | |
217 int Lstream_seekable_p (Lstream *lstr); | |
218 int Lstream_close (Lstream *lstr); | |
219 void Lstream_delete (Lstream *lstr); | |
220 void Lstream_set_character_mode (Lstream *str); | |
221 | |
222 /* Call the function equivalent if the out buffer is full. Otherwise, | |
223 add to the end of the out buffer and, if line buffering is called for | |
224 and the character marks the end of a line, write out the buffer. */ | |
225 | |
226 #define Lstream_putc(stream, c) \ | |
227 ((stream)->out_buffer_ind >= (stream)->out_buffer_size ? \ | |
228 Lstream_fputc (stream, c) : \ | |
229 ((stream)->out_buffer[(stream)->out_buffer_ind++] = \ | |
230 (unsigned char) (c), \ | |
231 (stream)->byte_count++, \ | |
232 (stream)->buffering == LSTREAM_LINE_BUFFERED && \ | |
233 (stream)->out_buffer[(stream)->out_buffer_ind - 1] == '\n' ? \ | |
234 Lstream_flush_out (stream) : 0)) | |
235 | |
236 /* Retrieve from unget buffer if there are any characters there; | |
237 else retrieve from in buffer if there's anything there; | |
238 else call the function equivalent */ | |
239 #define Lstream_getc(stream) \ | |
240 ((stream)->unget_buffer_ind > 0 ? \ | |
241 ((stream)->byte_count++, \ | |
242 (stream)->unget_buffer[--(stream)->unget_buffer_ind]) : \ | |
243 (stream)->in_buffer_ind < (stream)->in_buffer_current ? \ | |
244 ((stream)->byte_count++, \ | |
245 (stream)->in_buffer[(stream)->in_buffer_ind++]) : \ | |
246 Lstream_fgetc (stream)) | |
247 | |
248 /* Add to the end if it won't overflow buffer; otherwise call the | |
249 function equivalent */ | |
250 #define Lstream_ungetc(stream, c) \ | |
251 ((stream)->unget_buffer_ind >= (stream)->unget_buffer_size ? \ | |
252 Lstream_fungetc (stream, c) : \ | |
253 (void) ((stream)->byte_count--, \ | |
254 ((stream)->unget_buffer[(stream)->unget_buffer_ind++] = \ | |
255 (unsigned char) (c)))) | |
256 | |
257 #define Lstream_data(stream) ((void *) ((stream)->data)) | |
258 #define Lstream_byte_count(stream) ((stream)->byte_count) | |
259 | |
260 | |
261 /************************************************************************/ | |
262 /* working with an Lstream as a stream of Emchars */ | |
263 /************************************************************************/ | |
264 | |
265 #ifdef MULE | |
266 | |
267 #ifndef BYTE_ASCII_P | |
268 #include "mule-charset.h" | |
269 #endif | |
270 | |
271 INLINE Emchar Lstream_get_emchar (Lstream *stream); | |
272 INLINE Emchar | |
273 Lstream_get_emchar (Lstream *stream) | |
274 { | |
275 int c = Lstream_getc (stream); | |
276 return BYTE_ASCII_P (c) ? (Emchar) c : | |
277 Lstream_get_emchar_1 (stream, c); | |
278 } | |
279 | |
280 INLINE int Lstream_put_emchar (Lstream *stream, Emchar ch); | |
281 INLINE int | |
282 Lstream_put_emchar (Lstream *stream, Emchar ch) | |
283 { | |
284 return CHAR_ASCII_P (ch) ? | |
285 Lstream_putc (stream, ch) : | |
286 Lstream_fput_emchar (stream, ch); | |
287 } | |
288 | |
289 INLINE void Lstream_unget_emchar (Lstream *stream, Emchar ch); | |
290 INLINE void | |
291 Lstream_unget_emchar (Lstream *stream, Emchar ch) | |
292 { | |
293 if (CHAR_ASCII_P (ch)) | |
294 Lstream_ungetc (stream, ch); | |
295 else | |
296 Lstream_funget_emchar (stream, ch); | |
297 } | |
298 #else /* not MULE */ | |
299 | |
300 # define Lstream_get_emchar(stream) Lstream_getc (stream) | |
301 # define Lstream_put_emchar(stream, ch) Lstream_putc (stream, ch) | |
302 # define Lstream_unget_emchar(stream, ch) Lstream_ungetc (stream, ch) | |
303 | |
304 #endif /* not MULE */ | |
305 | |
306 | |
307 /************************************************************************/ | |
308 /* Lstream implementations */ | |
309 /************************************************************************/ | |
310 | |
311 /* Flags we can pass to the filedesc and stdio streams. */ | |
312 | |
313 /* If set, close the descriptor or FILE * when the stream is closed. */ | |
314 #define LSTR_CLOSING 1 | |
315 | |
316 /* If set, allow quitting out of the actual I/O. */ | |
317 #define LSTR_ALLOW_QUIT 2 | |
318 | |
319 /* If set and filedesc_stream_set_pty_flushing() has been called | |
320 on the stream, do not send more than pty_max_bytes on a single | |
321 line without flushing the data out using the eof_char. */ | |
322 #define LSTR_PTY_FLUSHING 4 | |
323 | |
324 /* If set, an EWOULDBLOCK error is not treated as an error but | |
325 simply causes the write function to return 0 as the number | |
326 of bytes written out. */ | |
327 #define LSTR_BLOCKED_OK 8 | |
328 | |
329 Lisp_Object make_stdio_input_stream (FILE *stream, int flags); | |
330 Lisp_Object make_stdio_output_stream (FILE *stream, int flags); | |
331 Lisp_Object make_filedesc_input_stream (int filedesc, int offset, int count, | |
332 int flags); | |
333 Lisp_Object make_filedesc_output_stream (int filedesc, int offset, int count, | |
334 int flags); | |
335 void filedesc_stream_set_pty_flushing (Lstream *stream, | |
336 int pty_max_bytes, | |
337 Bufbyte eof_char); | |
338 int filedesc_stream_fd (Lstream *stream); | |
339 Lisp_Object make_lisp_string_input_stream (Lisp_Object string, | |
340 Bytecount offset, | |
341 Bytecount len); | |
342 Lisp_Object make_fixed_buffer_input_stream (CONST unsigned char *buf, | |
343 size_t size); | |
344 Lisp_Object make_fixed_buffer_output_stream (unsigned char *buf, | |
345 size_t size); | |
346 CONST unsigned char *fixed_buffer_input_stream_ptr (Lstream *stream); | |
347 unsigned char *fixed_buffer_output_stream_ptr (Lstream *stream); | |
348 Lisp_Object make_resizing_buffer_output_stream (void); | |
349 unsigned char *resizing_buffer_stream_ptr (Lstream *stream); | |
350 Lisp_Object make_dynarr_output_stream (unsigned_char_dynarr *dyn); | |
351 #define LSTR_SELECTIVE 1 | |
352 #define LSTR_IGNORE_ACCESSIBLE 2 | |
353 Lisp_Object make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start, | |
354 Bufpos end, int flags); | |
355 Lisp_Object make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos, | |
356 int flags); | |
357 Bufpos lisp_buffer_stream_startpos (Lstream *stream); | |
358 | |
359 #endif /* _XEMACS_LSTREAM_H_ */ |