comparison src/lstream.c @ 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 a5df635868b2
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* Generic stream implementation.
2 Copyright (C) 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Synched up with: Not in FSF. */
24
25 /* Written by Ben Wing. */
26
27 #include <config.h>
28 #include "lisp.h"
29 #include <limits.h>
30
31 #include "buffer.h"
32 #include "insdel.h"
33 #include "lstream.h"
34
35 #include "sysfile.h"
36 #include <errno.h>
37
38 /* This function provides a generic buffering stream implementation.
39 Conceptually, you send data to the stream or read data from the
40 stream, not caring what's on the other end of the stream. The
41 other end could be another stream, a file descriptor, a stdio
42 stream, a fixed block of memory, a reallocating block of memory,
43 etc. The main purpose of the stream is to provide a standard
44 interface and to do buffering. Macros are defined to read
45 or write characters, so the calling functions do not have to
46 worry about blocking data together in order to achieve efficiency.
47 */
48
49 /* Note that this object is called "stream" in Lisp but "lstream"
50 in C. The reason for this is that "stream" is too generic a name
51 for C; too much likelihood of conflict/confusion with C++, etc. */
52
53 /* Functions are as follows:
54
55 Lstream *Lstream_new (Lstream_implementation *imp, CONST char *mode)
56 Allocate and return a new Lstream. This function is not
57 really meant to be called directly; rather, each stream type
58 should provide its own stream creation function, which
59 creates the stream and does any other necessary creation
60 stuff (e.g. opening a file).
61
62 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
63 int buffering_size)
64 Change the buffering of a stream. See lstream.h. By default
65 the buffering is STREAM_BLOCK_BUFFERED.
66
67 int Lstream_flush (Lstream *lstr)
68 Flush out any pending unwritten data in the stream. Clear
69 any buffered input data. Returns 0 on success, -1 on error.
70
71 int Lstream_putc (Lstream *stream, int c)
72 Write out one byte to the stream. This is a macro and so
73 it is very efficient. The C argument is only evaluated once
74 but the STREAM argument is evaluated more than once. Returns
75 0 on success, -1 on error.
76
77 int Lstream_getc (Lstream *stream)
78 Read one byte from the stream. This is a macro and so it
79 is very efficient. The STREAM argument is evaluated more
80 than once. Return value is -1 for EOF or error.
81
82 void Lstream_ungetc (Lstream *stream, int c)
83 Push one byte back onto the input queue. This will be the
84 next byte read from the stream. Any number of bytes can be
85 pushed back and will be read in the reverse order they were
86 pushed back -- most recent first. (This is necessary for
87 consistency -- if there are a number of bytes that have been
88 unread and I read and unread a byte, it needs to be the first
89 to be read again.) This is a macro and so it is very
90 efficient. The C argument is only evaluated once but the
91 STREAM argument is evaluated more than once.
92
93 int Lstream_fputc (Lstream *stream, int c)
94 int Lstream_fgetc (Lstream *stream)
95 void Lstream_fungetc (Lstream *stream, int c)
96 Function equivalents of the above macros.
97
98 ssize_t Lstream_read (Lstream *stream, void *data, size_t size)
99 Read SIZE bytes of DATA from the stream. Return the number of
100 bytes read. 0 means EOF. -1 means an error occurred and no
101 bytes were read.
102
103 ssize_t Lstream_write (Lstream *stream, void *data, size_t size)
104 Write SIZE bytes of DATA to the stream. Return the number of
105 bytes written. -1 means an error occurred and no bytes were
106 written.
107
108 void Lstream_unread (Lstream *stream, void *data, size_t size)
109 Push back SIZE bytes of DATA onto the input queue. The
110 next call to Lstream_read() with the same size will read the
111 same bytes back. Note that this will be the case even if
112 there is other pending unread data.
113
114 int Lstream_delete (Lstream *stream)
115 Frees all memory associated with the stream is freed. Calling
116 this is not strictly necessary, but it is much more efficient
117 than having the Lstream be garbage-collected.
118
119 int Lstream_close (Lstream *stream)
120 Close the stream. All data will be flushed out.
121
122 void Lstream_reopen (Lstream *stream)
123 Reopen a closed stream. This enables I/O on it again.
124 This is not meant to be called except from a wrapper routine
125 that reinitializes variables and such -- the close routine
126 may well have freed some necessary storage structures, for
127 example.
128
129 void Lstream_rewind (Lstream *stream)
130 Rewind the stream to the beginning.
131 */
132
133 #define DEFAULT_BLOCK_BUFFERING_SIZE 512
134 #define MAX_READ_SIZE 512
135
136 static Lisp_Object
137 mark_lstream (Lisp_Object obj)
138 {
139 Lstream *lstr = XLSTREAM (obj);
140 return lstr->imp->marker ? (lstr->imp->marker) (obj) : Qnil;
141 }
142
143 static void
144 print_lstream (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
145 {
146 Lstream *lstr = XLSTREAM (obj);
147 char buf[200];
148
149 sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (%s lstream) 0x%lx>",
150 lstr->imp->name, (long) lstr);
151 write_c_string (buf, printcharfun);
152 }
153
154 static void
155 finalize_lstream (void *header, int for_disksave)
156 {
157 /* WARNING WARNING WARNING. This function (and all finalize functions)
158 may get called more than once on the same object, and may get called
159 (at dump time) on objects that are not being released. */
160 Lstream *lstr = (Lstream *) header;
161
162 #if 0 /* this may cause weird Broken Pipes? */
163 if (for_disksave)
164 {
165 Lstream_pseudo_close (lstr);
166 return;
167 }
168 #endif
169 if (lstr->flags & LSTREAM_FL_IS_OPEN)
170 {
171 if (for_disksave)
172 {
173 if (lstr->flags & LSTREAM_FL_CLOSE_AT_DISKSAVE)
174 Lstream_close (lstr);
175 }
176 else
177 /* Just close. */
178 Lstream_close (lstr);
179 }
180 }
181
182 static size_t
183 sizeof_lstream (CONST void *header)
184 {
185 CONST Lstream *lstr = (CONST Lstream *) header;
186 return sizeof (*lstr) + lstr->imp->size - 1;
187 }
188
189 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("stream", lstream,
190 mark_lstream, print_lstream,
191 finalize_lstream, 0, 0, 0,
192 sizeof_lstream, Lstream);
193
194 void
195 Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
196 int buffering_size)
197 {
198 lstr->buffering = buffering;
199 switch (buffering)
200 {
201 case LSTREAM_UNBUFFERED:
202 lstr->buffering_size = 0; break;
203 case LSTREAM_BLOCK_BUFFERED:
204 lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE; break;
205 case LSTREAM_BLOCKN_BUFFERED:
206 lstr->buffering_size = buffering_size; break;
207 case LSTREAM_LINE_BUFFERED:
208 case LSTREAM_UNLIMITED:
209 lstr->buffering_size = INT_MAX; break;
210 }
211 }
212
213 static CONST Lstream_implementation *lstream_types[32];
214 static Lisp_Object Vlstream_free_list[32];
215 static int lstream_type_count;
216
217 Lstream *
218 Lstream_new (CONST Lstream_implementation *imp, CONST char *mode)
219 {
220 Lstream *p;
221 int i;
222
223 for (i = 0; i < lstream_type_count; i++)
224 {
225 if (lstream_types[i] == imp)
226 break;
227 }
228
229 if (i == lstream_type_count)
230 {
231 assert (lstream_type_count < countof (lstream_types));
232 lstream_types[lstream_type_count] = imp;
233 Vlstream_free_list[lstream_type_count] =
234 make_lcrecord_list (sizeof (*p) + imp->size - 1,
235 &lrecord_lstream);
236 lstream_type_count++;
237 }
238
239 p = XLSTREAM (allocate_managed_lcrecord (Vlstream_free_list[i]));
240 /* Zero it out, except the header. */
241 memset ((char *) p + sizeof (p->header), 0,
242 sizeof (*p) - sizeof (p->header) + imp->size - 1);
243 p->imp = imp;
244 Lstream_set_buffering (p, LSTREAM_BLOCK_BUFFERED, 0);
245 p->flags = LSTREAM_FL_IS_OPEN;
246
247 /* convert mode (one of "r", "w", "rc", "wc") to p->flags */
248 assert (mode[0] == 'r' || mode[0] == 'w');
249 assert (mode[1] == 'c' || mode[1] == '\0');
250 p->flags |= (mode[0] == 'r' ? LSTREAM_FL_READ : LSTREAM_FL_WRITE);
251 if (mode[1] == 'c')
252 p->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
253
254 return p;
255 }
256
257 void
258 Lstream_set_character_mode (Lstream *lstr)
259 {
260 lstr->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
261 }
262
263 void
264 Lstream_delete (Lstream *lstr)
265 {
266 int i;
267 Lisp_Object val;
268
269 XSETLSTREAM (val, lstr);
270 for (i = 0; i < lstream_type_count; i++)
271 {
272 if (lstream_types[i] == lstr->imp)
273 {
274 free_managed_lcrecord (Vlstream_free_list[i], val);
275 return;
276 }
277 }
278
279 abort ();
280 }
281
282 #define Lstream_internal_error(reason, lstr) \
283 Lstream_signal_simple_error ("Internal error: " reason, lstr)
284
285 static void Lstream_signal_simple_error (CONST char *reason, Lstream *lstr)
286 {
287 Lisp_Object obj;
288 XSETLSTREAM (obj, lstr);
289 signal_simple_error (reason, obj);
290 }
291
292 void
293 Lstream_reopen (Lstream *lstr)
294 {
295 if (lstr->flags & LSTREAM_FL_IS_OPEN)
296 Lstream_internal_error ("lstream already open", lstr);
297 lstr->flags |= LSTREAM_FL_IS_OPEN;
298 }
299
300 /* Attempt to flush out all of the buffered data for writing. */
301
302 int
303 Lstream_flush_out (Lstream *lstr)
304 {
305 ssize_t num_written;
306
307 while (lstr->out_buffer_ind > 0)
308 {
309 size_t size = lstr->out_buffer_ind;
310 if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
311 Lstream_internal_error ("lstream not open", lstr);
312 if (! (lstr->flags & LSTREAM_FL_WRITE))
313 Lstream_internal_error ("lstream not open for writing", lstr);
314 if (!lstr->imp->writer)
315 Lstream_internal_error ("lstream has no writer", lstr);
316
317 if (lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
318 /* It's quite possible for us to get passed an incomplete
319 character at the end. We need to spit back that
320 incomplete character. */
321 {
322 CONST unsigned char *data = lstr->out_buffer;
323 CONST unsigned char *dataend = data + size - 1;
324 assert (size > 0); /* safety check ... */
325 /* Optimize the most common case. */
326 if (!BYTE_ASCII_P (*dataend))
327 {
328 /* Go back to the beginning of the last (and possibly partial)
329 character, and bump forward to see if the character is
330 complete. */
331 VALIDATE_CHARPTR_BACKWARD (dataend);
332 if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != data + size)
333 /* If not, chop the size down to ignore the last char
334 and stash it away for next time. */
335 size = dataend - data;
336 /* If we don't even have one character to write, then just
337 skip out. */
338 if (size == 0)
339 break;
340 }
341 }
342
343 num_written = (lstr->imp->writer) (lstr, lstr->out_buffer, size);
344 if (num_written == 0)
345 /* If nothing got written, then just hold the data. This may
346 occur, for example, if this stream does non-blocking I/O;
347 the attempt to write the data might have resulted in an
348 EWOULDBLOCK error. */
349 return 0;
350 else if (num_written >= lstr->out_buffer_ind)
351 lstr->out_buffer_ind = 0;
352 else if (num_written > 0)
353 {
354 memmove (lstr->out_buffer, lstr->out_buffer + num_written,
355 lstr->out_buffer_ind - num_written);
356 lstr->out_buffer_ind -= num_written;
357 }
358 else
359 /* If error, just hold the data, for similar reasons as above. */
360 return -1;
361 }
362
363 if (lstr->imp->flusher)
364 return (lstr->imp->flusher) (lstr);
365
366 return 0;
367 }
368
369 int
370 Lstream_flush (Lstream *lstr)
371 {
372 if (Lstream_flush_out (lstr) < 0)
373 return -1;
374
375 /* clear out buffered data */
376 lstr->in_buffer_current = lstr->in_buffer_ind = 0;
377 lstr->unget_buffer_ind = 0;
378
379 return 0;
380 }
381
382 /* We want to add NUM characters. This function ensures that the
383 buffer is large enough for this (per the buffering size specified
384 in the stream) and returns the number of characters we can
385 actually write. If FORCE is set, ignore the buffering size
386 and go ahead and make space for all the chars even if it exceeds
387 the buffering size. (This is used to deal with the possibility
388 that the stream writer might refuse to write any bytes now, e.g.
389 if it's getting EWOULDBLOCK errors. We have to keep stocking them
390 up until they can be written, so as to avoid losing data. */
391
392 static size_t
393 Lstream_adding (Lstream *lstr, size_t num, int force)
394 {
395 /* Compute the size that the outbuffer needs to be after the
396 chars are added. */
397 size_t size_needed = max (lstr->out_buffer_size,
398 num + lstr->out_buffer_ind);
399 /* Maybe chop it down so that we don't buffer more characters
400 than our advertised buffering size. */
401 if (!force)
402 size_needed = min (lstr->buffering_size, size_needed);
403 DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size,
404 size_needed, unsigned char);
405 /* There might be more data buffered than the buffering size,
406 so make sure we don't return a negative number here. */
407 return max (0, min (num, size_needed - lstr->out_buffer_ind));
408 }
409
410 /* Like Lstream_write(), but does not handle line-buffering correctly. */
411
412 static ssize_t
413 Lstream_write_1 (Lstream *lstr, CONST void *data, size_t size)
414 {
415 CONST unsigned char *p = (CONST unsigned char *) data;
416 ssize_t off = 0;
417 if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
418 Lstream_internal_error ("lstream not open", lstr);
419 if (! (lstr->flags & LSTREAM_FL_WRITE))
420 Lstream_internal_error ("lstream not open for writing", lstr);
421 {
422 int couldnt_write_last_time = 0;
423
424 while (1)
425 {
426 /* Figure out how much we can add to the buffer */
427 size_t chunk = Lstream_adding (lstr, size, 0);
428 if (chunk == 0)
429 {
430 if (couldnt_write_last_time)
431 /* Ung, we ran out of space and tried to flush
432 the buffer, but it didn't work because the stream
433 writer is refusing to accept any data. So we
434 just have to squirrel away all the rest of the
435 stuff. */
436 chunk = Lstream_adding (lstr, size, 1);
437 else
438 couldnt_write_last_time = 1;
439 }
440 /* Do it. */
441 if (chunk > 0)
442 {
443 memcpy (lstr->out_buffer + lstr->out_buffer_ind, p + off, chunk);
444 lstr->out_buffer_ind += chunk;
445 lstr->byte_count += chunk;
446 size -= chunk;
447 off += chunk;
448 }
449 /* If the buffer is full and we have more to add, flush it out. */
450 if (size > 0)
451 {
452 if (Lstream_flush_out (lstr) < 0)
453 {
454 if (off == 0)
455 return -1;
456 else
457 return off;
458 }
459 }
460 else
461 break;
462 }
463 }
464 return off;
465 }
466
467 /* If the stream is not line-buffered, then we can just call
468 Lstream_write_1(), which writes in chunks. Otherwise, we
469 repeatedly call Lstream_putc(), which knows how to handle
470 line buffering. */
471
472 ssize_t
473 Lstream_write (Lstream *lstr, CONST void *data, size_t size)
474 {
475 size_t i;
476 CONST unsigned char *p = (CONST unsigned char *) data;
477
478 if (size == 0)
479 return size;
480 if (lstr->buffering != LSTREAM_LINE_BUFFERED)
481 return Lstream_write_1 (lstr, data, size);
482 for (i = 0; i < size; i++)
483 {
484 if (Lstream_putc (lstr, p[i]) < 0)
485 break;
486 }
487 return i == 0 ? -1 : 0;
488 }
489
490 int
491 Lstream_was_blocked_p (Lstream *lstr)
492 {
493 return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p (lstr) : 0;
494 }
495
496 static int
497 Lstream_raw_read (Lstream *lstr, unsigned char *buffer, size_t size)
498 {
499 if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
500 Lstream_internal_error ("lstream not open", lstr);
501 if (! (lstr->flags & LSTREAM_FL_READ))
502 Lstream_internal_error ("lstream not open for reading", lstr);
503 if (!lstr->imp->reader)
504 Lstream_internal_error ("lstream has no reader", lstr);
505
506 return (lstr->imp->reader) (lstr, buffer, size);
507 }
508
509 /* Assuming the buffer is empty, fill it up again. */
510
511 static ssize_t
512 Lstream_read_more (Lstream *lstr)
513 {
514 #if 0
515 ssize_t size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
516 #else
517 /* If someone requested a larger buffer size, so be it! */
518 ssize_t size_needed = max (1, lstr->buffering_size);
519 #endif
520 ssize_t size_gotten;
521
522 DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
523 size_needed, unsigned char);
524 size_gotten = Lstream_raw_read (lstr, lstr->in_buffer, size_needed);
525 lstr->in_buffer_current = max (0, size_gotten);
526 lstr->in_buffer_ind = 0;
527 return size_gotten < 0 ? -1 : size_gotten;
528 }
529
530 ssize_t
531 Lstream_read (Lstream *lstr, void *data, size_t size)
532 {
533 unsigned char *p = (unsigned char *) data;
534 size_t off = 0;
535 size_t chunk;
536 int error_occurred = 0;
537
538 if (size == 0)
539 return 0;
540
541 /* First try to get some data from the unget buffer */
542 chunk = min (size, lstr->unget_buffer_ind);
543 if (chunk > 0)
544 {
545 /* The bytes come back in reverse order. */
546 for (; off < chunk; off++)
547 p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
548 lstr->byte_count += chunk;
549 size -= chunk;
550 }
551
552 while (size > 0)
553 {
554 /* Take whatever we can from the in buffer */
555 chunk = min (size, lstr->in_buffer_current - lstr->in_buffer_ind);
556 if (chunk > 0)
557 {
558 memcpy (p + off, lstr->in_buffer + lstr->in_buffer_ind, chunk);
559 lstr->in_buffer_ind += chunk;
560 lstr->byte_count += chunk;
561 size -= chunk;
562 off += chunk;
563 }
564
565 /* If we need some more, try to get some more from the stream's end */
566 if (size > 0)
567 {
568 ssize_t retval = Lstream_read_more (lstr);
569 if (retval < 0)
570 error_occurred = 1;
571 if (retval <= 0)
572 break;
573 }
574 }
575
576 /* #### Beware of OFF ending up 0. */
577 if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0)
578 {
579 /* It's quite possible for us to get passed an incomplete
580 character at the end. We need to spit back that
581 incomplete character. */
582 CONST unsigned char *dataend = p + off - 1;
583 /* Optimize the most common case. */
584 if (!BYTE_ASCII_P (*dataend))
585 {
586 /* Go back to the beginning of the last (and possibly partial)
587 character, and bump forward to see if the character is
588 complete. */
589 VALIDATE_CHARPTR_BACKWARD (dataend);
590 if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != p + off)
591 {
592 size_t newoff = dataend - p;
593 /* If not, chop the size down to ignore the last char
594 and stash it away for next time. */
595 Lstream_unread (lstr, dataend, off - newoff);
596 off = newoff;
597 }
598 }
599 }
600
601 return off == 0 && error_occurred ? -1 : (ssize_t) off;
602 }
603
604 void
605 Lstream_unread (Lstream *lstr, CONST void *data, size_t size)
606 {
607 CONST unsigned char *p = (CONST unsigned char *) data;
608
609 /* Make sure buffer is big enough */
610 DO_REALLOC (lstr->unget_buffer, lstr->unget_buffer_size,
611 lstr->unget_buffer_ind + size, unsigned char);
612
613 lstr->byte_count -= size;
614
615 /* Bytes have to go on in reverse order -- they are reversed
616 again when read back. */
617 while (size--)
618 lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
619 }
620
621 int
622 Lstream_rewind (Lstream *lstr)
623 {
624 if (!lstr->imp->rewinder)
625 Lstream_internal_error ("lstream has no rewinder", lstr);
626 if (Lstream_flush (lstr) < 0)
627 return -1;
628 lstr->byte_count = 0;
629 return (lstr->imp->rewinder) (lstr);
630 }
631
632 int
633 Lstream_seekable_p (Lstream *lstr)
634 {
635 if (!lstr->imp->rewinder)
636 return 0;
637 if (!lstr->imp->seekable_p)
638 return 1;
639 return (lstr->imp->seekable_p) (lstr);
640 }
641
642 static int
643 Lstream_pseudo_close (Lstream *lstr)
644 {
645 if (!lstr->flags & LSTREAM_FL_IS_OPEN)
646 Lstream_internal_error ("lstream is not open", lstr);
647
648 /* don't check errors here -- best not to risk file descriptor loss */
649 return Lstream_flush (lstr);
650 }
651
652 int
653 Lstream_close (Lstream *lstr)
654 {
655 int rc = 0;
656
657 if (lstr->flags & LSTREAM_FL_IS_OPEN)
658 {
659 rc = Lstream_pseudo_close (lstr);
660 /*
661 * We used to return immediately if the closer method reported
662 * failure, leaving the stream open. But this is no good, for
663 * the following reasons.
664 *
665 * 1. The finalizer method used in GC makes no provision for
666 * failure, so we must not return without freeing buffer
667 * memory.
668 *
669 * 2. The closer method may have already freed some memory
670 * used for I/O in this stream. E.g. encoding_closer frees
671 * ENCODING_STREAM_DATA(stream)->runoff. If a writer method
672 * tries to use this buffer later, it will write into memory
673 * that may have been allocated elsewhere. Sometime later
674 * you will see a sign that says "Welcome to Crash City."
675 *
676 * 3. The closer can report failure if a flush fails in the
677 * other stream in a MULE encoding/decoding stream pair.
678 * The other stream in the pair is closed, but returning
679 * early leaves the current stream open. If we try to
680 * flush the current stream later, we will crash when the
681 * flusher notices that the other end stream is closed.
682 *
683 * So, we no longer abort the close if the closer method
684 * reports some kind of failure. We still report the failure
685 * to the caller.
686 */
687 if (lstr->imp->closer)
688 if ((lstr->imp->closer) (lstr) < 0)
689 rc = -1;
690 }
691
692 lstr->flags &= ~LSTREAM_FL_IS_OPEN;
693 lstr->byte_count = 0;
694 /* Note that Lstream_flush() reset all the buffer indices. That way,
695 the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
696 on a closed stream will call into the function equivalents, which will
697 cause an error. */
698
699 /* We set the pointers to 0 so that we don't lose when this function
700 is called more than once on the same object */
701 if (lstr->out_buffer)
702 {
703 xfree (lstr->out_buffer);
704 lstr->out_buffer = 0;
705 }
706 if (lstr->in_buffer)
707 {
708 xfree (lstr->in_buffer);
709 lstr->in_buffer = 0;
710 }
711 if (lstr->unget_buffer)
712 {
713 xfree (lstr->unget_buffer);
714 lstr->unget_buffer = 0;
715 }
716
717 return rc;
718 }
719
720 int
721 Lstream_fputc (Lstream *lstr, int c)
722 {
723 unsigned char ch = (unsigned char) c;
724 ssize_t retval = Lstream_write_1 (lstr, &ch, 1);
725 if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
726 return Lstream_flush_out (lstr);
727 return retval < 0 ? -1 : 0;
728 }
729
730 int
731 Lstream_fgetc (Lstream *lstr)
732 {
733 unsigned char ch;
734 if (Lstream_read (lstr, &ch, 1) <= 0)
735 return -1;
736 return ch;
737 }
738
739 void
740 Lstream_fungetc (Lstream *lstr, int c)
741 {
742 unsigned char ch = (unsigned char) c;
743 Lstream_unread (lstr, &ch, 1);
744 }
745
746
747 /************************ some stream implementations *********************/
748
749 /*********** a stdio stream ***********/
750
751 struct stdio_stream
752 {
753 FILE *file;
754 int closing;
755 };
756
757 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
758
759 DEFINE_LSTREAM_IMPLEMENTATION ("stdio", lstream_stdio,
760 sizeof (struct stdio_stream));
761
762 static Lisp_Object
763 make_stdio_stream_1 (FILE *stream, int flags, CONST char *mode)
764 {
765 Lisp_Object obj;
766 Lstream *lstr = Lstream_new (lstream_stdio, mode);
767 struct stdio_stream *str = STDIO_STREAM_DATA (lstr);
768 str->file = stream;
769 str->closing = flags & LSTR_CLOSING;
770 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
771 XSETLSTREAM (obj, lstr);
772 return obj;
773 }
774
775 Lisp_Object
776 make_stdio_input_stream (FILE *stream, int flags)
777 {
778 return make_stdio_stream_1 (stream, flags, "r");
779 }
780
781 Lisp_Object
782 make_stdio_output_stream (FILE *stream, int flags)
783 {
784 return make_stdio_stream_1 (stream, flags, "w");
785 }
786
787 /* #### From reading the Unix 98 specification, it appears that if we
788 want stdio_reader() to be completely correct, we should check for
789 0 < val < size and if so, check to see if an error has occurred.
790 If an error has occurred, but val is non-zero, we should go ahead
791 and act as if the read was successful, but remember in some fashion
792 or other, that an error has occurred, and report that on the next
793 call to stdio_reader instead of calling fread() again.
794
795 Currently, in such a case, we end up calling fread() twice and we
796 assume that
797
798 1) this is not harmful, and
799 2) the error will still be reported on the second read.
800
801 This is probably reasonable, so I don't think we should change this
802 code (it could even be argued that the error might have fixed
803 itself, so we should do the fread() again. */
804
805 static ssize_t
806 stdio_reader (Lstream *stream, unsigned char *data, size_t size)
807 {
808 struct stdio_stream *str = STDIO_STREAM_DATA (stream);
809 size_t val = fread (data, 1, size, str->file);
810 if (!val && ferror (str->file))
811 return -1;
812 return val;
813 }
814
815 static ssize_t
816 stdio_writer (Lstream *stream, CONST unsigned char *data, size_t size)
817 {
818 struct stdio_stream *str = STDIO_STREAM_DATA (stream);
819 size_t val = fwrite (data, 1, size, str->file);
820 if (!val && ferror (str->file))
821 return -1;
822 return val;
823 }
824
825 static int
826 stdio_rewinder (Lstream *stream)
827 {
828 rewind (STDIO_STREAM_DATA (stream)->file);
829 return 0;
830 }
831
832 static int
833 stdio_seekable_p (Lstream *stream)
834 {
835 struct stat lestat;
836 struct stdio_stream *str = STDIO_STREAM_DATA (stream);
837
838 if (fstat (fileno (str->file), &lestat) < 0)
839 return 0;
840 return S_ISREG (lestat.st_mode);
841 }
842
843 static int
844 stdio_flusher (Lstream *stream)
845 {
846 struct stdio_stream *str = STDIO_STREAM_DATA (stream);
847 if (stream->flags & LSTREAM_FL_WRITE)
848 return fflush (str->file);
849 else
850 return 0;
851 }
852
853 static int
854 stdio_closer (Lstream *stream)
855 {
856 struct stdio_stream *str = STDIO_STREAM_DATA (stream);
857 if (str->closing)
858 return fclose (str->file);
859 else
860 if (stream->flags & LSTREAM_FL_WRITE)
861 return fflush (str->file);
862 else
863 return 0;
864 }
865
866 /*********** a file descriptor ***********/
867
868 struct filedesc_stream
869 {
870 int fd;
871 int pty_max_bytes;
872 Bufbyte eof_char;
873 int starting_pos;
874 int current_pos;
875 int end_pos;
876 int chars_sans_newline;
877 unsigned int closing :1;
878 unsigned int allow_quit :1;
879 unsigned int blocked_ok :1;
880 unsigned int pty_flushing :1;
881 unsigned int blocking_error_p :1;
882 };
883
884 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
885
886 DEFINE_LSTREAM_IMPLEMENTATION ("filedesc", lstream_filedesc,
887 sizeof (struct filedesc_stream));
888
889 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
890 OFFSET is the offset from the *current* file pointer that the reading
891 should start at. COUNT is the number of bytes to be read (it is
892 ignored when writing); -1 for unlimited. */
893 static Lisp_Object
894 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
895 CONST char *mode)
896 {
897 Lisp_Object obj;
898 Lstream *lstr = Lstream_new (lstream_filedesc, mode);
899 struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
900 fstr->fd = filedesc;
901 fstr->closing = !!(flags & LSTR_CLOSING);
902 fstr->allow_quit = !!(flags & LSTR_ALLOW_QUIT);
903 fstr->blocked_ok = !!(flags & LSTR_BLOCKED_OK);
904 fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
905 fstr->blocking_error_p = 0;
906 fstr->chars_sans_newline = 0;
907 fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
908 fstr->current_pos = max (fstr->starting_pos, 0);
909 if (count < 0)
910 fstr->end_pos = -1;
911 else
912 fstr->end_pos = fstr->starting_pos + count;
913 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
914 XSETLSTREAM (obj, lstr);
915 return obj;
916 }
917
918 Lisp_Object
919 make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
920 {
921 return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
922 }
923
924 Lisp_Object
925 make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
926 {
927 return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
928 }
929
930 static ssize_t
931 filedesc_reader (Lstream *stream, unsigned char *data, size_t size)
932 {
933 ssize_t nread;
934 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
935 if (str->end_pos >= 0)
936 size = min (size, (size_t) (str->end_pos - str->current_pos));
937 nread = (str->allow_quit ? read_allowing_quit : read) (str->fd, data, size);
938 if (nread > 0)
939 str->current_pos += nread;
940 return nread;
941 }
942
943 static int
944 errno_would_block_p (int val)
945 {
946 #ifdef EWOULDBLOCK
947 if (val == EWOULDBLOCK)
948 return 1;
949 #endif
950 #ifdef EAGAIN
951 if (val == EAGAIN)
952 return 1;
953 #endif
954 return 0;
955 }
956
957 static ssize_t
958 filedesc_writer (Lstream *stream, CONST unsigned char *data, size_t size)
959 {
960 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
961 ssize_t retval;
962 int need_newline = 0;
963
964 /* This function would be simple if it were not for the blasted
965 PTY max-bytes stuff. Why the hell can't they just have written
966 the PTY drivers right so this problem doesn't exist?
967
968 Maybe all the PTY crap here should be moved into another stream
969 that does nothing but periodically insert EOF's as necessary. */
970 if (str->pty_flushing)
971 {
972 /* To make life easy, only send out one line at the most. */
973 CONST unsigned char *ptr;
974
975 ptr = (CONST unsigned char *) memchr (data, '\n', size);
976 if (ptr)
977 need_newline = 1;
978 else
979 ptr = data + size;
980 if (ptr - data >= str->pty_max_bytes - str->chars_sans_newline)
981 {
982 ptr = data + str->pty_max_bytes - str->chars_sans_newline;
983 need_newline = 0;
984 }
985 size = ptr - data;
986 }
987
988 /**** start of non-PTY-crap ****/
989 if (size > 0)
990 retval = ((str->allow_quit ? write_allowing_quit : write)
991 (str->fd, data, size));
992 else
993 retval = 0;
994 if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
995 {
996 str->blocking_error_p = 1;
997 return 0;
998 }
999 str->blocking_error_p = 0;
1000 if (retval < 0)
1001 return retval;
1002 /**** end non-PTY-crap ****/
1003
1004 if (str->pty_flushing)
1005 {
1006 str->chars_sans_newline += retval;
1007 /* Note that a newline was not among the bytes written out.
1008 Add to the number of non-newline bytes written out,
1009 and flush with an EOF if necessary. Be careful to
1010 keep track of write errors as we go along and look
1011 out for EWOULDBLOCK. */
1012 if (str->chars_sans_newline >= str->pty_max_bytes)
1013 {
1014 ssize_t retval2 = ((str->allow_quit ? write_allowing_quit : write)
1015 (str->fd, &str->eof_char, 1));
1016 if (retval2 > 0)
1017 str->chars_sans_newline = 0;
1018 else if (retval2 < 0)
1019 {
1020 /* Error writing the EOF char. If nothing got written,
1021 then treat this as an error -- either return an error
1022 condition or set the blocking-error flag. */
1023 if (retval == 0)
1024 {
1025 if (errno_would_block_p (errno) && str->blocked_ok)
1026 {
1027 str->blocking_error_p = 1;
1028 return 0;
1029 }
1030 else
1031 return retval2;
1032 }
1033 else
1034 return retval;
1035 }
1036 }
1037 }
1038
1039 /* The need_newline flag is necessary because otherwise when the
1040 first byte is a newline, we'd get stuck never writing anything
1041 in pty-flushing mode. */
1042 if (need_newline)
1043 {
1044 Bufbyte nl = '\n';
1045 ssize_t retval2 = ((str->allow_quit ? write_allowing_quit : write)
1046 (str->fd, &nl, 1));
1047 if (retval2 > 0)
1048 {
1049 str->chars_sans_newline = 0;
1050 retval++;
1051 }
1052 else if (retval2 < 0)
1053 {
1054 /* Error writing the newline char. If nothing got written,
1055 then treat this as an error -- either return an error
1056 condition or set the blocking-error flag. */
1057 if (retval == 0)
1058 {
1059 if (errno_would_block_p (errno) && str->blocked_ok)
1060 {
1061 str->blocking_error_p = 1;
1062 return 0;
1063 }
1064 else
1065 return retval2;
1066 }
1067 else
1068 return retval;
1069 }
1070 }
1071
1072 return retval;
1073 }
1074
1075 static int
1076 filedesc_rewinder (Lstream *stream)
1077 {
1078 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1079 if (str->starting_pos < 0 ||
1080 lseek (FILEDESC_STREAM_DATA (stream)->fd, str->starting_pos,
1081 SEEK_SET) == -1)
1082 return -1;
1083 else
1084 {
1085 str->current_pos = str->starting_pos;
1086 return 0;
1087 }
1088 }
1089
1090 static int
1091 filedesc_seekable_p (Lstream *stream)
1092 {
1093 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1094 if (str->starting_pos < 0)
1095 return 0;
1096 else
1097 {
1098 struct stat lestat;
1099
1100 if (fstat (str->fd, &lestat) < 0)
1101 return 0;
1102 return S_ISREG (lestat.st_mode);
1103 }
1104 }
1105
1106 static int
1107 filedesc_closer (Lstream *stream)
1108 {
1109 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1110 if (str->closing)
1111 return close (str->fd);
1112 else
1113 return 0;
1114 }
1115
1116 static int
1117 filedesc_was_blocked_p (Lstream *stream)
1118 {
1119 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1120 return str->blocking_error_p;
1121 }
1122
1123 void
1124 filedesc_stream_set_pty_flushing (Lstream *stream, int pty_max_bytes,
1125 Bufbyte eof_char)
1126 {
1127 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1128 str->pty_max_bytes = pty_max_bytes;
1129 str->eof_char = eof_char;
1130 str->pty_flushing = 1;
1131 }
1132
1133 int
1134 filedesc_stream_fd (Lstream *stream)
1135 {
1136 struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1137 return str->fd;
1138 }
1139
1140 /*********** read from a Lisp string ***********/
1141
1142 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1143
1144 struct lisp_string_stream
1145 {
1146 Lisp_Object obj;
1147 Bytecount init_offset;
1148 Bytecount offset, end;
1149 };
1150
1151 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-string", lstream_lisp_string,
1152 sizeof (struct lisp_string_stream));
1153
1154 Lisp_Object
1155 make_lisp_string_input_stream (Lisp_Object string, Bytecount offset,
1156 Bytecount len)
1157 {
1158 Lisp_Object obj;
1159 Lstream *lstr;
1160 struct lisp_string_stream *str;
1161
1162 CHECK_STRING (string);
1163 if (len < 0)
1164 len = XSTRING_LENGTH (string) - offset;
1165 assert (offset >= 0);
1166 assert (len >= 0);
1167 assert (offset + len <= XSTRING_LENGTH (string));
1168
1169 lstr = Lstream_new (lstream_lisp_string, "r");
1170 str = LISP_STRING_STREAM_DATA (lstr);
1171 str->offset = offset;
1172 str->end = offset + len;
1173 str->init_offset = offset;
1174 str->obj = string;
1175 XSETLSTREAM (obj, lstr);
1176 return obj;
1177 }
1178
1179 static ssize_t
1180 lisp_string_reader (Lstream *stream, unsigned char *data, size_t size)
1181 {
1182 struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1183 /* Don't lose if the string shrank past us ... */
1184 Bytecount offset = min (str->offset, XSTRING_LENGTH (str->obj));
1185 Bufbyte *strstart = XSTRING_DATA (str->obj);
1186 Bufbyte *start = strstart + offset;
1187
1188 /* ... or if someone changed the string and we ended up in the
1189 middle of a character. */
1190 /* Being in the middle of a character is `normal' unless
1191 LSTREAM_NO_PARTIAL_CHARS - mrb */
1192 if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
1193 VALIDATE_CHARPTR_BACKWARD (start);
1194 offset = start - strstart;
1195 size = min (size, (size_t) (str->end - offset));
1196 memcpy (data, start, size);
1197 str->offset = offset + size;
1198 return size;
1199 }
1200
1201 static int
1202 lisp_string_rewinder (Lstream *stream)
1203 {
1204 struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1205 int pos = str->init_offset;
1206 if (pos > str->end)
1207 pos = str->end;
1208 /* Don't lose if the string shrank past us ... */
1209 pos = min (pos, XSTRING_LENGTH (str->obj));
1210 /* ... or if someone changed the string and we ended up in the
1211 middle of a character. */
1212 {
1213 Bufbyte *strstart = XSTRING_DATA (str->obj);
1214 Bufbyte *start = strstart + pos;
1215 VALIDATE_CHARPTR_BACKWARD (start);
1216 pos = start - strstart;
1217 }
1218 str->offset = pos;
1219 return 0;
1220 }
1221
1222 static Lisp_Object
1223 lisp_string_marker (Lisp_Object stream)
1224 {
1225 struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream));
1226 return str->obj;
1227 }
1228
1229 /*********** a fixed buffer ***********/
1230
1231 #define FIXED_BUFFER_STREAM_DATA(stream) \
1232 LSTREAM_TYPE_DATA (stream, fixed_buffer)
1233
1234 struct fixed_buffer_stream
1235 {
1236 CONST unsigned char *inbuf;
1237 unsigned char *outbuf;
1238 size_t size;
1239 size_t offset;
1240 };
1241
1242 DEFINE_LSTREAM_IMPLEMENTATION ("fixed-buffer", lstream_fixed_buffer,
1243 sizeof (struct fixed_buffer_stream));
1244
1245 Lisp_Object
1246 make_fixed_buffer_input_stream (CONST unsigned char *buf, size_t size)
1247 {
1248 Lisp_Object obj;
1249 Lstream *lstr = Lstream_new (lstream_fixed_buffer, "r");
1250 struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1251 str->inbuf = buf;
1252 str->size = size;
1253 XSETLSTREAM (obj, lstr);
1254 return obj;
1255 }
1256
1257 Lisp_Object
1258 make_fixed_buffer_output_stream (unsigned char *buf, size_t size)
1259 {
1260 Lisp_Object obj;
1261 Lstream *lstr = Lstream_new (lstream_fixed_buffer, "w");
1262 struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1263 str->outbuf = buf;
1264 str->size = size;
1265 XSETLSTREAM (obj, lstr);
1266 return obj;
1267 }
1268
1269 static ssize_t
1270 fixed_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1271 {
1272 struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1273 size = min (size, str->size - str->offset);
1274 memcpy (data, str->inbuf + str->offset, size);
1275 str->offset += size;
1276 return size;
1277 }
1278
1279 static ssize_t
1280 fixed_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1281 {
1282 struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1283 if (str->offset == str->size)
1284 {
1285 /* If we're at the end, just throw away the data and pretend
1286 we wrote all of it. If we return 0, then the lstream routines
1287 will try again and again to write it out. */
1288 return size;
1289 }
1290 size = min (size, str->size - str->offset);
1291 memcpy (str->outbuf + str->offset, data, size);
1292 str->offset += size;
1293 return size;
1294 }
1295
1296 static int
1297 fixed_buffer_rewinder (Lstream *stream)
1298 {
1299 FIXED_BUFFER_STREAM_DATA (stream)->offset = 0;
1300 return 0;
1301 }
1302
1303 CONST unsigned char *
1304 fixed_buffer_input_stream_ptr (Lstream *stream)
1305 {
1306 assert (stream->imp == lstream_fixed_buffer);
1307 return FIXED_BUFFER_STREAM_DATA (stream)->inbuf;
1308 }
1309
1310 unsigned char *
1311 fixed_buffer_output_stream_ptr (Lstream *stream)
1312 {
1313 assert (stream->imp == lstream_fixed_buffer);
1314 return FIXED_BUFFER_STREAM_DATA (stream)->outbuf;
1315 }
1316
1317 /*********** write to a resizing buffer ***********/
1318
1319 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1320 LSTREAM_TYPE_DATA (stream, resizing_buffer)
1321
1322 struct resizing_buffer_stream
1323 {
1324 unsigned char *buf;
1325 size_t allocked;
1326 int max_stored;
1327 int stored;
1328 };
1329
1330 DEFINE_LSTREAM_IMPLEMENTATION ("resizing-buffer", lstream_resizing_buffer,
1331 sizeof (struct resizing_buffer_stream));
1332
1333 Lisp_Object
1334 make_resizing_buffer_output_stream (void)
1335 {
1336 Lisp_Object obj;
1337 XSETLSTREAM (obj, Lstream_new (lstream_resizing_buffer, "w"));
1338 return obj;
1339 }
1340
1341 static ssize_t
1342 resizing_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1343 {
1344 struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1345 DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
1346 memcpy (str->buf + str->stored, data, size);
1347 str->stored += size;
1348 str->max_stored = max (str->max_stored, str->stored);
1349 return size;
1350 }
1351
1352 static int
1353 resizing_buffer_rewinder (Lstream *stream)
1354 {
1355 RESIZING_BUFFER_STREAM_DATA (stream)->stored = 0;
1356 return 0;
1357 }
1358
1359 static int
1360 resizing_buffer_closer (Lstream *stream)
1361 {
1362 struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1363 if (str->buf)
1364 {
1365 xfree (str->buf);
1366 str->buf = 0;
1367 }
1368 return 0;
1369 }
1370
1371 unsigned char *
1372 resizing_buffer_stream_ptr (Lstream *stream)
1373 {
1374 return RESIZING_BUFFER_STREAM_DATA (stream)->buf;
1375 }
1376
1377 /*********** write to an unsigned-char dynarr ***********/
1378
1379 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1380 but which is really just an unsigned_char_dynarr (e.g. its type
1381 is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1382
1383 #define DYNARR_STREAM_DATA(stream) \
1384 LSTREAM_TYPE_DATA (stream, dynarr)
1385
1386 struct dynarr_stream
1387 {
1388 unsigned_char_dynarr *dyn;
1389 };
1390
1391 DEFINE_LSTREAM_IMPLEMENTATION ("dynarr", lstream_dynarr,
1392 sizeof (struct dynarr_stream));
1393
1394 Lisp_Object
1395 make_dynarr_output_stream (unsigned_char_dynarr *dyn)
1396 {
1397 Lisp_Object obj;
1398 XSETLSTREAM (obj, Lstream_new (lstream_dynarr, "w"));
1399 DYNARR_STREAM_DATA (XLSTREAM (obj))->dyn = dyn;
1400 return obj;
1401 }
1402
1403 static ssize_t
1404 dynarr_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1405 {
1406 struct dynarr_stream *str = DYNARR_STREAM_DATA (stream);
1407 Dynarr_add_many (str->dyn, data, size);
1408 return size;
1409 }
1410
1411 static int
1412 dynarr_rewinder (Lstream *stream)
1413 {
1414 Dynarr_reset (DYNARR_STREAM_DATA (stream)->dyn);
1415 return 0;
1416 }
1417
1418 static int
1419 dynarr_closer (Lstream *stream)
1420 {
1421 return 0;
1422 }
1423
1424 /************ read from or write to a Lisp buffer ************/
1425
1426 /* Note: Lisp-buffer read streams never return partial characters,
1427 and Lisp-buffer write streams expect to never get partial
1428 characters. */
1429
1430 #define LISP_BUFFER_STREAM_DATA(stream) \
1431 LSTREAM_TYPE_DATA (stream, lisp_buffer)
1432
1433 struct lisp_buffer_stream
1434 {
1435 Lisp_Object buffer;
1436 Lisp_Object orig_start;
1437 /* we use markers to properly deal with insertion/deletion */
1438 Lisp_Object start, end;
1439 int flags;
1440 };
1441
1442 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-buffer", lstream_lisp_buffer,
1443 sizeof (struct lisp_buffer_stream));
1444
1445 static Lisp_Object
1446 make_lisp_buffer_stream_1 (struct buffer *buf, Bufpos start, Bufpos end,
1447 int flags, CONST char *mode)
1448 {
1449 Lisp_Object obj;
1450 Lstream *lstr;
1451 struct lisp_buffer_stream *str;
1452 Bufpos bmin, bmax;
1453 int reading = !strcmp (mode, "r");
1454
1455 /* Make sure the luser didn't pass "w" in. */
1456 if (!strcmp (mode, "w"))
1457 abort ();
1458
1459 if (flags & LSTR_IGNORE_ACCESSIBLE)
1460 {
1461 bmin = BUF_BEG (buf);
1462 bmax = BUF_Z (buf);
1463 }
1464 else
1465 {
1466 bmin = BUF_BEGV (buf);
1467 bmax = BUF_ZV (buf);
1468 }
1469
1470 if (start == -1)
1471 start = bmin;
1472 if (end == -1)
1473 end = bmax;
1474 assert (bmin <= start);
1475 assert (start <= bmax);
1476 if (reading)
1477 {
1478 assert (bmin <= end);
1479 assert (end <= bmax);
1480 assert (start <= end);
1481 }
1482
1483 lstr = Lstream_new (lstream_lisp_buffer, mode);
1484 str = LISP_BUFFER_STREAM_DATA (lstr);
1485 {
1486 Lisp_Object marker;
1487 Lisp_Object buffer;
1488
1489 XSETBUFFER (buffer, buf);
1490 marker = Fmake_marker ();
1491 Fset_marker (marker, make_int (start), buffer);
1492 str->start = marker;
1493 marker = Fmake_marker ();
1494 Fset_marker (marker, make_int (start), buffer);
1495 str->orig_start = marker;
1496 if (reading)
1497 {
1498 marker = Fmake_marker ();
1499 Fset_marker (marker, make_int (end), buffer);
1500 str->end = marker;
1501 }
1502 else
1503 str->end = Qnil;
1504 str->buffer = buffer;
1505 }
1506 str->flags = flags;
1507 XSETLSTREAM (obj, lstr);
1508 return obj;
1509 }
1510
1511 Lisp_Object
1512 make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start, Bufpos end,
1513 int flags)
1514 {
1515 return make_lisp_buffer_stream_1 (buf, start, end, flags, "r");
1516 }
1517
1518 Lisp_Object
1519 make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos, int flags)
1520 {
1521 Lisp_Object lstr = make_lisp_buffer_stream_1 (buf, pos, 0, flags, "wc");
1522
1523 Lstream_set_character_mode (XLSTREAM (lstr));
1524 return lstr;
1525 }
1526
1527 static ssize_t
1528 lisp_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1529 {
1530 struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1531 unsigned char *orig_data = data;
1532 Bytind start;
1533 Bytind end;
1534 struct buffer *buf = XBUFFER (str->buffer);
1535
1536 if (!BUFFER_LIVE_P (buf))
1537 return 0; /* Fut. */
1538
1539 /* NOTE: We do all our operations in Bytind's.
1540 Keep in mind that SIZE is a value in bytes, not chars. */
1541
1542 start = bi_marker_position (str->start);
1543 end = bi_marker_position (str->end);
1544 if (!(str->flags & LSTR_IGNORE_ACCESSIBLE))
1545 {
1546 start = bytind_clip_to_bounds (BI_BUF_BEGV (buf), start,
1547 BI_BUF_ZV (buf));
1548 end = bytind_clip_to_bounds (BI_BUF_BEGV (buf), end,
1549 BI_BUF_ZV (buf));
1550 }
1551
1552 size = min (size, (size_t) (end - start));
1553 end = start + size;
1554 /* We cannot return a partial character. */
1555 VALIDATE_BYTIND_BACKWARD (buf, end);
1556
1557 while (start < end)
1558 {
1559 Bytind ceil;
1560 Bytecount chunk;
1561
1562 if (str->flags & LSTR_IGNORE_ACCESSIBLE)
1563 ceil = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, start);
1564 else
1565 ceil = BI_BUF_CEILING_OF (buf, start);
1566 chunk = min (ceil, end) - start;
1567 memcpy (data, BI_BUF_BYTE_ADDRESS (buf, start), chunk);
1568 data += chunk;
1569 start += chunk;
1570 }
1571
1572 if (EQ (buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE)
1573 {
1574 /* What a kludge. What a kludge. What a kludge. */
1575 unsigned char *p;
1576 for (p = orig_data; p < data; p++)
1577 if (*p == '\r')
1578 *p = '\n';
1579 }
1580
1581 set_bi_marker_position (str->start, end);
1582 return data - orig_data;
1583 }
1584
1585 static ssize_t
1586 lisp_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1587 {
1588 struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1589 Bufpos pos;
1590 struct buffer *buf = XBUFFER (str->buffer);
1591
1592 if (!BUFFER_LIVE_P (buf))
1593 return 0; /* Fut. */
1594
1595 pos = marker_position (str->start);
1596 pos += buffer_insert_raw_string_1 (buf, pos, data, size, 0);
1597 set_marker_position (str->start, pos);
1598 return size;
1599 }
1600
1601 static int
1602 lisp_buffer_rewinder (Lstream *stream)
1603 {
1604 struct lisp_buffer_stream *str =
1605 LISP_BUFFER_STREAM_DATA (stream);
1606 struct buffer *buf = XBUFFER (str->buffer);
1607 long pos = marker_position (str->orig_start);
1608 if (!BUFFER_LIVE_P (buf))
1609 return -1; /* Fut. */
1610 if (pos > BUF_ZV (buf))
1611 pos = BUF_ZV (buf);
1612 if (pos < marker_position (str->orig_start))
1613 pos = marker_position (str->orig_start);
1614 if (MARKERP (str->end) && pos > marker_position (str->end))
1615 pos = marker_position (str->end);
1616 set_marker_position (str->start, pos);
1617 return 0;
1618 }
1619
1620 static Lisp_Object
1621 lisp_buffer_marker (Lisp_Object stream)
1622 {
1623 struct lisp_buffer_stream *str =
1624 LISP_BUFFER_STREAM_DATA (XLSTREAM (stream));
1625
1626 mark_object (str->start);
1627 mark_object (str->end);
1628 return str->buffer;
1629 }
1630
1631 Bufpos
1632 lisp_buffer_stream_startpos (Lstream *stream)
1633 {
1634 return marker_position (LISP_BUFFER_STREAM_DATA (stream)->start);
1635 }
1636
1637
1638 /************************************************************************/
1639 /* initialization */
1640 /************************************************************************/
1641
1642 void
1643 lstream_type_create (void)
1644 {
1645 LSTREAM_HAS_METHOD (stdio, reader);
1646 LSTREAM_HAS_METHOD (stdio, writer);
1647 LSTREAM_HAS_METHOD (stdio, rewinder);
1648 LSTREAM_HAS_METHOD (stdio, seekable_p);
1649 LSTREAM_HAS_METHOD (stdio, flusher);
1650 LSTREAM_HAS_METHOD (stdio, closer);
1651
1652 LSTREAM_HAS_METHOD (filedesc, reader);
1653 LSTREAM_HAS_METHOD (filedesc, writer);
1654 LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
1655 LSTREAM_HAS_METHOD (filedesc, rewinder);
1656 LSTREAM_HAS_METHOD (filedesc, seekable_p);
1657 LSTREAM_HAS_METHOD (filedesc, closer);
1658
1659 LSTREAM_HAS_METHOD (lisp_string, reader);
1660 LSTREAM_HAS_METHOD (lisp_string, rewinder);
1661 LSTREAM_HAS_METHOD (lisp_string, marker);
1662
1663 LSTREAM_HAS_METHOD (fixed_buffer, reader);
1664 LSTREAM_HAS_METHOD (fixed_buffer, writer);
1665 LSTREAM_HAS_METHOD (fixed_buffer, rewinder);
1666
1667 LSTREAM_HAS_METHOD (resizing_buffer, writer);
1668 LSTREAM_HAS_METHOD (resizing_buffer, rewinder);
1669 LSTREAM_HAS_METHOD (resizing_buffer, closer);
1670
1671 LSTREAM_HAS_METHOD (dynarr, writer);
1672 LSTREAM_HAS_METHOD (dynarr, rewinder);
1673 LSTREAM_HAS_METHOD (dynarr, closer);
1674
1675 LSTREAM_HAS_METHOD (lisp_buffer, reader);
1676 LSTREAM_HAS_METHOD (lisp_buffer, writer);
1677 LSTREAM_HAS_METHOD (lisp_buffer, rewinder);
1678 LSTREAM_HAS_METHOD (lisp_buffer, marker);
1679 }
1680
1681 void
1682 reinit_vars_of_lstream (void)
1683 {
1684 int i;
1685
1686 for (i = 0; i < countof (Vlstream_free_list); i++)
1687 {
1688 Vlstream_free_list[i] = Qnil;
1689 staticpro_nodump (&Vlstream_free_list[i]);
1690 }
1691 }
1692
1693 void
1694 vars_of_lstream (void)
1695 {
1696 reinit_vars_of_lstream ();
1697 }