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);
159 sprintf(buf, "#<INTERNAL OBJECT (SXEmacs bug?) (%s lstream) 0x%lx>",
160 lstr->imp->name, (long)lstr);
161 write_c_string(buf, printcharfun);
164 static void finalize_lstream(void *header, int for_disksave)
166 /* WARNING WARNING WARNING. This function (and all finalize functions)
167 may get called more than once on the same object, and may get called
168 (at dump time) on objects that are not being released. */
169 lstream_t lstr = header;
171 #if 0 /* this may cause weird Broken Pipes? */
173 Lstream_pseudo_close(lstr);
177 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
179 if (lstr->flags & LSTREAM_FL_CLOSE_AT_DISKSAVE)
188 aligned_sizeof_lstream(size_t lstream_type_specific_size)
190 return ALIGN_SIZE(offsetof(struct lstream_s, data) +
191 lstream_type_specific_size,
192 ALIGNOF(max_align_t));
196 sizeof_lstream(const void *header)
198 REGISTER size_t imp_size = ((const struct lstream_s*)header)->imp->size;
199 return aligned_sizeof_lstream(imp_size);
202 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("stream", lstream,
203 mark_lstream, print_lstream,
204 finalize_lstream, 0, 0, 0,
205 sizeof_lstream, struct lstream_s);
208 * Replaces DO_REALLOC from lisp.h. */
209 #define LSTR_ALLOC_TO DO_REALLOC_ATOMIC
213 Lstream_set_buffering(lstream_t lstr, Lstream_buffering buffering, int bsz)
215 lstr->buffering = buffering;
217 case LSTREAM_UNBUFFERED:
218 lstr->buffering_size = 0;
220 case LSTREAM_BLOCK_BUFFERED:
221 lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE;
223 case LSTREAM_BLOCKN_BUFFERED:
224 lstr->buffering_size = bsz;
226 case LSTREAM_LINE_BUFFERED:
227 case LSTREAM_UNLIMITED:
228 lstr->buffering_size = INT_MAX;
235 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
236 static const Lstream_implementation *lstream_types[32];
237 static Lisp_Object Vlstream_free_list[32];
238 static int lstream_type_count;
241 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
243 lstr_finaliser(void *obj, void *UNUSED(data))
245 finalize_lstream(obj, 0);
251 Lstream_new(const Lstream_implementation *imp, const char *mode)
255 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
256 GC_finalization_proc *foo = NULL;
259 p = xmalloc(aligned_sizeof_lstream(imp->size));
260 set_lheader_implementation(&p->header.lheader, &lrecord_lstream);
262 GC_REGISTER_FINALIZER(p, lstr_finaliser, NULL, foo, bar);
267 for (i = 0; i < lstream_type_count; i++) {
268 if (lstream_types[i] == imp)
272 if (i == lstream_type_count) {
273 assert(lstream_type_count < countof(lstream_types));
274 lstream_types[lstream_type_count] = imp;
275 Vlstream_free_list[lstream_type_count] =
276 make_lcrecord_list(aligned_sizeof_lstream(imp->size),
278 lstream_type_count++;
281 tmp = allocate_managed_lcrecord(Vlstream_free_list[i]);
283 /* Zero it out, except the header. */
284 memset((char *)p + sizeof(p->header), '\0',
285 aligned_sizeof_lstream(imp->size) - sizeof(p->header));
289 Lstream_set_buffering(p, LSTREAM_BLOCK_BUFFERED, 0);
290 p->flags = LSTREAM_FL_IS_OPEN;
292 /* convert mode (one of "r", "w", "rc", "wc") to p->flags */
293 assert(mode[0] == 'r' || mode[0] == 'w');
294 assert(mode[1] == 'c' || mode[1] == '\0');
295 p->flags |= (mode[0] == 'r' ? LSTREAM_FL_READ : LSTREAM_FL_WRITE);
296 if (mode[1] == 'c') {
297 p->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
303 Lstream_set_character_mode(lstream_t lstr)
305 lstr->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
309 Lstream_delete(lstream_t lstr)
311 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
318 XSETLSTREAM(val, lstr);
319 for (int i = 0; i < lstream_type_count; i++) {
320 if (lstream_types[i] == lstr->imp) {
321 free_managed_lcrecord(Vlstream_free_list[i], val);
330 #define Lstream_internal_error(reason, lstr) \
331 Lstream_signal_simple_error(lstr, "Internal error: " reason)
334 Lstream_signal_simple_error(lstream_t lstr, const char *reason)
337 XSETLSTREAM(obj, lstr);
338 signal_simple_error(reason, obj);
342 Lstream_reopen(lstream_t lstr)
344 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
345 Lstream_internal_error("lstream already open", lstr);
347 lstr->flags |= LSTREAM_FL_IS_OPEN;
350 /* Attempt to flush out all of the buffered data for writing. */
353 Lstream_flush_out(lstream_t lstr)
355 Lstream_data_count num_written;
357 while (lstr->out_buffer_ind > 0) {
358 Lstream_data_count size = lstr->out_buffer_ind;
359 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
360 Lstream_internal_error("lstream not open", lstr);
362 if (!(lstr->flags & LSTREAM_FL_WRITE)) {
363 Lstream_internal_error("lstream not open for writing",
366 if (!lstr->imp->writer) {
367 Lstream_internal_error("lstream has no writer", lstr);
369 if (lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
370 /* It's quite possible for us to get passed an
371 incomplete character at the end. We need to spit
372 back that incomplete character. */
374 const unsigned char *data = lstr->out_buffer;
375 const unsigned char *dataend = data + size - 1;
376 assert(size > 0); /* safety check ... */
377 /* Optimize the most common case. */
378 if (!BYTE_ASCII_P(*dataend)) {
379 /* Go back to the beginning of the last (and
380 possibly partial) character, and bump forward
381 to see if the character is complete. */
382 VALIDATE_CHARPTR_BACKWARD(dataend);
384 REP_BYTES_BY_FIRST_BYTE(*dataend) !=
386 /* If not, chop the size down to ignore
387 the last char and stash it away for
389 size = dataend - data;
391 /* If we don't even have one character to write,
392 then just skip out. */
399 num_written = lstr->imp->writer(lstr, lstr->out_buffer, size);
400 if (num_written == 0) {
401 /* If nothing got written, then just hold the data.
402 This may occur, for example, if this stream does
403 non-blocking I/O; the attempt to write the data might
404 have resulted in an EWOULDBLOCK error. */
406 } else if (num_written >= lstr->out_buffer_ind) {
407 lstr->out_buffer_ind = 0;
408 } else if (num_written > 0) {
409 memmove(lstr->out_buffer,
410 lstr->out_buffer + num_written,
411 lstr->out_buffer_ind - num_written);
412 lstr->out_buffer_ind -= num_written;
414 /* If error, just hold the data, for similar reasons as
420 if (lstr->imp->flusher) {
421 return (lstr->imp->flusher) (lstr);
427 Lstream_flush(lstream_t lstr)
429 if (Lstream_flush_out(lstr) < 0) {
432 /* clear out buffered data */
433 lstr->in_buffer_current = lstr->in_buffer_ind = 0;
434 lstr->unget_buffer_ind = 0;
439 /* We want to add NUM characters. This function ensures that the
440 buffer is large enough for this (per the buffering size specified
441 in the stream) and returns the number of characters we can
442 actually write. If FORCE is set, ignore the buffering size
443 and go ahead and make space for all the chars even if it exceeds
444 the buffering size. (This is used to deal with the possibility
445 that the stream writer might refuse to write any bytes now, e.g.
446 if it's getting EWOULDBLOCK errors. We have to keep stocking them
447 up until they can be written, so as to avoid losing data. */
449 static Lstream_data_count
450 Lstream_adding(lstream_t lstr, Lstream_data_count num, int force)
452 Lstream_data_count size = num + lstr->out_buffer_ind;
454 if (size <= lstr->out_buffer_size) {
457 /* Maybe chop it down so that we don't buffer more characters
458 than our advertised buffering size. */
459 if ((size > lstr->buffering_size) && !force) {
460 size = lstr->buffering_size;
461 /* There might be more data buffered than the buffering size. */
462 if (size <= lstr->out_buffer_ind) {
467 LSTR_ALLOC_TO(lstr->out_buffer,
468 lstr->out_buffer_size, size, unsigned char);
470 return size - lstr->out_buffer_ind;
473 /* Like Lstream_write(), but does not handle line-buffering correctly. */
475 static Lstream_data_count
476 Lstream_write_1(lstream_t lstr, const void *data, Lstream_data_count size)
478 const unsigned char *p = data;
479 Lstream_data_count off = 0;
480 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
481 Lstream_internal_error("lstream not open", lstr);
483 if (!(lstr->flags & LSTREAM_FL_WRITE)) {
484 Lstream_internal_error("lstream not open for writing", lstr);
487 bool couldnt_write_last_time = false;
490 /* Figure out how much we can add to the buffer */
491 Lstream_data_count chunk =
492 Lstream_adding(lstr, size, 0);
494 if (couldnt_write_last_time) {
495 /* Ung, we ran out of space and tried to
496 flush the buffer, but it didn't work
497 because the stream writer is refusing
498 to accept any data. So we just have
499 to squirrel away all the rest of the
501 chunk = Lstream_adding(lstr, size, 1);
503 couldnt_write_last_time = true;
508 memcpy(lstr->out_buffer + lstr->out_buffer_ind,
510 lstr->out_buffer_ind += chunk;
511 lstr->byte_count += chunk;
515 /* If the buffer is full and we have more to add, flush
518 if (Lstream_flush_out(lstr) < 0) {
533 /* If the stream is not line-buffered, then we can just call
534 Lstream_write_1(), which writes in chunks. Otherwise, we
535 repeatedly call Lstream_putc(), which knows how to handle
536 line buffering. Returns number of bytes written. */
539 Lstream_write(lstream_t lstr, const void *data, Lstream_data_count size)
541 Lstream_data_count i;
542 const unsigned char *p = data;
547 if (lstr->buffering != LSTREAM_LINE_BUFFERED) {
548 return Lstream_write_1(lstr, data, size);
550 for (i = 0; i < size; i++) {
551 if (Lstream_putc(lstr, p[i]) < 0) {
555 return i == 0 ? -1 : i;
559 Lstream_was_blocked_p(lstream_t lstr)
561 return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p(lstr) : 0;
564 static Lstream_data_count
565 Lstream_raw_read(lstream_t lstr, unsigned char *buffer, Lstream_data_count size)
567 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
568 Lstream_internal_error("lstream not open", lstr);
570 if (!(lstr->flags & LSTREAM_FL_READ)) {
571 Lstream_internal_error("lstream not open for reading", lstr);
573 if (!lstr->imp->reader) {
574 Lstream_internal_error("lstream has no reader", lstr);
576 return lstr->imp->reader(lstr, buffer, size);
579 /* Assuming the buffer is empty, fill it up again. */
581 static Lstream_data_count
582 Lstream_read_more(lstream_t lstr)
584 /* If someone requested a larger buffer size, so be it! */
585 Lstream_data_count size_needed = max(1, lstr->buffering_size);
586 Lstream_data_count size_gotten;
588 LSTR_ALLOC_TO(lstr->in_buffer, lstr->in_buffer_size,
589 size_needed, unsigned char);
590 size_gotten = Lstream_raw_read(lstr, lstr->in_buffer, size_needed);
591 lstr->in_buffer_current = max(0, size_gotten);
592 lstr->in_buffer_ind = 0;
593 return size_gotten < 0 ? -1 : size_gotten;
597 Lstream_read(lstream_t lstr, void *data, Lstream_data_count size)
599 unsigned char *p = data;
600 Lstream_data_count off = 0;
601 Lstream_data_count chunk;
602 int error_occurred = 0;
604 /* trivial cases first */
605 if (UNLIKELY(size == 0)) {
609 /* First try to get some data from the unget buffer */
610 chunk = min(size, lstr->unget_buffer_ind);
612 /* The bytes come back in reverse order. */
613 for (; off < chunk; off++) {
614 p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
616 lstr->byte_count += chunk;
621 /* Take whatever we can from the in buffer */
623 lstr->in_buffer_current - lstr->in_buffer_ind);
625 memcpy(p + off, lstr->in_buffer + lstr->in_buffer_ind,
627 lstr->in_buffer_ind += chunk;
628 lstr->byte_count += chunk;
633 /* If we need some more, try to get some more from the stream's
636 Lstream_data_count retval = Lstream_read_more(lstr);
646 /* #### Beware of OFF ending up 0. */
647 if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0) {
648 /* It's quite possible for us to get passed an incomplete
649 character at the end. We need to spit back that
650 incomplete character. */
651 const unsigned char *dataend = p + off - 1;
652 /* Optimize the most common case. */
653 if (!BYTE_ASCII_P(*dataend)) {
654 /* Go back to the beginning of the last (and possibly
655 partial) character, and bump forward to see if the
656 character is complete. */
657 VALIDATE_CHARPTR_BACKWARD(dataend);
658 if (dataend + REP_BYTES_BY_FIRST_BYTE(*dataend) !=
660 Lstream_data_count newoff = dataend - p;
661 /* If not, chop the size down to ignore the last
662 char and stash it away for next time. */
663 Lstream_unread(lstr, dataend, off - newoff);
669 return off == 0 && error_occurred ? -1 : off;
673 Lstream_unread(lstream_t lstr, const void *data, Lstream_data_count size)
675 const unsigned char *p = data;
677 /* Make sure buffer is big enough */
678 LSTR_ALLOC_TO(lstr->unget_buffer, lstr->unget_buffer_size,
679 lstr->unget_buffer_ind + size, unsigned char);
681 lstr->byte_count -= size;
683 /* Bytes have to go on in reverse order -- they are reversed
684 again when read back. */
686 lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
692 Lstream_rewind(lstream_t lstr)
694 if (!lstr->imp->rewinder) {
695 Lstream_internal_error("lstream has no rewinder", lstr);
697 if (Lstream_flush(lstr) < 0) {
700 lstr->byte_count = 0;
701 return lstr->imp->rewinder(lstr);
705 Lstream_seekable_p(lstream_t lstr)
707 if (!lstr->imp->rewinder) {
710 if (!lstr->imp->seekable_p) {
713 return lstr->imp->seekable_p(lstr);
717 Lstream_pseudo_close(lstream_t lstr)
719 if (!(lstr->flags & LSTREAM_FL_IS_OPEN)) {
720 Lstream_internal_error("lstream is not open", lstr);
722 /* don't check errors here -- best not to risk file descriptor loss */
723 return Lstream_flush(lstr);
727 Lstream_close(lstream_t lstr)
731 if (lstr->flags & LSTREAM_FL_IS_OPEN) {
732 rc = Lstream_pseudo_close(lstr);
734 * We used to return immediately if the closer method reported
735 * failure, leaving the stream open. But this is no good, for
736 * the following reasons.
738 * 1. The finalizer method used in GC makes no provision for
739 * failure, so we must not return without freeing buffer
742 * 2. The closer method may have already freed some memory
743 * used for I/O in this stream. E.g. encoding_closer frees
744 * ENCODING_STREAM_DATA(stream)->runoff. If a writer method
745 * tries to use this buffer later, it will write into memory
746 * that may have been allocated elsewhere. Sometime later
747 * you will see a sign that says "Welcome to Crash City."
749 * 3. The closer can report failure if a flush fails in the
750 * other stream in a MULE encoding/decoding stream pair.
751 * The other stream in the pair is closed, but returning
752 * early leaves the current stream open. If we try to
753 * flush the current stream later, we will crash when the
754 * flusher notices that the other end stream is closed.
756 * So, we no longer abort the close if the closer method
757 * reports some kind of failure. We still report the failure
760 if (lstr->imp->closer) {
761 if ((lstr->imp->closer) (lstr) < 0) {
767 lstr->flags &= ~LSTREAM_FL_IS_OPEN;
768 lstr->byte_count = 0;
769 /* Note that Lstream_flush() reset all the buffer indices. That way,
770 the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
771 on a closed stream will call into the function equivalents, which
772 will cause an error. */
774 /* We set the pointers to 0 so that we don't lose when this function is
775 called more than once on the same object */
776 if (lstr->out_buffer) {
777 xfree(lstr->out_buffer);
778 lstr->out_buffer = 0;
780 if (lstr->in_buffer) {
781 xfree(lstr->in_buffer);
784 if (lstr->unget_buffer) {
785 xfree(lstr->unget_buffer);
786 lstr->unget_buffer = 0;
793 Lstream_fputc(lstream_t lstr, int c)
795 unsigned char ch = (unsigned char)c;
796 Lstream_data_count retval = Lstream_write_1(lstr, &ch, 1);
797 if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED
799 return Lstream_flush_out(lstr);
801 return retval < 0 ? -1 : 0;
805 Lstream_fgetc(lstream_t lstr)
808 if (Lstream_read(lstr, &ch, 1) <= 0) {
815 Lstream_fungetc(lstream_t lstr, int c)
817 unsigned char ch = (unsigned char)c;
818 Lstream_unread(lstr, &ch, 1);
822 Lstream_get_fd(lstream_t lstr)
826 if (lstr->imp->get_fd && (rc = (lstr->imp->get_fd)(lstr)) < 0) {
832 /************************ some stream implementations *********************/
834 /*********** a stdio stream ***********/
836 typedef struct stdio_stream_s *stdio_stream_t;
837 struct stdio_stream_s {
842 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
844 DEFINE_LSTREAM_IMPLEMENTATION("stdio", lstream_stdio,
845 sizeof(struct stdio_stream_s));
848 make_stdio_stream_1(FILE * stream, int flags, const char *mode)
851 lstream_t lstr = Lstream_new(lstream_stdio, mode);
852 stdio_stream_t str = STDIO_STREAM_DATA(lstr);
854 str->closing = flags & LSTR_CLOSING;
855 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
856 XSETLSTREAM(obj, lstr);
860 Lisp_Object make_stdio_input_stream(FILE * stream, int flags)
862 return make_stdio_stream_1(stream, flags, "r");
865 Lisp_Object make_stdio_output_stream(FILE * stream, int flags)
867 return make_stdio_stream_1(stream, flags, "w");
870 /* #### From reading the Unix 98 specification, it appears that if we
871 want stdio_reader() to be completely correct, we should check for
872 0 < val < size and if so, check to see if an error has occurred.
873 If an error has occurred, but val is non-zero, we should go ahead
874 and act as if the read was successful, but remember in some fashion
875 or other, that an error has occurred, and report that on the next
876 call to stdio_reader instead of calling fread() again.
878 Currently, in such a case, we end up calling fread() twice and we
881 1) this is not harmful, and
882 2) the error will still be reported on the second read.
884 This is probably reasonable, so I don't think we should change this
885 code (it could even be argued that the error might have fixed
886 itself, so we should do the fread() again. */
888 static Lstream_data_count
889 stdio_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
891 stdio_stream_t str = STDIO_STREAM_DATA(stream);
892 Lstream_data_count val = fread(data, 1, size, str->file);
893 if (!val && ferror(str->file)) {
899 static Lstream_data_count
900 stdio_writer(lstream_t stream, const unsigned char *data,
901 Lstream_data_count size)
903 stdio_stream_t str = STDIO_STREAM_DATA(stream);
904 Lstream_data_count val = fwrite(data, 1, size, str->file);
905 if (!val && ferror(str->file)) {
912 stdio_rewinder(lstream_t stream)
914 stdio_stream_t p = STDIO_STREAM_DATA(stream);
920 stdio_seekable_p(lstream_t stream)
923 stdio_stream_t str = STDIO_STREAM_DATA(stream);
925 if (fstat(fileno(str->file), &lestat) < 0) {
928 return S_ISREG(lestat.st_mode);
932 stdio_flusher(lstream_t stream)
934 stdio_stream_t str = STDIO_STREAM_DATA(stream);
936 if (stream->flags & LSTREAM_FL_WRITE) {
937 return fflush(str->file);
944 stdio_closer(lstream_t stream)
946 stdio_stream_t str = STDIO_STREAM_DATA(stream);
949 return fclose(str->file);
950 } else if (stream->flags & LSTREAM_FL_WRITE) {
951 return fflush(str->file);
957 /*********** a file descriptor ***********/
959 typedef struct filedesc_stream_s *filedesc_stream_t;
960 struct filedesc_stream_s {
967 int chars_sans_newline;
972 bool blocking_error_p:1;
975 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
977 DEFINE_LSTREAM_IMPLEMENTATION("filedesc", lstream_filedesc,
978 sizeof(struct filedesc_stream_s));
980 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
981 OFFSET is the offset from the *current* file pointer that the reading
982 should start at. COUNT is the number of bytes to be read (it is
983 ignored when writing); -1 for unlimited. */
985 make_filedesc_stream_1(int filedesc, int offset, int count, int flags,
989 lstream_t lstr = Lstream_new(lstream_filedesc, mode);
990 filedesc_stream_t fstr = FILEDESC_STREAM_DATA(lstr);
993 fstr->closing = !!(flags & LSTR_CLOSING);
994 fstr->allow_quit = !!(flags & LSTR_ALLOW_QUIT);
995 fstr->blocked_ok = !!(flags & LSTR_BLOCKED_OK);
996 fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
997 fstr->blocking_error_p = 0;
998 fstr->chars_sans_newline = 0;
999 fstr->starting_pos = lseek(filedesc, offset, SEEK_CUR);
1000 fstr->current_pos = max(fstr->starting_pos, 0);
1005 fstr->end_pos = fstr->starting_pos + count;
1007 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
1008 XSETLSTREAM(obj, lstr);
1013 make_filedesc_input_stream(int filedesc, int offset, int count, int flags)
1015 return make_filedesc_stream_1(filedesc, offset, count, flags, "r");
1019 make_filedesc_output_stream(int filedesc, int offset, int count, int flags)
1021 return make_filedesc_stream_1(filedesc, offset, count, flags, "w");
1024 static Lstream_data_count
1025 filedesc_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1027 Lstream_data_count nread;
1028 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1030 if (str->end_pos >= 0) {
1032 (Lstream_data_count)
1033 (str->end_pos - str->current_pos));
1035 nread = str->allow_quit
1036 ? read_allowing_quit(str->fd, data, size)
1037 : read(str->fd, data, size);
1039 str->current_pos += nread;
1045 errno_would_block_p(int val)
1048 if (val == EWOULDBLOCK) {
1053 if (val == EAGAIN) {
1060 static Lstream_data_count
1061 filedesc_writer(lstream_t stream, const unsigned char *data,
1062 Lstream_data_count size)
1064 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1065 Lstream_data_count retval;
1066 int need_newline = 0;
1068 /* This function would be simple if it were not for the blasted
1069 PTY max-bytes stuff. Why the hell can't they just have written
1070 the PTY drivers right so this problem doesn't exist?
1072 Maybe all the PTY crap here should be moved into another stream
1073 that does nothing but periodically insert EOF's as necessary. */
1074 if (str->pty_flushing) {
1075 /* To make life easy, only send out one line at the most. */
1076 const unsigned char *ptr;
1078 ptr = (const unsigned char *)memchr(data, '\n', size);
1085 str->pty_max_bytes - str->chars_sans_newline) {
1087 str->pty_max_bytes - str->chars_sans_newline;
1093 /**** start of non-PTY-crap ****/
1095 retval = str->allow_quit
1096 ? write_allowing_quit(str->fd, data, size)
1097 : write(str->fd, data, size);
1101 if (retval < 0 && errno_would_block_p(errno) && str->blocked_ok) {
1102 str->blocking_error_p = 1;
1105 str->blocking_error_p = 0;
1109 /**** end non-PTY-crap ****/
1111 if (str->pty_flushing) {
1112 str->chars_sans_newline += retval;
1113 /* Note that a newline was not among the bytes written out.
1114 Add to the number of non-newline bytes written out,
1115 and flush with an EOF if necessary. Be careful to
1116 keep track of write errors as we go along and look
1117 out for EWOULDBLOCK. */
1118 if (str->chars_sans_newline >= str->pty_max_bytes) {
1119 Lstream_data_count retval2 = str->allow_quit
1120 ? write_allowing_quit(
1121 str->fd, &str->eof_char, 1)
1122 : write(str->fd, &str->eof_char, 1);
1125 str->chars_sans_newline = 0;
1127 else if (retval2 < 0) {
1128 /* Error writing the EOF char. If nothing got
1129 written, then treat this as an error --
1130 either return an error condition or set the
1131 blocking-error flag. */
1133 if (errno_would_block_p(errno)
1134 && str->blocked_ok) {
1135 str->blocking_error_p = 1;
1146 /* The need_newline flag is necessary because otherwise when the
1147 first byte is a newline, we'd get stuck never writing anything
1148 in pty-flushing mode. */
1151 Lstream_data_count retval2 = str->allow_quit
1152 ? write_allowing_quit(str->fd, &nl, 1)
1153 : write(str->fd, &nl, 1);
1156 str->chars_sans_newline = 0;
1158 } else if (retval2 < 0) {
1159 /* Error writing the newline char. If nothing got
1160 written, then treat this as an error -- either return
1161 an error condition or set the blocking-error flag. */
1163 if (errno_would_block_p(errno)
1164 && str->blocked_ok) {
1165 str->blocking_error_p = 1;
1180 filedesc_rewinder(lstream_t stream)
1182 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1183 if (str->starting_pos < 0 ||
1184 lseek(FILEDESC_STREAM_DATA(stream)->fd, str->starting_pos,
1188 str->current_pos = str->starting_pos;
1194 filedesc_seekable_p(lstream_t stream)
1196 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1198 if (str->starting_pos < 0) {
1203 if (fstat(str->fd, &lestat) < 0) {
1206 return S_ISREG(lestat.st_mode);
1211 filedesc_closer(lstream_t stream)
1213 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1216 return close(str->fd);
1223 filedesc_was_blocked_p(lstream_t stream)
1225 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1226 return str->blocking_error_p;
1230 filedesc_stream_set_pty_flushing(lstream_t stream, int pty_max_bytes,
1233 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1234 str->pty_max_bytes = pty_max_bytes;
1235 str->eof_char = eof_char;
1236 str->pty_flushing = 1;
1241 filedesc_get_fd(lstream_t stream)
1243 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1247 /*********** read from a Lisp string ***********/
1249 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1251 typedef struct lisp_string_stream_s *lisp_string_stream_t;
1252 struct lisp_string_stream_s {
1254 Bytecount init_offset;
1255 Bytecount offset, end;
1258 DEFINE_LSTREAM_IMPLEMENTATION("lisp-string", lstream_lisp_string,
1259 sizeof(struct lisp_string_stream_s));
1262 make_lisp_string_input_stream(Lisp_Object string, Bytecount offset,
1267 lisp_string_stream_t str;
1269 CHECK_STRING(string);
1271 len = XSTRING_LENGTH(string) - offset;
1273 assert(offset >= 0);
1275 assert(offset + len <= XSTRING_LENGTH(string));
1277 lstr = Lstream_new(lstream_lisp_string, "r");
1278 str = LISP_STRING_STREAM_DATA(lstr);
1279 str->offset = offset;
1280 str->end = offset + len;
1281 str->init_offset = offset;
1283 XSETLSTREAM(obj, lstr);
1287 static Lstream_data_count
1288 lisp_string_reader(lstream_t stream, unsigned char *data,
1289 Lstream_data_count size)
1291 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1292 /* Don't lose if the string shrank past us ... */
1293 Bytecount offset = min(str->offset, XSTRING_LENGTH(str->obj));
1294 Bufbyte *strstart = XSTRING_DATA(str->obj);
1295 Bufbyte *start = strstart + offset;
1297 /* ... or if someone changed the string and we ended up in the
1298 middle of a character. */
1299 /* Being in the middle of a character is `normal' unless
1300 LSTREAM_NO_PARTIAL_CHARS - mrb */
1301 if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS) {
1302 VALIDATE_CHARPTR_BACKWARD(start);
1304 offset = start - strstart;
1305 size = min(size, (Lstream_data_count) (str->end - offset));
1306 memcpy(data, start, size);
1307 str->offset = offset + size;
1312 lisp_string_rewinder(lstream_t stream)
1314 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1315 int pos = str->init_offset;
1317 if (pos > str->end) {
1320 /* Don't lose if the string shrank past us ... */
1321 pos = min(pos, XSTRING_LENGTH(str->obj));
1322 /* ... or if someone changed the string and we ended up in the
1323 middle of a character. */
1325 Bufbyte *strstart = XSTRING_DATA(str->obj);
1326 Bufbyte *start = strstart + pos;
1327 VALIDATE_CHARPTR_BACKWARD(start);
1328 pos = start - strstart;
1335 lisp_string_marker(Lisp_Object stream)
1337 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(XLSTREAM(stream));
1341 /*********** a fixed buffer ***********/
1343 #define FIXED_BUFFER_STREAM_DATA(stream) \
1344 LSTREAM_TYPE_DATA (stream, fixed_buffer)
1346 typedef struct fixed_buffer_stream_s *fixed_buffer_stream_t;
1347 struct fixed_buffer_stream_s {
1348 const unsigned char *inbuf;
1349 unsigned char *outbuf;
1350 Lstream_data_count size;
1351 Lstream_data_count offset;
1354 DEFINE_LSTREAM_IMPLEMENTATION("fixed-buffer", lstream_fixed_buffer,
1355 sizeof(struct fixed_buffer_stream_s));
1358 make_fixed_buffer_input_stream(const void *buf, Lstream_data_count size)
1361 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "r");
1362 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1363 str->inbuf = (const unsigned char *)buf;
1365 XSETLSTREAM(obj, lstr);
1370 make_fixed_buffer_output_stream(void *buf, Lstream_data_count size)
1373 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "w");
1374 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1375 str->outbuf = (unsigned char *)buf;
1377 XSETLSTREAM(obj, lstr);
1381 static Lstream_data_count
1382 fixed_buffer_reader(lstream_t stream, unsigned char *data,
1383 Lstream_data_count size)
1385 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1386 size = min(size, str->size - str->offset);
1387 memcpy(data, str->inbuf + str->offset, size);
1388 str->offset += size;
1392 static Lstream_data_count
1393 fixed_buffer_writer(lstream_t stream, const unsigned char *data,
1394 Lstream_data_count size)
1396 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1397 if (str->offset == str->size) {
1398 /* If we're at the end, just throw away the data and pretend
1399 we wrote all of it. If we return 0, then the lstream routines
1400 will try again and again to write it out. */
1403 size = min(size, str->size - str->offset);
1404 memcpy(str->outbuf + str->offset, data, size);
1405 str->offset += size;
1410 fixed_buffer_rewinder(lstream_t stream)
1412 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1417 const unsigned char*
1418 fixed_buffer_input_stream_ptr(lstream_t stream)
1420 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1421 assert(stream->imp == lstream_fixed_buffer);
1426 fixed_buffer_output_stream_ptr(lstream_t stream)
1428 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1429 assert(stream->imp == lstream_fixed_buffer);
1433 /*********** write to a resizing buffer ***********/
1435 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1436 LSTREAM_TYPE_DATA (stream, resizing_buffer)
1438 typedef struct resizing_buffer_stream_s *resizing_buffer_stream_t;
1439 struct resizing_buffer_stream_s {
1441 Lstream_data_count allocked;
1446 DEFINE_LSTREAM_IMPLEMENTATION("resizing-buffer", lstream_resizing_buffer,
1447 sizeof(struct resizing_buffer_stream_s));
1449 Lisp_Object make_resizing_buffer_output_stream(void)
1452 XSETLSTREAM(obj, Lstream_new(lstream_resizing_buffer, "w"));
1456 static Lstream_data_count
1457 resizing_buffer_writer(lstream_t stream, const unsigned char *data,
1458 Lstream_data_count size)
1460 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1462 LSTR_ALLOC_TO(str->buf, str->allocked, str->stored + size,
1464 memcpy(str->buf + str->stored, data, size);
1465 str->stored += size;
1466 str->max_stored = max(str->max_stored, str->stored);
1471 resizing_buffer_rewinder(lstream_t stream)
1473 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1479 resizing_buffer_closer(lstream_t stream)
1481 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1491 resizing_buffer_stream_ptr(lstream_t stream)
1493 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1497 /*********** write to an unsigned-char dynarr ***********/
1499 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1500 but which is really just an unsigned_char_dynarr (e.g. its type
1501 is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1503 #define DYNARR_STREAM_DATA(stream) \
1504 LSTREAM_TYPE_DATA (stream, dynarr)
1506 typedef struct dynarr_stream_s *dynarr_stream_t;
1507 struct dynarr_stream_s {
1508 unsigned_char_dynarr *dyn;
1511 DEFINE_LSTREAM_IMPLEMENTATION("dynarr", lstream_dynarr,
1512 sizeof(struct dynarr_stream_s));
1515 make_dynarr_output_stream(unsigned_char_dynarr * dyn)
1520 XSETLSTREAM(obj, Lstream_new(lstream_dynarr, "w"));
1521 p = DYNARR_STREAM_DATA(XLSTREAM(obj));
1526 static Lstream_data_count
1527 dynarr_writer(lstream_t stream, const unsigned char *data,
1528 Lstream_data_count size)
1530 dynarr_stream_t str = DYNARR_STREAM_DATA(stream);
1531 Dynarr_add_many(str->dyn, data, size);
1536 dynarr_rewinder(lstream_t stream)
1538 dynarr_stream_t p = DYNARR_STREAM_DATA(stream);
1539 Dynarr_reset(p->dyn);
1544 dynarr_closer(lstream_t stream)
1549 /************ read from or write to a Lisp buffer ************/
1551 /* Note: Lisp-buffer read streams never return partial characters,
1552 and Lisp-buffer write streams expect to never get partial
1555 #define LISP_BUFFER_STREAM_DATA(stream) \
1556 LSTREAM_TYPE_DATA (stream, lisp_buffer)
1558 typedef struct lisp_buffer_stream_s *lisp_buffer_stream_t;
1559 struct lisp_buffer_stream_s {
1561 Lisp_Object orig_start;
1562 /* we use markers to properly deal with insertion/deletion */
1563 Lisp_Object start, end;
1567 DEFINE_LSTREAM_IMPLEMENTATION("lisp-buffer", lstream_lisp_buffer,
1568 sizeof(struct lisp_buffer_stream_s));
1571 make_lisp_buffer_stream_1(struct buffer *buf, Bufpos start, Bufpos end,
1572 int flags, const char *mode)
1576 lisp_buffer_stream_t str;
1578 int reading = !strcmp(mode, "r");
1580 /* Make sure the luser didn't pass "w" in. */
1581 if (!strcmp(mode, "w")) {
1585 if (flags & LSTR_IGNORE_ACCESSIBLE) {
1586 bmin = BUF_BEG(buf);
1589 bmin = BUF_BEGV(buf);
1599 assert(bmin <= start);
1600 assert(start <= bmax);
1602 assert(bmin <= end);
1603 assert(end <= bmax);
1604 assert(start <= end);
1607 lstr = Lstream_new(lstream_lisp_buffer, mode);
1608 str = LISP_BUFFER_STREAM_DATA(lstr);
1613 XSETBUFFER(buffer, buf);
1614 marker = Fmake_marker();
1615 Fset_marker(marker, make_int(start), buffer);
1616 str->start = marker;
1617 marker = Fmake_marker();
1618 Fset_marker(marker, make_int(start), buffer);
1619 str->orig_start = marker;
1621 marker = Fmake_marker();
1622 Fset_marker(marker, make_int(end), buffer);
1627 str->buffer = buffer;
1630 XSETLSTREAM(obj, lstr);
1635 make_lisp_buffer_input_stream(struct buffer *buf, Bufpos start, Bufpos end,
1638 return make_lisp_buffer_stream_1(buf, start, end, flags, "r");
1642 make_lisp_buffer_output_stream(struct buffer *buf, Bufpos pos, int flags)
1644 Lisp_Object lstr = make_lisp_buffer_stream_1(buf, pos, 0, flags, "wc");
1646 Lstream_set_character_mode(XLSTREAM(lstr));
1650 static Lstream_data_count
1651 lisp_buffer_reader(lstream_t stream, unsigned char *data,
1652 Lstream_data_count size)
1654 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1655 unsigned char *orig_data = data;
1658 struct buffer *buf = XBUFFER(str->buffer);
1660 if (!BUFFER_LIVE_P(buf)) {
1665 /* NOTE: We do all our operations in Bytind's.
1666 Keep in mind that SIZE is a value in bytes, not chars. */
1668 start = bi_marker_position(str->start);
1669 end = bi_marker_position(str->end);
1670 if (!(str->flags & LSTR_IGNORE_ACCESSIBLE)) {
1671 start = bytind_clip_to_bounds(BI_BUF_BEGV(buf), start,
1673 end = bytind_clip_to_bounds(BI_BUF_BEGV(buf), end,
1677 size = min(size, (Lstream_data_count) (end - start));
1679 /* We cannot return a partial character. */
1680 VALIDATE_BYTIND_BACKWARD(buf, end);
1682 while (start < end) {
1686 if (str->flags & LSTR_IGNORE_ACCESSIBLE) {
1687 _ceil_ = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE(
1690 _ceil_ = BI_BUF_CEILING_OF(buf, start);
1692 chunk = min(_ceil_, end) - start;
1693 memcpy(data, BI_BUF_BYTE_ADDRESS(buf, start), chunk);
1698 if (EQ(buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE) {
1699 /* What a kludge. What a kludge. What a kludge. */
1701 for (p = orig_data; p < data; p++) {
1708 set_bi_marker_position(str->start, end);
1709 return data - orig_data;
1712 static Lstream_data_count
1713 lisp_buffer_writer(lstream_t stream, const unsigned char *data,
1714 Lstream_data_count size)
1716 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1718 struct buffer *buf = XBUFFER(str->buffer);
1720 if (!BUFFER_LIVE_P(buf)) {
1725 pos = marker_position(str->start);
1726 pos += buffer_insert_raw_string_1(buf, pos, data, size, 0);
1727 set_marker_position(str->start, pos);
1732 lisp_buffer_rewinder(lstream_t stream)
1734 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1735 struct buffer *buf = XBUFFER(str->buffer);
1736 long pos = marker_position(str->orig_start);
1738 if (!BUFFER_LIVE_P(buf)) {
1742 if (pos > BUF_ZV(buf)) {
1745 if (pos < marker_position(str->orig_start)) {
1746 pos = marker_position(str->orig_start);
1748 if (MARKERP(str->end) && pos > marker_position(str->end)) {
1749 pos = marker_position(str->end);
1751 set_marker_position(str->start, pos);
1756 lisp_buffer_marker(Lisp_Object stream)
1758 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(XLSTREAM(stream));
1760 mark_object(str->start);
1761 mark_object(str->end);
1766 lisp_buffer_stream_startpos(lstream_t stream)
1768 lisp_buffer_stream_t p = LISP_BUFFER_STREAM_DATA(stream);
1769 return marker_position(p->start);
1772 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1773 #include "openssl.h"
1775 typedef struct ssl_stream_s *ssl_stream_t;
1776 struct ssl_stream_s {
1781 bool blocking_error_p:1;
1784 #define SSL_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, ssl)
1786 DEFINE_LSTREAM_IMPLEMENTATION("ssl", lstream_ssl, sizeof(struct ssl_stream_s));
1789 make_ssl_stream_1(SSL *conn, int flags, const char *mode)
1792 lstream_t lstr = Lstream_new(lstream_ssl, mode);
1793 ssl_stream_t str = SSL_STREAM_DATA(lstr);
1795 XSETLSTREAM(obj, lstr);
1800 make_ssl_input_stream(SSL *conn, int flags)
1802 return make_ssl_stream_1(conn, flags, "r");
1806 make_ssl_output_stream(SSL *conn, int flags)
1808 return make_ssl_stream_1(conn, flags, "w");
1811 static Lstream_data_count
1812 ssl_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1814 Lstream_data_count nread;
1815 ssl_stream_t str = SSL_STREAM_DATA(stream);
1817 nread = SSL_read(str->conn, data, size);
1824 static Lstream_data_count
1825 ssl_writer(lstream_t stream, const unsigned char *data,
1826 Lstream_data_count size)
1828 Lstream_data_count nwrite;
1829 ssl_stream_t str = SSL_STREAM_DATA(stream);
1831 nwrite = SSL_write(str->conn, data, size);
1839 ssl_closer(lstream_t stream)
1841 ssl_stream_t str = SSL_STREAM_DATA(stream);
1843 return SSL_shutdown(str->conn);
1850 ssl_get_fd(lstream_t stream)
1852 ssl_stream_t str = SSL_STREAM_DATA(stream);
1853 return SSL_get_rfd(str->conn);
1857 /************************************************************************/
1858 /* initialization */
1859 /************************************************************************/
1861 void lstream_type_create(void)
1863 LSTREAM_HAS_METHOD(stdio, reader);
1864 LSTREAM_HAS_METHOD(stdio, writer);
1865 LSTREAM_HAS_METHOD(stdio, rewinder);
1866 LSTREAM_HAS_METHOD(stdio, seekable_p);
1867 LSTREAM_HAS_METHOD(stdio, flusher);
1868 LSTREAM_HAS_METHOD(stdio, closer);
1870 LSTREAM_HAS_METHOD(filedesc, reader);
1871 LSTREAM_HAS_METHOD(filedesc, writer);
1872 LSTREAM_HAS_METHOD(filedesc, was_blocked_p);
1873 LSTREAM_HAS_METHOD(filedesc, rewinder);
1874 LSTREAM_HAS_METHOD(filedesc, seekable_p);
1875 LSTREAM_HAS_METHOD(filedesc, closer);
1876 LSTREAM_HAS_METHOD(filedesc, get_fd);
1878 LSTREAM_HAS_METHOD(lisp_string, reader);
1879 LSTREAM_HAS_METHOD(lisp_string, rewinder);
1880 LSTREAM_HAS_METHOD(lisp_string, marker);
1882 LSTREAM_HAS_METHOD(fixed_buffer, reader);
1883 LSTREAM_HAS_METHOD(fixed_buffer, writer);
1884 LSTREAM_HAS_METHOD(fixed_buffer, rewinder);
1886 LSTREAM_HAS_METHOD(resizing_buffer, writer);
1887 LSTREAM_HAS_METHOD(resizing_buffer, rewinder);
1888 LSTREAM_HAS_METHOD(resizing_buffer, closer);
1890 LSTREAM_HAS_METHOD(dynarr, writer);
1891 LSTREAM_HAS_METHOD(dynarr, rewinder);
1892 LSTREAM_HAS_METHOD(dynarr, closer);
1894 LSTREAM_HAS_METHOD(lisp_buffer, reader);
1895 LSTREAM_HAS_METHOD(lisp_buffer, writer);
1896 LSTREAM_HAS_METHOD(lisp_buffer, rewinder);
1897 LSTREAM_HAS_METHOD(lisp_buffer, marker);
1899 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1900 LSTREAM_HAS_METHOD(ssl, reader);
1901 LSTREAM_HAS_METHOD(ssl, writer);
1902 LSTREAM_HAS_METHOD(ssl, closer);
1903 LSTREAM_HAS_METHOD(ssl, get_fd);
1907 void reinit_vars_of_lstream(void)
1909 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
1910 for (int i = 0; i < countof(Vlstream_free_list); i++) {
1911 Vlstream_free_list[i] = Qnil;
1912 staticpro_nodump(&Vlstream_free_list[i]);
1917 void vars_of_lstream(void)
1919 INIT_LRECORD_IMPLEMENTATION(lstream);
1921 reinit_vars_of_lstream();
1924 /* lstream.c ends here */