aboutsummaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-05-30 10:02:40 +0900
committerGitHub <noreply@github.com>2023-05-30 10:02:40 +0900
commit18e55fc1e1ec20e8f3166e3059e76c885fc9f8f2 (patch)
tree7e35773b3cd1ae50a0a94937df7fb175a3bed9ba /internal
parent7ddcd0622f3275effa603c16934b0215cc8a542b (diff)
downloadruby-18e55fc1e1ec20e8f3166e3059e76c885fc9f8f2.tar.gz
Hide most of the implementation of `struct rb_io`. (#6511)
* Add rb_io_path and rb_io_open_descriptor. * Use rb_io_open_descriptor to create PTY objects * Rename FMODE_PREP -> FMODE_EXTERNAL and expose it FMODE_PREP I believe refers to the concept of a "pre-prepared" file, but FMODE_EXTERNAL is clearer about what the file descriptor represents and aligns with language in the IO::Buffer module. * Ensure that rb_io_open_descriptor closes the FD if it fails If FMODE_EXTERNAL is not set, then it's guaranteed that Ruby will be responsible for closing your file, eventually, if you pass it to rb_io_open_descriptor, even if it raises an exception. * Rename IS_EXTERNAL_FD -> RUBY_IO_EXTERNAL_P * Expose `rb_io_closed_p`. * Add `rb_io_mode` to get IO mode. --------- Co-authored-by: KJ Tsanaktsidis <ktsanaktsidis@zendesk.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/io.h119
1 files changed, 118 insertions, 1 deletions
diff --git a/internal/io.h b/internal/io.h
index b5f15499d7..c97fd1e616 100644
--- a/internal/io.h
+++ b/internal/io.h
@@ -8,8 +8,125 @@
* file COPYING are met. Consult the file for details.
* @brief Internal header for IO.
*/
+
+#define RB_IO_T
+
#include "ruby/ruby.h" /* for VALUE */
-#include "ruby/io.h" /* for rb_io_t */
+#include "ruby/io.h"
+
+/**
+ * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and
+ * ::rb_io_t::rbuf. People don't manipulate it directly.
+ */
+RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN()
+struct rb_io_internal_buffer {
+
+ /** Pointer to the underlying memory region, of at least `capa` bytes. */
+ char *ptr; /* off + len <= capa */
+
+ /** Offset inside of `ptr`. */
+ int off;
+
+ /** Length of the buffer. */
+ int len;
+
+ /** Designed capacity of the buffer. */
+ int capa;
+} RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END();
+
+/** Ruby's IO, metadata and buffers. */
+struct rb_io {
+ /** The IO's Ruby level counterpart. */
+ VALUE self;
+
+ /** stdio ptr for read/write, if available. */
+ FILE *stdio_file;
+
+ /** file descriptor. */
+ int fd;
+
+ /** mode flags: FMODE_XXXs */
+ int mode;
+
+ /** child's pid (for pipes) */
+ rb_pid_t pid;
+
+ /** number of lines read */
+ int lineno;
+
+ /** pathname for file */
+ VALUE pathv;
+
+ /**
+ * Duplex IO object, if set.
+ *
+ * @see rb_io_set_write_io()
+ */
+ VALUE tied_io_for_writing;
+
+ /** finalize proc */
+ void (*finalize)(struct rb_io*,int);
+
+ /** Write buffer. */
+ struct rb_io_internal_buffer wbuf;
+
+ /**
+ * (Byte) read buffer. Note also that there is a field called
+ * ::rb_io_t::cbuf, which also concerns read IO.
+ */
+ struct rb_io_internal_buffer rbuf;
+
+ struct rb_io_encoding encs; /**< Decomposed encoding flags. */
+
+ /** Encoding converter used when reading from this IO. */
+ rb_econv_t *readconv;
+
+ /**
+ * rb_io_ungetc() destination. This buffer is read before checking
+ * ::rb_io_t::rbuf
+ */
+ struct rb_io_internal_buffer cbuf;
+
+ /** Encoding converter used when writing to this IO. */
+ rb_econv_t *writeconv;
+
+ /**
+ * This is, when set, an instance of ::rb_cString which holds the "common"
+ * encoding. Write conversion can convert strings twice... In case
+ * conversion from encoding X to encoding Y does not exist, Ruby finds an
+ * encoding Z that bridges the two, so that X to Z to Y conversion happens.
+ */
+ VALUE writeconv_asciicompat;
+
+ /** Whether ::rb_io_t::writeconv is already set up. */
+ int writeconv_initialized;
+
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before
+ * initialising ::rb_io_t::writeconv.
+ */
+ int writeconv_pre_ecflags;
+
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising
+ * ::rb_io_t::writeconv.
+ */
+ VALUE writeconv_pre_ecopts;
+
+ /**
+ * This is a Ruby level mutex. It avoids multiple threads to write to an
+ * IO at once; helps for instance rb_io_puts() to ensure newlines right
+ * next to its arguments.
+ *
+ * This of course doesn't help inter-process IO interleaves, though.
+ */
+ VALUE write_lock;
+
+ /**
+ * The timeout associated with this IO when performing blocking operations.
+ */
+ VALUE timeout;
+};
/* io.c */
void ruby_set_inplace_mode(const char *);