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,
991 lstream_t lstr = Lstream_new(lstream_filedesc, mode);
992 filedesc_stream_t fstr = FILEDESC_STREAM_DATA(lstr);
995 fstr->closing = !!(flags & LSTR_CLOSING);
996 fstr->allow_quit = !!(flags & LSTR_ALLOW_QUIT);
997 fstr->blocked_ok = !!(flags & LSTR_BLOCKED_OK);
998 fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
999 fstr->blocking_error_p = 0;
1000 fstr->chars_sans_newline = 0;
1001 fstr->starting_pos = lseek(filedesc, offset, SEEK_CUR);
1002 fstr->current_pos = max(fstr->starting_pos, 0);
1007 fstr->end_pos = fstr->starting_pos + count;
1009 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
1010 XSETLSTREAM(obj, lstr);
1015 make_filedesc_input_stream(int filedesc, int offset, int count, int flags)
1017 return make_filedesc_stream_1(filedesc, offset, count, flags, "r");
1021 make_filedesc_output_stream(int filedesc, int offset, int count, int flags)
1023 return make_filedesc_stream_1(filedesc, offset, count, flags, "w");
1026 static Lstream_data_count
1027 filedesc_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1029 Lstream_data_count nread;
1030 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1032 if (str->end_pos >= 0) {
1034 (Lstream_data_count)
1035 (str->end_pos - str->current_pos));
1037 nread = str->allow_quit
1038 ? read_allowing_quit(str->fd, data, size)
1039 : read(str->fd, data, size);
1041 str->current_pos += nread;
1047 errno_would_block_p(int val)
1050 if (val == EWOULDBLOCK) {
1055 if (val == EAGAIN) {
1062 static Lstream_data_count
1063 filedesc_writer(lstream_t stream, const unsigned char *data,
1064 Lstream_data_count size)
1066 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1067 Lstream_data_count retval;
1068 int need_newline = 0;
1070 /* This function would be simple if it were not for the blasted
1071 PTY max-bytes stuff. Why the hell can't they just have written
1072 the PTY drivers right so this problem doesn't exist?
1074 Maybe all the PTY crap here should be moved into another stream
1075 that does nothing but periodically insert EOF's as necessary. */
1076 if (str->pty_flushing) {
1077 /* To make life easy, only send out one line at the most. */
1078 const unsigned char *ptr;
1080 ptr = (const unsigned char *)memchr(data, '\n', size);
1087 str->pty_max_bytes - str->chars_sans_newline) {
1089 str->pty_max_bytes - str->chars_sans_newline;
1095 /**** start of non-PTY-crap ****/
1097 retval = str->allow_quit
1098 ? write_allowing_quit(str->fd, data, size)
1099 : write(str->fd, data, size);
1103 if (retval < 0 && errno_would_block_p(errno) && str->blocked_ok) {
1104 str->blocking_error_p = 1;
1107 str->blocking_error_p = 0;
1111 /**** end non-PTY-crap ****/
1113 if (str->pty_flushing) {
1114 str->chars_sans_newline += retval;
1115 /* Note that a newline was not among the bytes written out.
1116 Add to the number of non-newline bytes written out,
1117 and flush with an EOF if necessary. Be careful to
1118 keep track of write errors as we go along and look
1119 out for EWOULDBLOCK. */
1120 if (str->chars_sans_newline >= str->pty_max_bytes) {
1121 Lstream_data_count retval2 = str->allow_quit
1122 ? write_allowing_quit(
1123 str->fd, &str->eof_char, 1)
1124 : write(str->fd, &str->eof_char, 1);
1127 str->chars_sans_newline = 0;
1129 else if (retval2 < 0) {
1130 /* Error writing the EOF char. If nothing got
1131 written, then treat this as an error --
1132 either return an error condition or set the
1133 blocking-error flag. */
1135 if (errno_would_block_p(errno)
1136 && str->blocked_ok) {
1137 str->blocking_error_p = 1;
1148 /* The need_newline flag is necessary because otherwise when the
1149 first byte is a newline, we'd get stuck never writing anything
1150 in pty-flushing mode. */
1153 Lstream_data_count retval2 = str->allow_quit
1154 ? write_allowing_quit(str->fd, &nl, 1)
1155 : write(str->fd, &nl, 1);
1158 str->chars_sans_newline = 0;
1160 } else if (retval2 < 0) {
1161 /* Error writing the newline char. If nothing got
1162 written, then treat this as an error -- either return
1163 an error condition or set the blocking-error flag. */
1165 if (errno_would_block_p(errno)
1166 && str->blocked_ok) {
1167 str->blocking_error_p = 1;
1182 filedesc_rewinder(lstream_t stream)
1184 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1185 if (str->starting_pos < 0 ||
1186 lseek(FILEDESC_STREAM_DATA(stream)->fd, str->starting_pos,
1190 str->current_pos = str->starting_pos;
1196 filedesc_seekable_p(lstream_t stream)
1198 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1200 if (str->starting_pos < 0) {
1205 if (fstat(str->fd, &lestat) < 0) {
1208 return S_ISREG(lestat.st_mode);
1213 filedesc_closer(lstream_t stream)
1215 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1218 return close(str->fd);
1225 filedesc_was_blocked_p(lstream_t stream)
1227 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1228 return str->blocking_error_p;
1232 filedesc_stream_set_pty_flushing(lstream_t stream, int pty_max_bytes,
1235 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1236 str->pty_max_bytes = pty_max_bytes;
1237 str->eof_char = eof_char;
1238 str->pty_flushing = 1;
1243 filedesc_get_fd(lstream_t stream)
1245 filedesc_stream_t str = FILEDESC_STREAM_DATA(stream);
1249 /*********** read from a Lisp string ***********/
1251 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1253 typedef struct lisp_string_stream_s *lisp_string_stream_t;
1254 struct lisp_string_stream_s {
1256 Bytecount init_offset;
1257 Bytecount offset, end;
1260 DEFINE_LSTREAM_IMPLEMENTATION("lisp-string", lstream_lisp_string,
1261 sizeof(struct lisp_string_stream_s));
1264 make_lisp_string_input_stream(Lisp_Object string, Bytecount offset,
1269 lisp_string_stream_t str;
1271 CHECK_STRING(string);
1273 len = XSTRING_LENGTH(string) - offset;
1275 assert(offset >= 0);
1277 assert(offset + len <= XSTRING_LENGTH(string));
1279 lstr = Lstream_new(lstream_lisp_string, "r");
1280 str = LISP_STRING_STREAM_DATA(lstr);
1281 str->offset = offset;
1282 str->end = offset + len;
1283 str->init_offset = offset;
1285 XSETLSTREAM(obj, lstr);
1289 static Lstream_data_count
1290 lisp_string_reader(lstream_t stream, unsigned char *data,
1291 Lstream_data_count size)
1293 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1294 /* Don't lose if the string shrank past us ... */
1295 Bytecount offset = min(str->offset, XSTRING_LENGTH(str->obj));
1296 Bufbyte *strstart = XSTRING_DATA(str->obj);
1297 Bufbyte *start = strstart + offset;
1299 /* ... or if someone changed the string and we ended up in the
1300 middle of a character. */
1301 /* Being in the middle of a character is `normal' unless
1302 LSTREAM_NO_PARTIAL_CHARS - mrb */
1303 if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS) {
1304 VALIDATE_CHARPTR_BACKWARD(start);
1306 offset = start - strstart;
1307 size = min(size, (Lstream_data_count) (str->end - offset));
1308 memcpy(data, start, size);
1309 str->offset = offset + size;
1314 lisp_string_rewinder(lstream_t stream)
1316 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(stream);
1317 int pos = str->init_offset;
1319 if (pos > str->end) {
1322 /* Don't lose if the string shrank past us ... */
1323 pos = min(pos, XSTRING_LENGTH(str->obj));
1324 /* ... or if someone changed the string and we ended up in the
1325 middle of a character. */
1327 Bufbyte *strstart = XSTRING_DATA(str->obj);
1328 Bufbyte *start = strstart + pos;
1329 VALIDATE_CHARPTR_BACKWARD(start);
1330 pos = start - strstart;
1337 lisp_string_marker(Lisp_Object stream)
1339 lisp_string_stream_t str = LISP_STRING_STREAM_DATA(XLSTREAM(stream));
1343 /*********** a fixed buffer ***********/
1345 #define FIXED_BUFFER_STREAM_DATA(stream) \
1346 LSTREAM_TYPE_DATA (stream, fixed_buffer)
1348 typedef struct fixed_buffer_stream_s *fixed_buffer_stream_t;
1349 struct fixed_buffer_stream_s {
1350 const unsigned char *inbuf;
1351 unsigned char *outbuf;
1352 Lstream_data_count size;
1353 Lstream_data_count offset;
1356 DEFINE_LSTREAM_IMPLEMENTATION("fixed-buffer", lstream_fixed_buffer,
1357 sizeof(struct fixed_buffer_stream_s));
1360 make_fixed_buffer_input_stream(const void *buf, Lstream_data_count size)
1363 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "r");
1364 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1365 str->inbuf = (const unsigned char *)buf;
1367 XSETLSTREAM(obj, lstr);
1372 make_fixed_buffer_output_stream(void *buf, Lstream_data_count size)
1375 lstream_t lstr = Lstream_new(lstream_fixed_buffer, "w");
1376 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(lstr);
1377 str->outbuf = (unsigned char *)buf;
1379 XSETLSTREAM(obj, lstr);
1383 static Lstream_data_count
1384 fixed_buffer_reader(lstream_t stream, unsigned char *data,
1385 Lstream_data_count size)
1387 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1388 size = min(size, str->size - str->offset);
1389 memcpy(data, str->inbuf + str->offset, size);
1390 str->offset += size;
1394 static Lstream_data_count
1395 fixed_buffer_writer(lstream_t stream, const unsigned char *data,
1396 Lstream_data_count size)
1398 fixed_buffer_stream_t str = FIXED_BUFFER_STREAM_DATA(stream);
1399 if (str->offset == str->size) {
1400 /* If we're at the end, just throw away the data and pretend
1401 we wrote all of it. If we return 0, then the lstream routines
1402 will try again and again to write it out. */
1405 size = min(size, str->size - str->offset);
1406 memcpy(str->outbuf + str->offset, data, size);
1407 str->offset += size;
1412 fixed_buffer_rewinder(lstream_t stream)
1414 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1419 const unsigned char*
1420 fixed_buffer_input_stream_ptr(lstream_t stream)
1422 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1423 assert(stream->imp == lstream_fixed_buffer);
1428 fixed_buffer_output_stream_ptr(lstream_t stream)
1430 fixed_buffer_stream_t p = FIXED_BUFFER_STREAM_DATA(stream);
1431 assert(stream->imp == lstream_fixed_buffer);
1435 /*********** write to a resizing buffer ***********/
1437 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1438 LSTREAM_TYPE_DATA (stream, resizing_buffer)
1440 typedef struct resizing_buffer_stream_s *resizing_buffer_stream_t;
1441 struct resizing_buffer_stream_s {
1443 Lstream_data_count allocked;
1448 DEFINE_LSTREAM_IMPLEMENTATION("resizing-buffer", lstream_resizing_buffer,
1449 sizeof(struct resizing_buffer_stream_s));
1451 Lisp_Object make_resizing_buffer_output_stream(void)
1454 XSETLSTREAM(obj, Lstream_new(lstream_resizing_buffer, "w"));
1458 static Lstream_data_count
1459 resizing_buffer_writer(lstream_t stream, const unsigned char *data,
1460 Lstream_data_count size)
1462 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1464 LSTR_ALLOC_TO(str->buf, str->allocked, str->stored + size,
1466 memcpy(str->buf + str->stored, data, size);
1467 str->stored += size;
1468 str->max_stored = max(str->max_stored, str->stored);
1473 resizing_buffer_rewinder(lstream_t stream)
1475 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1481 resizing_buffer_closer(lstream_t stream)
1483 resizing_buffer_stream_t str = RESIZING_BUFFER_STREAM_DATA(stream);
1493 resizing_buffer_stream_ptr(lstream_t stream)
1495 resizing_buffer_stream_t p = RESIZING_BUFFER_STREAM_DATA(stream);
1499 /*********** write to an unsigned-char dynarr ***********/
1501 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1502 but which is really just an unsigned_char_dynarr (e.g. its type
1503 is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1505 #define DYNARR_STREAM_DATA(stream) \
1506 LSTREAM_TYPE_DATA (stream, dynarr)
1508 typedef struct dynarr_stream_s *dynarr_stream_t;
1509 struct dynarr_stream_s {
1510 unsigned_char_dynarr *dyn;
1513 DEFINE_LSTREAM_IMPLEMENTATION("dynarr", lstream_dynarr,
1514 sizeof(struct dynarr_stream_s));
1517 make_dynarr_output_stream(unsigned_char_dynarr * dyn)
1522 XSETLSTREAM(obj, Lstream_new(lstream_dynarr, "w"));
1523 p = DYNARR_STREAM_DATA(XLSTREAM(obj));
1528 static Lstream_data_count
1529 dynarr_writer(lstream_t stream, const unsigned char *data,
1530 Lstream_data_count size)
1532 dynarr_stream_t str = DYNARR_STREAM_DATA(stream);
1533 Dynarr_add_many(str->dyn, data, size);
1538 dynarr_rewinder(lstream_t stream)
1540 dynarr_stream_t p = DYNARR_STREAM_DATA(stream);
1541 Dynarr_reset(p->dyn);
1546 dynarr_closer(lstream_t stream)
1551 /************ read from or write to a Lisp buffer ************/
1553 /* Note: Lisp-buffer read streams never return partial characters,
1554 and Lisp-buffer write streams expect to never get partial
1557 #define LISP_BUFFER_STREAM_DATA(stream) \
1558 LSTREAM_TYPE_DATA (stream, lisp_buffer)
1560 typedef struct lisp_buffer_stream_s *lisp_buffer_stream_t;
1561 struct lisp_buffer_stream_s {
1563 Lisp_Object orig_start;
1564 /* we use markers to properly deal with insertion/deletion */
1565 Lisp_Object start, end;
1569 DEFINE_LSTREAM_IMPLEMENTATION("lisp-buffer", lstream_lisp_buffer,
1570 sizeof(struct lisp_buffer_stream_s));
1573 make_lisp_buffer_stream_1(struct buffer *buf, Bufpos start, Bufpos end,
1574 int flags, const char *mode)
1578 lisp_buffer_stream_t str;
1580 int reading = !strcmp(mode, "r");
1582 /* Make sure the luser didn't pass "w" in. */
1583 if (!strcmp(mode, "w")) {
1587 if (flags & LSTR_IGNORE_ACCESSIBLE) {
1588 bmin = BUF_BEG(buf);
1591 bmin = BUF_BEGV(buf);
1601 assert(bmin <= start);
1602 assert(start <= bmax);
1604 assert(bmin <= end);
1605 assert(end <= bmax);
1606 assert(start <= end);
1609 lstr = Lstream_new(lstream_lisp_buffer, mode);
1610 str = LISP_BUFFER_STREAM_DATA(lstr);
1615 XSETBUFFER(buffer, buf);
1616 marker = Fmake_marker();
1617 Fset_marker(marker, make_int(start), buffer);
1618 str->start = marker;
1619 marker = Fmake_marker();
1620 Fset_marker(marker, make_int(start), buffer);
1621 str->orig_start = marker;
1623 marker = Fmake_marker();
1624 Fset_marker(marker, make_int(end), buffer);
1629 str->buffer = buffer;
1632 XSETLSTREAM(obj, lstr);
1637 make_lisp_buffer_input_stream(struct buffer *buf, Bufpos start, Bufpos end,
1640 return make_lisp_buffer_stream_1(buf, start, end, flags, "r");
1644 make_lisp_buffer_output_stream(struct buffer *buf, Bufpos pos, int flags)
1646 Lisp_Object lstr = make_lisp_buffer_stream_1(buf, pos, 0, flags, "wc");
1648 Lstream_set_character_mode(XLSTREAM(lstr));
1652 static Lstream_data_count
1653 lisp_buffer_reader(lstream_t stream, unsigned char *data,
1654 Lstream_data_count size)
1656 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1657 unsigned char *orig_data = data;
1660 struct buffer *buf = XBUFFER(str->buffer);
1662 if (!BUFFER_LIVE_P(buf)) {
1667 /* NOTE: We do all our operations in Bytind's.
1668 Keep in mind that SIZE is a value in bytes, not chars. */
1670 start = bi_marker_position(str->start);
1671 end = bi_marker_position(str->end);
1672 if (!(str->flags & LSTR_IGNORE_ACCESSIBLE)) {
1673 start = bytind_clip_to_bounds(BI_BUF_BEGV(buf), start,
1675 end = bytind_clip_to_bounds(BI_BUF_BEGV(buf), end,
1679 size = min(size, (Lstream_data_count) (end - start));
1681 /* We cannot return a partial character. */
1682 VALIDATE_BYTIND_BACKWARD(buf, end);
1684 while (start < end) {
1688 if (str->flags & LSTR_IGNORE_ACCESSIBLE) {
1689 _ceil_ = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE(
1692 _ceil_ = BI_BUF_CEILING_OF(buf, start);
1694 chunk = min(_ceil_, end) - start;
1695 memcpy(data, BI_BUF_BYTE_ADDRESS(buf, start), chunk);
1700 if (EQ(buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE) {
1701 /* What a kludge. What a kludge. What a kludge. */
1703 for (p = orig_data; p < data; p++) {
1710 set_bi_marker_position(str->start, end);
1711 return data - orig_data;
1714 static Lstream_data_count
1715 lisp_buffer_writer(lstream_t stream, const unsigned char *data,
1716 Lstream_data_count size)
1718 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1720 struct buffer *buf = XBUFFER(str->buffer);
1722 if (!BUFFER_LIVE_P(buf)) {
1727 pos = marker_position(str->start);
1728 pos += buffer_insert_raw_string_1(buf, pos, data, size, 0);
1729 set_marker_position(str->start, pos);
1734 lisp_buffer_rewinder(lstream_t stream)
1736 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(stream);
1737 struct buffer *buf = XBUFFER(str->buffer);
1738 long pos = marker_position(str->orig_start);
1740 if (!BUFFER_LIVE_P(buf)) {
1744 if (pos > BUF_ZV(buf)) {
1747 if (pos < marker_position(str->orig_start)) {
1748 pos = marker_position(str->orig_start);
1750 if (MARKERP(str->end) && pos > marker_position(str->end)) {
1751 pos = marker_position(str->end);
1753 set_marker_position(str->start, pos);
1758 lisp_buffer_marker(Lisp_Object stream)
1760 lisp_buffer_stream_t str = LISP_BUFFER_STREAM_DATA(XLSTREAM(stream));
1762 mark_object(str->start);
1763 mark_object(str->end);
1768 lisp_buffer_stream_startpos(lstream_t stream)
1770 lisp_buffer_stream_t p = LISP_BUFFER_STREAM_DATA(stream);
1771 return marker_position(p->start);
1774 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1775 #include "openssl.h"
1777 typedef struct ssl_stream_s *ssl_stream_t;
1778 struct ssl_stream_s {
1783 bool blocking_error_p:1;
1786 #define SSL_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, ssl)
1788 DEFINE_LSTREAM_IMPLEMENTATION("ssl", lstream_ssl, sizeof(struct ssl_stream_s));
1791 make_ssl_stream_1(SSL *conn, int flags, const char *mode)
1794 lstream_t lstr = Lstream_new(lstream_ssl, mode);
1795 ssl_stream_t str = SSL_STREAM_DATA(lstr);
1797 XSETLSTREAM(obj, lstr);
1802 make_ssl_input_stream(SSL *conn, int flags)
1804 return make_ssl_stream_1(conn, flags, "r");
1808 make_ssl_output_stream(SSL *conn, int flags)
1810 return make_ssl_stream_1(conn, flags, "w");
1813 static Lstream_data_count
1814 ssl_reader(lstream_t stream, unsigned char *data, Lstream_data_count size)
1816 Lstream_data_count nread;
1817 ssl_stream_t str = SSL_STREAM_DATA(stream);
1819 nread = SSL_read(str->conn, data, size);
1826 static Lstream_data_count
1827 ssl_writer(lstream_t stream, const unsigned char *data,
1828 Lstream_data_count size)
1830 Lstream_data_count nwrite;
1831 ssl_stream_t str = SSL_STREAM_DATA(stream);
1833 nwrite = SSL_write(str->conn, data, size);
1841 ssl_closer(lstream_t stream)
1843 ssl_stream_t str = SSL_STREAM_DATA(stream);
1845 return SSL_shutdown(str->conn);
1852 ssl_get_fd(lstream_t stream)
1854 ssl_stream_t str = SSL_STREAM_DATA(stream);
1855 return SSL_get_rfd(str->conn);
1859 /************************************************************************/
1860 /* initialization */
1861 /************************************************************************/
1863 void lstream_type_create(void)
1865 LSTREAM_HAS_METHOD(stdio, reader);
1866 LSTREAM_HAS_METHOD(stdio, writer);
1867 LSTREAM_HAS_METHOD(stdio, rewinder);
1868 LSTREAM_HAS_METHOD(stdio, seekable_p);
1869 LSTREAM_HAS_METHOD(stdio, flusher);
1870 LSTREAM_HAS_METHOD(stdio, closer);
1872 LSTREAM_HAS_METHOD(filedesc, reader);
1873 LSTREAM_HAS_METHOD(filedesc, writer);
1874 LSTREAM_HAS_METHOD(filedesc, was_blocked_p);
1875 LSTREAM_HAS_METHOD(filedesc, rewinder);
1876 LSTREAM_HAS_METHOD(filedesc, seekable_p);
1877 LSTREAM_HAS_METHOD(filedesc, closer);
1878 LSTREAM_HAS_METHOD(filedesc, get_fd);
1880 LSTREAM_HAS_METHOD(lisp_string, reader);
1881 LSTREAM_HAS_METHOD(lisp_string, rewinder);
1882 LSTREAM_HAS_METHOD(lisp_string, marker);
1884 LSTREAM_HAS_METHOD(fixed_buffer, reader);
1885 LSTREAM_HAS_METHOD(fixed_buffer, writer);
1886 LSTREAM_HAS_METHOD(fixed_buffer, rewinder);
1888 LSTREAM_HAS_METHOD(resizing_buffer, writer);
1889 LSTREAM_HAS_METHOD(resizing_buffer, rewinder);
1890 LSTREAM_HAS_METHOD(resizing_buffer, closer);
1892 LSTREAM_HAS_METHOD(dynarr, writer);
1893 LSTREAM_HAS_METHOD(dynarr, rewinder);
1894 LSTREAM_HAS_METHOD(dynarr, closer);
1896 LSTREAM_HAS_METHOD(lisp_buffer, reader);
1897 LSTREAM_HAS_METHOD(lisp_buffer, writer);
1898 LSTREAM_HAS_METHOD(lisp_buffer, rewinder);
1899 LSTREAM_HAS_METHOD(lisp_buffer, marker);
1901 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
1902 LSTREAM_HAS_METHOD(ssl, reader);
1903 LSTREAM_HAS_METHOD(ssl, writer);
1904 LSTREAM_HAS_METHOD(ssl, closer);
1905 LSTREAM_HAS_METHOD(ssl, get_fd);
1909 void reinit_vars_of_lstream(void)
1911 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
1912 for (int i = 0; i < countof(Vlstream_free_list); i++) {
1913 Vlstream_free_list[i] = Qnil;
1914 staticpro_nodump(&Vlstream_free_list[i]);
1919 void vars_of_lstream(void)
1921 INIT_LRECORD_IMPLEMENTATION(lstream);
1923 reinit_vars_of_lstream();
1926 /* lstream.c ends here */