aboutsummaryrefslogtreecommitdiffstats
path: root/include
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 /include
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 'include')
-rw-r--r--include/ruby/internal/core/rfile.h9
-rw-r--r--include/ruby/io.h159
2 files changed, 43 insertions, 125 deletions
diff --git a/include/ruby/internal/core/rfile.h b/include/ruby/internal/core/rfile.h
index f8dddde9e5..8cf2c4db5b 100644
--- a/include/ruby/internal/core/rfile.h
+++ b/include/ruby/internal/core/rfile.h
@@ -23,9 +23,10 @@
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/cast.h"
-/* rb_io_t is in ruby/io.h. The header file has historically not been included
- * into ruby/ruby.h. We follow that tradition. */
-struct rb_io_t;
+/* rb_io is in ruby/io.h and internal/io.h. The header file has historically
+ * not been included into ruby/ruby.h. We follow that tradition.
+ */
+struct rb_io;
/**
* Ruby's File and IO. Ruby's IO are not just file descriptors. They have
@@ -38,7 +39,7 @@ struct RFile {
struct RBasic basic;
/** IO's specific fields. */
- struct rb_io_t *fptr;
+ struct rb_io *fptr;
};
/**
diff --git a/include/ruby/io.h b/include/ruby/io.h
index 8be83a215c..881bac03a7 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -84,29 +84,6 @@ typedef enum {
RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */
} rb_io_event_t;
-/**
- * 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_buffer_t {
-
- /** 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();
-
-/** @alias{rb_io_buffer_t} */
-typedef struct rb_io_buffer_t rb_io_buffer_t;
-
/** Decomposed encoding flags (e.g. `"enc:enc2""`). */
/*
* enc enc2 read action write action
@@ -114,7 +91,7 @@ typedef struct rb_io_buffer_t rb_io_buffer_t;
* e1 NULL force_encoding(e1) convert str.encoding to e1
* e1 e2 convert from e2 to e1 convert str.encoding to e2
*/
-struct rb_io_enc_t {
+struct rb_io_encoding {
/** Internal encoding. */
rb_encoding *enc;
/** External encoding. */
@@ -135,103 +112,10 @@ struct rb_io_enc_t {
VALUE ecopts;
};
-/** Ruby's IO, metadata and buffers. */
-typedef struct rb_io_t {
-
- /** 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;
-
- /** finalize proc */
- void (*finalize)(struct rb_io_t*,int);
-
- /** Write buffer. */
- rb_io_buffer_t wbuf;
-
- /**
- * (Byte) read buffer. Note also that there is a field called
- * ::rb_io_t::cbuf, which also concerns read IO.
- */
- rb_io_buffer_t rbuf;
-
- /**
- * Duplex IO object, if set.
- *
- * @see rb_io_set_write_io()
- */
- VALUE tied_io_for_writing;
-
- struct rb_io_enc_t 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
- */
- rb_io_buffer_t 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;
+struct rb_io;
+typedef struct rb_io rb_io_t;
- /**
- * 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;
-} rb_io_t;
-
-/** @alias{rb_io_enc_t} */
-typedef struct rb_io_enc_t rb_io_enc_t;
+typedef struct rb_io_encoding rb_io_enc_t;
/**
* @private
@@ -331,7 +215,16 @@ typedef struct rb_io_enc_t rb_io_enc_t;
* Setting this one and #FMODE_BINMODE at the same time is a contradiction.
*/
#define FMODE_TEXTMODE 0x00001000
-/* #define FMODE_PREP 0x00010000 */
+/**
+ * This flag means that an IO object is wrapping an "external" file descriptor,
+ * which is owned by something outside the Ruby interpreter (usually a C extension).
+ * Ruby will not close this file when the IO object is garbage collected.
+ * If this flag is set, then IO#autoclose? is false, and vice-versa.
+ *
+ * This flag was previously called FMODE_PREP internally.
+ */
+#define FMODE_EXTERNAL 0x00010000
+
/* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */
/**
@@ -346,6 +239,18 @@ typedef struct rb_io_enc_t rb_io_enc_t;
/** @} */
/**
+ * Allocate a new IO object, with the given file descriptor.
+ */
+VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding);
+
+/**
+ * Returns whether or not the underlying IO is closed.
+ *
+ * @return Whether the underlying IO is closed.
+ */
+VALUE rb_io_closed_p(VALUE io);
+
+/**
* Queries the underlying IO pointer.
*
* @param[in] obj An IO object.
@@ -704,6 +609,12 @@ VALUE rb_io_set_write_io(VALUE io, VALUE w);
void rb_io_set_nonblock(rb_io_t *fptr);
/**
+ * Returns the path for the given IO.
+ *
+ */
+VALUE rb_io_path(VALUE io);
+
+/**
* Returns an integer representing the numeric file descriptor for
* <em>io</em>.
*
@@ -713,6 +624,12 @@ void rb_io_set_nonblock(rb_io_t *fptr);
int rb_io_descriptor(VALUE io);
/**
+ * Get the mode of the IO.
+ *
+ */
+int rb_io_mode(VALUE io);
+
+/**
* This function breaks down the option hash that `IO#initialize` takes into
* components. This is an implementation detail of rb_io_extract_modeenc()
* today. People prefer that API instead.