diff options
author | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2023-05-30 10:02:40 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-30 10:02:40 +0900 |
commit | 18e55fc1e1ec20e8f3166e3059e76c885fc9f8f2 (patch) | |
tree | 7e35773b3cd1ae50a0a94937df7fb175a3bed9ba /internal | |
parent | 7ddcd0622f3275effa603c16934b0215cc8a542b (diff) | |
download | ruby-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.h | 119 |
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 *); |