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.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
24 /* Written by Ben Wing. */
30 #include "ui/insdel.h"
36 /*! \page lstream Lstream
39 * A lot to tell here ...
43 /* This function provides a generic buffering stream implementation.
44 Conceptually, you send data to the stream or read data from the
45 stream, not caring what's on the other end of the stream. The
46 other end could be another stream, a file descriptor, a stdio
47 stream, a fixed block of memory, a reallocating block of memory,
48 etc. The main purpose of the stream is to provide a standard
49 interface and to do buffering. Macros are defined to read
50 or write characters, so the calling functions do not have to
51 worry about blocking data together in order to achieve efficiency.
54 /* Note that this object is called "stream" in Lisp but "lstream"
55 in C. The reason for this is that "stream" is too generic a name
56 for C; too much likelihood of conflict/confusion with C++, etc. */
58 /* Functions are as follows:
60 Lstream *Lstream_new (Lstream_implementation *imp, const char *mode)
61 Allocate and return a new Lstream. This function is not
62 really meant to be called directly; rather, each stream type
63 should provide its own stream creation function, which
64 creates the stream and does any other necessary creation
65 stuff (e.g. opening a file).
67 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
69 Change the buffering of a stream. See lstream.h. By default
70 the buffering is STREAM_BLOCK_BUFFERED.
72 int Lstream_flush (Lstream *lstr)
73 Flush out any pending unwritten data in the stream. Clear
74 any buffered input data. Returns 0 on success, -1 on error.
76 int Lstream_putc (Lstream *stream, int c)
77 Write out one byte to the stream. This is a macro and so
78 it is very efficient. The C argument is only evaluated once
79 but the STREAM argument is evaluated more than once. Returns
80 0 on success, -1 on error.
82 int Lstream_getc (Lstream *stream)
83 Read one byte from the stream and returns it as an unsigned
84 char cast to an int, or EOF on end of file or error.
85 This is a macro and so it is very efficient. The STREAM
86 argument is evaluated more than once.
88 void Lstream_ungetc (Lstream *stream, int c)
89 Push one byte back onto the input queue, cast to unsigned char.
90 This will be the next byte read from the stream. Any number
91 of bytes can be pushed back and will be read in the reverse
92 order they were pushed back -- most recent first. (This is
93 necessary for consistency -- if there are a number of bytes
94 that have been unread and I read and unread a byte, it needs
95 to be the first to be read again.) This is a macro and so it
96 is very efficient. The C argument is only evaluated once but
97 the STREAM argument is evaluated more than once.
99 int Lstream_fputc (Lstream *stream, int c)
100 int Lstream_fgetc (Lstream *stream)
101 void Lstream_fungetc (Lstream *stream, int c)
102 Function equivalents of the above macros.
104 Lstream_data_count Lstream_read (Lstream *stream, void *data,
105 Lstream_data_count size)
106 Read SIZE bytes of DATA from the stream. Return the number of
107 bytes read. 0 means EOF. -1 means an error occurred and no
110 Lstream_data_count Lstream_write (Lstream *stream, void *data,
111 Lstream_data_count size)
112 Write SIZE bytes of DATA to the stream. Return the number of
113 bytes written. -1 means an error occurred and no bytes were
116 void Lstream_unread (Lstream *stream, void *data, Lstream_data_count size)
117 Push back SIZE bytes of DATA onto the input queue. The
118 next call to Lstream_read() with the same size will read the
119 same bytes back. Note that this will be the case even if
120 there is other pending unread data.
122 int Lstream_delete (Lstream *stream)
123 Frees all memory associated with the stream is freed. Calling
124 this is not strictly necessary, but it is much more efficient
125 than having the Lstream be garbage-collected.
127 int Lstream_close (Lstream *stream)
128 Close the stream. All data will be flushed out.
130 int Lstream_get_fd (Lstream *stream)
131 Return the underlying filedescriptor or -1.
133 void Lstream_reopen (Lstream *stream)
134 Reopen a closed stream. This enables I/O on it again.
135 This is not meant to be called except from a wrapper routine
136 that reinitializes variables and such -- the close routine
137 may well have freed some necessary storage structures, for
140 void Lstream_rewind (Lstream *stream)
141 Rewind the stream to the beginning.
144 #define DEFAULT_BLOCK_BUFFERING_SIZE 512
145 #define MAX_READ_SIZE 512
147 static Lisp_Object mark_lstream(Lisp_Object obj)
149 lstream_t lstr = XLSTREAM(obj);
150 return lstr->imp->marker ? (lstr->imp->marker) (obj) : Qnil;
154 print_lstream(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
156 lstream_t lstr = XLSTREAM(obj);
157 write_fmt_string(printcharfun, "#<INTERNAL OBJECT (SXEmacs bug?) (%s lstream) 0x%lx>",
158 lstr->imp->name, (long)lstr);
161 static void finalize_lstream(void *header, int for_disksave)
163 /* WARNING WARNING WARNING. This function (and all finalize functions)
164 may get called more than once on the same object, and may get called
165 (at dump time) on objects that are not being released. */
166 lstream_t lstr = header;
168 #if 0 /* this may cause weird Broken Pipes? */
170 Lstream_pseudo_close(lstr);
174 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
176 if (lstr->flags & LSTREAM_FL_CLOSE_AT_DISKSAVE)
185 aligned_sizeof_lstream(size_t lstream_type_specific_size)
187 return ALIGN_SIZE(offsetof(struct lstream_s, data) +
188 lstream_type_specific_size,
189 ALIGNOF(max_align_t));
193 sizeof_lstream(const void *header)
195 REGISTER size_t imp_size = ((const struct lstream_s*)header)->imp->size;
196 return aligned_sizeof_lstream(imp_size);
199 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("stream", lstream,
200 mark_lstream, print_lstream,
201 finalize_lstream, 0, 0, 0,
202 sizeof_lstream, struct lstream_s);
205 * Replaces DO_REALLOC from lisp.h. */
206 #define LSTR_ALLOC_TO DO_REALLOC_ATOMIC
210 Lstream_set_buffering(lstream_t lstr, Lstream_buffering buffering, int bsz)
212 lstr->buffering = buffering;
214 case LSTREAM_UNBUFFERED:
215 lstr->buffering_size = 0;
217 case LSTREAM_BLOCK_BUFFERED:
218 lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE;
220 case LSTREAM_BLOCKN_BUFFERED:
221 lstr->buffering_size = bsz;
223 case LSTREAM_LINE_BUFFERED:
224 case LSTREAM_UNLIMITED:
225 lstr->buffering_size = INT_MAX;
232 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
233 static const Lstream_implementation *lstream_types[32];
234 static Lisp_Object Vlstream_free_list[32];
235 static int lstream_type_count;
238 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
240 lstr_finaliser(void *obj, void *UNUSED(data))
242 finalize_lstream(obj, 0);
248 Lstream_new(const Lstream_implementation *imp, const char *mode)
252 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
253 GC_finalization_proc *foo = NULL;
256 p = xmalloc(aligned_sizeof_lstream(imp->size));
257 set_lheader_implementation(&p->header.lheader, &lrecord_lstream);
259 GC_REGISTER_FINALIZER(p, lstr_finaliser, NULL, foo, bar);
264 for (i = 0; i < lstream_type_count; i++) {
265 if (lstream_types[i] == imp)
269 if (i == lstream_type_count) {
270 assert(lstream_type_count < countof(lstream_types));
271 lstream_types[lstream_type_count] = imp;
272 Vlstream_free_list[lstream_type_count] =
273 make_lcrecord_list(aligned_sizeof_lstream(imp->size),
275 lstream_type_count++;
278 tmp = allocate_managed_lcrecord(Vlstream_free_list[i]);
280 /* Zero it out, except the header. */
281 memset((char *)p + sizeof(p->header), '\0',
282 aligned_sizeof_lstream(imp->size) - sizeof(p->header));
286 Lstream_set_buffering(p, LSTREAM_BLOCK_BUFFERED, 0);
287 p->flags = LSTREAM_FL_IS_OPEN;
289 /* convert mode (one of "r", "w", "rc", "wc") to p->flags */
290 assert(mode[0] == 'r' || mode[0] == 'w');
291 assert(mode[1] == 'c' || mode[1] == '\0');
292 p->flags |= (mode[0] == 'r' ? LSTREAM_FL_READ : LSTREAM_FL_WRITE);
293 if (mode[1] == 'c') {
294 p->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
300 Lstream_set_character_mode(lstream_t lstr)
302 lstr->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
306 Lstream_delete(lstream_t lstr)
308 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
315 XSETLSTREAM(val, lstr);
316 for (int i = 0; i < lstream_type_count; i++) {
317 if (lstream_types[i] == lstr->imp) {
318 free_managed_lcrecord(Vlstream_free_list[i], val);
327 #define Lstream_internal_error(reason, lstr) \
328 Lstream_signal_simple_error(lstr, "Internal error: " reason)
331 Lstream_signal_simple_error(lstream_t lstr, const char *reason)
334 XSETLSTREAM(obj, lstr);
335 signal_simple_error(reason, obj);
339 Lstream_reopen(lstream_t lstr)
341 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
342 Lstream_internal_error("lstream already open", lstr);
344 lstr->flags |= LSTREAM_FL_IS_OPEN;
347 /* Attempt to flush out all of the buffered data for writing. */
350 Lstream_flush_out(lstream_t lstr)
352 Lstream_data_count num_written;
354 while (lstr->out_buffer_ind > 0) {
355 Lstream_data_count size = lstr->out_buffer_ind;
356 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
357 Lstream_internal_error("lstream not open", lstr);
359 if (!(lstr->flags & LSTREAM_FL_WRITE)) {
360 Lstream_internal_error("lstream not open for writing",
363 if (!lstr->imp->writer) {
364 Lstream_internal_error("lstream has no writer", lstr);
366 if (lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
367 /* It's quite possible for us to get passed an
368 incomplete character at the end. We need to spit
369 back that incomplete character. */
371 const unsigned char *data = lstr->out_buffer;
372 const unsigned char *dataend = data + size - 1;
373 assert(size > 0); /* safety check ... */
374 /* Optimize the most common case. */
375 if (!BYTE_ASCII_P(*dataend)) {
376 /* Go back to the beginning of the last (and
377 possibly partial) character, and bump forward
378 to see if the character is complete. */
379 VALIDATE_CHARPTR_BACKWARD(dataend);
381 REP_BYTES_BY_FIRST_BYTE(*dataend) !=
383 /* If not, chop the size down to ignore
384 the last char and stash it away for
386 size = dataend - data;
388 /* If we don't even have one character to write,
389 then just skip out. */
396 num_written = lstr->imp->writer(lstr, lstr->out_buffer, size);
397 if (num_written == 0) {
398 /* If nothing got written, then just hold the data.
399 This may occur, for example, if this stream does
400 non-blocking I/O; the attempt to write the data might
401 have resulted in an EWOULDBLOCK error. */
403 } else if (num_written >= lstr->out_buffer_ind) {
404 lstr->out_buffer_ind = 0;
405 } else if (num_written > 0) {
406 memmove(lstr->out_buffer,
407 lstr->out_buffer + num_written,
408 lstr->out_buffer_ind - num_written);
409 lstr->out_buffer_ind -= num_written;
411 /* If error, just hold the data, for similar reasons as
417 if (lstr->imp->flusher) {
418 return (lstr->imp->flusher) (lstr);
424 Lstream_flush(lstream_t lstr)
426 if (Lstream_flush_out(lstr) < 0) {
429 /* clear out buffered data */
430 lstr->in_buffer_current = lstr->in_buffer_ind = 0;
431 lstr->unget_buffer_ind = 0;
436 /* We want to add NUM characters. This function ensures that the
437 buffer is large enough for this (per the buffering size specified
438 in the stream) and returns the number of characters we can
439 actually write. If FORCE is set, ignore the buffering size
440 and go ahead and make space for all the chars even if it exceeds
441 the buffering size. (This is used to deal with the possibility
442 that the stream writer might refuse to write any bytes now, e.g.
443 if it's getting EWOULDBLOCK errors. We have to keep stocking them
444 up until they can be written, so as to avoid losing data. */
446 static Lstream_data_count
447 Lstream_adding(lstream_t lstr, Lstream_data_count num, int force)
449 Lstream_data_count size = num + lstr->out_buffer_ind;
451 if (size <= lstr->out_buffer_size) {
454 /* Maybe chop it down so that we don't buffer more characters
455 than our advertised buffering size. */
456 if ((size > lstr->buffering_size) && !force) {
457 size = lstr->buffering_size;
458 /* There might be more data buffered than the buffering size. */
459 if (size <= lstr->out_buffer_ind) {
464 LSTR_ALLOC_TO(lstr->out_buffer,
465 lstr->out_buffer_size, size, unsigned char);
467 return size - lstr->out_buffer_ind;
470 /* Like Lstream_write(), but does not handle line-buffering correctly. */
472 static Lstream_data_count
473 Lstream_write_1(lstream_t lstr, const void *data, Lstream_data_count size)
475 const unsigned char *p = data;
476 Lstream_data_count off = 0;
477 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
478 Lstream_internal_error("lstream not open", lstr);
480 if (!(lstr->flags & LSTREAM_FL_WRITE)) {
481 Lstream_internal_error("lstream not open for writing", lstr);
484 bool couldnt_write_last_time = false;
487 /* Figure out how much we can add to the buffer */
488 Lstream_data_count chunk =
489 Lstream_adding(lstr, size, 0);
491 if (couldnt_write_last_time) {
492 /* Ung, we ran out of space and tried to
493 flush the buffer, but it didn't work
494 because the stream writer is refusing
495 to accept any data. So we just have
496 to squirrel away all the rest of the
498 chunk = Lstream_adding(lstr, size, 1);
500 couldnt_write_last_time = true;
505 memcpy(lstr->out_buffer + lstr->out_buffer_ind,
507 lstr->out_buffer_ind += chunk;
508 lstr->byte_count += chunk;
512 /* If the buffer is full and we have more to add, flush
515 if (Lstream_flush_out(lstr) < 0) {
530 /* If the stream is not line-buffered, then we can just call
531 Lstream_write_1(), which writes in chunks. Otherwise, we
532 repeatedly call Lstream_putc(), which knows how to handle
533 line buffering. Returns number of bytes written. */
536 Lstream_write(lstream_t lstr, const void *data, Lstream_data_count size)
538 Lstream_data_count i;
539 const unsigned char *p = data;
544 if (lstr->buffering != LSTREAM_LINE_BUFFERED) {
545 return Lstream_write_1(lstr, data, size);
547 for (i = 0; i < size; i++) {
548 if (Lstream_putc(lstr, p[i]) < 0) {
552 return i == 0 ? -1 : i;
556 Lstream_was_blocked_p(lstream_t lstr)
558 return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p(lstr) : 0;
561 static Lstream_data_count
562 Lstream_raw_read(lstream_t lstr, unsigned char *buffer, Lstream_data_count size)
564 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
565 Lstream_internal_error("lstream not open", lstr);
567 if (!(lstr->flags & LSTREAM_FL_READ)) {
568 Lstream_internal_error("lstream not open for reading", lstr);
570 if (!lstr->imp->reader) {
571 Lstream_internal_error("lstream has no reader", lstr);
573 return lstr->imp->reader(lstr, buffer, size);
576 /* Assuming the buffer is empty, fill it up again. */
578 static Lstream_data_count
579 Lstream_read_more(lstream_t lstr)
581 /* If someone requested a larger buffer size, so be it! */
582 Lstream_data_count size_needed = max(1, lstr->buffering_size);
583 Lstream_data_count size_gotten;
585 LSTR_ALLOC_TO(lstr->in_buffer, lstr->in_buffer_size,
586 size_needed, unsigned char);
587 size_gotten = Lstream_raw_read(lstr, lstr->in_buffer, size_needed);
588 lstr->in_buffer_current = max(0, size_gotten);
589 lstr->in_buffer_ind = 0;
590 return size_gotten < 0 ? -1 : size_gotten;
594 Lstream_read(lstream_t lstr, void *data, Lstream_data_count size)
596 unsigned char *p = data;
597 Lstream_data_count off = 0;
598 Lstream_data_count chunk;
599 int error_occurred = 0;
601 /* trivial cases first */
602 if (UNLIKELY(size == 0)) {
606 /* First try to get some data from the unget buffer */
607 chunk = min(size, lstr->unget_buffer_ind);
609 /* The bytes come back in reverse order. */
610 for (; off < chunk; off++) {
611 p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
613 lstr->byte_count += chunk;
618 /* Take whatever we can from the in buffer */
620 lstr->in_buffer_current - lstr->in_buffer_ind);
622 memcpy(p + off, lstr->in_buffer + lstr->in_buffer_ind,
624 lstr->in_buffer_ind += chunk;
625 lstr->byte_count += chunk;
630 /* If we need some more, try to get some more from the stream's
633 Lstream_data_count retval = Lstream_read_more(lstr);
643 /* #### Beware of OFF ending up 0. */
644 if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0) {
645 /* It's quite possible for us to get passed an incomplete
646 character at the end. We need to spit back that
647 incomplete character. */
648 const unsigned char *dataend = p + off - 1;
649 /* Optimize the most common case. */
650 if (!BYTE_ASCII_P(*dataend)) {
651 /* Go back to the beginning of the last (and possibly
652 partial) character, and bump forward to see if the
653 character is complete. */
654 VALIDATE_CHARPTR_BACKWARD(dataend);
655 if (dataend + REP_BYTES_BY_FIRST_BYTE(*dataend) !=
657 Lstream_data_count newoff = dataend - p;
658 /* If not, chop the size down to ignore the last
659 char and stash it away for next time. */
660 Lstream_unread(lstr, dataend, off - newoff);
666 return off == 0 && error_occurred ? -1 : off;
670 Lstream_unread(lstream_t lstr, const void *data, Lstream_data_count size)
672 const unsigned char *p = data;
674 /* Make sure buffer is big enough */
675 LSTR_ALLOC_TO(lstr->unget_buffer, lstr->unget_buffer_size,
676 lstr->unget_buffer_ind + size, unsigned char);
678 lstr->byte_count -= size;
680 /* Bytes have to go on in reverse order -- they are reversed
681 again when read back. */
683 lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
689 Lstream_rewind(lstream_t lstr)
691 if (!lstr->imp->rewinder) {
692 Lstream_internal_error("lstream has no rewinder", lstr);
694 if (Lstream_flush(lstr) < 0) {
697 lstr->byte_count = 0;
698 return lstr->imp->rewinder(lstr);
702 Lstream_seekable_p(lstream_t lstr)
704 if (!lstr->imp->rewinder) {
707 if (!lstr->imp->seekable_p) {
710 return lstr->imp->seekable_p(lstr);
714 Lstream_pseudo_close(lstream_t lstr)
716 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
717 Lstream_internal_error("lstream is not open", lstr);
719 /* don't check errors here -- best not to risk file descriptor loss */
720 return Lstream_flush(lstr);
724 Lstream_close(lstream_t lstr)
728 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
729 rc = Lstream_pseudo_close(lstr);
731 * We used to return immediately if the closer method reported
732 * failure, leaving the stream open. But this is no good, for
733 * the following reasons.
735 * 1. The finalizer method used in GC makes no provision for
736 * failure, so we must not return without freeing buffer
739 * 2. The closer method may have already freed some memory
740 * used for I/O in this stream. E.g. encoding_closer frees
741 * ENCODING_STREAM_DATA(stream)->runoff. If a writer method
742 * tries to use this buffer later, it will write into memory
743 * that may have been allocated elsewhere. Sometime later
744 * you will see a sign that says "Welcome to Crash City."
746 * 3. The closer can report failure if a flush fails in the
747 * other stream in a MULE encoding/decoding stream pair.
748 * The other stream in the pair is closed, but returning
749 * early leaves the current stream open. If we try to
750 * flush the current stream later, we will crash when the
751 * flusher notices that the other end stream is closed.
753 * So, we no longer abort the close if the closer method
754 * reports some kind of failure. We still report the failure
757 if (lstr->imp->closer) {
758 if ((lstr->imp->closer) (lstr) < 0) {
764 lstr->flags &= ~LSTREAM_FL_IS_OPEN;
765 lstr->byte_count = 0;
766 /* Note that Lstream_flush() reset all the buffer indices. That way,
767 the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
768 on a closed stream will call into the function equivalents, which
769 will cause an error. */
771 /* We set the pointers to 0 so that we don't lose when this function is
772 called more than once on the same object */
773 if (lstr->out_buffer) {
774 xfree(lstr->out_buffer);
775 lstr->out_buffer = 0;
777 if (lstr->in_buffer) {
778 xfree(lstr->in_buffer);
781 if (lstr->unget_buffer) {
782 xfree(lstr->unget_buffer);
783 lstr->unget_buffer = 0;
790 Lstream_fputc(lstream_t lstr, int c)
792 unsigned char ch = (unsigned char)c;
793 Lstream_data_count retval = Lstream_write_1(lstr, &ch, 1);
794 if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED
796 return Lstream_flush_out(lstr);
798 return retval < 0 ? -1 : 0;
802 Lstream_fgetc(lstream_t lstr)
805 if (Lstream_read(lstr, &ch, 1) <= 0) {
812 Lstream_fungetc(lstream_t lstr, int c)
814 unsigned char ch = (unsigned char)c;
815 Lstream_unread(lstr, &ch, 1);
819 Lstream_get_fd(lstream_t lstr)
823 if (lstr->imp->get_fd && (rc = (lstr->imp->get_fd)(lstr)) < 0) {
829 /************************ some stream implementations *********************/
831 /*********** a stdio stream ***********/
833 typedef struct stdio_stream_s *stdio_stream_t;
834 struct stdio_stream_s {
839 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
841 DEFINE_LSTREAM_IMPLEMENTATION("stdio", lstream_stdio,
842 sizeof(struct stdio_stream_s));
845 make_stdio_stream_1(FILE * stream, int flags, const char *mode)
848 lstream_t lstr = Lstream_new(lstream_stdio, mode);
849 stdio_stream_t str = STDIO_STREAM_DATA(lstr);
851 str->closing = flags & LSTR_CLOSING;
852 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
853 XSETLSTREAM(obj, lstr);
857 Lisp_Object make_stdio_input_stream(FILE * stream, int flags)
859 return make_stdio_stream_1(stream, flags, "r");
862 Lisp_Object make_stdio_output_stream(FILE * stream, int flags)
864 return make_stdio_stream_1(stream, flags, "w");
867 /* #### From reading the Unix 98 specification, it appears that if we
868 want stdio_reader() to be completely correct, we should check for
869 0 < val < size and if so, check to see if an error has occurred.
870 If an error has occurred, but val is non-zero, we should go ahead
871 and act as if the read was successful, but remember in some fashion
872 or other, that an error has occurred, and report that on the next
873 call to stdio_reader instead of calling fread() again.
875 Currently, in such a case, we end up calling fread() twice and we
878 1) this is not harmful, and
879 2) the error will still be reported on the second read.
881 This is probably reasonable, so I don't think we should change this
882 code (it could even be argued that the error might have fixed
883 itself, so we should do the fread() again. */
885 static Lstream_data_count
886 stdio_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
888 stdio_stream_t str = STDIO_STREAM_DATA(stream);
889 Lstream_data_count val = fread(data, 1, size, str->file);
890 if (!val && ferror(str->file)) {
896 static Lstream_data_count
897 stdio_writer(lstream_t stream, const unsigned char *data,
898 Lstream_data_count size)
900 stdio_stream_t str = STDIO_STREAM_DATA(stream);
901 Lstream_data_count val = fwrite(data, 1, size, str->file);
902 if (!val && ferror(str->file)) {
909 stdio_rewinder(lstream_t stream)
911 stdio_stream_t p = STDIO_STREAM_DATA(stream);
917 stdio_seekable_p(lstream_t stream)
920 stdio_stream_t str = STDIO_STREAM_DATA(stream);
922 if (fstat(fileno(str->file), &lestat) < 0) {
925 return S_ISREG(lestat.st_mode);
929 stdio_flusher(lstream_t stream)
931 stdio_stream_t str = STDIO_STREAM_DATA(stream);
933 if (stream->flags & LSTREAM_FL_WRITE) {
934 return fflush(str->file);
941 stdio_closer(lstream_t stream)
943 stdio_stream_t str = STDIO_STREAM_DATA(stream);
946 return fclose(str->file);
947 } else if (stream->flags & LSTREAM_FL_WRITE) {
948 return fflush(str->file);
954 /*********** a file descriptor ***********/
956 typedef struct filedesc_stream_s *filedesc_stream_t;
957 struct filedesc_stream_s {
964 int chars_sans_newline;
969 bool blocking_error_p:1;
972 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
974 DEFINE_LSTREAM_IMPLEMENTATION("filedesc", lstream_filedesc,
975 sizeof(struct filedesc_stream_s));
977 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
978 OFFSET is the offset from the *current* file pointer that the reading
979 should start at. COUNT is the number of bytes to be read (it is
980 ignored when writing); -1 for unlimited. */
982 make_filedesc_stream_1(int filedesc, int offset, int count, int flags,
985 Lisp_Object obj = Qnil;
988 lstream_t lstr = Lstream_new(lstream_filedesc, mode);
989 filedesc_stream_t fstr = FILEDESC_STREAM_DATA(lstr);
992 fstr->closing = !!(flags & LSTR_CLOSING);
993 fstr->allow_quit = !!(flags & LSTR_ALLOW_QUIT);
994 fstr->blocked_ok = !!(flags & LSTR_BLOCKED_OK);
995 fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
996 fstr->blocking_error_p = 0;
997 fstr->chars_sans_newline = 0;
998 fstr->starting_pos = lseek(filedesc, offset, SEEK_CUR);
999 fstr->current_pos = max(fstr->starting_pos, 0);
1004 fstr->end_pos = fstr->starting_pos + count;
1006 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
1007 XSETLSTREAM(obj, lstr);
1012 make_filedesc_input_stream(int filedesc, int offset, int count, int flags)
1014 return make_filedesc_stream_1(filedesc, offset, count, flags, "r");
1018 make_filedesc_output_stream(int filedesc, int offset, int count, int flags)
1020 return make_filedesc_stream_1(filedesc, offset, count, flags, "w");
1023 static Lstream_data_count
1024 filedesc_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1026 Lstream_data_count nread;
1027 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1029 if (str->end_pos >= 0) {
1031 (Lstream_data_count)
1032 (str->end_pos - str->current_pos));
1034 nread = str->allow_quit
1035 ? read_allowing_quit(str->fd, data, size)
1036 : read(str->fd, data, size);
1038 str->current_pos += nread;
1044 errno_would_block_p(int val)
1047 if (val == EWOULDBLOCK) {
1052 if (val == EAGAIN) {
1059 static Lstream_data_count
1060 filedesc_writer(lstream_t stream, const unsigned char *data,
1061 Lstream_data_count size)
1063 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1064 Lstream_data_count retval;
1065 int need_newline = 0;
1067 /* This function would be simple if it were not for the blasted
1068 PTY max-bytes stuff. Why the hell can't they just have written
1069 the PTY drivers right so this problem doesn't exist?
1071 Maybe all the PTY crap here should be moved into another stream
1072 that does nothing but periodically insert EOF's as necessary. */
1073 if (str->pty_flushing) {
1074 /* To make life easy, only send out one line at the most. */
1075 const unsigned char *ptr;
1077 ptr = (const unsigned char *)memchr(data, '\n', size);
1084 str->pty_max_bytes - str->chars_sans_newline) {
1086 str->pty_max_bytes - str->chars_sans_newline;
1092 /**** start of non-PTY-crap ****/
1094 retval = str->allow_quit
1095 ? write_allowing_quit(str->fd, data, size)
1096 : write(str->fd, data, size);
1100 if (retval < 0 && errno_would_block_p(errno) && str->blocked_ok) {
1101 str->blocking_error_p = 1;
1104 str->blocking_error_p = 0;
1108 /**** end non-PTY-crap ****/
1110 if (str->pty_flushing) {
1111 str->chars_sans_newline += retval;
1112 /* Note that a newline was not among the bytes written out.
1113 Add to the number of non-newline bytes written out,
1114 and flush with an EOF if necessary. Be careful to
1115 keep track of write errors as we go along and look
1116 out for EWOULDBLOCK. */
1117 if (str->chars_sans_newline >= str->pty_max_bytes) {
1118 Lstream_data_count retval2 = str->allow_quit
1119 ? write_allowing_quit(
1120 str->fd, &str->eof_char, 1)
1121 : write(str->fd, &str->eof_char, 1);
1124 str->chars_sans_newline = 0;
1126 else if (retval2 < 0) {
1127 /* Error writing the EOF char. If nothing got
1128 written, then treat this as an error --
1129 either return an error condition or set the
1130 blocking-error flag. */
1132 if (errno_would_block_p(errno)
1133 && str->blocked_ok) {
1134 str->blocking_error_p = 1;
1145 /* The need_newline flag is necessary because otherwise when the
1146 first byte is a newline, we'd get stuck never writing anything
1147 in pty-flushing mode. */
1150 Lstream_data_count retval2 = str->allow_quit
1151 ? write_allowing_quit(str->fd, &nl, 1)
1152 : write(str->fd, &nl, 1);
1155 str->chars_sans_newline = 0;
1157 } else if (retval2 < 0) {
1158 /* Error writing the newline char. If nothing got
1159 written, then treat this as an error -- either return
1160 an error condition or set the blocking-error flag. */
1162 if (errno_would_block_p(errno)
1163 && str->blocked_ok) {
1164 str->blocking_error_p = 1;
1179 filedesc_rewinder(lstream_t stream)
1181 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1182 if (str->starting_pos < 0 ||
1183 lseek(FILEDESC_STREAM_DATA(stream)->fd, str->starting_pos,
1187 str->current_pos = str->starting_pos;
1193 filedesc_seekable_p(lstream_t stream)
1195 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1197 if (str->starting_pos < 0) {
1202 if (fstat(str->fd, &lestat) < 0) {
1205 return S_ISREG(lestat.st_mode);
1210 filedesc_closer(lstream_t stream)
1212 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1215 return close(str->fd);
1222 filedesc_was_blocked_p(lstream_t stream)
1224 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1225 return str->blocking_error_p;
1229 filedesc_stream_set_pty_flushing(lstream_t stream, int pty_max_bytes,
1232 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1233 str->pty_max_bytes = pty_max_bytes;
1234 str->eof_char = eof_char;
1235 str->pty_flushing = 1;
1240 filedesc_get_fd(lstream_t stream)
1242 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1246 /*********** read from a Lisp string ***********/
1248 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1250 typedef struct lisp_string_stream_s *lisp_string_stream_t;
1251 struct lisp_string_stream_s {
1253 Bytecount init_offset;
1254 Bytecount offset, end;
1257 DEFINE_LSTREAM_IMPLEMENTATION("lisp-string", lstream_lisp_string,
1258 sizeof(struct lisp_string_stream_s));
1261 make_lisp_string_input_stream(Lisp_Object string, Bytecount offset,
1266 lisp_string_stream_t str;
1268 CHECK_STRING(string);
1270 len = XSTRING_LENGTH(string) - offset;
1272 assert(offset >= 0);
1274 assert(offset + len <= XSTRING_LENGTH(string));
1276 lstr = Lstream_new(lstream_lisp_string, "r");
1277 str = LISP_STRING_STREAM_DATA(lstr);
1278 str->offset = offset;
1279 str->end = offset + len;
1280 str->init_offset = offset;
1282 XSETLSTREAM(obj, lstr);
1286 static Lstream_data_count
1287 lisp_string_reader(lstream_t stream, unsigned char *data,
1288 Lstream_data_count size)
1290 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1291 /* Don't lose if the string shrank past us ... */
1292 Bytecount offset = min(str->offset, XSTRING_LENGTH(str->obj));
1293 Bufbyte *strstart = XSTRING_DATA(str->obj);
1294 Bufbyte *start = strstart + offset;
1296 /* ... or if someone changed the string and we ended up in the
1297 middle of a character. */
1298 /* Being in the middle of a character is `normal' unless
1299 LSTREAM_NO_PARTIAL_CHARS - mrb */
1300 if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS) {
1301 VALIDATE_CHARPTR_BACKWARD(start);
1303 offset = start - strstart;
1304 size = min(size, (Lstream_data_count) (str->end - offset));
1305 memcpy(data, start, size);
1306 str->offset = offset + size;
1311 lisp_string_rewinder(lstream_t stream)
1313 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1314 int pos = str->init_offset;
1316 if (pos > str->end) {
1319 /* Don't lose if the string shrank past us ... */
1320 pos = min(pos, XSTRING_LENGTH(str->obj));
1321 /* ... or if someone changed the string and we ended up in the
1322 middle of a character. */
1324 Bufbyte *strstart = XSTRING_DATA(str->obj);
1325 Bufbyte *start = strstart + pos;
1326 VALIDATE_CHARPTR_BACKWARD(start);
1327 pos = start - strstart;
1334 lisp_string_marker(Lisp_Object stream)
1336 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(XLSTREAM(stream));
1340 /*********** a fixed buffer ***********/
1342 #define FIXED_BUFFER_STREAM_DATA(stream) \
1343 LSTREAM_TYPE_DATA (stream, fixed_buffer)
1345 typedef struct fixed_buffer_stream_s *fixed_buffer_stream_t;
1346 struct fixed_buffer_stream_s {
1347 const unsigned char *inbuf;
1348 unsigned char *outbuf;
1349 Lstream_data_count size;
1350 Lstream_data_count offset;
1353 DEFINE_LSTREAM_IMPLEMENTATION("fixed-buffer", lstream_fixed_buffer,
1354 sizeof(struct fixed_buffer_stream_s));
1357 make_fixed_buffer_input_stream(const void *buf, Lstream_data_count size)
1360 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "r");
1361 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1362 str->inbuf = (const unsigned char *)buf;
1364 XSETLSTREAM(obj, lstr);
1369 make_fixed_buffer_output_stream(void *buf, Lstream_data_count size)
1372 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "w");
1373 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1374 str->outbuf = (unsigned char *)buf;
1376 XSETLSTREAM(obj, lstr);
1380 static Lstream_data_count
1381 fixed_buffer_reader(lstream_t stream, unsigned char *data,
1382 Lstream_data_count size)
1384 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1385 size = min(size, str->size - str->offset);
1386 memcpy(data, str->inbuf + str->offset, size);
1387 str->offset += size;
1391 static Lstream_data_count
1392 fixed_buffer_writer(lstream_t stream, const unsigned char *data,
1393 Lstream_data_count size)
1395 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1396 if (str->offset == str->size) {
1397 /* If we're at the end, just throw away the data and pretend
1398 we wrote all of it. If we return 0, then the lstream routines
1399 will try again and again to write it out. */
1402 size = min(size, str->size - str->offset);
1403 memcpy(str->outbuf + str->offset, data, size);
1404 str->offset += size;
1409 fixed_buffer_rewinder(lstream_t stream)
1411 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1416 const unsigned char*
1417 fixed_buffer_input_stream_ptr(lstream_t stream)
1419 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1420 assert(stream->imp == lstream_fixed_buffer);
1425 fixed_buffer_output_stream_ptr(lstream_t stream)
1427 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1428 assert(stream->imp == lstream_fixed_buffer);
1432 /*********** write to a resizing buffer ***********/
1434 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1435 LSTREAM_TYPE_DATA (stream, resizing_buffer)
1437 typedef struct resizing_buffer_stream_s *resizing_buffer_stream_t;
1438 struct resizing_buffer_stream_s {
1440 Lstream_data_count allocked;
1445 DEFINE_LSTREAM_IMPLEMENTATION("resizing-buffer", lstream_resizing_buffer,
1446 sizeof(struct resizing_buffer_stream_s));
1448 Lisp_Object make_resizing_buffer_output_stream(void)
1451 XSETLSTREAM(obj, Lstream_new(lstream_resizing_buffer, "w"));
1455 static Lstream_data_count
1456 resizing_buffer_writer(lstream_t stream, const unsigned char *data,
1457 Lstream_data_count size)
1459 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1461 LSTR_ALLOC_TO(str->buf, str->allocked, str->stored + size,
1463 memcpy(str->buf + str->stored, data, size);
1464 str->stored += size;
1465 str->max_stored = max(str->max_stored, str->stored);
1470 resizing_buffer_rewinder(lstream_t stream)
1472 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1478 resizing_buffer_closer(lstream_t stream)
1480 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1490 resizing_buffer_stream_ptr(lstream_t stream)
1492 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1496 /*********** write to an unsigned-char dynarr ***********/
1498 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1499 but which is really just an unsigned_char_dynarr (e.g. its type
1500 is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1502 #define DYNARR_STREAM_DATA(stream) \
1503 LSTREAM_TYPE_DATA (stream, dynarr)
1505 typedef struct dynarr_stream_s *dynarr_stream_t;
1506 struct dynarr_stream_s {
1507 unsigned_char_dynarr *dyn;
1510 DEFINE_LSTREAM_IMPLEMENTATION("dynarr", lstream_dynarr,
1511 sizeof(struct dynarr_stream_s));
1514 make_dynarr_output_stream(unsigned_char_dynarr * dyn)
1519 XSETLSTREAM(obj, Lstream_new(lstream_dynarr, "w"));
1520 p = DYNARR_STREAM_DATA(XLSTREAM(obj));
1525 static Lstream_data_count
1526 dynarr_writer(lstream_t stream, const unsigned char *data,
1527 Lstream_data_count size)
1529 dynarr_stream_t str = DYNARR_STREAM_DATA(stream);
1530 Dynarr_add_many(str->dyn, data, size);
1535 dynarr_rewinder(lstream_t stream)
1537 dynarr_stream_t p = DYNARR_STREAM_DATA(stream);
1538 Dynarr_reset(p->dyn);
1543 dynarr_closer(lstream_t stream)
1548 /************ read from or write to a Lisp buffer ************/
1550 /* Note: Lisp-buffer read streams never return partial characters,
1551 and Lisp-buffer write streams expect to never get partial
1554 #define LISP_BUFFER_STREAM_DATA(stream) \
1555 LSTREAM_TYPE_DATA (stream, lisp_buffer)
1557 typedef struct lisp_buffer_stream_s *lisp_buffer_stream_t;
1558 struct lisp_buffer_stream_s {
1560 Lisp_Object orig_start;
1561 /* we use markers to properly deal with insertion/deletion */
1562 Lisp_Object start, end;
1566 DEFINE_LSTREAM_IMPLEMENTATION("lisp-buffer", lstream_lisp_buffer,
1567 sizeof(struct lisp_buffer_stream_s));
1570 make_lisp_buffer_stream_1(struct buffer *buf, Bufpos start, Bufpos end,
1571 int flags, const char *mode)
1575 lisp_buffer_stream_t str;
1577 int reading = !strcmp(mode, "r");
1579 /* Make sure the luser didn't pass "w" in. */
1580 if (!strcmp(mode, "w")) {
1584 if (flags & LSTR_IGNORE_ACCESSIBLE) {
1585 bmin = BUF_BEG(buf);
1588 bmin = BUF_BEGV(buf);
1598 assert(bmin <= start);
1599 assert(start <= bmax);
1601 assert(bmin <= end);
1602 assert(end <= bmax);
1603 assert(start <= end);
1606 lstr = Lstream_new(lstream_lisp_buffer, mode);
1607 str = LISP_BUFFER_STREAM_DATA(lstr);
1612 XSETBUFFER(buffer, buf);
1613 marker = Fmake_marker();
1614 Fset_marker(marker, make_int(start), buffer);
1615 str->start = marker;
1616 marker = Fmake_marker();
1617 Fset_marker(marker, make_int(start), buffer);
1618 str->orig_start = marker;
1620 marker = Fmake_marker();
1621 Fset_marker(marker, make_int(end), buffer);
1626 str->buffer = buffer;
1629 XSETLSTREAM(obj, lstr);
1634 make_lisp_buffer_input_stream(struct buffer *buf, Bufpos start, Bufpos end,
1637 return make_lisp_buffer_stream_1(buf, start, end, flags, "r");
1641 make_lisp_buffer_output_stream(struct buffer *buf, Bufpos pos, int flags)
1643 Lisp_Object lstr = make_lisp_buffer_stream_1(buf, pos, 0, flags, "wc");
1645 Lstream_set_character_mode(XLSTREAM(lstr));
1649 static Lstream_data_count
1650 lisp_buffer_reader(lstream_t stream, unsigned char *data,
1651 Lstream_data_count size)
1653 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1654 unsigned char *orig_data = data;
1657 struct buffer *buf = XBUFFER(str->buffer);
1659 if (!BUFFER_LIVE_P(buf)) {
1664 /* NOTE: We do all our operations in Bytind's.
1665 Keep in mind that SIZE is a value in bytes, not chars. */
1667 start = bi_marker_position(str->start);
1668 end = bi_marker_position(str->end);
1669 if (!(str->flags & LSTR_IGNORE_ACCESSIBLE)) {
1670 start = bytind_clip_to_bounds(BI_BUF_BEGV(buf), start,
1672 end = bytind_clip_to_bounds(BI_BUF_BEGV(buf), end,
1676 size = min(size, (Lstream_data_count) (end - start));
1678 /* We cannot return a partial character. */
1679 VALIDATE_BYTIND_BACKWARD(buf, end);
1681 while (start < end) {
1685 if (str->flags & LSTR_IGNORE_ACCESSIBLE) {
1686 _ceil_ = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE(
1689 _ceil_ = BI_BUF_CEILING_OF(buf, start);
1691 chunk = min(_ceil_, end) - start;
1692 memcpy(data, BI_BUF_BYTE_ADDRESS(buf, start), chunk);
1697 if (EQ(buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE) {
1698 /* What a kludge. What a kludge. What a kludge. */
1700 for (p = orig_data; p < data; p++) {
1707 set_bi_marker_position(str->start, end);
1708 return data - orig_data;
1711 static Lstream_data_count
1712 lisp_buffer_writer(lstream_t stream, const unsigned char *data,
1713 Lstream_data_count size)
1715 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1717 struct buffer *buf = XBUFFER(str->buffer);
1719 if (!BUFFER_LIVE_P(buf)) {
1724 pos = marker_position(str->start);
1725 pos += buffer_insert_raw_string_1(buf, pos, data, size, 0);
1726 set_marker_position(str->start, pos);
1731 lisp_buffer_rewinder(lstream_t stream)
1733 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1734 struct buffer *buf = XBUFFER(str->buffer);
1735 long pos = marker_position(str->orig_start);
1737 if (!BUFFER_LIVE_P(buf)) {
1741 if (pos > BUF_ZV(buf)) {
1744 if (pos < marker_position(str->orig_start)) {
1745 pos = marker_position(str->orig_start);
1747 if (MARKERP(str->end) && pos > marker_position(str->end)) {
1748 pos = marker_position(str->end);
1750 set_marker_position(str->start, pos);
1755 lisp_buffer_marker(Lisp_Object stream)
1757 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(XLSTREAM(stream));
1759 mark_object(str->start);
1760 mark_object(str->end);
1765 lisp_buffer_stream_startpos(lstream_t stream)
1767 lisp_buffer_stream_t p = LISP_BUFFER_STREAM_DATA(stream);
1768 return marker_position(p->start);
1771 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1772 #include "openssl.h"
1774 typedef struct ssl_stream_s *ssl_stream_t;
1775 struct ssl_stream_s {
1780 bool blocking_error_p:1;
1783 #define SSL_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, ssl)
1785 DEFINE_LSTREAM_IMPLEMENTATION("ssl", lstream_ssl, sizeof(struct ssl_stream_s));
1788 make_ssl_stream_1(SSL *conn, int flags, const char *mode)
1791 lstream_t lstr = Lstream_new(lstream_ssl, mode);
1792 ssl_stream_t str = SSL_STREAM_DATA(lstr);
1794 XSETLSTREAM(obj, lstr);
1799 make_ssl_input_stream(SSL *conn, int flags)
1801 return make_ssl_stream_1(conn, flags, "r");
1805 make_ssl_output_stream(SSL *conn, int flags)
1807 return make_ssl_stream_1(conn, flags, "w");
1810 static Lstream_data_count
1811 ssl_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1813 Lstream_data_count nread;
1814 ssl_stream_t str = SSL_STREAM_DATA(stream);
1816 nread = SSL_read(str->conn, data, size);
1823 static Lstream_data_count
1824 ssl_writer(lstream_t stream, const unsigned char *data,
1825 Lstream_data_count size)
1827 Lstream_data_count nwrite;
1828 ssl_stream_t str = SSL_STREAM_DATA(stream);
1830 nwrite = SSL_write(str->conn, data, size);
1838 ssl_closer(lstream_t stream)
1840 ssl_stream_t str = SSL_STREAM_DATA(stream);
1842 return SSL_shutdown(str->conn);
1849 ssl_get_fd(lstream_t stream)
1851 ssl_stream_t str = SSL_STREAM_DATA(stream);
1852 return SSL_get_rfd(str->conn);
1856 /************************************************************************/
1857 /* initialization */
1858 /************************************************************************/
1860 void lstream_type_create(void)
1862 LSTREAM_HAS_METHOD(stdio, reader);
1863 LSTREAM_HAS_METHOD(stdio, writer);
1864 LSTREAM_HAS_METHOD(stdio, rewinder);
1865 LSTREAM_HAS_METHOD(stdio, seekable_p);
1866 LSTREAM_HAS_METHOD(stdio, flusher);
1867 LSTREAM_HAS_METHOD(stdio, closer);
1869 LSTREAM_HAS_METHOD(filedesc, reader);
1870 LSTREAM_HAS_METHOD(filedesc, writer);
1871 LSTREAM_HAS_METHOD(filedesc, was_blocked_p);
1872 LSTREAM_HAS_METHOD(filedesc, rewinder);
1873 LSTREAM_HAS_METHOD(filedesc, seekable_p);
1874 LSTREAM_HAS_METHOD(filedesc, closer);
1875 LSTREAM_HAS_METHOD(filedesc, get_fd);
1877 LSTREAM_HAS_METHOD(lisp_string, reader);
1878 LSTREAM_HAS_METHOD(lisp_string, rewinder);
1879 LSTREAM_HAS_METHOD(lisp_string, marker);
1881 LSTREAM_HAS_METHOD(fixed_buffer, reader);
1882 LSTREAM_HAS_METHOD(fixed_buffer, writer);
1883 LSTREAM_HAS_METHOD(fixed_buffer, rewinder);
1885 LSTREAM_HAS_METHOD(resizing_buffer, writer);
1886 LSTREAM_HAS_METHOD(resizing_buffer, rewinder);
1887 LSTREAM_HAS_METHOD(resizing_buffer, closer);
1889 LSTREAM_HAS_METHOD(dynarr, writer);
1890 LSTREAM_HAS_METHOD(dynarr, rewinder);
1891 LSTREAM_HAS_METHOD(dynarr, closer);
1893 LSTREAM_HAS_METHOD(lisp_buffer, reader);
1894 LSTREAM_HAS_METHOD(lisp_buffer, writer);
1895 LSTREAM_HAS_METHOD(lisp_buffer, rewinder);
1896 LSTREAM_HAS_METHOD(lisp_buffer, marker);
1898 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1899 LSTREAM_HAS_METHOD(ssl, reader);
1900 LSTREAM_HAS_METHOD(ssl, writer);
1901 LSTREAM_HAS_METHOD(ssl, closer);
1902 LSTREAM_HAS_METHOD(ssl, get_fd);
1906 void reinit_vars_of_lstream(void)
1908 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
1909 for (int i = 0; i < countof(Vlstream_free_list); i++) {
1910 Vlstream_free_list[i] = Qnil;
1911 staticpro_nodump(&Vlstream_free_list[i]);
1916 void vars_of_lstream(void)
1918 INIT_LRECORD_IMPLEMENTATION(lstream);
1920 reinit_vars_of_lstream();
1923 /* lstream.c ends here */