class fatal - Ruby 2.0.0-p576 Core API Reference API Reference

Ruby 2.0.0-p576 Core API Reference API Reference

This is the API documentation for 'Ruby 2.0.0-p576 Core API Reference API Reference'.

Classes/Modules

  • Encoding
  • Encoding::CompatibilityError
  • Encoding::Converter
  • Encoding::ConverterNotFoundError
  • Encoding::InvalidByteSequenceError
  • Encoding::UndefinedConversionError
  • Process
  • Process::GID
  • Process::Status
  • Process::Sys
  • Process::UID
  • Enumerator
  • Enumerator::Generator
  • Enumerator::Lazy
  • Enumerator::Yielder
  • File
  • File::Constants
  • File::Stat
  • IO
  • IO::WaitReadable
  • IO::WaitWritable
  • RubyVM
  • RubyVM::Env
  • RubyVM::InstructionSequence
  • Complex
  • Complex::compatible
  • GC
  • GC::Profiler
  • Math
  • Math::DomainError
  • ObjectSpace
  • ObjectSpace::WeakMap
  • Rational
  • Rational::compatible
  • ARGF
  • ArgumentError
  • Array
  • BasicObject
  • Bignum
  • Binding
  • Class
  • Comparable
  • Continuation
  • Data
  • Dir
  • ENV
  • EOFError
  • EncodingError
  • Enumerable
  • Errno
  • Exception
  • FalseClass
  • Fiber
  • FiberError
  • FileTest
  • Fixnum
  • Float
  • FloatDomainError
  • Hash
  • IOError
  • IndexError
  • Integer
  • Interrupt
  • Kernel
  • KeyError
  • LoadError
  • LocalJumpError
  • Marshal
  • MatchData
  • Method
  • Module
  • Mutex
  • NameError
  • NilClass
  • NoMemoryError
  • NoMethodError
  • NotImplementedError
  • Numeric
  • Object
  • Proc
  • Random
  • Range
  • RangeError
  • Regexp
  • RegexpError
  • Ripper
  • RuntimeError
  • ScriptError
  • SecurityError
  • Signal
  • SignalException
  • StandardError
  • StopIteration
  • String
  • Struct
  • Symbol
  • SyntaxError
  • SystemCallError
  • SystemExit
  • SystemStackError
  • Thread
  • ThreadError
  • ThreadGroup
  • Time
  • TracePoint
  • TrueClass
  • TypeError
  • UnboundMethod
  • ZeroDivisionError
  • fatal

Generated by RDoc 3.12.2.

Generated with the Darkfish Rdoc Generator 3.


class ARGF - Ruby 2.0.0-p576 Core API Reference API Reference

class ARGF

ARGF is a stream designed for use in scripts that process files given as command-line arguments or passed in via STDIN.

The arguments passed to your script are stored in the ARGV Array, one argument per element. ARGF assumes that any arguments that aren't filenames have been removed from ARGV. For example:

$ ruby argf.rb --verbose file1 file2

ARGV  #=> ["--verbose", "file1", "file2"]
option = ARGV.shift #=> "--verbose"
ARGV  #=> ["file1", "file2"]

You can now use ARGF to work with a concatenation of each of these named files. For instance, ARGF.read will return the contents of file1 followed by the contents of file2.

After a file in ARGV has been read ARGF removes it from the Array. Thus, after all files have been read ARGV will be empty.

You can manipulate ARGV yourself to control what ARGF operates on. If you remove a file from ARGV, it is ignored by ARGF; if you add files to ARGV, they are treated as if they were named on the command line. For example:

ARGV.replace ["file1"]
ARGF.readlines # Returns the contents of file1 as an Array
ARGV           #=> []
ARGV.replace ["file2", "file3"]
ARGF.read      # Returns the contents of file2 and file3

If ARGV is empty, ARGF acts as if it contained STDIN, i.e. the data piped to your script. For example:

$ echo "glark" | ruby -e 'p ARGF.read'
"glark\n"

In Files

  • io.c

Parent

Object

Included Modules

  • Enumerable

Public Instance Methods

argv → ARGV click to toggle source

Returns the ARGV array, which contains the arguments passed to your script, one per element.

For example:

$ ruby argf.rb -v glark.txt

ARGF.argv   #=> ["-v", "glark.txt"]

static VALUE
argf_argv(VALUE argf)
{
    return ARGF.argv;
}
binmode → ARGF click to toggle source

Puts ARGF into binary mode. Once a stream is in binary mode, it cannot be reset to non-binary mode. This option has the following effects:

  • Newline conversion is disabled.

  • Encoding conversion is disabled.

  • Content is treated as ASCII-8BIT.

static VALUE
argf_binmode_m(VALUE argf)
{
    ARGF.binmode = 1;
    next_argv();
    ARGF_FORWARD(0, 0);
    rb_io_ascii8bit_binmode(ARGF.current_file);
    return argf;
}
binmode? → true or false click to toggle source
Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
enable binary mode use +ARGF.binmode+.

For example:

ARGF.binmode?  #=> false
ARGF.binmode
ARGF.binmode?  #=> true

static VALUE
argf_binmode_p(VALUE argf)
{
    return ARGF.binmode ? Qtrue : Qfalse;
}
bytes() click to toggle source

This is a deprecated alias for each_byte.

static VALUE
argf_bytes(VALUE argf)
{
    rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
    return argf_each_byte(argf);
}
chars() click to toggle source

This is a deprecated alias for each_char.

static VALUE
argf_chars(VALUE argf)
{
    rb_warn("ARGF#chars is deprecated; use #each_char instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
    return argf_each_char(argf);
}
close → ARGF click to toggle source
Closes the current file and skips to the next in the stream. Trying to
close a file that has already been closed causes an +IOError+ to be
raised.

For example:

$ ruby argf.rb foo bar

ARGF.filename  #=> "foo"
ARGF.close
ARGF.filename  #=> "bar"
ARGF.close
ARGF.close     #=> closed stream (IOError)

static VALUE
argf_close_m(VALUE argf)
{
    next_argv();
    argf_close(ARGF.current_file);
    if (ARGF.next_p != -1) {
        ARGF.next_p = 1;
    }
    ARGF.lineno = 0;
    return argf;
}
closed? → true or false click to toggle source

Returns true if the current file has been closed; false otherwise. Use ARGF.close to actually close the current file.

static VALUE
argf_closed(VALUE argf)
{
    next_argv();
    ARGF_FORWARD(0, 0);
    return rb_io_closed(ARGF.current_file);
}
codepoints() click to toggle source

This is a deprecated alias for each_codepoint.

static VALUE
argf_codepoints(VALUE argf)
{
    rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
    return argf_each_codepoint(argf);
}
each(sep=$/) {|line| block } → ARGF click to toggle source
each(sep=$/,limit) {|line| block } → ARGF
each(...) → an_enumerator
each_line(sep=$/) {|line| block } → ARGF
each_line(sep=$/,limit) {|line| block } → ARGF
each_line(...) → an_enumerator

Returns an enumerator which iterates over each line (separated by sep, which defaults to your platform's newline character) of each file in ARGV. If a block is supplied, each line in turn will be yielded to the block, otherwise an enumerator is returned. The optional limit argument is a Fixnum specifying the maximum length of each line; longer lines will be split according to this limit.

This method allows you to treat the files supplied on the command line as a single file consisting of the concatenation of each named file. After the last line of the first file has been returned, the first line of the second file is returned. The ARGF.filename and ARGF.lineno methods can be used to determine the filename and line number, respectively, of the current line.

For example, the following code prints out each line of each named file prefixed with its line number, displaying the filename once per file:

ARGF.lines do |line|
  puts ARGF.filename if ARGF.lineno == 1
  puts "#{ARGF.lineno}: #{line}"
end

static VALUE
argf_each_line(int argc, VALUE *argv, VALUE argf)
{
    RETURN_ENUMERATOR(argf, argc, argv);
    for (;;) {
        if (!next_argv()) return argf;
        rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
        ARGF.next_p = 1;
    }
}
bytes {|byte| block } → ARGF click to toggle source
bytes → an_enumerator
each_byte {|byte| block } → ARGF
each_byte → an_enumerator
Iterates over each byte of each file in +ARGV+.
A byte is returned as a +Fixnum+ in the range 0..255.

This method allows you to treat the files supplied on the command line as
a single file consisting of the concatenation of each named file. After
the last byte of the first file has been returned, the first byte of the
second file is returned. The +ARGF.filename+ method can be used to
determine the filename of the current byte.

If no block is given, an enumerator is returned instead.

For example:

ARGF.bytes.to_a  #=> [35, 32, ... 95, 10]

static VALUE
argf_each_byte(VALUE argf)
{
    RETURN_ENUMERATOR(argf, 0, 0);
    for (;;) {
        if (!next_argv()) return argf;
        rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
        ARGF.next_p = 1;
    }
}
each_char {|char| block } → ARGF click to toggle source
each_char → an_enumerator

Iterates over each character of each file in ARGF.

This method allows you to treat the files supplied on the command line as a single file consisting of the concatenation of each named file. After the last character of the first file has been returned, the first character of the second file is returned. The ARGF.filename method can be used to determine the name of the file in which the current character appears.

If no block is given, an enumerator is returned instead.

static VALUE
argf_each_char(VALUE argf)
{
    RETURN_ENUMERATOR(argf, 0, 0);
    for (;;) {
        if (!next_argv()) return argf;
        rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
        ARGF.next_p = 1;
    }
}
each_codepoint {|codepoint| block } → ARGF click to toggle source
each_codepoint → an_enumerator

Iterates over each codepoint of each file in ARGF.

This method allows you to treat the files supplied on the command line as a single file consisting of the concatenation of each named file. After the last codepoint of the first file has been returned, the first codepoint of the second file is returned. The ARGF.filename method can be used to determine the name of the file in which the current codepoint appears.

If no block is given, an enumerator is returned instead.

static VALUE
argf_each_codepoint(VALUE argf)
{
    RETURN_ENUMERATOR(argf, 0, 0);
    for (;;) {
        if (!next_argv()) return argf;
        rb_block_call(ARGF.current_file, rb_intern("each_codepoint"), 0, 0, 0, 0);
        ARGF.next_p = 1;
    }
}
each(sep=$/) {|line| block } → ARGF click to toggle source
each(sep=$/,limit) {|line| block } → ARGF
each(...) → an_enumerator
each_line(sep=$/) {|line| block } → ARGF
each_line(sep=$/,limit) {|line| block } → ARGF
each_line(...) → an_enumerator

Returns an enumerator which iterates over each line (separated by sep, which defaults to your platform's newline character) of each file in ARGV. If a block is supplied, each line in turn will be yielded to the block, otherwise an enumerator is returned. The optional limit argument is a Fixnum specifying the maximum length of each line; longer lines will be split according to this limit.

This method allows you to treat the files supplied on the command line as a single file consisting of the concatenation of each named file. After the last line of the first file has been returned, the first line of the second file is returned. The ARGF.filename and ARGF.lineno methods can be used to determine the filename and line number, respectively, of the current line.

For example, the following code prints out each line of each named file prefixed with its line number, displaying the filename once per file:

ARGF.lines do |line|
  puts ARGF.filename if ARGF.lineno == 1
  puts "#{ARGF.lineno}: #{line}"
end

static VALUE
argf_each_line(int argc, VALUE *argv, VALUE argf)
{
    RETURN_ENUMERATOR(argf, argc, argv);
    for (;;) {
        if (!next_argv()) return argf;
        rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
        ARGF.next_p = 1;
    }
}
eof? → true or false click to toggle source
eof → true or false

Returns true if the current file in ARGF is at end of file, i.e. it has no data to read. The stream must be opened for reading or an IOError will be raised.

$ echo "eof" | ruby argf.rb

ARGF.eof?                 #=> false
3.times { ARGF.readchar }
ARGF.eof?                 #=> false
ARGF.readchar             #=> "\n"
ARGF.eof?                 #=> true

static VALUE
argf_eof(VALUE argf)
{
    next_argv();
    if (RTEST(ARGF.current_file)) {
        if (ARGF.init_p == 0) return Qtrue;
        next_argv();
        ARGF_FORWARD(0, 0);
        if (rb_io_eof(ARGF.current_file)) {
            return Qtrue;
        }
    }
    return Qfalse;
}
eof? → true or false click to toggle source
eof → true or false

Returns true if the current file in ARGF is at end of file, i.e. it has no data to read. The stream must be opened for reading or an IOError will be raised.

$ echo "eof" | ruby argf.rb

ARGF.eof?                 #=> false
3.times { ARGF.readchar }
ARGF.eof?                 #=> false
ARGF.readchar             #=> "\n"
ARGF.eof?                 #=> true

static VALUE
argf_eof(VALUE argf)
{
    next_argv();
    if (RTEST(ARGF.current_file)) {
        if (ARGF.init_p == 0) return Qtrue;
        next_argv();
        ARGF_FORWARD(0, 0);
        if (rb_io_eof(ARGF.current_file)) {
            return Qtrue;
        }
    }
    return Qfalse;
}
external_encoding → encoding click to toggle source
Returns the external encoding for files read from +ARGF+ as an +Encoding+
object. The external encoding is the encoding of the text as stored in a
file. Contrast with +ARGF.internal_encoding+, which is the encoding used
to represent this text within Ruby.

To set the external encoding use +ARGF.set_encoding+.

For example:

ARGF.external_encoding  #=>  #<Encoding:UTF-8>

static VALUE
argf_external_encoding(VALUE argf)
{
    if (!RTEST(ARGF.current_file)) {
        return rb_enc_from_encoding(rb_default_external_encoding());
    }
    return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
}
file → IO or File object click to toggle source

Returns the current file as an IO or File object. #<IO:<STDIN>> is returned when the current file is STDIN.

For example:

$ echo "foo" > foo
$ echo "bar" > bar

$ ruby argf.rb foo bar

ARGF.file      #=> #<File:foo>
ARGF.read(5)   #=> "foo\nb"
ARGF.file      #=> #<File:bar>

static VALUE
argf_file(VALUE argf)
{
    next_argv();
    return ARGF.current_file;
}
filename → String click to toggle source
path → String

Returns the current filename. “-” is returned when the current file is STDIN.

For example:

$ echo "foo" > foo
$ echo "bar" > bar
$ echo "glark" > glark

$ ruby argf.rb foo bar glark

ARGF.filename  #=> "foo"
ARGF.read(5)   #=> "foo\nb"
ARGF.filename  #=> "bar"
ARGF.skip
ARGF.filename  #=> "glark"

static VALUE
argf_filename(VALUE argf)
{
    next_argv();
    return ARGF.filename;
}
fileno → fixnum click to toggle source
to_i → fixnum

Returns an integer representing the numeric file descriptor for the current file. Raises an ArgumentError if there isn't a current file.

ARGF.fileno    #=> 3

static VALUE
argf_fileno(VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream");
    }
    ARGF_FORWARD(0, 0);
    return rb_io_fileno(ARGF.current_file);
}
getbyte → Fixnum or nil click to toggle source

Gets the next 8-bit byte (0..255) from ARGF. Returns nil if called at the end of the stream.

For example:

$ echo "foo" > file
$ ruby argf.rb file

ARGF.getbyte #=> 102
ARGF.getbyte #=> 111
ARGF.getbyte #=> 111
ARGF.getbyte #=> 10
ARGF.getbyte #=> nil

static VALUE
argf_getbyte(VALUE argf)
{
    VALUE ch;

  retry:
    if (!next_argv()) return Qnil;
    if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
        ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
    }
    else {
        ch = rb_io_getbyte(ARGF.current_file);
    }
    if (NIL_P(ch) && ARGF.next_p != -1) {
        argf_close(ARGF.current_file);
        ARGF.next_p = 1;
        goto retry;
    }

    return ch;
}
getc → String or nil click to toggle source

Reads the next character from ARGF and returns it as a String. Returns nil at the end of the stream.

ARGF treats the files named on the command line as a single file created by concatenating their contents. After returning the last character of the first file, it returns the first character of the second file, and so on.

For example:

$ echo "foo" > file
$ ruby argf.rb file

ARGF.getc  #=> "f"
ARGF.getc  #=> "o"
ARGF.getc  #=> "o"
ARGF.getc  #=> "\n"
ARGF.getc  #=> nil
ARGF.getc  #=> nil

static VALUE
argf_getc(VALUE argf)
{
    VALUE ch;

  retry:
    if (!next_argv()) return Qnil;
    if (ARGF_GENERIC_INPUT_P()) {
        ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
    }
    else {
        ch = rb_io_getc(ARGF.current_file);
    }
    if (NIL_P(ch) && ARGF.next_p != -1) {
        argf_close(ARGF.current_file);
        ARGF.next_p = 1;
        goto retry;
    }

    return ch;
}
gets(sep=$/) → string click to toggle source
gets(limit) → string
gets(sep, limit) → string

Returns the next line from the current file in ARGF.

By default lines are assumed to be separated by +$/+; to use a different character as a separator, supply it as a String for the sep argument.

The optional limit argument specifies how many characters of each line to return. By default all characters are returned.

static VALUE
argf_gets(int argc, VALUE *argv, VALUE argf)
{
    VALUE line;

    line = argf_getline(argc, argv, argf);
    rb_lastline_set(line);

    return line;
}
inplace_mode → String click to toggle source

Returns the file extension appended to the names of modified files under inplace-edit mode. This value can be set using ARGF.inplace_mode= or passing the -i switch to the Ruby binary.

static VALUE
argf_inplace_mode_get(VALUE argf)
{
    if (!ARGF.inplace) return Qnil;
    return rb_str_new2(ARGF.inplace);
}
inplace_mode = ext → ARGF click to toggle source
Sets the filename extension for inplace editing mode to the given String.
Each file being edited has this value appended to its filename. The
modified file is saved under this new name.

For example:

    $ ruby argf.rb file.txt

    ARGF.inplace_mode = '.bak'
    ARGF.lines do |line|
      print line.sub("foo","bar")
    end

Each line of file.txt has the first occurrence of “foo” replaced with “bar”, then the new line is written out to file.txt.bak.

static VALUE
argf_inplace_mode_set(VALUE argf, VALUE val)
{
    if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
        rb_insecure_operation();

    if (!RTEST(val)) {
        if (ARGF.inplace) free(ARGF.inplace);
        ARGF.inplace = 0;
    }
    else {
        StringValue(val);
        if (ARGF.inplace) free(ARGF.inplace);
        ARGF.inplace = 0;
        ARGF.inplace = strdup(RSTRING_PTR(val));
    }
    return argf;
}
inspect() click to toggle source
Alias for: to_s
internal_encoding → encoding click to toggle source

Returns the internal encoding for strings read from ARGF as an Encoding object.

If ARGF.set_encoding has been called with two encoding names, the second is returned. Otherwise, if Encoding.default_external has been set, that value is returned. Failing that, if a default external encoding was specified on the command-line, that value is used. If the encoding is unknown, nil is returned.

static VALUE
argf_internal_encoding(VALUE argf)
{
    if (!RTEST(ARGF.current_file)) {
        return rb_enc_from_encoding(rb_default_external_encoding());
    }
    return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
}
lineno → integer click to toggle source

Returns the current line number of ARGF as a whole. This value can be set manually with ARGF.lineno=.

For example:

ARGF.lineno   #=> 0
ARGF.readline #=> "This is line 1\n"
ARGF.lineno   #=> 1

static VALUE
argf_lineno(VALUE argf)
{
    return INT2FIX(ARGF.lineno);
}
lineno = integer → integer click to toggle source

Sets the line number of ARGF as a whole to the given Integer.

ARGF sets the line number automatically as you read data, so normally you will not need to set it explicitly. To access the current line number use ARGF.lineno.

For example:

ARGF.lineno      #=> 0
ARGF.readline    #=> "This is line 1\n"
ARGF.lineno      #=> 1
ARGF.lineno = 0  #=> 0
ARGF.lineno      #=> 0

static VALUE
argf_set_lineno(VALUE argf, VALUE val)
{
    ARGF.lineno = NUM2INT(val);
    ARGF.last_lineno = ARGF.lineno;
    return Qnil;
}
lines(*args) click to toggle source

This is a deprecated alias for each_line.

static VALUE
argf_lines(int argc, VALUE *argv, VALUE argf)
{
    rb_warn("ARGF#lines is deprecated; use #each_line instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
    return argf_each_line(argc, argv, argf);
}
filename → String click to toggle source
path → String

Returns the current filename. “-” is returned when the current file is STDIN.

For example:

$ echo "foo" > foo
$ echo "bar" > bar
$ echo "glark" > glark

$ ruby argf.rb foo bar glark

ARGF.filename  #=> "foo"
ARGF.read(5)   #=> "foo\nb"
ARGF.filename  #=> "bar"
ARGF.skip
ARGF.filename  #=> "glark"

static VALUE
argf_filename(VALUE argf)
{
    next_argv();
    return ARGF.filename;
}
tell → Integer click to toggle source
pos → Integer

Returns the current offset (in bytes) of the current file in ARGF.

ARGF.pos    #=> 0
ARGF.gets   #=> "This is line one\n"
ARGF.pos    #=> 17

static VALUE
argf_tell(VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to tell");
    }
    ARGF_FORWARD(0, 0);
    return rb_io_tell(ARGF.current_file);
}
pos = position → Integer click to toggle source

Seeks to the position given by position (in bytes) in ARGF.

For example:

ARGF.pos = 17
ARGF.gets   #=> "This is line two\n"

static VALUE
argf_set_pos(VALUE argf, VALUE offset)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to set position");
    }
    ARGF_FORWARD(1, &offset);
    return rb_io_set_pos(ARGF.current_file, offset);
}
print() → nil click to toggle source
print(obj, ...) → nil

Writes the given object(s) to ios. The stream must be opened for writing. If the output field separator ($,) is not nil, it will be inserted between each object. If the output record separator ($\</code>) is not <code>nil, it will be appended to the output. If no arguments are given, prints $_. Objects that aren't strings will be converted by calling their to_s method. With no argument, prints the contents of the variable $_. Returns nil.

$stdout.print("This is ", 100, " percent.\n")

produces:

This is 100 percent.
VALUE
rb_io_print(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print `$_' */
    if (argc == 0) {
        argc = 1;
        line = rb_lastline_get();
        argv = &line;
    }
    for (i=0; i<argc; i++) {
        if (!NIL_P(rb_output_fs) && i>0) {
            rb_io_write(out, rb_output_fs);
        }
        rb_io_write(out, argv[i]);
    }
    if (argc > 0 && !NIL_P(rb_output_rs)) {
        rb_io_write(out, rb_output_rs);
    }

    return Qnil;
}
printf(format_string [, obj, ...]) → nil click to toggle source

Formats and writes to ios, converting parameters under control of the format string. See Kernel#sprintf for details.

VALUE
rb_io_printf(int argc, VALUE *argv, VALUE out)
{
    rb_io_write(out, rb_f_sprintf(argc, argv));
    return Qnil;
}
putc(obj) → obj click to toggle source

If obj is Numeric, write the character whose code is the least-significant byte of obj, otherwise write the first byte of the string representation of obj to ios. Note: This method is not safe for use with multi-byte characters as it will truncate them.

$stdout.putc "A"
$stdout.putc 65

produces:

AA
static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
    VALUE str;
    if (RB_TYPE_P(ch, T_STRING)) {
        str = rb_str_substr(ch, 0, 1);
    }
    else {
        char c = NUM2CHR(ch);
        str = rb_str_new(&c, 1);
    }
    rb_io_write(io, str);
    return ch;
}
puts(obj, ...) → nil click to toggle source

Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line. If called without arguments, outputs a single record separator.

$stdout.puts("this", "is", "a", "test")

produces:

this
is
a
test
VALUE
rb_io_puts(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print newline. */
    if (argc == 0) {
        rb_io_write(out, rb_default_rs);
        return Qnil;
    }
    for (i=0; i<argc; i++) {
        if (RB_TYPE_P(argv[i], T_STRING)) {
            line = argv[i];
            goto string;
        }
        if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
            continue;
        }
        line = rb_obj_as_string(argv[i]);
      string:
        rb_io_write(out, line);
        if (RSTRING_LEN(line) == 0 ||
            !str_end_with_asciichar(line, '\n')) {
            rb_io_write(out, rb_default_rs);
        }
    }

    return Qnil;
}
read([length [, outbuf]]) → string, outbuf, or nil click to toggle source
Reads _length_ bytes from ARGF. The files named on the command line
are concatenated and treated as a single file by this method, so when
called without arguments the contents of this pseudo file are returned in
their entirety.

_length_ must be a non-negative integer or nil. If it is a positive
integer, +read+ tries to read at most _length_ bytes. It returns nil
if an EOF was encountered before anything could be read. Fewer than
_length_ bytes may be returned if an EOF is encountered during the read.

If _length_ is omitted or is _nil_, it reads until EOF. A String is
returned even if EOF is encountered before any data is read.

If _length_ is zero, it returns _""_.

If the optional _outbuf_ argument is present, it must reference a String,
which will receive the data.
The <i>outbuf</i> will contain only the received data after the method call
even if it is not empty at the beginning.

For example:

   $ echo "small" > small.txt
   $ echo "large" > large.txt
   $ ./glark.rb small.txt large.txt

   ARGF.read      #=> "small\nlarge"
   ARGF.read(200) #=> "small\nlarge"
   ARGF.read(2)   #=> "sm"
   ARGF.read(0)   #=> ""

Note that this method behaves like fread() function in C.  If you need the
behavior like read(2) system call, consider +ARGF.readpartial+.

static VALUE
argf_read(int argc, VALUE *argv, VALUE argf)
{
    VALUE tmp, str, length;
    long len = 0;

    rb_scan_args(argc, argv, "02", &length, &str);
    if (!NIL_P(length)) {
        len = NUM2LONG(argv[0]);
    }
    if (!NIL_P(str)) {
        StringValue(str);
        rb_str_resize(str,0);
        argv[1] = Qnil;
    }

  retry:
    if (!next_argv()) {
        return str;
    }
    if (ARGF_GENERIC_INPUT_P()) {
        tmp = argf_forward(argc, argv, argf);
    }
    else {
        tmp = io_read(argc, argv, ARGF.current_file);
    }
    if (NIL_P(str)) str = tmp;
    else if (!NIL_P(tmp)) rb_str_append(str, tmp);
    if (NIL_P(tmp) || NIL_P(length)) {
        if (ARGF.next_p != -1) {
            argf_close(ARGF.current_file);
            ARGF.next_p = 1;
            goto retry;
        }
    }
    else if (argc >= 1) {
        if (RSTRING_LEN(str) < len) {
            len -= RSTRING_LEN(str);
            argv[0] = INT2NUM(len);
            goto retry;
        }
    }
    return str;
}
read_nonblock(maxlen) → string click to toggle source
read_nonblock(maxlen, outbuf) → outbuf

Reads at most maxlen bytes from the ARGF stream in non-blocking mode.

static VALUE
argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
{
    return argf_getpartial(argc, argv, argf, 1);
}
readbyte → Fixnum click to toggle source

Reads the next 8-bit byte from ARGF and returns it as a Fixnum. Raises an EOFError after the last byte of the last file has been read.

For example:

$ echo "foo" > file
$ ruby argf.rb file

ARGF.readbyte  #=> 102
ARGF.readbyte  #=> 111
ARGF.readbyte  #=> 111
ARGF.readbyte  #=> 10
ARGF.readbyte  #=> end of file reached (EOFError)

static VALUE
argf_readbyte(VALUE argf)
{
    VALUE c;

    NEXT_ARGF_FORWARD(0, 0);
    c = argf_getbyte(argf);
    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}
readchar → String or nil click to toggle source

Reads the next character from ARGF and returns it as a String. Raises an EOFError after the last character of the last file has been read.

For example:

$ echo "foo" > file
$ ruby argf.rb file

ARGF.readchar  #=> "f"
ARGF.readchar  #=> "o"
ARGF.readchar  #=> "o"
ARGF.readchar  #=> "\n"
ARGF.readchar  #=> end of file reached (EOFError)

static VALUE
argf_readchar(VALUE argf)
{
    VALUE ch;

  retry:
    if (!next_argv()) rb_eof_error();
    if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
        ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
    }
    else {
        ch = rb_io_getc(ARGF.current_file);
    }
    if (NIL_P(ch) && ARGF.next_p != -1) {
        argf_close(ARGF.current_file);
        ARGF.next_p = 1;
        goto retry;
    }

    return ch;
}
readline(sep=$/) → string click to toggle source
readline(limit) → string
readline(sep, limit) → string

Returns the next line from the current file in ARGF.

By default lines are assumed to be separated by +$/+; to use a different character as a separator, supply it as a String for the sep argument.

The optional limit argument specifies how many characters of each line to return. By default all characters are returned.

An EOFError is raised at the end of the file.

static VALUE
argf_readline(int argc, VALUE *argv, VALUE argf)
{
    VALUE line;

    if (!next_argv()) rb_eof_error();
    ARGF_FORWARD(argc, argv);
    line = argf_gets(argc, argv, argf);
    if (NIL_P(line)) {
        rb_eof_error();
    }

    return line;
}
readlines(sep=$/) → array click to toggle source
readlines(limit) → array
readlines(sep, limit) → array
to_a(sep=$/) → array
to_a(limit) → array
to_a(sep, limit) → array

Reads ARGF's current file in its entirety, returning an Array of its lines, one line per element. Lines are assumed to be separated by sep.

lines = ARGF.readlines
lines[0]                #=> "This is line one\n"

static VALUE
argf_readlines(int argc, VALUE *argv, VALUE argf)
{
    long lineno = ARGF.lineno;
    VALUE lines, ary;

    ary = rb_ary_new();
    while (next_argv()) {
        if (ARGF_GENERIC_INPUT_P()) {
            lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
        }
        else {
            lines = rb_io_readlines(argc, argv, ARGF.current_file);
            argf_close(ARGF.current_file);
        }
        ARGF.next_p = 1;
        rb_ary_concat(ary, lines);
        ARGF.lineno = lineno + RARRAY_LEN(ary);
        ARGF.last_lineno = ARGF.lineno;
    }
    ARGF.init_p = 0;
    return ary;
}
readpartial(maxlen) → string click to toggle source
readpartial(maxlen, outbuf) → outbuf

Reads at most maxlen bytes from the ARGF stream. It blocks only if ARGF has no data immediately available. If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning. It raises EOFError on end of file.

readpartial is designed for streams such as pipes, sockets, and ttys. It blocks only when no data is immediately available. This means that it blocks only when following all conditions hold:

  • The byte buffer in the IO object is empty.

  • The content of the stream is empty.

  • The stream has not reached EOF.

When readpartial blocks, it waits for data or EOF. If some data is read, readpartial returns with the data. If EOF is reached, readpartial raises an EOFError.

When readpartial doesn't block, it returns or raises immediately. If the byte buffer is not empty, it returns the data in the buffer. Otherwise, if the stream has some content, it returns the data in the stream. If the stream reaches EOF an EOFError is raised.

static VALUE
argf_readpartial(int argc, VALUE *argv, VALUE argf)
{
    return argf_getpartial(argc, argv, argf, 0);
}
rewind → 0 click to toggle source

Positions the current file to the beginning of input, resetting ARGF.lineno to zero.

ARGF.readline   #=> "This is line one\n"
ARGF.rewind     #=> 0
ARGF.lineno     #=> 0
ARGF.readline   #=> "This is line one\n"

static VALUE
argf_rewind(VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to rewind");
    }
    ARGF_FORWARD(0, 0);
    return rb_io_rewind(ARGF.current_file);
}
seek(amount, whence=IO::SEEK_SET) → 0 click to toggle source

Seeks to offset amount (an Integer) in the ARGF stream according to the value of whence. See +IO#seek+ for further details.

static VALUE
argf_seek_m(int argc, VALUE *argv, VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to seek");
    }
    ARGF_FORWARD(argc, argv);
    return rb_io_seek_m(argc, argv, ARGF.current_file);
}
set_encoding(ext_enc) → ARGF click to toggle source
set_encoding("ext_enc:int_enc") → ARGF
set_encoding(ext_enc, int_enc) → ARGF
set_encoding("ext_enc:int_enc", opt) → ARGF
set_encoding(ext_enc, int_enc, opt) → ARGF

If single argument is specified, strings read from ARGF are tagged with the encoding specified.

If two encoding names separated by a colon are given, e.g. “ascii:utf-8”, the read string is converted from the first encoding (external encoding) to the second encoding (internal encoding), then tagged with the second encoding.

If two arguments are specified, they must be encoding objects or encoding names. Again, the first specifies the external encoding; the second specifies the internal encoding.

If the external encoding and the internal encoding are specified, the optional Hash argument can be used to adjust the conversion process. The structure of this hash is explained in the +String#encode+ documentation.

For example:

ARGF.set_encoding('ascii')         # Tag the input as US-ASCII text
ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
                                   # to UTF-8.
static VALUE
argf_set_encoding(int argc, VALUE *argv, VALUE argf)
{
    rb_io_t *fptr;

    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to set encoding");
    }
    rb_io_set_encoding(argc, argv, ARGF.current_file);
    GetOpenFile(ARGF.current_file, fptr);
    ARGF.encs = fptr->encs;
    return argf;
}
skip → ARGF click to toggle source
Sets the current file to the next file in ARGV. If there aren't any more
files it has no effect.

For example:

$ ruby argf.rb foo bar
ARGF.filename  #=> "foo"
ARGF.skip
ARGF.filename  #=> "bar"

static VALUE
argf_skip(VALUE argf)
{
    if (ARGF.init_p && ARGF.next_p == 0) {
        argf_close(ARGF.current_file);
        ARGF.next_p = 1;
    }
    return argf;
}
tell → Integer click to toggle source
pos → Integer

Returns the current offset (in bytes) of the current file in ARGF.

ARGF.pos    #=> 0
ARGF.gets   #=> "This is line one\n"
ARGF.pos    #=> 17

static VALUE
argf_tell(VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream to tell");
    }
    ARGF_FORWARD(0, 0);
    return rb_io_tell(ARGF.current_file);
}
readlines(sep=$/) → array click to toggle source
readlines(limit) → array
readlines(sep, limit) → array
to_a(sep=$/) → array
to_a(limit) → array
to_a(sep, limit) → array

Reads ARGF's current file in its entirety, returning an Array of its lines, one line per element. Lines are assumed to be separated by sep.

lines = ARGF.readlines
lines[0]                #=> "This is line one\n"

static VALUE
argf_readlines(int argc, VALUE *argv, VALUE argf)
{
    long lineno = ARGF.lineno;
    VALUE lines, ary;

    ary = rb_ary_new();
    while (next_argv()) {
        if (ARGF_GENERIC_INPUT_P()) {
            lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
        }
        else {
            lines = rb_io_readlines(argc, argv, ARGF.current_file);
            argf_close(ARGF.current_file);
        }
        ARGF.next_p = 1;
        rb_ary_concat(ary, lines);
        ARGF.lineno = lineno + RARRAY_LEN(ary);
        ARGF.last_lineno = ARGF.lineno;
    }
    ARGF.init_p = 0;
    return ary;
}
fileno → fixnum click to toggle source
to_i → fixnum

Returns an integer representing the numeric file descriptor for the current file. Raises an ArgumentError if there isn't a current file.

ARGF.fileno    #=> 3

static VALUE
argf_fileno(VALUE argf)
{
    if (!next_argv()) {
        rb_raise(rb_eArgError, "no stream");
    }
    ARGF_FORWARD(0, 0);
    return rb_io_fileno(ARGF.current_file);
}
to_io → IO click to toggle source

Returns an IO object representing the current file. This will be a File object unless the current file is a stream such as STDIN.

For example:

ARGF.to_io    #=> #<File:glark.txt>
ARGF.to_io    #=> #<IO:<STDIN>>

static VALUE
argf_to_io(VALUE argf)
{
    next_argv();
    ARGF_FORWARD(0, 0);
    return ARGF.current_file;
}
to_s → String click to toggle source

Returns “ARGF”.

static VALUE
argf_to_s(VALUE argf)
{
    return rb_str_new2("ARGF");
}
Also aliased as: inspect
to_write_io → io click to toggle source

Returns IO instance tied to ARGF for writing if inplace mode is enabled.

static VALUE
argf_write_io(VALUE argf)
{
    if (!RTEST(ARGF.current_file)) {
        rb_raise(rb_eIOError, "not opened for writing");
    }
    return GetWriteIO(ARGF.current_file);
}
write(string) → integer click to toggle source

Writes string if inplace mode.

static VALUE
argf_write(VALUE argf, VALUE str)
{
    return rb_io_write(argf_write_io(argf), str);
}


class ArgumentError - Ruby 2.0.0-p576 Core API Reference API Reference

class ArgumentError

Raised when the arguments are wrong and there isn't a more specific Exception class.

Ex: passing the wrong number of arguments

[1, 2, 3].first(4, 5)

raises the exception:

ArgumentError: wrong number of arguments (2 for 1)

Ex: passing an argument that is not acceptable:

[1, 2, 3].first(-4)

raises the exception:

ArgumentError: negative array size

In Files

  • error.c

Parent

StandardError


class Array - Ruby 2.0.0-p576 Core API Reference API Reference

class Array

Arrays are ordered, integer-indexed collections of any object.

Array indexing starts at 0, as in C or Java. A negative index is assumed to be relative to the end of the array—that is, an index of -1 indicates the last element of the array, -2 is the next to last element in the array, and so on.

Creating Arrays

A new array can be created by using the literal constructor []. Arrays can contain different types of objects. For example, the array below contains an Integer, a String and a Float:

ary = [1, "two", 3.0] #=> [1, "two", 3.0]

An array can also be created by explicitly calling ::new with zero, one (the initial size of the Array) or two arguments (the initial size and a default object).

ary = Array.new    #=> []
Array.new(3)       #=> [nil, nil, nil]
Array.new(3, true) #=> [true, true, true]

Note that the second argument populates the array with references to the same object. Therefore, it is only recommended in cases when you need to instantiate arrays with natively immutable objects such as Symbols, numbers, true or false.

To create an array with separate objects a block can be passed instead. This method is safe to use with mutable objects such as hashes, strings or other arrays:

Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]

This is also a quick way to build up multi-dimensional arrays:

empty_table = Array.new(3) { Array.new(3) }
#=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

An array can also be created by using the Array() method, provided by Kernel, which tries to call to_ary, then to_a on its argument.

Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]

Example Usage

In addition to the methods it mixes in through the Enumerable module, the Array class has proprietary methods for accessing, searching and otherwise manipulating arrays.

Some of the more common ones are illustrated below.

Accessing Elements

Elements in an array can be retrieved using the Array#[] method. It can take a single integer argument (a numeric index), a pair of arguments (start and length) or a range.

arr = [1, 2, 3, 4, 5, 6]
arr[2]    #=> 3
arr[100]  #=> nil
arr[-3]   #=> 4
arr[2, 3] #=> [3, 4, 5]
arr[1..4] #=> [2, 3, 4, 5]

Another way to access a particular array element is by using the at method

arr.at(0) #=> 1

The slice method works in an identical manner to Array#[].

To raise an error for indices outside of the array bounds or else to provide a default value when that happens, you can use fetch.

arr = ['a', 'b', 'c', 'd', 'e', 'f']
arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
arr.fetch(100, "oops") #=> "oops"

The special methods first and last will return the first and last elements of an array, respectively.

arr.first #=> 1
arr.last  #=> 6

To return the first n elements of an array, use take

arr.take(3) #=> [1, 2, 3]

drop does the opposite of take, by returning the elements after n elements have been dropped:

arr.drop(3) #=> [4, 5, 6]

Obtaining Information about an Array

Arrays keep track of their own length at all times. To query an array about the number of elements it contains, use length, count or size.

browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
browsers.length #=> 5
browsers.count #=> 5

To check whether an array contains any elements at all

browsers.empty? #=> false

To check whether a particular item is included in the array

browsers.include?('Konqueror') #=> false

Adding Items to Arrays

Items can be added to the end of an array by using either push or #<<

arr = [1, 2, 3, 4]
arr.push(5) #=> [1, 2, 3, 4, 5]
arr << 6    #=> [1, 2, 3, 4, 5, 6]

unshift will add a new item to the beginning of an array.

arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]

With insert you can add a new element to an array at any position.

arr.insert(3, 'apple')  #=> [0, 1, 2, 'apple', 3, 4, 5, 6]

Using the insert method, you can also insert multiple values at once:

arr.insert(3, 'orange', 'pear', 'grapefruit')
#=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]

Removing Items from an Array

The method pop removes the last element in an array and returns it:

arr =  [1, 2, 3, 4, 5, 6]
arr.pop #=> 6
arr #=> [1, 2, 3, 4, 5]

To retrieve and at the same time remove the first item, use shift:

arr.shift #=> 1
arr #=> [2, 3, 4, 5]

To delete an element at a particular index:

arr.delete_at(2) #=> 4
arr #=> [2, 3, 5]

To delete a particular element anywhere in an array, use delete:

arr = [1, 2, 2, 3]
arr.delete(2) #=> [1, 3]

A useful method if you need to remove nil values from an array is compact:

arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact  #=> ['foo', 0, 'bar', 7, 'baz']
arr          #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
arr          #=> ['foo', 0, 'bar', 7, 'baz']

Another common need is to remove duplicate elements from an array.

It has the non-destructive uniq, and destructive method uniq!

arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]

Iterating over Arrays

Like all classes that include the Enumerable module, Array has an each method, which defines what elements should be iterated over and how. In case of Array's each, all elements in the Array instance are yielded to the supplied block in sequence.

Note that this operation leaves the array unchanged.

arr = [1, 2, 3, 4, 5]
arr.each { |a| print a -= 10, " " }
# prints: -9 -8 -7 -6 -5
#=> [1, 2, 3, 4, 5]

Another sometimes useful iterator is reverse_each which will iterate over the elements in the array in reverse order.

words = %w[rats live on no evil star]
str = ""
words.reverse_each { |word| str += "#{word.reverse} " }
str #=> "rats live on no evil star "

The map method can be used to create a new array based on the original array, but with the values modified by the supplied block:

arr.map { |a| 2*a }   #=> [2, 4, 6, 8, 10]
arr                   #=> [1, 2, 3, 4, 5]
arr.map! { |a| a**2 } #=> [1, 4, 9, 16, 25]
arr                   #=> [1, 4, 9, 16, 25]

Selecting Items from an Array

Elements can be selected from an array according to criteria defined in a block. The selection can happen in a destructive or a non-destructive manner. While the destructive operations will modify the array they were called on, the non-destructive methods usually return a new array with the selected elements, but leave the original array unchanged.

Non-destructive Selection

arr = [1, 2, 3, 4, 5, 6]
arr.select { |a| a > 3 }     #=> [4, 5, 6]
arr.reject { |a| a < 3 }     #=> [3, 4, 5, 6]
arr.drop_while { |a| a < 4 } #=> [4, 5, 6]
arr                          #=> [1, 2, 3, 4, 5, 6]

Destructive Selection

select! and reject! are the corresponding destructive methods to select and reject

Similar to select vs. reject, delete_if and keep_if have the exact opposite result when supplied with the same block:

arr.delete_if { |a| a < 4 } #=> [4, 5, 6]
arr                         #=> [4, 5, 6]

arr = [1, 2, 3, 4, 5, 6]
arr.keep_if { |a| a < 4 } #=> [1, 2, 3]
arr                       #=> [1, 2, 3]

In Files

  • array.c
  • pack.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

[](*args) click to toggle source

Returns a new array populated with the given objects.

Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/]
Array[ 1, 'a', /^A/ ]    # => [1, "a", /^A/]
[ 1, 'a', /^A/ ]         # => [1, "a", /^A/]

static VALUE
rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
{
    VALUE ary = ary_new(klass, argc);
    if (argc > 0 && argv) {
        MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
        ARY_SET_LEN(ary, argc);
    }

    return ary;
}
new(size=0, obj=nil) click to toggle source
new(array)
new(size) {|index| block }

Returns a new array.

In the first form, if no arguments are sent, the new array will be empty. When a size and an optional obj are sent, an array is created with size copies of obj. Take notice that all elements will reference the same object obj.

The second form creates a copy of the array passed as a parameter (the array is generated by calling #to_ary on the parameter).

first_array = ["Matz", "Guido"]

second_array = Array.new(first_array) #=> ["Matz", "Guido"]

first_array.equal? second_array       #=> false

In the last form, an array of the given size is created. Each element in this array is created by passing the element's index to the given block and storing the return value.

Array.new(3){ |index| index ** 2 }
# => [0, 1, 4]

Common gotchas

When sending the second parameter, the same object will be used as the value for all the array elements:

a = Array.new(2, Hash.new)
# => [{}, {}]

a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]

a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]

Since all the Array elements store the same hash, changes to one of them will affect them all.

If multiple copies are what you want, you should use the block version which uses the result of that block each time an element of the array needs to be initialized:

a = Array.new(2) { Hash.new }
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {}]

static VALUE
rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
{
    long len;
    VALUE size, val;

    rb_ary_modify(ary);
    if (argc == 0) {
        if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
            xfree(RARRAY_PTR(ary));
        }
        rb_ary_unshare_safe(ary);
        FL_SET_EMBED(ary);
        ARY_SET_EMBED_LEN(ary, 0);
        if (rb_block_given_p()) {
            rb_warning("given block not used");
        }
        return ary;
    }
    rb_scan_args(argc, argv, "02", &size, &val);
    if (argc == 1 && !FIXNUM_P(size)) {
        val = rb_check_array_type(size);
        if (!NIL_P(val)) {
            rb_ary_replace(ary, val);
            return ary;
        }
    }

    len = NUM2LONG(size);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative array size");
    }
    if (len > ARY_MAX_SIZE) {
        rb_raise(rb_eArgError, "array size too big");
    }
    rb_ary_modify(ary);
    ary_resize_capa(ary, len);
    if (rb_block_given_p()) {
        long i;

        if (argc == 2) {
            rb_warn("block supersedes default value argument");
        }
        for (i=0; i<len; i++) {
            rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
            ARY_SET_LEN(ary, i + 1);
        }
    }
    else {
        memfill(RARRAY_PTR(ary), len, val);
        ARY_SET_LEN(ary, len);
    }
    return ary;
}
try_convert(obj) → array or nil click to toggle source

Tries to convert obj into an array, using to_ary method. Returns the converted array or nil if obj cannot be converted for any reason. This method can be used to check if an argument is an array.

Array.try_convert([1])   #=> [1]
Array.try_convert("1")   #=> nil

if tmp = Array.try_convert(arg)
  # the argument is an array
elsif tmp = String.try_convert(arg)
  # the argument is a string
end

static VALUE
rb_ary_s_try_convert(VALUE dummy, VALUE ary)
{
    return rb_check_array_type(ary);
}

Public Instance Methods

ary & other_ary → new_ary click to toggle source

Set Intersection — Returns a new array containing elements common to the two arrays, excluding any duplicates. The order is preserved from the original array.

It compares elements using their hash and eql? methods for efficiency.

[ 1, 1, 3, 5 ] & [ 1, 2, 3 ]                 #=> [ 1, 3 ]
[ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ]   #=> [ 'a', 'b' ]

See also #uniq.

static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
            RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
    hash = ary_make_hash(ary2);

    if (RHASH_EMPTY_P(hash))
        return ary3;

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        vv = (st_data_t)(v = rb_ary_elt(ary1, i));
        if (st_delete(RHASH_TBL(hash), &vv, 0)) {
            rb_ary_push(ary3, v);
        }
    }
    ary_recycle_hash(hash);

    return ary3;
}
ary * int → new_ary click to toggle source
ary * str → new_string

Repetition — With a String argument, equivalent to ary.join(str).

Otherwise, returns a new array built by concatenating the int copies of self.

[ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
[ 1, 2, 3 ] * ","  #=> "1,2,3"

static VALUE
rb_ary_times(VALUE ary, VALUE times)
{
    VALUE ary2, tmp, *ptr, *ptr2;
    long t, len;

    tmp = rb_check_string_type(times);
    if (!NIL_P(tmp)) {
        return rb_ary_join(ary, tmp);
    }

    len = NUM2LONG(times);
    if (len == 0) {
        ary2 = ary_new(rb_obj_class(ary), 0);
        goto out;
    }
    if (len < 0) {
        rb_raise(rb_eArgError, "negative argument");
    }
    if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
        rb_raise(rb_eArgError, "argument too big");
    }
    len *= RARRAY_LEN(ary);

    ary2 = ary_new(rb_obj_class(ary), len);
    ARY_SET_LEN(ary2, len);

    ptr = RARRAY_PTR(ary);
    ptr2 = RARRAY_PTR(ary2);
    t = RARRAY_LEN(ary);
    if (0 < t) {
        MEMCPY(ptr2, ptr, VALUE, t);
        while (t <= len/2) {
            MEMCPY(ptr2+t, ptr2, VALUE, t);
            t *= 2;
        }
        if (t < len) {
            MEMCPY(ptr2+t, ptr2, VALUE, len-t);
        }
    }
  out:
    OBJ_INFECT(ary2, ary);

    return ary2;
}
ary + other_ary → new_ary click to toggle source

Concatenation — Returns a new array built by concatenating the two arrays together to produce a third array.

[ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
a = [ "a", "b", "c" ]
a + [ "d", "e", "f" ]
a                         #=> [ "a", "b", "c", "d", "e", "f" ]

See also #concat.

VALUE
rb_ary_plus(VALUE x, VALUE y)
{
    VALUE z;
    long len;

    y = to_ary(y);
    len = RARRAY_LEN(x) + RARRAY_LEN(y);
    z = rb_ary_new2(len);
    MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
    MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
    ARY_SET_LEN(z, len);
    return z;
}
ary - other_ary → new_ary click to toggle source

Array Difference

Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.

It compares elements using their hash and eql? methods for efficiency.

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]

If you need set-like behavior, see the library class Set.

static VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
    VALUE ary3;
    volatile VALUE hash;
    long i;

    hash = ary_make_hash(to_ary(ary2));
    ary3 = rb_ary_new();

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
        rb_ary_push(ary3, rb_ary_elt(ary1, i));
    }
    ary_recycle_hash(hash);
    return ary3;
}
ary << obj → ary click to toggle source

Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.

[ 1, 2 ] << "c" << "d" << [ 3, 4 ]
        #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]

VALUE
rb_ary_push(VALUE ary, VALUE item)
{
    long idx = RARRAY_LEN(ary);

    ary_ensure_room_for_push(ary, 1);
    RARRAY_PTR(ary)[idx] = item;
    ARY_SET_LEN(ary, idx + 1);
    return ary;
}
ary <=> other_ary → -1, 0, +1 or nil click to toggle source

Comparison — Returns an integer (-1, 0, or +1) if this array is less than, equal to, or greater than other_ary.

nil is returned if the two values are incomparable.

Each object in each array is compared (using the <=> operator).

Arrays are compared in an “element-wise” manner; the first two elements that are not equal will determine the return value for the whole comparison.

If all the values are equal, then the return is based on a comparison of the array lengths. Thus, two arrays are “equal” according to Array#<=> if, and only if, they have the same length and the value of each element is equal to the value of the corresponding element in the other array.

[ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
[ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1

VALUE
rb_ary_cmp(VALUE ary1, VALUE ary2)
{
    long len;
    VALUE v;

    ary2 = rb_check_array_type(ary2);
    if (NIL_P(ary2)) return Qnil;
    if (ary1 == ary2) return INT2FIX(0);
    v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
    if (v != Qundef) return v;
    len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
    if (len == 0) return INT2FIX(0);
    if (len > 0) return INT2FIX(1);
    return INT2FIX(-1);
}
ary == other_ary → bool click to toggle source

Equality — Two arrays are equal if they contain the same number of elements and if each element is equal to (according to Object#==) the corresponding element in other_ary.

[ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
[ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
[ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false

static VALUE
rb_ary_equal(VALUE ary1, VALUE ary2)
{
    if (ary1 == ary2) return Qtrue;
    if (!RB_TYPE_P(ary2, T_ARRAY)) {
        if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
            return Qfalse;
        }
        return rb_equal(ary2, ary1);
    }
    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
    return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
}
ary[index] → obj or nil click to toggle source
ary[start, length] → new_ary or nil
ary[range] → new_ary or nil
slice(index) → obj or nil
slice(start, length) → new_ary or nil
slice(range) → new_ary or nil

Element Reference — Returns the element at index, or returns a subarray starting at the start index and continuing for length elements, or returns a subarray specified by range of indices.

Negative indices count backward from the end of the array (-1 is the last element). For start and range cases the starting index is just before an element. Additionally, an empty array is returned when the starting index for an element range is at the end of the array.

Returns nil if the index (or starting index) are out of range.

a = [ "a", "b", "c", "d", "e" ]
a[2] +  a[0] + a[1]    #=> "cab"
a[6]                   #=> nil
a[1, 2]                #=> [ "b", "c" ]
a[1..3]                #=> [ "b", "c", "d" ]
a[4..7]                #=> [ "e" ]
a[6..10]               #=> nil
a[-3, 3]               #=> [ "c", "d", "e" ]
# special cases
a[5]                   #=> nil
a[6, 1]                #=> nil
a[5, 1]                #=> []
a[5..10]               #=> []

VALUE
rb_ary_aref(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg;
    long beg, len;

    if (argc == 2) {
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        if (beg < 0) {
            beg += RARRAY_LEN(ary);
        }
        return rb_ary_subseq(ary, beg, len);
    }
    if (argc != 1) {
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    arg = argv[0];
    /* special case - speeding up */
    if (FIXNUM_P(arg)) {
        return rb_ary_entry(ary, FIX2LONG(arg));
    }
    /* check if idx is Range */
    switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
      case Qfalse:
        break;
      case Qnil:
        return Qnil;
      default:
        return rb_ary_subseq(ary, beg, len);
    }
    return rb_ary_entry(ary, NUM2LONG(arg));
}
ary[index] = obj → obj click to toggle source
ary[start, length] = obj or other_ary or nil → obj or other_ary or nil
ary[range] = obj or other_ary or nil → obj or other_ary or nil

Element Assignment — Sets the element at index, or replaces a subarray from the start index for length elements, or replaces a subarray specified by the range of indices.

If indices are greater than the current capacity of the array, the array grows automatically. Elements are inserted into the array at start if length is zero.

Negative indices will count backward from the end of the array. For start and range cases the starting index is just before an element.

An IndexError is raised if a negative index points past the beginning of the array.

See also #push, and #unshift.

a = Array.new
a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
a[0..2] = "A"               #=> ["A", "4"]
a[-1]   = "Z"               #=> ["A", "Z"]
a[1..-1] = nil              #=> ["A", nil]
a[1..-1] = []               #=> ["A"]
a[0, 0] = [ 1, 2 ]          #=> [1, 2, "A"]
a[3, 0] = "B"               #=> [1, 2, "A", "B"]

static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
    long offset, beg, len;

    if (argc == 3) {
        rb_ary_modify_check(ary);
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        rb_ary_splice(ary, beg, len, argv[2]);
        return argv[2];
    }
    rb_check_arity(argc, 2, 2);
    rb_ary_modify_check(ary);
    if (FIXNUM_P(argv[0])) {
        offset = FIX2LONG(argv[0]);
        goto fixnum;
    }
    if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
        /* check if idx is Range */
        rb_ary_splice(ary, beg, len, argv[1]);
        return argv[1];
    }

    offset = NUM2LONG(argv[0]);
fixnum:
    rb_ary_store(ary, offset, argv[1]);
    return argv[1];
}
assoc(obj) → new_ary or nil click to toggle source

Searches through an array whose elements are also arrays comparing obj with the first element of each contained array using obj.==.

Returns the first contained array that matches (that is, the first associated array), or nil if no match is found.

See also #rassoc

s1 = [ "colors", "red", "blue", "green" ]
s2 = [ "letters", "a", "b", "c" ]
s3 = "foo"
a  = [ s1, s2, s3 ]
a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
a.assoc("foo")      #=> nil

VALUE
rb_ary_assoc(VALUE ary, VALUE key)
{
    long i;
    VALUE v;

    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        v = rb_check_array_type(RARRAY_PTR(ary)[i]);
        if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
            rb_equal(RARRAY_PTR(v)[0], key))
            return v;
    }
    return Qnil;
}
at(index) → obj or nil click to toggle source

Returns the element at index. A negative index counts from the end of self. Returns nil if the index is out of range. See also Array#[].

a = [ "a", "b", "c", "d", "e" ]
a.at(0)     #=> "a"
a.at(-1)    #=> "e"

static VALUE
rb_ary_at(VALUE ary, VALUE pos)
{
    return rb_ary_entry(ary, NUM2LONG(pos));
}
bsearch {|x| block } → elem click to toggle source

By using binary search, finds a value from this array which meets the given condition in O(log n) where n is the size of the array.

You can use this method in two use cases: a find-minimum mode and a find-any mode. In either case, the elements of the array must be monotone (or sorted) with respect to the block.

In find-minimum mode (this is a good choice for typical use case), the block must return true or false, and there must be an index i (0 <= i <= ary.size) so that:

  • the block returns false for any element whose index is less than i, and

  • the block returns true for any element whose index is greater than or equal to i.

This method returns the i-th element. If i is equal to ary.size, it returns nil.

ary = [0, 4, 7, 10, 12]
ary.bsearch {|x| x >=   4 } #=> 4
ary.bsearch {|x| x >=   6 } #=> 7
ary.bsearch {|x| x >=  -1 } #=> 0
ary.bsearch {|x| x >= 100 } #=> nil

In find-any mode (this behaves like libc's bsearch(3)), the block must return a number, and there must be two indices i and j (0 <= i <= j <= ary.size) so that:

  • the block returns a positive number for ary if 0 <= k < i,

  • the block returns zero for ary if i <= k < j, and

  • the block returns a negative number for ary if j <= k < ary.size.

Under this condition, this method returns any element whose index is within i…j. If i is equal to j (i.e., there is no element that satisfies the block), this method returns nil.

ary = [0, 4, 7, 10, 12]
# try to find v such that 4 <= v < 8
ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
# try to find v such that 8 <= v < 10
ary.bsearch {|x| 4 - x / 2 } #=> nil

You must not mix the two modes at a time; the block must always return either true/false, or always return a number. It is undefined which value is actually picked up at each iteration.

static VALUE
rb_ary_bsearch(VALUE ary)
{
    long low = 0, high = RARRAY_LEN(ary), mid;
    int smaller = 0, satisfied = 0;
    VALUE v, val;

    RETURN_ENUMERATOR(ary, 0, 0);
    while (low < high) {
        mid = low + ((high - low) / 2);
        val = rb_ary_entry(ary, mid);
        v = rb_yield(val);
        if (FIXNUM_P(v)) {
            if (FIX2INT(v) == 0) return val;
            smaller = FIX2INT(v) < 0;
        }
        else if (v == Qtrue) {
            satisfied = 1;
            smaller = 1;
        }
        else if (v == Qfalse || v == Qnil) {
            smaller = 0;
        }
        else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
            switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
                case 0: return val;
                case 1: smaller = 1; break;
                case -1: smaller = 0;
            }
        }
        else {
            rb_raise(rb_eTypeError, "wrong argument type %s"
                " (must be numeric, true, false or nil)",
                rb_obj_classname(v));
        }
        if (smaller) {
            high = mid;
        }
        else {
            low = mid + 1;
        }
    }
    if (low == RARRAY_LEN(ary)) return Qnil;
    if (!satisfied) return Qnil;
    return rb_ary_entry(ary, low);
}
clear → ary click to toggle source

Removes all elements from self.

a = [ "a", "b", "c", "d", "e" ]
a.clear    #=> [ ]

VALUE
rb_ary_clear(VALUE ary)
{
    rb_ary_modify_check(ary);
    ARY_SET_LEN(ary, 0);
    if (ARY_SHARED_P(ary)) {
        if (!ARY_EMBED_P(ary)) {
            rb_ary_unshare(ary);
            FL_SET_EMBED(ary);
        }
    }
    else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
        ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
    }
    return ary;
}
collect { |item| block } → new_ary click to toggle source
map { |item| block } → new_ary
collect → Enumerator
map → Enumerator

Invokes the given block once for each element of self.

Creates a new array containing the values returned by the block.

See also Enumerable#collect.

If no block is given, an Enumerator is returned instead.

a = [ "a", "b", "c", "d" ]
a.map { |x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
a                       #=> ["a", "b", "c", "d"]

static VALUE
rb_ary_collect(VALUE ary)
{
    long i;
    VALUE collect;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    collect = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return collect;
}
collect! {|item| block } → ary click to toggle source
map! {|item| block } → ary
collect! → Enumerator
map! → Enumerator

Invokes the given block once for each element of self, replacing the element with the value returned by the block.

See also Enumerable#collect.

If no block is given, an Enumerator is returned instead.

a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=>  [ "a!", "b!", "c!", "d!" ]

static VALUE
rb_ary_collect_bang(VALUE ary)
{
    long i;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rb_ary_modify(ary);
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return ary;
}
combination(n) { |c| block } → ary click to toggle source
combination(n) → Enumerator

When invoked with a block, yields all combinations of length n of elements from the array and then returns the array itself.

The implementation makes no guarantees about the order in which the combinations are yielded.

If no block is given, an Enumerator is returned instead.

Examples:

a = [1, 2, 3, 4]
a.combination(1).to_a  #=> [[1],[2],[3],[4]]
a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
a.combination(4).to_a  #=> [[1,2,3,4]]
a.combination(0).to_a  #=> [[]] # one combination of length 0
a.combination(5).to_a  #=> []   # no combinations of length 5

static VALUE
rb_ary_combination(VALUE ary, VALUE num)
{
    long n, i, len;

    n = NUM2LONG(num);
    RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
    len = RARRAY_LEN(ary);
    if (n < 0 || len < n) {
        /* yield nothing */
    }
    else if (n == 0) {
        rb_yield(rb_ary_new2(0));
    }
    else if (n == 1) {
        for (i = 0; i < len; i++) {
            rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
        }
    }
    else {
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        volatile VALUE t0;
        long *stack = ALLOCV_N(long, t0, n+1);
        long lev = 0;

        RBASIC(ary0)->klass = 0;
        MEMZERO(stack+1, long, n);
        stack[0] = -1;
        for (;;) {
            for (lev++; lev < n; lev++) {
                stack[lev+1] = stack[lev]+1;
            }
            if (!yield_indexed_values(ary0, n, stack+1)) {
                rb_raise(rb_eRuntimeError, "combination reentered");
            }
            do {
                if (lev == 0) goto done;
                stack[lev--]++;
            } while (stack[lev+1]+n == len+lev+1);
        }
    done:
        ALLOCV_END(t0);
        RBASIC(ary0)->klass = rb_cArray;
    }
    return ary;
}
compact → new_ary click to toggle source

Returns a copy of self with all nil elements removed.

[ "a", nil, "b", nil, "c", nil ].compact
                  #=> [ "a", "b", "c" ]

static VALUE
rb_ary_compact(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_compact_bang(ary);
    return ary;
}
compact! → ary or nil click to toggle source

Removes nil elements from the array.

Returns nil if no changes were made, otherwise returns the array.

[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
[ "a", "b", "c" ].compact!           #=> nil

static VALUE
rb_ary_compact_bang(VALUE ary)
{
    VALUE *p, *t, *end;
    long n;

    rb_ary_modify(ary);
    p = t = RARRAY_PTR(ary);
    end = p + RARRAY_LEN(ary);

    while (t < end) {
        if (NIL_P(*t)) t++;
        else *p++ = *t++;
    }
    n = p - RARRAY_PTR(ary);
    if (RARRAY_LEN(ary) == n) {
        return Qnil;
    }
    ARY_SET_LEN(ary, n);
    if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
        ary_resize_capa(ary, n * 2);
    }

    return ary;
}
concat(other_ary) → ary click to toggle source

Appends the elements of other_ary to self.

[ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
a = [ 1, 2, 3 ]
a.concat( [ 4, 5 ] )
a                                 #=> [ 1, 2, 3, 4, 5 ]

See also Array#+.

VALUE
rb_ary_concat(VALUE x, VALUE y)
{
    rb_ary_modify_check(x);
    y = to_ary(y);
    if (RARRAY_LEN(y) > 0) {
        rb_ary_splice(x, RARRAY_LEN(x), 0, y);
    }
    return x;
}
count → int click to toggle source
count(obj) → int
count { |item| block } → int

Returns the number of elements.

If an argument is given, counts the number of elements which equal obj using ===.

If a block is given, counts the number of elements for which the block returns a true value.

ary = [1, 2, 4, 2]
ary.count                  #=> 4
ary.count(2)               #=> 2
ary.count { |x| x%2 == 0 } #=> 3

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long i, n = 0;

    if (argc == 0) {
        VALUE v;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        for (i = 0; i < RARRAY_LEN(ary); i++) {
            v = RARRAY_PTR(ary)[i];
            if (RTEST(rb_yield(v))) n++;
        }
    }
    else {
        VALUE obj;

        rb_scan_args(argc, argv, "1", &obj);
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            if (rb_equal(RARRAY_PTR(ary)[i], obj)) n++;
        }
    }

    return LONG2NUM(n);
}
cycle(n=nil) { |obj| block } → nil click to toggle source
cycle(n=nil) → Enumerator

Calls the given block for each element n times or forever if nil is given.

Does nothing if a non-positive number is given or the array is empty.

Returns nil if the loop has finished without getting interrupted.

If no block is given, an Enumerator is returned instead.

a = ["a", "b", "c"]
a.cycle { |x| puts x }     # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x }  # print, a, b, c, a, b, c.

static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
    long n, i;
    VALUE nv = Qnil;

    rb_scan_args(argc, argv, "01", &nv);

    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
    if (NIL_P(nv)) {
        n = -1;
    }
    else {
        n = NUM2LONG(nv);
        if (n <= 0) return Qnil;
    }

    while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
        for (i=0; i<RARRAY_LEN(ary); i++) {
            rb_yield(RARRAY_PTR(ary)[i]);
        }
    }
    return Qnil;
}
delete(obj) → item or nil click to toggle source
delete(obj) { block } → item or result of block

Deletes all items from self that are equal to obj.

Returns the last deleted item, or nil if no matching item is found.

If the optional code block is given, the result of the block is returned if the item is not found. (To remove nil elements and get an informative return value, use #compact!)

a = [ "a", "b", "b", "b", "c" ]
a.delete("b")                   #=> "b"
a                               #=> ["a", "c"]
a.delete("z")                   #=> nil
a.delete("z") { "not found" }   #=> "not found"

VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
    VALUE v = item;
    long i1, i2;

    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
        VALUE e = RARRAY_PTR(ary)[i1];

        if (rb_equal(e, item)) {
            v = e;
            continue;
        }
        if (i1 != i2) {
            rb_ary_store(ary, i2, e);
        }
        i2++;
    }
    if (RARRAY_LEN(ary) == i2) {
        if (rb_block_given_p()) {
            return rb_yield(item);
        }
        return Qnil;
    }

    ary_resize_smaller(ary, i2);

    return v;
}
delete_at(index) → obj or nil click to toggle source

Deletes the element at the specified index, returning that element, or nil if the index is out of range.

See also #slice!

a = ["ant", "bat", "cat", "dog"]
a.delete_at(2)    #=> "cat"
a                 #=> ["ant", "bat", "dog"]
a.delete_at(99)   #=> nil

static VALUE
rb_ary_delete_at_m(VALUE ary, VALUE pos)
{
    return rb_ary_delete_at(ary, NUM2LONG(pos));
}
delete_if { |item| block } → ary click to toggle source
delete_if → Enumerator

Deletes every element of self for which block evaluates to true.

The array is changed instantly every time the block is called, not after the iteration is over.

See also #reject!

If no block is given, an Enumerator is returned instead.

a = [ "a", "b", "c" ]
a.delete_if {|x| x >= "b" }   #=> ["a"]

static VALUE
rb_ary_delete_if(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    ary_reject_bang(ary);
    return ary;
}
drop(n) → new_ary click to toggle source

Drops first n elements from ary and returns the rest of the elements in an array.

If a negative number is given, raises an ArgumentError.

See also #take

a = [1, 2, 3, 4, 5, 0]
a.drop(3)             #=> [4, 5, 0]

static VALUE
rb_ary_drop(VALUE ary, VALUE n)
{
    VALUE result;
    long pos = NUM2LONG(n);
    if (pos < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }

    result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
    if (result == Qnil) result = rb_ary_new();
    return result;
}
drop_while { |arr| block } → new_ary click to toggle source
drop_while → Enumerator

Drops elements up to, but not including, the first element for which the block returns nil or false and returns an array containing the remaining elements.

If no block is given, an Enumerator is returned instead.

See also #take_while

a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]

static VALUE
rb_ary_drop_while(VALUE ary)
{
    long i;

    RETURN_ENUMERATOR(ary, 0, 0);
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
    }
    return rb_ary_drop(ary, LONG2FIX(i));
}
each { |item| block } → ary click to toggle source
each → Enumerator

Calls the given block once for each element in self, passing that element as a parameter.

An Enumerator is returned if no block is given.

a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }

produces:

a -- b -- c --
VALUE
rb_ary_each(VALUE array)
{
    long i;
    volatile VALUE ary = array;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    for (i=0; i<RARRAY_LEN(ary); i++) {
        rb_yield(RARRAY_PTR(ary)[i]);
    }
    return ary;
}
each_index { |index| block } → ary click to toggle source
each_index → Enumerator

Same as #each, but passes the index of the element instead of the element itself.

An Enumerator is returned if no block is given.

a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }

produces:

0 -- 1 -- 2 --
static VALUE
rb_ary_each_index(VALUE ary)
{
    long i;
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);

    for (i=0; i<RARRAY_LEN(ary); i++) {
        rb_yield(LONG2NUM(i));
    }
    return ary;
}
empty? → true or false click to toggle source

Returns true if self contains no elements.

[].empty?   #=> true

static VALUE
rb_ary_empty_p(VALUE ary)
{
    if (RARRAY_LEN(ary) == 0)
        return Qtrue;
    return Qfalse;
}
eql?(other) → true or false click to toggle source

Returns true if self and other are the same object, or are both arrays with the same content (according to Object#eql?).

static VALUE
rb_ary_eql(VALUE ary1, VALUE ary2)
{
    if (ary1 == ary2) return Qtrue;
    if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
    return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
fetch(index) → obj click to toggle source
fetch(index, default) → obj
fetch(index) { |index| block } → obj

Tries to return the element at position index, but throws an IndexError exception if the referenced index lies outside of the array bounds. This error can be prevented by supplying a second argument, which will act as a default value.

Alternatively, if a block is given it will only be executed when an invalid index is referenced. Negative values of index count from the end of the array.

a = [ 11, 22, 33, 44 ]
a.fetch(1)               #=> 22
a.fetch(-1)              #=> 44
a.fetch(4, 'cat')        #=> "cat"
a.fetch(100) { |i| puts "#{i} is out of bounds" }
                         #=> "100 is out of bounds"

static VALUE
rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
{
    VALUE pos, ifnone;
    long block_given;
    long idx;

    rb_scan_args(argc, argv, "11", &pos, &ifnone);
    block_given = rb_block_given_p();
    if (block_given && argc == 2) {
        rb_warn("block supersedes default value argument");
    }
    idx = NUM2LONG(pos);

    if (idx < 0) {
        idx +=  RARRAY_LEN(ary);
    }
    if (idx < 0 || RARRAY_LEN(ary) <= idx) {
        if (block_given) return rb_yield(pos);
        if (argc == 1) {
            rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
                        idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
        }
        return ifnone;
    }
    return RARRAY_PTR(ary)[idx];
}
fill(obj) → ary click to toggle source
fill(obj, start [, length]) → ary
fill(obj, range ) → ary
fill { |index| block } → ary
fill(start [, length] ) { |index| block } → ary
fill(range) { |index| block } → ary

The first three forms set the selected elements of self (which may be the entire array) to obj.

A start of nil is equivalent to zero.

A length of nil is equivalent to the length of the array.

The last three forms fill the array with the value of the given block, which is passed the absolute index of each element to be filled.

Negative values of start count from the end of the array, where -1 is the last element.

a = [ "a", "b", "c", "d" ]
a.fill("x")              #=> ["x", "x", "x", "x"]
a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
a.fill { |i| i*i }       #=> [0, 1, 4, 9]
a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]

static VALUE
rb_ary_fill(int argc, VALUE *argv, VALUE ary)
{
    VALUE item, arg1, arg2;
    long beg = 0, end = 0, len = 0;
    VALUE *p, *pend;
    int block_p = FALSE;

    if (rb_block_given_p()) {
        block_p = TRUE;
        rb_scan_args(argc, argv, "02", &arg1, &arg2);
        argc += 1;             /* hackish */
    }
    else {
        rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
    }
    switch (argc) {
      case 1:
        beg = 0;
        len = RARRAY_LEN(ary);
        break;
      case 2:
        if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
            break;
        }
        /* fall through */
      case 3:
        beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
        if (beg < 0) {
            beg = RARRAY_LEN(ary) + beg;
            if (beg < 0) beg = 0;
        }
        len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
        break;
    }
    rb_ary_modify(ary);
    if (len < 0) {
        return ary;
    }
    if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
        rb_raise(rb_eArgError, "argument too big");
    }
    end = beg + len;
    if (RARRAY_LEN(ary) < end) {
        if (end >= ARY_CAPA(ary)) {
            ary_resize_capa(ary, end);
        }
        rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
        ARY_SET_LEN(ary, end);
    }

    if (block_p) {
        VALUE v;
        long i;

        for (i=beg; i<end; i++) {
            v = rb_yield(LONG2NUM(i));
            if (i>=RARRAY_LEN(ary)) break;
            RARRAY_PTR(ary)[i] = v;
        }
    }
    else {
        p = RARRAY_PTR(ary) + beg;
        pend = p + len;
        while (p < pend) {
            *p++ = item;
        }
    }
    return ary;
}
index(obj) → int or nil click to toggle source
index { |item| block } → int or nil
index → Enumerator

Returns the index of the first object in ary such that the object is == to obj.

If a block is given instead of an argument, returns the index of the first object for which the block returns true. Returns nil if no match is found.

See also #rindex.

An Enumerator is returned if neither a block nor argument is given.

a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1

This is an alias of #find_index.

static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
    VALUE val;
    long i;

    if (argc == 0) {
        RETURN_ENUMERATOR(ary, 0, 0);
        for (i=0; i<RARRAY_LEN(ary); i++) {
            if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
                return LONG2NUM(i);
            }
        }
        return Qnil;
    }
    rb_scan_args(argc, argv, "1", &val);
    if (rb_block_given_p())
        rb_warn("given block not used");
    for (i=0; i<RARRAY_LEN(ary); i++) {
        if (rb_equal(RARRAY_PTR(ary)[i], val))
            return LONG2NUM(i);
    }
    return Qnil;
}
first → obj or nil click to toggle source
first(n) → new_ary

Returns the first element, or the first n elements, of the array. If the array is empty, the first form returns nil, and the second form returns an empty array. See also #last for the opposite effect.

a = [ "q", "r", "s", "t" ]
a.first     #=> "q"
a.first(2)  #=> ["q", "r"]

static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
    if (argc == 0) {
        if (RARRAY_LEN(ary) == 0) return Qnil;
        return RARRAY_PTR(ary)[0];
    }
    else {
        return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    }
}
flatten → new_ary click to toggle source
flatten(level) → new_ary

Returns a new array that is a one-dimensional flattening of self (recursively).

That is, for every element that is an array, extract its elements into the new array.

The optional level argument determines the level of recursion to flatten.

s = [ 1, 2, 3 ]           #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1)              #=> [1, 2, 3, [4, 5]]

static VALUE
rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

    rb_scan_args(argc, argv, "01", &lv);
    if (!NIL_P(lv)) level = NUM2INT(lv);
    if (level == 0) return ary_make_shared_copy(ary);

    result = flatten(ary, level, &mod);
    OBJ_INFECT(result, ary);

    return result;
}
flatten! → ary or nil click to toggle source
flatten!(level) → ary or nil

Flattens self in place.

Returns nil if no modifications were made (i.e., the array contains no subarrays.)

The optional level argument determines the level of recursion to flatten.

a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!   #=> [1, 2, 3, 4, 5]
a.flatten!   #=> nil
a            #=> [1, 2, 3, 4, 5]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!(1) #=> [1, 2, 3, [4, 5]]

static VALUE
rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

    rb_scan_args(argc, argv, "01", &lv);
    rb_ary_modify_check(ary);
    if (!NIL_P(lv)) level = NUM2INT(lv);
    if (level == 0) return Qnil;

    result = flatten(ary, level, &mod);
    if (mod == 0) {
        ary_discard(result);
        return Qnil;
    }
    if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
    rb_ary_replace(ary, result);
    if (mod) ARY_SET_EMBED_LEN(result, 0);

    return ary;
}
frozen? → true or false click to toggle source

Return true if this array is frozen (or temporarily frozen while being sorted). See also Object#frozen?

static VALUE
rb_ary_frozen_p(VALUE ary)
{
    if (OBJ_FROZEN(ary)) return Qtrue;
    return Qfalse;
}
hash → fixnum click to toggle source

Compute a hash-code for this array.

Two arrays with the same content will have the same hash code (and will compare using eql?).

static VALUE
rb_ary_hash(VALUE ary)
{
    return rb_exec_recursive_outer(recursive_hash, ary, 0);
}
include?(object) → true or false click to toggle source

Returns true if the given object is present in self (that is, if any element == object), otherwise returns false.

a = [ "a", "b", "c" ]
a.include?("b")   #=> true
a.include?("z")   #=> false

VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;

    for (i=0; i<RARRAY_LEN(ary); i++) {
        if (rb_equal(RARRAY_PTR(ary)[i], item)) {
            return Qtrue;
        }
    }
    return Qfalse;
}
index(obj) → int or nil click to toggle source
index { |item| block } → int or nil
index → Enumerator

Returns the index of the first object in ary such that the object is == to obj.

If a block is given instead of an argument, returns the index of the first object for which the block returns true. Returns nil if no match is found.

See also #rindex.

An Enumerator is returned if neither a block nor argument is given.

a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1

This is an alias of #find_index.

static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
    VALUE val;
    long i;

    if (argc == 0) {
        RETURN_ENUMERATOR(ary, 0, 0);
        for (i=0; i<RARRAY_LEN(ary); i++) {
            if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
                return LONG2NUM(i);
            }
        }
        return Qnil;
    }
    rb_scan_args(argc, argv, "1", &val);
    if (rb_block_given_p())
        rb_warn("given block not used");
    for (i=0; i<RARRAY_LEN(ary); i++) {
        if (rb_equal(RARRAY_PTR(ary)[i], val))
            return LONG2NUM(i);
    }
    return Qnil;
}
replace(other_ary) → ary click to toggle source

Replaces the contents of self with the contents of other_ary, truncating or expanding if necessary.

a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]

VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
        VALUE *ptr;
        VALUE shared = 0;

        if (ARY_OWNS_HEAP_P(copy)) {
            xfree(RARRAY_PTR(copy));
        }
        else if (ARY_SHARED_P(copy)) {
            shared = ARY_SHARED(copy);
            FL_UNSET_SHARED(copy);
        }
        FL_SET_EMBED(copy);
        ptr = RARRAY_PTR(orig);
        MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
        if (shared) {
            rb_ary_decrement_share(shared);
        }
        ARY_SET_LEN(copy, RARRAY_LEN(orig));
    }
    else {
        VALUE shared = ary_make_shared(orig);
        if (ARY_OWNS_HEAP_P(copy)) {
            xfree(RARRAY_PTR(copy));
        }
        else {
            rb_ary_unshare_safe(copy);
        }
        FL_UNSET_EMBED(copy);
        ARY_SET_PTR(copy, RARRAY_PTR(orig));
        ARY_SET_LEN(copy, RARRAY_LEN(orig));
        rb_ary_set_shared(copy, shared);
    }
    return copy;
}
insert(index, obj...) → ary click to toggle source

Inserts the given values before the element with the given index.

Negative indices count backwards from the end of the array, where -1 is the last element.

a = %w{ a b c d }
a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]

static VALUE
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
    long pos;

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    rb_ary_modify_check(ary);
    if (argc == 1) return ary;
    pos = NUM2LONG(argv[0]);
    if (pos == -1) {
        pos = RARRAY_LEN(ary);
    }
    if (pos < 0) {
        pos++;
    }
    rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
    return ary;
}
inspect → string click to toggle source
to_s → string

Creates a string representation of self.

[ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"

static VALUE
rb_ary_inspect(VALUE ary)
{
    if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
    return rb_exec_recursive(inspect_ary, ary, 0);
}
Also aliased as: to_s
join(separator=$,) → str click to toggle source

Returns a string created by converting each element of the array to a string, separated by the given separator. If the separator is nil, it uses current $,. If both the separator and $, are nil, it uses empty string.

[ "a", "b", "c" ].join        #=> "abc"
[ "a", "b", "c" ].join("-")   #=> "a-b-c"

static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE sep;

    rb_scan_args(argc, argv, "01", &sep);
    if (NIL_P(sep)) sep = rb_output_fs;

    return rb_ary_join(ary, sep);
}
keep_if { |item| block } → ary click to toggle source
keep_if → Enumerator

Deletes every element of self for which the given block evaluates to false.

See also #select!

If no block is given, an Enumerator is returned instead.

a = %w{ a b c d e f }
a.keep_if { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]

static VALUE
rb_ary_keep_if(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rb_ary_select_bang(ary);
    return ary;
}
last → obj or nil click to toggle source
last(n) → new_ary

Returns the last element(s) of self. If the array is empty, the first form returns nil.

See also #first for the opposite effect.

a = [ "w", "x", "y", "z" ]
a.last     #=> "z"
a.last(2)  #=> ["y", "z"]

VALUE
rb_ary_last(int argc, VALUE *argv, VALUE ary)
{
    if (argc == 0) {
        if (RARRAY_LEN(ary) == 0) return Qnil;
        return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
    }
    else {
        return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    }
}
length → int click to toggle source

Returns the number of elements in self. May be zero.

[ 1, 2, 3, 4, 5 ].length   #=> 5
[].length                  #=> 0

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}
Also aliased as: size
collect { |item| block } → new_ary click to toggle source
map { |item| block } → new_ary
collect → Enumerator
map → Enumerator

Invokes the given block once for each element of self.

Creates a new array containing the values returned by the block.

See also Enumerable#collect.

If no block is given, an Enumerator is returned instead.

a = [ "a", "b", "c", "d" ]
a.map { |x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
a                       #=> ["a", "b", "c", "d"]

static VALUE
rb_ary_collect(VALUE ary)
{
    long i;
    VALUE collect;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    collect = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return collect;
}
collect! {|item| block } → ary click to toggle source
map! {|item| block } → ary
collect! → Enumerator
map! → Enumerator

Invokes the given block once for each element of self, replacing the element with the value returned by the block.

See also Enumerable#collect.

If no block is given, an Enumerator is returned instead.

a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=>  [ "a!", "b!", "c!", "d!" ]

static VALUE
rb_ary_collect_bang(VALUE ary)
{
    long i;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rb_ary_modify(ary);
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return ary;
}
pack ( aTemplateString ) → aBinaryString click to toggle source

Packs the contents of arr into a binary sequence according to the directives in aTemplateString (see the table below) Directives “A,'' “a,'' and “Z'' may be followed by a count, which gives the width of the resulting field. The remaining directives also may take a count, indicating the number of array elements to convert. If the count is an asterisk (“*''), all remaining array elements will be converted. Any of the directives “sSiIlL'' may be followed by an underscore (“_'') or exclamation mark (“!'') to use the underlying platform's native size for the specified type; otherwise, they use a platform-independent size. Spaces are ignored in the template string. See also String#unpack.

a = [ "a", "b", "c" ]
n = [ 65, 66, 67 ]
a.pack("A3A3A3")   #=> "a  b  c  "
a.pack("a3a3a3")   #=> "a\000\000b\000\000c\000\000"
n.pack("ccc")      #=> "ABC"

Directives for pack.

Integer      | Array   |
Directive    | Element | Meaning
---------------------------------------------------------------------------
   C         | Integer | 8-bit unsigned (unsigned char)
   S         | Integer | 16-bit unsigned, native endian (uint16_t)
   L         | Integer | 32-bit unsigned, native endian (uint32_t)
   Q         | Integer | 64-bit unsigned, native endian (uint64_t)
             |         |
   c         | Integer | 8-bit signed (signed char)
   s         | Integer | 16-bit signed, native endian (int16_t)
   l         | Integer | 32-bit signed, native endian (int32_t)
   q         | Integer | 64-bit signed, native endian (int64_t)
             |         |
   S_, S!    | Integer | unsigned short, native endian
   I, I_, I! | Integer | unsigned int, native endian
   L_, L!    | Integer | unsigned long, native endian
             |         |
   s_, s!    | Integer | signed short, native endian
   i, i_, i! | Integer | signed int, native endian
   l_, l!    | Integer | signed long, native endian
             |         |
   S> L> Q>  | Integer | same as the directives without ">" except
   s> l> q>  |         | big endian
   S!> I!>   |         | (available since Ruby 1.9.3)
   L!>       |         | "S>" is same as "n"
   s!> i!>   |         | "L>" is same as "N"
   l!>       |         |
             |         |
   S< L< Q<  | Integer | same as the directives without "<" except
   s< l< q<  |         | little endian
   S!< I!<   |         | (available since Ruby 1.9.3)
   L!<       |         | "S<" is same as "v"
   s!< i!<   |         | "L<" is same as "V"
   l!<       |         |
             |         |
   n         | Integer | 16-bit unsigned, network (big-endian) byte order
   N         | Integer | 32-bit unsigned, network (big-endian) byte order
   v         | Integer | 16-bit unsigned, VAX (little-endian) byte order
   V         | Integer | 32-bit unsigned, VAX (little-endian) byte order
             |         |
   U         | Integer | UTF-8 character
   w         | Integer | BER-compressed integer

Float        |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   D, d      | Float   | double-precision, native format
   F, f      | Float   | single-precision, native format
   E         | Float   | double-precision, little-endian byte order
   e         | Float   | single-precision, little-endian byte order
   G         | Float   | double-precision, network (big-endian) byte order
   g         | Float   | single-precision, network (big-endian) byte order

String       |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   A         | String  | arbitrary binary string (space padded, count is width)
   a         | String  | arbitrary binary string (null padded, count is width)
   Z         | String  | same as ``a'', except that null is added with *
   B         | String  | bit string (MSB first)
   b         | String  | bit string (LSB first)
   H         | String  | hex string (high nibble first)
   h         | String  | hex string (low nibble first)
   u         | String  | UU-encoded string
   M         | String  | quoted printable, MIME encoding (see RFC2045)
   m         | String  | base64 encoded string (see RFC 2045, count is width)
             |         | (if count is 0, no line feed are added, see RFC 4648)
   P         | String  | pointer to a structure (fixed-length string)
   p         | String  | pointer to a null-terminated string

Misc.        |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   @         | ---     | moves to absolute position
   X         | ---     | back up a byte
   x         | ---     | null byte
static VALUE
pack_pack(VALUE ary, VALUE fmt)
{
    static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
    static const char spc10[] = "          ";
    const char *p, *pend;
    VALUE res, from, associates = 0;
    char type;
    long items, len, idx, plen;
    const char *ptr;
    int enc_info = 1;           /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
#ifdef NATINT_PACK
    int natint;         /* native integer */
#endif
    int integer_size, bigendian_p;

    StringValue(fmt);
    p = RSTRING_PTR(fmt);
    pend = p + RSTRING_LEN(fmt);
    res = rb_str_buf_new(0);

    items = RARRAY_LEN(ary);
    idx = 0;

#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
#define THISFROM (items > 0 ? RARRAY_PTR(ary)[idx] : TOO_FEW)
#define NEXTFROM (items-- > 0 ? RARRAY_PTR(ary)[idx++] : TOO_FEW)

    while (p < pend) {
        int explicit_endian = 0;
        if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
            rb_raise(rb_eRuntimeError, "format string modified");
        }
        type = *p++;           /* get data type */
#ifdef NATINT_PACK
        natint = 0;
#endif

        if (ISSPACE(type)) continue;
        if (type == '#') {
            while ((p < pend) && (*p != '\n')) {
                p++;
            }
            continue;
        }

        {
            static const char natstr[] = "sSiIlL";
            static const char endstr[] = "sSiIlLqQ";

          modifiers:
            switch (*p) {
              case '_':
              case '!':
                if (strchr(natstr, type)) {
#ifdef NATINT_PACK
                    natint = 1;
#endif
                    p++;
                }
                else {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
                }
                goto modifiers;

              case '<':
              case '>':
                if (!strchr(endstr, type)) {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
                }
                if (explicit_endian) {
                    rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
                }
                explicit_endian = *p++;
                goto modifiers;
            }
        }

        if (*p == '*') {       /* set data length */
            len = strchr("@Xxu", type) ? 0
                : strchr("PMm", type) ? 1
                : items;
            p++;
        }
        else if (ISDIGIT(*p)) {
            errno = 0;
            len = STRTOUL(p, (char**)&p, 10);
            if (errno) {
                rb_raise(rb_eRangeError, "pack length too big");
            }
        }
        else {
            len = 1;
        }

        switch (type) {
          case 'U':
            /* if encoding is US-ASCII, upgrade to UTF-8 */
            if (enc_info == 1) enc_info = 2;
            break;
          case 'm': case 'M': case 'u':
            /* keep US-ASCII (do nothing) */
            break;
          default:
            /* fall back to BINARY */
            enc_info = 0;
            break;
        }
        switch (type) {
          case 'A': case 'a': case 'Z':
          case 'B': case 'b':
          case 'H': case 'h':
            from = NEXTFROM;
            if (NIL_P(from)) {
                ptr = "";
                plen = 0;
            }
            else {
                StringValue(from);
                ptr = RSTRING_PTR(from);
                plen = RSTRING_LEN(from);
                OBJ_INFECT(res, from);
            }

            if (p[-1] == '*')
                len = plen;

            switch (type) {
              case 'a':                /* arbitrary binary string (null padded)  */
              case 'A':         /* arbitrary binary string (ASCII space padded) */
              case 'Z':         /* null terminated string  */
                if (plen >= len) {
                    rb_str_buf_cat(res, ptr, len);
                    if (p[-1] == '*' && type == 'Z')
                        rb_str_buf_cat(res, nul10, 1);
                }
                else {
                    rb_str_buf_cat(res, ptr, plen);
                    len -= plen;
                    while (len >= 10) {
                        rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
                        len -= 10;
                    }
                    rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
                }
                break;

#define castchar(from) (char)((from) & 0xff)

              case 'b':                /* bit string (ascending) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len - plen + 1)/2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (*ptr & 1)
                            byte |= 128;
                        if (i & 7)
                            byte >>= 1;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 7) {
                        char c;
                        byte >>= 7 - (len & 7);
                        c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'B':                /* bit string (descending) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len - plen + 1)/2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        byte |= *ptr & 1;
                        if (i & 7)
                            byte <<= 1;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 7) {
                        char c;
                        byte <<= 7 - (len & 7);
                        c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'h':                /* hex string (low nibble first) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len + 1) / 2 - (plen + 1) / 2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (ISALPHA(*ptr))
                            byte |= (((*ptr & 15) + 9) & 15) << 4;
                        else
                            byte |= (*ptr & 15) << 4;
                        if (i & 1)
                            byte >>= 4;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 1) {
                        char c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'H':                /* hex string (high nibble first) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len + 1) / 2 - (plen + 1) / 2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (ISALPHA(*ptr))
                            byte |= ((*ptr & 15) + 9) & 15;
                        else
                            byte |= *ptr & 15;
                        if (i & 1)
                            byte <<= 4;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 1) {
                        char c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;
            }
            break;

          case 'c':            /* signed char */
          case 'C':            /* unsigned char */
            while (len-- > 0) {
                char c;

                from = NEXTFROM;
                c = (char)num2i32(from);
                rb_str_buf_cat(res, &c, sizeof(char));
            }
            break;

          case 's':            /* signed short */
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'S':            /* unsigned short */
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'i':            /* signed int */
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'I':            /* unsigned int */
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'l':            /* signed long */
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'L':            /* unsigned long */
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'q':            /* signed quad (64bit) int */
            integer_size = 8;
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'Q':            /* unsigned quad (64bit) int */
            integer_size = 8;
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'n':            /* unsigned short (network byte-order)  */
            integer_size = 2;
            bigendian_p = 1;
            goto pack_integer;

          case 'N':            /* unsigned long (network byte-order) */
            integer_size = 4;
            bigendian_p = 1;
            goto pack_integer;

          case 'v':            /* unsigned short (VAX byte-order) */
            integer_size = 2;
            bigendian_p = 0;
            goto pack_integer;

          case 'V':            /* unsigned long (VAX byte-order) */
            integer_size = 4;
            bigendian_p = 0;
            goto pack_integer;

          pack_integer:
            if (explicit_endian) {
                bigendian_p = explicit_endian == '>';
            }

            switch (integer_size) {
#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT16_T:
                while (len-- > 0) {
                    union {
                        int16_t i;
                        char a[sizeof(int16_t)];
                    } v;

                    from = NEXTFROM;
                    v.i = (int16_t)num2i32(from);
                    if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
                    rb_str_buf_cat(res, v.a, sizeof(int16_t));
                }
                break;
#endif

#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT32_T:
                while (len-- > 0) {
                    union {
                        int32_t i;
                        char a[sizeof(int32_t)];
                    } v;

                    from = NEXTFROM;
                    v.i = (int32_t)num2i32(from);
                    if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
                    rb_str_buf_cat(res, v.a, sizeof(int32_t));
                }
                break;
#endif

#if defined(HAVE_INT64_T) && SIZEOF_LONG == SIZEOF_INT64_T && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT64_T:
                while (len-- > 0) {
                    union {
                        int64_t i;
                        char a[sizeof(int64_t)];
                    } v;

                    from = NEXTFROM;
                    v.i = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
                    if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
                    rb_str_buf_cat(res, v.a, sizeof(int64_t));
                }
                break;
#endif

              default:
                if (integer_size > MAX_INTEGER_PACK_SIZE)
                    rb_bug("unexpected intger size for pack: %d", integer_size);
                while (len-- > 0) {
                    union {
                        unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG];
                        char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG*SIZEOF_LONG];
                    } v;
                    int num_longs = (integer_size+SIZEOF_LONG-1)/SIZEOF_LONG;
                    int i;

                    from = NEXTFROM;
                    rb_big_pack(from, v.i, num_longs);
                    if (bigendian_p) {
                        for (i = 0; i < num_longs/2; i++) {
                            unsigned long t = v.i[i];
                            v.i[i] = v.i[num_longs-1-i];
                            v.i[num_longs-1-i] = t;
                        }
                    }
                    if (bigendian_p != BIGENDIAN_P()) {
                        for (i = 0; i < num_longs; i++)
                            v.i[i] = swapl(v.i[i]);
                    }
                    rb_str_buf_cat(res,
                                   bigendian_p ?
                                     v.a + sizeof(long)*num_longs - integer_size :
                                     v.a,
                                   integer_size);
                }
                break;
            }
            break;

          case 'f':            /* single precision float in native format */
          case 'F':            /* ditto */
            while (len-- > 0) {
                float f;

                from = NEXTFROM;
                f = (float)RFLOAT_VALUE(rb_to_float(from));
                rb_str_buf_cat(res, (char*)&f, sizeof(float));
            }
            break;

          case 'e':            /* single precision float in VAX byte-order */
            while (len-- > 0) {
                float f;
                FLOAT_CONVWITH(ftmp);

                from = NEXTFROM;
                f = (float)RFLOAT_VALUE(rb_to_float(from));
                f = HTOVF(f,ftmp);
                rb_str_buf_cat(res, (char*)&f, sizeof(float));
            }
            break;

          case 'E':            /* double precision float in VAX byte-order */
            while (len-- > 0) {
                double d;
                DOUBLE_CONVWITH(dtmp);

                from = NEXTFROM;
                d = RFLOAT_VALUE(rb_to_float(from));
                d = HTOVD(d,dtmp);
                rb_str_buf_cat(res, (char*)&d, sizeof(double));
            }
            break;

          case 'd':            /* double precision float in native format */
          case 'D':            /* ditto */
            while (len-- > 0) {
                double d;

                from = NEXTFROM;
                d = RFLOAT_VALUE(rb_to_float(from));
                rb_str_buf_cat(res, (char*)&d, sizeof(double));
            }
            break;

          case 'g':            /* single precision float in network byte-order */
            while (len-- > 0) {
                float f;
                FLOAT_CONVWITH(ftmp);

                from = NEXTFROM;
                f = (float)RFLOAT_VALUE(rb_to_float(from));
                f = HTONF(f,ftmp);
                rb_str_buf_cat(res, (char*)&f, sizeof(float));
            }
            break;

          case 'G':            /* double precision float in network byte-order */
            while (len-- > 0) {
                double d;
                DOUBLE_CONVWITH(dtmp);

                from = NEXTFROM;
                d = RFLOAT_VALUE(rb_to_float(from));
                d = HTOND(d,dtmp);
                rb_str_buf_cat(res, (char*)&d, sizeof(double));
            }
            break;

          case 'x':            /* null byte */
          grow:
            while (len >= 10) {
                rb_str_buf_cat(res, nul10, 10);
                len -= 10;
            }
            rb_str_buf_cat(res, nul10, len);
            break;

          case 'X':            /* back up byte */
          shrink:
            plen = RSTRING_LEN(res);
            if (plen < len)
                rb_raise(rb_eArgError, "X outside of string");
            rb_str_set_len(res, plen - len);
            break;

          case '@':            /* null fill to absolute position */
            len -= RSTRING_LEN(res);
            if (len > 0) goto grow;
            len = -len;
            if (len > 0) goto shrink;
            break;

          case '%':
            rb_raise(rb_eArgError, "%% is not supported");
            break;

          case 'U':            /* Unicode character */
            while (len-- > 0) {
                SIGNED_VALUE l;
                char buf[8];
                int le;

                from = NEXTFROM;
                from = rb_to_int(from);
                l = NUM2LONG(from);
                if (l < 0) {
                    rb_raise(rb_eRangeError, "pack(U): value out of range");
                }
                le = rb_uv_to_utf8(buf, l);
                rb_str_buf_cat(res, (char*)buf, le);
            }
            break;

          case 'u':            /* uuencoded string */
          case 'm':            /* base64 encoded string */
            from = NEXTFROM;
            StringValue(from);
            ptr = RSTRING_PTR(from);
            plen = RSTRING_LEN(from);

            if (len == 0 && type == 'm') {
                encodes(res, ptr, plen, type, 0);
                ptr += plen;
                break;
            }
            if (len <= 2)
                len = 45;
            else if (len > 63 && type == 'u')
                len = 63;
            else
                len = len / 3 * 3;
            while (plen > 0) {
                long todo;

                if (plen > len)
                    todo = len;
                else
                    todo = plen;
                encodes(res, ptr, todo, type, 1);
                plen -= todo;
                ptr += todo;
            }
            break;

          case 'M':            /* quoted-printable encoded string */
            from = rb_obj_as_string(NEXTFROM);
            if (len <= 1)
                len = 72;
            qpencode(res, from, len);
            break;

          case 'P':            /* pointer to packed byte string */
            from = THISFROM;
            if (!NIL_P(from)) {
                StringValue(from);
                if (RSTRING_LEN(from) < len) {
                    rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
                             RSTRING_LEN(from), len);
                }
            }
            len = 1;
            /* FALL THROUGH */
          case 'p':            /* pointer to string */
            while (len-- > 0) {
                char *t;
                from = NEXTFROM;
                if (NIL_P(from)) {
                    t = 0;
                }
                else {
                    t = StringValuePtr(from);
                }
                if (!associates) {
                    associates = rb_ary_new();
                }
                rb_ary_push(associates, from);
                rb_obj_taint(from);
                rb_str_buf_cat(res, (char*)&t, sizeof(char*));
            }
            break;

          case 'w':            /* BER compressed integer  */
            while (len-- > 0) {
                unsigned long ul;
                VALUE buf = rb_str_new(0, 0);
                char c, *bufs, *bufe;

                from = NEXTFROM;
                if (RB_TYPE_P(from, T_BIGNUM)) {
                    VALUE big128 = rb_uint2big(128);
                    while (RB_TYPE_P(from, T_BIGNUM)) {
                        from = rb_big_divmod(from, big128);
                        c = castchar(NUM2INT(RARRAY_PTR(from)[1]) | 0x80); /* mod */
                        rb_str_buf_cat(buf, &c, sizeof(char));
                        from = RARRAY_PTR(from)[0]; /* div */
                    }
                }

                {
                    long l = NUM2LONG(from);
                    if (l < 0) {
                        rb_raise(rb_eArgError, "can't compress negative numbers");
                    }
                    ul = l;
                }

                while (ul) {
                    c = castchar((ul & 0x7f) | 0x80);
                    rb_str_buf_cat(buf, &c, sizeof(char));
                    ul >>=  7;
                }

                if (RSTRING_LEN(buf)) {
                    bufs = RSTRING_PTR(buf);
                    bufe = bufs + RSTRING_LEN(buf) - 1;
                    *bufs &= 0x7f; /* clear continue bit */
                    while (bufs < bufe) { /* reverse */
                        c = *bufs;
                        *bufs++ = *bufe;
                        *bufe-- = c;
                    }
                    rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
                }
                else {
                    c = 0;
                    rb_str_buf_cat(res, &c, sizeof(char));
                }
            }
            break;

          default:
            rb_warning("unknown pack directive '%c' in '%s'",
                type, RSTRING_PTR(fmt));
            break;
        }
    }

    if (associates) {
        rb_str_associate(res, associates);
    }
    OBJ_INFECT(res, fmt);
    switch (enc_info) {
      case 1:
        ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
        break;
      case 2:
        rb_enc_set_index(res, rb_utf8_encindex());
        break;
      default:
        /* do nothing, keep ASCII-8BIT */
        break;
    }
    return res;
}
permutation { |p| block } → ary click to toggle source
permutation → Enumerator
permutation(n) { |p| block } → ary
permutation(n) → Enumerator

When invoked with a block, yield all permutations of length n of the elements of the array, then return the array itself.

If n is not specified, yield all permutations of all elements.

The implementation makes no guarantees about the order in which the permutations are yielded.

If no block is given, an Enumerator is returned instead.

Examples:

a = [1, 2, 3]
a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(1).to_a #=> [[1],[2],[3]]
a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(0).to_a #=> [[]] # one permutation of length 0
a.permutation(4).to_a #=> []   # no permutations of length 4

static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
    VALUE num;
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
    rb_scan_args(argc, argv, "01", &num);
    r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */

    if (r < 0 || n < r) {
        /* no permutations: yield nothing */
    }
    else if (r == 0) { /* exactly one permutation: the zero-length array */
        rb_yield(rb_ary_new2(0));
    }
    else if (r == 1) { /* this is a special, easy case */
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
        }
    }
    else {             /* this is the general case */
        volatile VALUE t0 = tmpbuf(r,sizeof(long));
        long *p = (long*)RSTRING_PTR(t0);
        volatile VALUE t1 = tmpbuf(n,sizeof(char));
        char *used = (char*)RSTRING_PTR(t1);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC(ary0)->klass = 0;

        MEMZERO(used, char, n); /* initialize array */

        permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
        tmpbuf_discard(t0);
        tmpbuf_discard(t1);
        RBASIC(ary0)->klass = rb_cArray;
    }
    return ary;
}
pop → obj or nil click to toggle source
pop(n) → new_ary

Removes the last element from self and returns it, or nil if the array is empty.

If a number n is given, returns an array of the last n elements (or less) just like array.slice!(-n, n) does. See also #push for the opposite effect.

a = [ "a", "b", "c", "d" ]
a.pop     #=> "d"
a.pop(2)  #=> ["b", "c"]
a         #=> ["a"]

static VALUE
rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE result;

    if (argc == 0) {
        return rb_ary_pop(ary);
    }

    rb_ary_modify_check(ary);
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
    return result;
}
product(other_ary, ...) → new_ary click to toggle source
product(other_ary, ...) { |p| block } → ary

Returns an array of all combinations of elements from all arrays.

The length of the returned array is the product of the length of self and the argument arrays.

If given a block, product will yield all combinations and return self instead.

[1,2,3].product([4,5])     #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
[1,2].product([1,2])       #=> [[1,1],[1,2],[2,1],[2,2]]
[1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
                           #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
[1,2].product()            #=> [[1],[2]]
[1,2].product([])          #=> []

static VALUE
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
    int n = argc+1;    /* How many arrays we're operating on */
    volatile VALUE t0 = tmpary(n);
    volatile VALUE t1 = tmpbuf(n, sizeof(int));
    VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
    int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
    VALUE result = Qnil;      /* The array we'll be returning, when no block given */
    long i,j;
    long resultlen = 1;

    RBASIC(t0)->klass = 0;
    RBASIC(t1)->klass = 0;

    /* initialize the arrays of arrays */
    ARY_SET_LEN(t0, n);
    arrays[0] = ary;
    for (i = 1; i < n; i++) arrays[i] = Qnil;
    for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);

    /* initialize the counters for the arrays */
    for (i = 0; i < n; i++) counters[i] = 0;

    /* Otherwise, allocate and fill in an array of results */
    if (rb_block_given_p()) {
        /* Make defensive copies of arrays; exit if any is empty */
        for (i = 0; i < n; i++) {
            if (RARRAY_LEN(arrays[i]) == 0) goto done;
            arrays[i] = ary_make_shared_copy(arrays[i]);
        }
    }
    else {
        /* Compute the length of the result array; return [] if any is empty */
        for (i = 0; i < n; i++) {
            long k = RARRAY_LEN(arrays[i]);
            if (k == 0) {
                result = rb_ary_new2(0);
                goto done;
            }
            if (MUL_OVERFLOW_LONG_P(resultlen, k))
                rb_raise(rb_eRangeError, "too big to product");
            resultlen *= k;
        }
        result = rb_ary_new2(resultlen);
    }
    for (;;) {
        int m;
        /* fill in one subarray */
        VALUE subarray = rb_ary_new2(n);
        for (j = 0; j < n; j++) {
            rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
        }

        /* put it on the result array */
        if (NIL_P(result)) {
            FL_SET(t0, FL_USER5);
            rb_yield(subarray);
            if (! FL_TEST(t0, FL_USER5)) {
                rb_raise(rb_eRuntimeError, "product reentered");
            }
            else {
                FL_UNSET(t0, FL_USER5);
            }
        }
        else {
            rb_ary_push(result, subarray);
        }

        /*
         * Increment the last counter.  If it overflows, reset to 0
         * and increment the one before it.
         */
        m = n-1;
        counters[m]++;
        while (counters[m] == RARRAY_LEN(arrays[m])) {
            counters[m] = 0;
            /* If the first counter overflows, we are done */
            if (--m < 0) goto done;
            counters[m]++;
        }
    }
done:
    tmpary_discard(t0);
    tmpbuf_discard(t1);

    return NIL_P(result) ? ary : result;
}
push(obj, ... ) → ary click to toggle source

Append — Pushes the given object(s) on to the end of this array. This expression returns the array itself, so several appends may be chained together. See also #pop for the opposite effect.

a = [ "a", "b", "c" ]
a.push("d", "e", "f")
        #=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
        #=> [1, 2, 3, 4, 5]

static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
    return rb_ary_cat(ary, argv, argc);
}
rassoc(obj) → new_ary or nil click to toggle source

Searches through the array whose elements are also arrays.

Compares obj with the second element of each contained array using obj.==.

Returns the first contained array that matches obj.

See also #assoc.

a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
a.rassoc("two")    #=> [2, "two"]
a.rassoc("four")   #=> nil

VALUE
rb_ary_rassoc(VALUE ary, VALUE value)
{
    long i;
    VALUE v;

    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        v = RARRAY_PTR(ary)[i];
        if (RB_TYPE_P(v, T_ARRAY) &&
            RARRAY_LEN(v) > 1 &&
            rb_equal(RARRAY_PTR(v)[1], value))
            return v;
    }
    return Qnil;
}
reject {|item| block } → new_ary click to toggle source
reject → Enumerator

Returns a new array containing the items in self for which the given block is not true.

See also #delete_if

If no block is given, an Enumerator is returned instead.

static VALUE
rb_ary_reject(VALUE ary)
{
    VALUE rejected_ary;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rejected_ary = rb_ary_new();
    ary_reject(ary, rejected_ary);
    return rejected_ary;
}
reject! { |item| block } → ary or nil click to toggle source
reject! → Enumerator

Equivalent to #delete_if, deleting elements from self for which the block evaluates to true, but returns nil if no changes were made.

The array is changed instantly every time the block is called, not after the iteration is over.

See also Enumerable#reject and #delete_if.

If no block is given, an Enumerator is returned instead.

static VALUE
rb_ary_reject_bang(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    return ary_reject_bang(ary);
}
repeated_combination(n) { |c| block } → ary click to toggle source
repeated_combination(n) → Enumerator

When invoked with a block, yields all repeated combinations of length n of elements from the array and then returns the array itself.

The implementation makes no guarantees about the order in which the repeated combinations are yielded.

If no block is given, an Enumerator is returned instead.

Examples:

a = [1, 2, 3]
a.repeated_combination(1).to_a  #=> [[1], [2], [3]]
a.repeated_combination(2).to_a  #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
a.repeated_combination(3).to_a  #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
                                #    [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
a.repeated_combination(4).to_a  #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
                                #    [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
                                #    [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
a.repeated_combination(0).to_a  #=> [[]] # one combination of length 0

static VALUE
rb_ary_repeated_combination(VALUE ary, VALUE num)
{
    long n, i, len;

    n = NUM2LONG(num);                 /* Combination size from argument */
    RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);   /* Return enumerator if no block */
    len = RARRAY_LEN(ary);
    if (n < 0) {
        /* yield nothing */
    }
    else if (n == 0) {
        rb_yield(rb_ary_new2(0));
    }
    else if (n == 1) {
        for (i = 0; i < len; i++) {
            rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
        }
    }
    else if (len == 0) {
        /* yield nothing */
    }
    else {
        volatile VALUE t0 = tmpbuf(n, sizeof(long));
        long *p = (long*)RSTRING_PTR(t0);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC(ary0)->klass = 0;

        rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
        tmpbuf_discard(t0);
        RBASIC(ary0)->klass = rb_cArray;
    }
    return ary;
}
repeated_permutation(n) { |p| block } → ary click to toggle source
repeated_permutation(n) → Enumerator

When invoked with a block, yield all repeated permutations of length n of the elements of the array, then return the array itself.

The implementation makes no guarantees about the order in which the repeated permutations are yielded.

If no block is given, an Enumerator is returned instead.

Examples:

a = [1, 2]
a.repeated_permutation(1).to_a  #=> [[1], [2]]
a.repeated_permutation(2).to_a  #=> [[1,1],[1,2],[2,1],[2,2]]
a.repeated_permutation(3).to_a  #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
                                #    [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
a.repeated_permutation(0).to_a  #=> [[]] # one permutation of length 0

static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
{
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);      /* Return Enumerator if no block */
    r = NUM2LONG(num);                    /* Permutation size from argument */

    if (r < 0) {
        /* no permutations: yield nothing */
    }
    else if (r == 0) { /* exactly one permutation: the zero-length array */
        rb_yield(rb_ary_new2(0));
    }
    else if (r == 1) { /* this is a special, easy case */
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
        }
    }
    else {             /* this is the general case */
        volatile VALUE t0 = tmpbuf(r, sizeof(long));
        long *p = (long*)RSTRING_PTR(t0);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC(ary0)->klass = 0;

        rpermute0(n, r, p, 0, ary0); /* compute and yield repeated permutations */
        tmpbuf_discard(t0);
        RBASIC(ary0)->klass = rb_cArray;
    }
    return ary;
}
replace(other_ary) → ary click to toggle source

Replaces the contents of self with the contents of other_ary, truncating or expanding if necessary.

a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]

VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
        VALUE *ptr;
        VALUE shared = 0;

        if (ARY_OWNS_HEAP_P(copy)) {
            xfree(RARRAY_PTR(copy));
        }
        else if (ARY_SHARED_P(copy)) {
            shared = ARY_SHARED(copy);
            FL_UNSET_SHARED(copy);
        }
        FL_SET_EMBED(copy);
        ptr = RARRAY_PTR(orig);
        MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
        if (shared) {
            rb_ary_decrement_share(shared);
        }
        ARY_SET_LEN(copy, RARRAY_LEN(orig));
    }
    else {
        VALUE shared = ary_make_shared(orig);
        if (ARY_OWNS_HEAP_P(copy)) {
            xfree(RARRAY_PTR(copy));
        }
        else {
            rb_ary_unshare_safe(copy);
        }
        FL_UNSET_EMBED(copy);
        ARY_SET_PTR(copy, RARRAY_PTR(orig));
        ARY_SET_LEN(copy, RARRAY_LEN(orig));
        rb_ary_set_shared(copy, shared);
    }
    return copy;
}
reverse → new_ary click to toggle source

Returns a new array containing self's elements in reverse order.

[ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
[ 1 ].reverse               #=> [1]

static VALUE
rb_ary_reverse_m(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    VALUE dup = rb_ary_new2(len);

    if (len > 0) {
        VALUE *p1 = RARRAY_PTR(ary);
        VALUE *p2 = RARRAY_PTR(dup) + len - 1;
        do *p2-- = *p1++; while (--len > 0);
    }
    ARY_SET_LEN(dup, RARRAY_LEN(ary));
    return dup;
}
reverse! → ary click to toggle source

Reverses self in place.

a = [ "a", "b", "c" ]
a.reverse!       #=> ["c", "b", "a"]
a                #=> ["c", "b", "a"]

static VALUE
rb_ary_reverse_bang(VALUE ary)
{
    return rb_ary_reverse(ary);
}
reverse_each { |item| block } → ary click to toggle source
reverse_each → Enumerator

Same as #each, but traverses self in reverse order.

a = [ "a", "b", "c" ]
a.reverse_each {|x| print x, " " }

produces:

c b a
static VALUE
rb_ary_reverse_each(VALUE ary)
{
    long len;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    len = RARRAY_LEN(ary);
    while (len--) {
        rb_yield(RARRAY_PTR(ary)[len]);
        if (RARRAY_LEN(ary) < len) {
            len = RARRAY_LEN(ary);
        }
    }
    return ary;
}
rindex(obj) → int or nil click to toggle source
rindex { |item| block } → int or nil
rindex → Enumerator

Returns the index of the last object in self == to obj.

If a block is given instead of an argument, returns the index of the first object for which the block returns true, starting from the last object.

Returns nil if no match is found.

See also #index.

If neither block nor argument is given, an Enumerator is returned instead.

a = [ "a", "b", "b", "b", "c" ]
a.rindex("b")             #=> 3
a.rindex("z")             #=> nil
a.rindex { |x| x == "b" } #=> 3

static VALUE
rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
{
    VALUE val;
    long i = RARRAY_LEN(ary);

    if (argc == 0) {
        RETURN_ENUMERATOR(ary, 0, 0);
        while (i--) {
            if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
                return LONG2NUM(i);
            if (i > RARRAY_LEN(ary)) {
                i = RARRAY_LEN(ary);
            }
        }
        return Qnil;
    }
    rb_scan_args(argc, argv, "1", &val);
    if (rb_block_given_p())
        rb_warn("given block not used");
    while (i--) {
        if (rb_equal(RARRAY_PTR(ary)[i], val))
            return LONG2NUM(i);
        if (i > RARRAY_LEN(ary)) {
            i = RARRAY_LEN(ary);
        }
    }
    return Qnil;
}
rotate(count=1) → new_ary click to toggle source

Returns a new array by rotating self so that the element at count is the first element of the new array.

If count is negative then it rotates in the opposite direction, starting from the end of self where -1 is the last element.

a = [ "a", "b", "c", "d" ]
a.rotate         #=> ["b", "c", "d", "a"]
a                #=> ["a", "b", "c", "d"]
a.rotate(2)      #=> ["c", "d", "a", "b"]
a.rotate(-3)     #=> ["b", "c", "d", "a"]

static VALUE
rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE rotated, *ptr, *ptr2;
    long len, cnt = 1;

    switch (argc) {
      case 1: cnt = NUM2LONG(argv[0]);
      case 0: break;
      default: rb_scan_args(argc, argv, "01", NULL);
    }

    len = RARRAY_LEN(ary);
    rotated = rb_ary_new2(len);
    if (len > 0) {
        cnt = rotate_count(cnt, len);
        ptr = RARRAY_PTR(ary);
        ptr2 = RARRAY_PTR(rotated);
        len -= cnt;
        MEMCPY(ptr2, ptr + cnt, VALUE, len);
        MEMCPY(ptr2 + len, ptr, VALUE, cnt);
    }
    ARY_SET_LEN(rotated, RARRAY_LEN(ary));
    return rotated;
}
rotate!(count=1) → ary click to toggle source

Rotates self in place so that the element at count comes first, and returns self.

If count is negative then it rotates in the opposite direction, starting from the end of the array where -1 is the last element.

a = [ "a", "b", "c", "d" ]
a.rotate!        #=> ["b", "c", "d", "a"]
a                #=> ["b", "c", "d", "a"]
a.rotate!(2)     #=> ["d", "a", "b", "c"]
a.rotate!(-3)    #=> ["a", "b", "c", "d"]

static VALUE
rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
{
    long n = 1;

    switch (argc) {
      case 1: n = NUM2LONG(argv[0]);
      case 0: break;
      default: rb_scan_args(argc, argv, "01", NULL);
    }
    rb_ary_rotate(ary, n);
    return ary;
}
sample → obj click to toggle source
sample(random: rng) → obj
sample(n) → new_ary
sample(n, random: rng) → new_ary

Choose a random element or n random elements from the array.

The elements are chosen by using random and unique indices into the array in order to ensure that an element doesn't repeat itself unless the array already contained duplicate elements.

If the array is empty the first form returns nil and the second form returns an empty array.

The optional rng argument will be used as the random number generator.

a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
a.sample         #=> 7
a.sample(4)      #=> [6, 4, 2, 5]

static VALUE
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
{
    VALUE nv, result, *ptr;
    VALUE opts, randgen = rb_cRandom;
    long n, len, i, j, k, idx[10];
    long rnds[numberof(idx)];

    if (OPTHASH_GIVEN_P(opts)) {
        randgen = rb_hash_lookup2(opts, sym_random, randgen);
    }
    ptr = RARRAY_PTR(ary);
    len = RARRAY_LEN(ary);
    if (argc == 0) {
        if (len == 0) return Qnil;
        if (len == 1) {
            i = 0;
        }
        else {
            i = RAND_UPTO(len);
            if ((len = RARRAY_LEN(ary)) <= i) return Qnil;
            ptr = RARRAY_PTR(ary);
        }
        return ptr[i];
    }
    rb_scan_args(argc, argv, "1", &nv);
    n = NUM2LONG(nv);
    if (n < 0) rb_raise(rb_eArgError, "negative sample number");
    if (n > len) n = len;
    if (n <= numberof(idx)) {
        for (i = 0; i < n; ++i) {
            rnds[i] = RAND_UPTO(len - i);
        }
    }
    k = len;
    len = RARRAY_LEN(ary);
    ptr = RARRAY_PTR(ary);
    if (len < k) {
        if (n <= numberof(idx)) {
            for (i = 0; i < n; ++i) {
                if (rnds[i] >= len) {
                    return rb_ary_new2(0);
                }
            }
        }
    }
    if (n > len) n = len;
    switch (n) {
      case 0:
        return rb_ary_new2(0);
      case 1:
        i = rnds[0];
        return rb_ary_new4(1, &ptr[i]);
      case 2:
        i = rnds[0];
        j = rnds[1];
        if (j >= i) j++;
        return rb_ary_new3(2, ptr[i], ptr[j]);
      case 3:
        i = rnds[0];
        j = rnds[1];
        k = rnds[2];
        {
            long l = j, g = i;
            if (j >= i) l = i, g = ++j;
            if (k >= l && (++k >= g)) ++k;
        }
        return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
    }
    if (n <= numberof(idx)) {
        VALUE *ptr_result;
        long sorted[numberof(idx)];
        sorted[0] = idx[0] = rnds[0];
        for (i=1; i<n; i++) {
            k = rnds[i];
            for (j = 0; j < i; ++j) {
                if (k < sorted[j]) break;
                ++k;
            }
            memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
            sorted[j] = idx[i] = k;
        }
        result = rb_ary_new2(n);
        ptr_result = RARRAY_PTR(result);
        for (i=0; i<n; i++) {
            ptr_result[i] = ptr[idx[i]];
        }
    }
    else {
        VALUE *ptr_result;
        result = rb_ary_new4(len, ptr);
        RBASIC(result)->klass = 0;
        ptr_result = RARRAY_PTR(result);
        RB_GC_GUARD(ary);
        for (i=0; i<n; i++) {
            j = RAND_UPTO(len-i) + i;
            nv = ptr_result[j];
            ptr_result[j] = ptr_result[i];
            ptr_result[i] = nv;
        }
        RBASIC(result)->klass = rb_cArray;
    }
    ARY_SET_LEN(result, n);

    return result;
}
select { |item| block } → new_ary click to toggle source
select → Enumerator

Returns a new array containing all elements of ary for which the given block returns a true value.

If no block is given, an Enumerator is returned instead.

[1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]

a = %w{ a b c d e f }
a.select { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]

See also Enumerable#select.

static VALUE
rb_ary_select(VALUE ary)
{
    VALUE result;
    long i;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    result = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
            rb_ary_push(result, rb_ary_elt(ary, i));
        }
    }
    return result;
}
select! {|item| block } → ary or nil click to toggle source
select! → Enumerator

Invokes the given block passing in successive elements from self, deleting elements for which the block returns a false value.

If changes were made, it will return self, otherwise it returns nil.

See also #keep_if

If no block is given, an Enumerator is returned instead.

static VALUE
rb_ary_select_bang(VALUE ary)
{
    long i1, i2;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rb_ary_modify(ary);
    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
        VALUE v = RARRAY_PTR(ary)[i1];
        if (!RTEST(rb_yield(v))) continue;
        if (i1 != i2) {
            rb_ary_store(ary, i2, v);
        }
        i2++;
    }

    if (RARRAY_LEN(ary) == i2) return Qnil;
    if (i2 < RARRAY_LEN(ary))
        ARY_SET_LEN(ary, i2);
    return ary;
}
shift → obj or nil click to toggle source
shift(n) → new_ary

Removes the first element of self and returns it (shifting all other elements down by one). Returns nil if the array is empty.

If a number n is given, returns an array of the first n elements (or less) just like array.slice!(0, n) does. With ary containing only the remainder elements, not including what was shifted to new_ary. See also #unshift for the opposite effect.

args = [ "-m", "-q", "filename" ]
args.shift     #=> "-m"
args           #=> ["-q", "filename"]

args = [ "-m", "-q", "filename" ]
args.shift(2)  #=> ["-m", "-q"]
args           #=> ["filename"]

static VALUE
rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE result;
    long n;

    if (argc == 0) {
        return rb_ary_shift(ary);
    }

    rb_ary_modify_check(ary);
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    n = RARRAY_LEN(result);
    if (ARY_SHARED_P(ary)) {
        if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
            rb_mem_clear(RARRAY_PTR(ary), n);
        }
        ARY_INCREASE_PTR(ary, n);
    }
    else {
        MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
    }
    ARY_INCREASE_LEN(ary, -n);

    return result;
}
shuffle → new_ary click to toggle source
shuffle(random: rng) → new_ary

Returns a new array with elements of self shuffled.

a = [ 1, 2, 3 ]           #=> [1, 2, 3]
a.shuffle                 #=> [2, 3, 1]

The optional rng argument will be used as the random number generator.

a.shuffle(random: Random.new(1))  #=> [1, 3, 2]

static VALUE
rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_shuffle_bang(argc, argv, ary);
    return ary;
}
shuffle! → ary click to toggle source
shuffle!(random: rng) → ary

Shuffles elements in self in place.

The optional rng argument will be used as the random number generator.

static VALUE
rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE *ptr, opts, *snap_ptr, randgen = rb_cRandom;
    long i, snap_len;

    if (OPTHASH_GIVEN_P(opts)) {
        randgen = rb_hash_lookup2(opts, sym_random, randgen);
    }
    rb_check_arity(argc, 0, 0);
    rb_ary_modify(ary);
    i = RARRAY_LEN(ary);
    ptr = RARRAY_PTR(ary);
    snap_len = i;
    snap_ptr = ptr;
    while (i) {
        long j = RAND_UPTO(i);
        VALUE tmp;
        if (snap_len != RARRAY_LEN(ary) || snap_ptr != RARRAY_PTR(ary)) {
            rb_raise(rb_eRuntimeError, "modified during shuffle");
        }
        tmp = ptr[--i];
        ptr[i] = ptr[j];
        ptr[j] = tmp;
    }
    return ary;
}
size() click to toggle source
Alias for: length
ary[index] → obj or nil click to toggle source
ary[start, length] → new_ary or nil
ary[range] → new_ary or nil
slice(index) → obj or nil
slice(start, length) → new_ary or nil
slice(range) → new_ary or nil

Element Reference — Returns the element at index, or returns a subarray starting at the start index and continuing for length elements, or returns a subarray specified by range of indices.

Negative indices count backward from the end of the array (-1 is the last element). For start and range cases the starting index is just before an element. Additionally, an empty array is returned when the starting index for an element range is at the end of the array.

Returns nil if the index (or starting index) are out of range.

a = [ "a", "b", "c", "d", "e" ]
a[2] +  a[0] + a[1]    #=> "cab"
a[6]                   #=> nil
a[1, 2]                #=> [ "b", "c" ]
a[1..3]                #=> [ "b", "c", "d" ]
a[4..7]                #=> [ "e" ]
a[6..10]               #=> nil
a[-3, 3]               #=> [ "c", "d", "e" ]
# special cases
a[5]                   #=> nil
a[6, 1]                #=> nil
a[5, 1]                #=> []
a[5..10]               #=> []

VALUE
rb_ary_aref(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg;
    long beg, len;

    if (argc == 2) {
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        if (beg < 0) {
            beg += RARRAY_LEN(ary);
        }
        return rb_ary_subseq(ary, beg, len);
    }
    if (argc != 1) {
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    arg = argv[0];
    /* special case - speeding up */
    if (FIXNUM_P(arg)) {
        return rb_ary_entry(ary, FIX2LONG(arg));
    }
    /* check if idx is Range */
    switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
      case Qfalse:
        break;
      case Qnil:
        return Qnil;
      default:
        return rb_ary_subseq(ary, beg, len);
    }
    return rb_ary_entry(ary, NUM2LONG(arg));
}
slice!(index) → obj or nil click to toggle source
slice!(start, length) → new_ary or nil
slice!(range) → new_ary or nil

Deletes the element(s) given by an index (optionally up to length elements) or by a range.

Returns the deleted object (or objects), or nil if the index is out of range.

a = [ "a", "b", "c" ]
a.slice!(1)     #=> "b"
a               #=> ["a", "c"]
a.slice!(-1)    #=> "c"
a               #=> ["a"]
a.slice!(100)   #=> nil
a               #=> ["a"]

static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg1, arg2;
    long pos, len, orig_len;

    rb_ary_modify_check(ary);
    if (argc == 2) {
        pos = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
      delete_pos_len:
        if (len < 0) return Qnil;
        orig_len = RARRAY_LEN(ary);
        if (pos < 0) {
            pos += orig_len;
            if (pos < 0) return Qnil;
        }
        else if (orig_len < pos) return Qnil;
        if (orig_len < pos + len) {
            len = orig_len - pos;
        }
        if (len == 0) return rb_ary_new2(0);
        arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
        RBASIC(arg2)->klass = rb_obj_class(ary);
        rb_ary_splice(ary, pos, len, Qundef);
        return arg2;
    }

    if (argc != 1) {
        /* error report */
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    arg1 = argv[0];

    if (!FIXNUM_P(arg1)) {
        switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
          case Qtrue:
            /* valid range */
            goto delete_pos_len;
          case Qnil:
            /* invalid range */
            return Qnil;
          default:
            /* not a range */
            break;
        }
    }

    return rb_ary_delete_at(ary, NUM2LONG(arg1));
}
sort → new_ary click to toggle source
sort { |a, b| block } → new_ary

Returns a new array created by sorting self.

Comparisons for the sort will be done using the <=> operator or using an optional code block.

The block must implement a comparison between a and b, and return -1, when a follows b, 0 when a and b are equivalent, or +1 if b follows a.

See also Enumerable#sort_by.

a = [ "d", "a", "e", "c", "b" ]
a.sort                    #=> ["a", "b", "c", "d", "e"]
a.sort { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]

VALUE
rb_ary_sort(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_sort_bang(ary);
    return ary;
}
sort! → ary click to toggle source
sort! { |a, b| block } → ary

Sorts self in place.

Comparisons for the sort will be done using the <=> operator or using an optional code block.

The block must implement a comparison between a and b, and return -1, when a follows b, 0 when a and b are equivalent, or +1 if b follows a.

See also Enumerable#sort_by.

a = [ "d", "a", "e", "c", "b" ]
a.sort!                    #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]

VALUE
rb_ary_sort_bang(VALUE ary)
{
    rb_ary_modify(ary);
    assert(!ARY_SHARED_P(ary));
    if (RARRAY_LEN(ary) > 1) {
        VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
        struct ary_sort_data data;
        long len = RARRAY_LEN(ary);

        RBASIC(tmp)->klass = 0;
        data.ary = tmp;
        data.opt_methods = 0;
        data.opt_inited = 0;
        ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE),
                   rb_block_given_p()?sort_1:sort_2, &data);

        if (ARY_EMBED_P(tmp)) {
            assert(ARY_EMBED_P(tmp));
            if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
                rb_ary_unshare(ary);
            }
            FL_SET_EMBED(ary);
            MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
            ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
        }
        else {
            assert(!ARY_EMBED_P(tmp));
            if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
                assert(!ARY_EMBED_P(ary));
                FL_UNSET_SHARED(ary);
                ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
            }
            else {
                assert(!ARY_SHARED_P(tmp));
                if (ARY_EMBED_P(ary)) {
                    FL_UNSET_EMBED(ary);
                }
                else if (ARY_SHARED_P(ary)) {
                    /* ary might be destructively operated in the given block */
                    rb_ary_unshare(ary);
                }
                else {
                    xfree(ARY_HEAP_PTR(ary));
                }
                ARY_SET_PTR(ary, RARRAY_PTR(tmp));
                ARY_SET_HEAP_LEN(ary, len);
                ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
            }
            /* tmp was lost ownership for the ptr */
            FL_UNSET(tmp, FL_FREEZE);
            FL_SET_EMBED(tmp);
            ARY_SET_EMBED_LEN(tmp, 0);
            FL_SET(tmp, FL_FREEZE);
        }
        /* tmp will be GC'ed. */
        RBASIC(tmp)->klass = rb_cArray;
    }
    return ary;
}
sort_by! { |obj| block } → ary click to toggle source
sort_by! → Enumerator

Sorts self in place using a set of keys generated by mapping the values in self through the given block.

If no block is given, an Enumerator is returned instead.

static VALUE
rb_ary_sort_by_bang(VALUE ary)
{
    VALUE sorted;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
    rb_ary_modify(ary);
    sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
    rb_ary_replace(ary, sorted);
    return ary;
}
take(n) → new_ary click to toggle source

Returns first n elements from the array.

If a negative number is given, raises an ArgumentError.

See also #drop

a = [1, 2, 3, 4, 5, 0]
a.take(3)             #=> [1, 2, 3]

static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    return rb_ary_subseq(obj, 0, len);
}
take_while { |arr| block } → new_ary click to toggle source
take_while → Enumerator

Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements.

If no block is given, an Enumerator is returned instead.

See also #drop_while

a = [1, 2, 3, 4, 5, 0]
a.take_while { |i| i < 3 }  #=> [1, 2]

static VALUE
rb_ary_take_while(VALUE ary)
{
    long i;

    RETURN_ENUMERATOR(ary, 0, 0);
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
    }
    return rb_ary_take(ary, LONG2FIX(i));
}
to_a → ary click to toggle source

Returns self.

If called on a subclass of Array, converts the receiver to an Array object.

static VALUE
rb_ary_to_a(VALUE ary)
{
    if (rb_obj_class(ary) != rb_cArray) {
        VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
        rb_ary_replace(dup, ary);
        return dup;
    }
    return ary;
}
to_ary → ary click to toggle source

Returns self.

static VALUE
rb_ary_to_ary_m(VALUE ary)
{
    return ary;
}
to_s() click to toggle source
Alias for: inspect
transpose → new_ary click to toggle source

Assumes that self is an array of arrays and transposes the rows and columns.

a = [[1,2], [3,4], [5,6]]
a.transpose   #=> [[1, 3, 5], [2, 4, 6]]

If the length of the subarrays don't match, an IndexError is raised.

static VALUE
rb_ary_transpose(VALUE ary)
{
    long elen = -1, alen, i, j;
    VALUE tmp, result = 0;

    alen = RARRAY_LEN(ary);
    if (alen == 0) return rb_ary_dup(ary);
    for (i=0; i<alen; i++) {
        tmp = to_ary(rb_ary_elt(ary, i));
        if (elen < 0) {                /* first element */
            elen = RARRAY_LEN(tmp);
            result = rb_ary_new2(elen);
            for (j=0; j<elen; j++) {
                rb_ary_store(result, j, rb_ary_new2(alen));
            }
        }
        else if (elen != RARRAY_LEN(tmp)) {
            rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
                     RARRAY_LEN(tmp), elen);
        }
        for (j=0; j<elen; j++) {
            rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
        }
    }
    return result;
}
uniq → new_ary click to toggle source
uniq { |item| ... } → new_ary

Returns a new array by removing duplicate values in self.

If a block is given, it will use the return value of the block for comparison.

It compares values using their hash and eql? methods for efficiency.

a = [ "a", "a", "b", "b", "c" ]
a.uniq   # => ["a", "b", "c"]

b = [["student","sam"], ["student","george"], ["teacher","matz"]]
b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]

static VALUE
rb_ary_uniq(VALUE ary)
{
    VALUE hash, uniq, v;
    long i;

    if (RARRAY_LEN(ary) <= 1)
        return rb_ary_dup(ary);
    if (rb_block_given_p()) {
        hash = ary_make_hash_by(ary);
        uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
        st_foreach(RHASH_TBL(hash), push_value, uniq);
    }
    else {
        hash = ary_make_hash(ary);
        uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
        for (i=0; i<RARRAY_LEN(ary); i++) {
            st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
            if (st_delete(RHASH_TBL(hash), &vv, 0)) {
                rb_ary_push(uniq, v);
            }
        }
    }
    ary_recycle_hash(hash);

    return uniq;
}
uniq! → ary or nil click to toggle source
uniq! { |item| ... } → ary or nil

Removes duplicate elements from self.

If a block is given, it will use the return value of the block for comparison.

It compares values using their hash and eql? methods for efficiency.

Returns nil if no changes are made (that is, no duplicates are found).

a = [ "a", "a", "b", "b", "c" ]
a.uniq!   # => ["a", "b", "c"]

b = [ "a", "b", "c" ]
b.uniq!   # => nil

c = [["student","sam"], ["student","george"], ["teacher","matz"]]
c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]

static VALUE
rb_ary_uniq_bang(VALUE ary)
{
    VALUE hash, v;
    long i, j;

    rb_ary_modify_check(ary);
    if (RARRAY_LEN(ary) <= 1)
        return Qnil;
    if (rb_block_given_p()) {
        hash = ary_make_hash_by(ary);
        if (RARRAY_LEN(ary) == (i = RHASH_SIZE(hash))) {
            return Qnil;
        }
        ARY_SET_LEN(ary, 0);
        if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
            rb_ary_unshare(ary);
            FL_SET_EMBED(ary);
        }
        ary_resize_capa(ary, i);
        st_foreach(RHASH_TBL(hash), push_value, ary);
    }
    else {
        hash = ary_make_hash(ary);
        if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
            return Qnil;
        }
        for (i=j=0; i<RARRAY_LEN(ary); i++) {
            st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
            if (st_delete(RHASH_TBL(hash), &vv, 0)) {
                rb_ary_store(ary, j++, v);
            }
        }
        ARY_SET_LEN(ary, j);
    }
    ary_recycle_hash(hash);

    return ary;
}
unshift(obj, ...) → ary click to toggle source

Prepends objects to the front of self, moving other elements upwards. See also #shift for the opposite effect.

a = [ "b", "c", "d" ]
a.unshift("a")   #=> ["a", "b", "c", "d"]
a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]

static VALUE
rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
{
    long len = RARRAY_LEN(ary);

    if (argc == 0) {
        rb_ary_modify_check(ary);
        return ary;
    }

    ary_ensure_room_for_unshift(ary, argc);
    MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
    ARY_SET_LEN(ary, len + argc);
    return ary;
}
values_at(selector, ...) → new_ary click to toggle source

Returns an array containing the elements in self corresponding to the given selector(s).

The selectors may be either integer indices or ranges.

See also #select.

a = %w{ a b c d e f }
a.values_at(1, 3, 5)          # => ["b", "d", "f"]
a.values_at(1, 3, 5, 7)       # => ["b", "d", "f", nil]
a.values_at(-1, -2, -2, -7)   # => ["f", "e", "e", nil]
a.values_at(4..6, 3...6)      # => ["e", "f", nil, "d", "e", "f"]

static VALUE
rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
{
    return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
}
zip(arg, ...) → new_ary click to toggle source
zip(arg, ...) { |arr| block } → nil

Converts any arguments to arrays, then merges elements of self with corresponding elements from each argument.

This generates a sequence of ary.size n-element arrays, where n is one more than the count of arguments.

If the size of any argument is less than the size of the initial array, nil values are supplied.

If a block is given, it is invoked for each output array, otherwise an array of arrays is returned.

a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
[1, 2, 3].zip(a, b)   #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8])    #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]

static VALUE
rb_ary_zip(int argc, VALUE *argv, VALUE ary)
{
    int i, j;
    long len;
    VALUE result = Qnil;

    len = RARRAY_LEN(ary);
    for (i=0; i<argc; i++) {
        argv[i] = take_items(argv[i], len);
    }
    if (!rb_block_given_p()) {
        result = rb_ary_new2(len);
    }

    for (i=0; i<RARRAY_LEN(ary); i++) {
        VALUE tmp = rb_ary_new2(argc+1);

        rb_ary_push(tmp, rb_ary_elt(ary, i));
        for (j=0; j<argc; j++) {
            rb_ary_push(tmp, rb_ary_elt(argv[j], i));
        }
        if (NIL_P(result)) {
            rb_yield(tmp);
        }
        else {
            rb_ary_push(result, tmp);
        }
    }
    return result;
}
ary | other_ary → new_ary click to toggle source

Set Union — Returns a new array by joining ary with other_ary, excluding any duplicates and preserving the order from the original array.

It compares elements using their hash and eql? methods for efficiency.

[ "a", "b", "c" ] | [ "c", "d", "a" ]    #=> [ "a", "b", "c", "d" ]

See also #uniq.

static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
    hash = ary_add_hash(ary_make_hash(ary1), ary2);

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        vv = (st_data_t)(v = rb_ary_elt(ary1, i));
        if (st_delete(RHASH_TBL(hash), &vv, 0)) {
            rb_ary_push(ary3, v);
        }
    }
    for (i=0; i<RARRAY_LEN(ary2); i++) {
        vv = (st_data_t)(v = rb_ary_elt(ary2, i));
        if (st_delete(RHASH_TBL(hash), &vv, 0)) {
            rb_ary_push(ary3, v);
        }
    }
    ary_recycle_hash(hash);
    return ary3;
}


class BasicObject - Ruby 2.0.0-p576 Core API Reference API Reference

class BasicObject

BasicObject is the parent class of all classes in Ruby. It's an explicit blank class.

BasicObject can be used for creating object hierarchies independent of Ruby's object hierarchy, proxy objects like the Delegator class, or other uses where namespace pollution from Ruby's methods and classes must be avoided.

To avoid polluting BasicObject for other users an appropriately named subclass of BasicObject should be created instead of directly modifying BasicObject:

class MyObjectSystem < BasicObject
end

BasicObject does not include Kernel (for methods like puts) and BasicObject is outside of the namespace of the standard library so common classes will not be found without a using a full class path.

A variety of strategies can be used to provide useful portions of the standard library to subclasses of BasicObject. A subclass could include Kernel to obtain puts, exit, etc. A custom Kernel-like module could be created and included or delegation can be used via method_missing:

class MyObjectSystem < BasicObject
  DELEGATE = [:puts, :p]

  def method_missing(name, *args, &block)
    super unless DELEGATE.include? name
    ::Kernel.send(name, *args, &block)
  end

  def respond_to_missing?(name, include_private = false)
    DELEGATE.include?(name) or super
  end
end

Access to classes and modules from the Ruby standard library can be obtained in a BasicObject subclass by referencing the desired constant from the root like ::File or ::Enumerator. Like method_missing, const_missing can be used to delegate constant lookup to Object:

class MyObjectSystem < BasicObject
  def self.const_missing(name)
    ::Object.const_get(name)
  end
end

In Files

  • class.c
  • gc.c
  • object.c
  • vm_eval.c

Parent

Public Class Methods

new() click to toggle source

Not documented

static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

Public Instance Methods

!obj → true or false click to toggle source

Boolean negate.

VALUE
rb_obj_not(VALUE obj)
{
    return RTEST(obj) ? Qfalse : Qtrue;
}
obj != other → true or false click to toggle source

Returns true if two objects are not-equal, otherwise false.

VALUE
rb_obj_not_equal(VALUE obj1, VALUE obj2)
{
    VALUE result = rb_funcall(obj1, id_eq, 1, obj2);
    return RTEST(result) ? Qfalse : Qtrue;
}
obj == other → true or false click to toggle source
equal?(other) → true or false
eql?(other) → true or false

Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

Unlike ==, the equal? method should never be overridden by subclasses as it is used to determine object identity (that is, a.equal?(b) if and only if a is the same object as b):

obj = "a"
other = obj.dup

a == other      #=> true
a.equal? other  #=> false
a.equal? a      #=> true

The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}
__id__ → integer click to toggle source
object_id → integer

Returns an integer identifier for obj.

The same number will be returned on all calls to id for a given object, and no two active objects will share an id.

Object#object_id is a different concept from the :name notation, which returns the symbol id of name.

Replaces the deprecated Object#id.

VALUE
rb_obj_id(VALUE obj)
{
    /*
     *                32-bit VALUE space
     *          MSB ------------------------ LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol  ssssssssssssssssssssssss00001110
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
     *  fixnum  fffffffffffffffffffffffffffffff1
     *
     *                    object_id space
     *                                       LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
     *
     *  where A = sizeof(RVALUE)/4
     *
     *  sizeof(RVALUE) is
     *  20 if 32-bit, double is 4-byte aligned
     *  24 if 32-bit, double is 8-byte aligned
     *  40 if 64-bit
     */
    if (SYMBOL_P(obj)) {
        return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
    }
    else if (FLONUM_P(obj)) {
#if SIZEOF_LONG == SIZEOF_VOIDP
        return LONG2NUM((SIGNED_VALUE)obj);
#else
        return LL2NUM((SIGNED_VALUE)obj);
#endif
    }
    else if (SPECIAL_CONST_P(obj)) {
        return LONG2NUM((SIGNED_VALUE)obj);
    }
    return nonspecial_obj_id(obj);
}
send(symbol [, args...]) → obj click to toggle source
__send__(symbol [, args...]) → obj

Invokes the method identified by symbol, passing it any arguments specified. You can use __send__ if the name send clashes with an existing method in obj.

class Klass
  def hello(*args)
    "Hello " + args.join(' ')
  end
end
k = Klass.new
k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"

VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal(argc, argv, recv, CALL_FCALL);
}
obj == other → true or false click to toggle source
equal?(other) → true or false
eql?(other) → true or false

Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

Unlike ==, the equal? method should never be overridden by subclasses as it is used to determine object identity (that is, a.equal?(b) if and only if a is the same object as b):

obj = "a"
other = obj.dup

a == other      #=> true
a.equal? other  #=> false
a.equal? a      #=> true

The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}
instance_eval(string [, filename [, lineno]] ) → obj click to toggle source
instance_eval {| | block } → obj

Evaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj's instance variables. In the version of instance_eval that takes a String, the optional second and third parameters supply a filename and starting line number that are used when reporting compilation errors.

class KlassWithSecret
  def initialize
    @secret = 99
  end
end
k = KlassWithSecret.new
k.instance_eval { @secret }   #=> 99

VALUE
rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
{
    VALUE klass;

    if (SPECIAL_CONST_P(self)) {
        klass = rb_special_singleton_class(self);
    }
    else {
        klass = rb_singleton_class(self);
    }
    return specific_eval(argc, argv, klass, self);
}
instance_exec(arg...) {|var...| block } → obj click to toggle source

Executes the given block within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj's instance variables. Arguments are passed as block parameters.

class KlassWithSecret
  def initialize
    @secret = 99
  end
end
k = KlassWithSecret.new
k.instance_exec(5) {|x| @secret+x }   #=> 104

VALUE
rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
{
    VALUE klass;

    if (SPECIAL_CONST_P(self)) {
        klass = rb_special_singleton_class(self);
    }
    else {
        klass = rb_singleton_class(self);
    }
    return yield_under(klass, self, rb_ary_new4(argc, argv));
}


class Bignum - Ruby 2.0.0-p576 Core API Reference API Reference

class Bignum

Bignum objects hold integers outside the range of Fixnum. Bignum objects are created automatically when integer calculations would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted.

For the purposes of the bitwise operations and [], a Bignum is treated as if it were an infinite-length bitstring with 2's complement representation.

While Fixnum values are immediate, Bignum objects are not—assignment and parameter passing work with references to objects, not the objects themselves.

In Files

  • bignum.c

Parent

Integer

Public Instance Methods

big % other → Numeric click to toggle source
modulo(other) → Numeric

Returns big modulo other. See Numeric#divmod for more information.

VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}
big & numeric → integer click to toggle source

Performs bitwise and between big and numeric.

VALUE
rb_big_and(VALUE xx, VALUE yy)
{
    volatile VALUE x, y, z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '&');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigand_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] & ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?0:ds2[i];
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);
    return bignorm(z);
}
big * other → Numeric click to toggle source

Multiplies big and other, returning the result.

VALUE
rb_big_mul(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '*');
    }

    return bignorm(bigmul0(x, y));
}
big ** exponent → numeric click to toggle source

Raises big to the exponent power (which may be an integer, float, or anything that will coerce to a number). The result may be a Fixnum, Bignum, or Float

123456789 ** 2      #=> 15241578750190521
123456789 ** 1.2    #=> 5126464716.09932
123456789 ** -2     #=> 6.5610001194102e-17

VALUE
rb_big_pow(VALUE x, VALUE y)
{
    double d;
    SIGNED_VALUE yy;

    if (y == INT2FIX(0)) return INT2FIX(1);
    switch (TYPE(y)) {
      case T_FLOAT:
        d = RFLOAT_VALUE(y);
        if ((!RBIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
            return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
        break;

      case T_BIGNUM:
        rb_warn("in a**b, b may be too big");
        d = rb_big2dbl(y);
        break;

      case T_FIXNUM:
        yy = FIX2LONG(y);

        if (yy < 0)
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
        else {
            VALUE z = 0;
            SIGNED_VALUE mask;
            const long xlen = RBIGNUM_LEN(x) - 1;
            const long xbits = ffs(RBIGNUM_DIGITS(x)[xlen]) + SIZEOF_BDIGITS*BITSPERDIG*xlen;
            const long BIGLEN_LIMIT = BITSPERDIG*1024*1024;

            if ((xbits > BIGLEN_LIMIT) || (xbits * yy > BIGLEN_LIMIT)) {
                rb_warn("in a**b, b may be too big");
                d = (double)yy;
                break;
            }
            for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
                if (z) z = bigsqr(z);
                if (yy & mask) {
                    z = z ? bigtrunc(bigmul0(z, x)) : x;
                }
            }
            return bignorm(z);
        }
        /* NOTREACHED */
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
    return DBL2NUM(pow(rb_big2dbl(x), d));
}
big + other → Numeric click to toggle source

Adds big and other, returning the result.

VALUE
rb_big_plus(VALUE x, VALUE y)
{
    long n;

    switch (TYPE(y)) {
      case T_FIXNUM:
        n = FIX2LONG(y);
        if ((n > 0) != RBIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigsub_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigadd_int(x, n);

      case T_BIGNUM:
        return bignorm(bigadd(x, y, 1));

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
big - other → Numeric click to toggle source

Subtracts other from big, returning the result.

VALUE
rb_big_minus(VALUE x, VALUE y)
{
    long n;

    switch (TYPE(y)) {
      case T_FIXNUM:
        n = FIX2LONG(y);
        if ((n > 0) != RBIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigadd_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigsub_int(x, n);

      case T_BIGNUM:
        return bignorm(bigadd(x, y, 0));

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
-big → integer click to toggle source

Unary minus (returns an integer whose value is 0-big)

VALUE
rb_big_uminus(VALUE x)
{
    VALUE z = rb_big_clone(x);

    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));

    return bignorm(z);
}
big / other → Numeric click to toggle source

Performs division: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

VALUE
rb_big_div(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, '/');
}
big < real → true or false click to toggle source

Returns true if the value of big is less than that of real.

static VALUE
big_lt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_lt);
}
big << numeric → integer click to toggle source

Shifts big left numeric positions (right if numeric is negative).

VALUE
rb_big_lshift(VALUE x, VALUE y)
{
    long shift;
    int neg = 0;

    for (;;) {
        if (FIXNUM_P(y)) {
            shift = FIX2LONG(y);
            if (shift < 0) {
                neg = 1;
                shift = -shift;
            }
            break;
        }
        else if (RB_TYPE_P(y, T_BIGNUM)) {
            if (!RBIGNUM_SIGN(y)) {
                VALUE t = check_shiftdown(y, x);
                if (!NIL_P(t)) return t;
                neg = 1;
            }
            shift = big2ulong(y, "long", TRUE);
            break;
        }
        y = rb_to_int(y);
    }

    x = neg ? big_rshift(x, shift) : big_lshift(x, shift);
    return bignorm(x);
}
big <= real → true or false click to toggle source

Returns true if the value of big is less than or equal to that of real.

static VALUE
big_le(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_le);
}
big <=> numeric → -1, 0, +1 or nil click to toggle source

Comparison—Returns -1, 0, or +1 depending on whether big is less than, equal to, or greater than numeric. This is the basis for the tests in Comparable.

nil is returned if the two values are incomparable.

VALUE
rb_big_cmp(VALUE x, VALUE y)
{
    long xlen = RBIGNUM_LEN(x);
    BDIGIT *xds, *yds;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      case T_FLOAT:
        return rb_integer_float_cmp(x, y);

      default:
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }

    if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
    if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
    if (xlen < RBIGNUM_LEN(y))
        return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
    if (xlen > RBIGNUM_LEN(y))
        return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);

    xds = BDIGITS(x);
    yds = BDIGITS(y);

    while (xlen-- && (xds[xlen]==yds[xlen]));
    if (-1 == xlen) return INT2FIX(0);
    return (xds[xlen] > yds[xlen]) ?
        (RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
            (RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
}
big == obj → true or false click to toggle source

Returns true only if obj has the same value as big. Contrast this with Bignum#eql?, which requires obj to be a Bignum.

68719476736 == 68719476736.0   #=> true

VALUE
rb_big_eq(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;
      case T_BIGNUM:
        break;
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return rb_equal(y, x);
    }
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
big == obj → true or false click to toggle source

Returns true only if obj has the same value as big. Contrast this with Bignum#eql?, which requires obj to be a Bignum.

68719476736 == 68719476736.0   #=> true

VALUE
rb_big_eq(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;
      case T_BIGNUM:
        break;
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return rb_equal(y, x);
    }
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
big > real → true or false click to toggle source

Returns true if the value of big is greater than that of real.

static VALUE
big_gt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_gt);
}
big >= real → true or false click to toggle source

Returns true if the value of big is greater than or equal to that of real.

static VALUE
big_ge(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_ge);
}
big >> numeric → integer click to toggle source

Shifts big right numeric positions (left if numeric is negative).

VALUE
rb_big_rshift(VALUE x, VALUE y)
{
    long shift;
    int neg = 0;

    for (;;) {
        if (FIXNUM_P(y)) {
            shift = FIX2LONG(y);
            if (shift < 0) {
                neg = 1;
                shift = -shift;
            }
            break;
        }
        else if (RB_TYPE_P(y, T_BIGNUM)) {
            if (RBIGNUM_SIGN(y)) {
                VALUE t = check_shiftdown(y, x);
                if (!NIL_P(t)) return t;
            }
            else {
                neg = 1;
            }
            shift = big2ulong(y, "long", TRUE);
            break;
        }
        y = rb_to_int(y);
    }

    x = neg ? big_lshift(x, shift) : big_rshift(x, shift);
    return bignorm(x);
}
big[n] → 0, 1 click to toggle source

Bit Reference—Returns the nth bit in the (assumed) binary representation of big, where big is the least significant bit.

a = 9**15
50.downto(0) do |n|
  print a[n]
end

produces:

000101110110100000111000011110010100111100010111001
static VALUE
rb_big_aref(VALUE x, VALUE y)
{
    BDIGIT *xds;
    BDIGIT_DBL num;
    VALUE shift;
    long i, s1, s2;

    if (RB_TYPE_P(y, T_BIGNUM)) {
        if (!RBIGNUM_SIGN(y))
            return INT2FIX(0);
        bigtrunc(y);
        if (RBIGNUM_LEN(y) > DIGSPERLONG) {
          out_of_range:
            return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
        }
        shift = big2ulong(y, "long", FALSE);
    }
    else {
        i = NUM2LONG(y);
        if (i < 0) return INT2FIX(0);
        shift = (VALUE)i;
    }
    s1 = shift/BITSPERDIG;
    s2 = shift%BITSPERDIG;

    if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
    if (!RBIGNUM_SIGN(x)) {
        xds = BDIGITS(x);
        i = 0; num = 1;
        while (num += ~xds[i], ++i <= s1) {
            num = BIGDN(num);
        }
    }
    else {
        num = BDIGITS(x)[s1];
    }
    if (num & ((BDIGIT_DBL)1<<s2))
        return INT2FIX(1);
    return INT2FIX(0);
}
big ^ numeric → integer click to toggle source

Performs bitwise +exclusive or+ between big and numeric.

VALUE
rb_big_xor(VALUE xx, VALUE yy)
{
    volatile VALUE x, y;
    VALUE z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '^');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigxor_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    RBIGNUM_SET_SIGN(x, RBIGNUM_SIGN(x)?1:0);
    RBIGNUM_SET_SIGN(y, RBIGNUM_SIGN(y)?1:0);
    z = bignew(l2, !(RBIGNUM_SIGN(x) ^ RBIGNUM_SIGN(y)));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] ^ ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?ds2[i]:~ds2[i];
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);

    return bignorm(z);
}
abs → aBignum click to toggle source

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321

static VALUE
rb_big_abs(VALUE x)
{
    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        RBIGNUM_SET_SIGN(x, 1);
    }
    return x;
}
coerce(p1) click to toggle source

MISSING: documentation

static VALUE
rb_big_coerce(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_TYPE_P(y, T_BIGNUM)) {
        rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
                 rb_obj_classname(y));
    }
    return rb_assoc_new(y, x);
}
div(other) → integer click to toggle source

Performs integer division: returns integer value.

VALUE
rb_big_idiv(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, rb_intern("div"));
}
divmod(numeric) → array click to toggle source

See Numeric#divmod.

VALUE
rb_big_divmod(VALUE x, VALUE y)
{
    VALUE div, mod;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
    bigdivmod(x, y, &div, &mod);

    return rb_assoc_new(bignorm(div), bignorm(mod));
}
eql?(obj) → true or false click to toggle source

Returns true only if obj is a Bignum with the same value as big. Contrast this with Bignum#==, which performs type conversions.

68719476736.eql?(68719476736.0)   #=> false

VALUE
rb_big_eql(VALUE x, VALUE y)
{
    if (!RB_TYPE_P(y, T_BIGNUM)) return Qfalse;
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
even? → true or false click to toggle source

Returns true if big is an even number.

static VALUE
rb_big_even_p(VALUE num)
{
    if (BDIGITS(num)[0] & 1) {
        return Qfalse;
    }
    return Qtrue;
}
fdiv(numeric) → float click to toggle source

Returns the floating point result of dividing big by numeric.

-1234567890987654321.fdiv(13731)      #=> -89910996357705.5
-1234567890987654321.fdiv(13731.24)   #=> -89909424858035.7

VALUE
rb_big_fdiv(VALUE x, VALUE y)
{
    double dx, dy;

    dx = big2dbl(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
        dy = (double)FIX2LONG(y);
        if (isinf(dx))
            return big_fdiv(x, y);
        break;

      case T_BIGNUM:
        dy = rb_big2dbl(y);
        if (isinf(dx) || isinf(dy))
            return big_fdiv(x, y);
        break;

      case T_FLOAT:
        dy = RFLOAT_VALUE(y);
        if (isnan(dy))
            return y;
        if (isinf(dx))
            return big_fdiv(x, y);
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
    }
    return DBL2NUM(dx / dy);
}
hash → fixnum click to toggle source

Compute a hash based on the value of big.

static VALUE
rb_big_hash(VALUE x)
{
    st_index_t hash;

    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
    return INT2FIX(hash);
}
inspect(p1 = v1) click to toggle source
Alias for: to_s
abs → aBignum click to toggle source

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321

static VALUE
rb_big_abs(VALUE x)
{
    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        RBIGNUM_SET_SIGN(x, 1);
    }
    return x;
}
big % other → Numeric click to toggle source
modulo(other) → Numeric

Returns big modulo other. See Numeric#divmod for more information.

VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}
odd? → true or false click to toggle source

Returns true if big is an odd number.

static VALUE
rb_big_odd_p(VALUE num)
{
    if (BDIGITS(num)[0] & 1) {
        return Qtrue;
    }
    return Qfalse;
}
remainder(numeric) → number click to toggle source

Returns the remainder after dividing big by numeric.

-1234567890987654321.remainder(13731)      #=> -6966
-1234567890987654321.remainder(13731.24)   #=> -9906.22531493148

static VALUE
rb_big_remainder(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("remainder"));
    }
    bigdivrem(x, y, 0, &z);

    return bignorm(z);
}
size → integer click to toggle source

Returns the number of bytes in the machine representation of big.

(256**10 - 1).size   #=> 12
(256**20 - 1).size   #=> 20
(256**40 - 1).size   #=> 40

static VALUE
rb_big_size(VALUE big)
{
    return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
}
to_f → float click to toggle source

Converts big to a Float. If big doesn't fit in a Float, the result is infinity.

static VALUE
rb_big_to_f(VALUE x)
{
    return DBL2NUM(rb_big2dbl(x));
}
to_s(base=10) → string click to toggle source

Returns a string containing the representation of big radix base (2 through 36).

12345654321.to_s         #=> "12345654321"
12345654321.to_s(2)      #=> "1011011111110110111011110000110001"
12345654321.to_s(8)      #=> "133766736061"
12345654321.to_s(16)     #=> "2dfdbbc31"
78546939656932.to_s(36)  #=> "rubyrules"

static VALUE
rb_big_to_s(int argc, VALUE *argv, VALUE x)
{
    int base;

    if (argc == 0) base = 10;
    else {
        VALUE b;

        rb_scan_args(argc, argv, "01", &b);
        base = NUM2INT(b);
    }
    return rb_big2str(x, base);
}
Also aliased as: inspect
big | numeric → integer click to toggle source

Performs bitwise or between big and numeric.

VALUE
rb_big_or(VALUE xx, VALUE yy)
{
    volatile VALUE x, y, z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '|');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigor_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    z = bignew(l2, RBIGNUM_SIGN(x) && RBIGNUM_SIGN(y));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] | ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?ds2[i]:(BDIGIT)(BIGRAD-1);
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);
    return bignorm(z);
}
~big → integer click to toggle source

Inverts the bits in big. As Bignums are conceptually infinite length, the result acts as if it had an infinite number of one bits to the left. In hex representations, this is displayed as two periods to the left of the digits.

sprintf("%X", ~0x1122334455)    #=> "..FEEDDCCBBAA"

static VALUE
rb_big_neg(VALUE x)
{
    VALUE z = rb_big_clone(x);
    BDIGIT *ds;
    long i;

    if (!RBIGNUM_SIGN(x)) get2comp(z);
    ds = BDIGITS(z);
    i = RBIGNUM_LEN(x);
    if (!i) return INT2FIX(~(SIGNED_VALUE)0);
    while (i--) {
        ds[i] = ~ds[i];
    }
    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(z));
    if (RBIGNUM_SIGN(x)) get2comp(z);

    return bignorm(z);
}


class Binding - Ruby 2.0.0-p576 Core API Reference API Reference

class Binding

Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, value of self, and possibly an iterator block that can be accessed in this context are all retained. Binding objects can be created using Kernel#binding, and are made available to the callback of Kernel#set_trace_func.

These binding objects can be passed as the second argument of the Kernel#eval method, establishing an environment for the evaluation.

class Demo
  def initialize(n)
    @secret = n
  end
  def get_binding
    return binding()
  end
end

k1 = Demo.new(99)
b1 = k1.get_binding
k2 = Demo.new(-3)
b2 = k2.get_binding

eval("@secret", b1)   #=> 99
eval("@secret", b2)   #=> -3
eval("@secret")       #=> nil

Binding objects have no class-specific methods.

In Files

  • proc.c

Parent

Object

Public Instance Methods

eval(string [, filename [,lineno]]) → obj click to toggle source

Evaluates the Ruby expression(s) in string, in the binding's context. If the optional filename and lineno parameters are present, they will be used when reporting syntax errors.

def get_binding(param)
  return binding
end
b = get_binding("hello")
b.eval("param")   #=> "hello"

static VALUE
bind_eval(int argc, VALUE *argv, VALUE bindval)
{
    VALUE args[4];

    rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
    args[1] = bindval;
    return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
}


class Class - Ruby 2.0.0-p576 Core API Reference API Reference

class Class

Classes in Ruby are first-class objects—each is an instance of class Class.

Typically, you create a new class by using:

class Name
 # some class describing the class behavior
end

When a new class is created, an object of type Class is initialized and assigned to a global constant (Name in this case).

When Name.new is called to create a new object, the new method in Class is run by default. This can be demonstrated by overriding new in Class:

class Class
   alias oldNew  new
   def new(*args)
     print "Creating a new ", self.name, "\n"
     oldNew(*args)
   end
 end

 class Name
 end

 n = Name.new

produces:

Creating a new Name

Classes, modules, and objects are interrelated. In the diagram that follows, the vertical arrows represent inheritance, and the parentheses meta-classes. All metaclasses are instances of the class `Class'.

                         +---------+             +-...
                         |         |             |
         BasicObject-----|-->(BasicObject)-------|-...
             ^           |         ^             |
             |           |         |             |
          Object---------|----->(Object)---------|-...
             ^           |         ^             |
             |           |         |             |
             +-------+   |         +--------+    |
             |       |   |         |        |    |
             |    Module-|---------|--->(Module)-|-...
             |       ^   |         |        ^    |
             |       |   |         |        |    |
             |     Class-|---------|---->(Class)-|-...
             |       ^   |         |        ^    |
             |       +---+         |        +----+
             |                     |
obj--->OtherClass---------->(OtherClass)-----------...

In Files

  • class.c
  • object.c

Parent

Module

Public Class Methods

new(super_class=Object) → a_class click to toggle source
new(super_class=Object) { |mod| ... } → a_class

Creates a new anonymous (unnamed) class with the given superclass (or Object if no parameter is given). You can give a class a name by assigning the class object to a constant.

If a block is given, it is passed the class object, and the block is evaluated in the context of this class using class_eval.

fred = Class.new do
  def meth1
    "hello"
  end
  def meth2
    "bye"
  end
end

a = fred.new     #=> #<#<Class:0x100381890>:0x100376b98>
a.meth1          #=> "hello"
a.meth2          #=> "bye"

Assign the class to a constant (name starting uppercase) if you want to treat it like a regular class.

static VALUE
rb_class_initialize(int argc, VALUE *argv, VALUE klass)
{
    VALUE super;

    if (RCLASS_SUPER(klass) != 0 || klass == rb_cBasicObject) {
        rb_raise(rb_eTypeError, "already initialized class");
    }
    if (argc == 0) {
        super = rb_cObject;
    }
    else {
        rb_scan_args(argc, argv, "01", &super);
        rb_check_inheritable(super);
        if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
            rb_raise(rb_eTypeError, "can't inherit uninitialized class");
        }
    }
    RCLASS_SUPER(klass) = super;
    rb_make_metaclass(klass, RBASIC(super)->klass);
    rb_class_inherited(super, klass);
    rb_mod_initialize(klass);

    return klass;
}

Public Instance Methods

allocate() → obj click to toggle source

Allocates space for a new object of class's class and does not call initialize on the new instance. The returned object must be an instance of class.

klass = Class.new do
  def initialize(*args)
    @initialized = true
  end

  def initialized?
    @initialized || false
  end
end

klass.allocate.initialized? #=> false

VALUE
rb_obj_alloc(VALUE klass)
{
    VALUE obj;
    rb_alloc_func_t allocator;

    if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
        rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
    }
    if (FL_TEST(klass, FL_SINGLETON)) {
        rb_raise(rb_eTypeError, "can't create instance of singleton class");
    }
    allocator = rb_get_alloc_func(klass);
    if (!allocator) {
        rb_raise(rb_eTypeError, "allocator undefined for %"PRIsVALUE,
                 klass);
    }

#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED
    if (RUBY_DTRACE_OBJECT_CREATE_ENABLED()) {
        const char * file = rb_sourcefile();
        RUBY_DTRACE_OBJECT_CREATE(rb_class2name(klass),
                                  file ? file : "",
                                  rb_sourceline());
    }
#endif

    obj = (*allocator)(klass);

    if (rb_obj_class(obj) != rb_class_real(klass)) {
        rb_raise(rb_eTypeError, "wrong instance allocation");
    }
    return obj;
}
new(args, ...) → obj click to toggle source

Calls allocate to create a new object of class's class, then invokes that object's initialize method, passing it args. This is the method that ends up getting called whenever an object is constructed using .new.

VALUE
rb_class_new_instance(int argc, VALUE *argv, VALUE klass)
{
    VALUE obj;

    obj = rb_obj_alloc(klass);
    rb_obj_call_init(obj, argc, argv);

    return obj;
}
superclass → a_super_class or nil click to toggle source

Returns the superclass of class, or nil.

File.superclass          #=> IO
IO.superclass            #=> Object
Object.superclass        #=> BasicObject
class Foo; end
class Bar < Foo; end
Bar.superclass           #=> Foo

returns nil when the given class hasn't a parent class:

BasicObject.superclass   #=> nil

VALUE
rb_class_superclass(VALUE klass)
{
    VALUE super = RCLASS_SUPER(klass);

    if (!super) {
        if (klass == rb_cBasicObject) return Qnil;
        rb_raise(rb_eTypeError, "uninitialized class");
    }
    while (RB_TYPE_P(super, T_ICLASS)) {
        super = RCLASS_SUPER(super);
    }
    if (!super) {
        return Qnil;
    }
    return super;
}


module Comparable - Ruby 2.0.0-p576 Core API Reference API Reference

module Comparable

The Comparable mixin is used by classes whose objects may be ordered. The class must define the <=> operator, which compares the receiver against another object, returning -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object. If the other object is not comparable then the <=> operator should return nil. Comparable uses <=> to implement the conventional comparison operators (<, <=, ==, >=, and >) and the method between?.

class SizeMatters
  include Comparable
  attr :str
  def <=>(anOther)
    str.size <=> anOther.str.size
  end
  def initialize(str)
    @str = str
  end
  def inspect
    @str
  end
end

s1 = SizeMatters.new("Z")
s2 = SizeMatters.new("YY")
s3 = SizeMatters.new("XXX")
s4 = SizeMatters.new("WWWW")
s5 = SizeMatters.new("VVVVV")

s1 < s2                       #=> true
s4.between?(s1, s3)           #=> false
s4.between?(s3, s5)           #=> true
[ s3, s2, s5, s4, s1 ].sort   #=> [Z, YY, XXX, WWWW, VVVVV]

In Files

  • compar.c

Public Instance Methods

obj < other → true or false click to toggle source

Compares two objects based on the receiver's <=> method, returning true if it returns -1.

static VALUE
cmp_lt(VALUE x, VALUE y)
{
    VALUE c = rb_funcall(x, cmp, 1, y);

    if (rb_cmpint(c, x, y) < 0) return Qtrue;
    return Qfalse;
}
obj <= other → true or false click to toggle source

Compares two objects based on the receiver's <=> method, returning true if it returns -1 or 0.

static VALUE
cmp_le(VALUE x, VALUE y)
{
    VALUE c = rb_funcall(x, cmp, 1, y);

    if (rb_cmpint(c, x, y) <= 0) return Qtrue;
    return Qfalse;
}
obj == other → true or false click to toggle source

Compares two objects based on the receiver's <=> method, returning true if it returns 0. Also returns true if obj and other are the same object.

Even if obj <=> other raised an exception, the exception is ignoread and returns false.

static VALUE
cmp_equal(VALUE x, VALUE y)
{
    VALUE a[2];

    if (x == y) return Qtrue;

    a[0] = x; a[1] = y;
    return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
}
obj > other → true or false click to toggle source

Compares two objects based on the receiver's <=> method, returning true if it returns 1.

static VALUE
cmp_gt(VALUE x, VALUE y)
{
    VALUE c = rb_funcall(x, cmp, 1, y);

    if (rb_cmpint(c, x, y) > 0) return Qtrue;
    return Qfalse;
}
obj >= other → true or false click to toggle source

Compares two objects based on the receiver's <=> method, returning true if it returns 0 or 1.

static VALUE
cmp_ge(VALUE x, VALUE y)
{
    VALUE c = rb_funcall(x, cmp, 1, y);

    if (rb_cmpint(c, x, y) >= 0) return Qtrue;
    return Qfalse;
}
between?(min, max) → true or false click to toggle source

Returns false if obj <=> min is less than zero or if anObject <=> max is greater than zero, true otherwise.

3.between?(1, 5)               #=> true
6.between?(1, 5)               #=> false
'cat'.between?('ant', 'dog')   #=> true
'gnu'.between?('ant', 'dog')   #=> false

static VALUE
cmp_between(VALUE x, VALUE min, VALUE max)
{
    if (RTEST(cmp_lt(x, min))) return Qfalse;
    if (RTEST(cmp_gt(x, max))) return Qfalse;
    return Qtrue;
}


class Complex - Ruby 2.0.0-p576 Core API Reference API Reference

class Complex

A complex number can be represented as a paired real number with imaginary unit; a+bi. Where a is real part, b is imaginary part and i is imaginary unit. Real a equals complex a+0i mathematically.

In ruby, you can create complex object with Complex, ::rect, ::polar or #to_c method.

Complex(1)           #=> (1+0i)
Complex(2, 3)        #=> (2+3i)
Complex.polar(2, 3)  #=> (-1.9799849932008908+0.2822400161197344i)
3.to_c               #=> (3+0i)

You can also create complex object from floating-point numbers or strings.

Complex(0.3)         #=> (0.3+0i)
Complex('0.3-0.5i')  #=> (0.3-0.5i)
Complex('2/3+3/4i')  #=> ((2/3)+(3/4)*i)
Complex('1@2')       #=> (-0.4161468365471424+0.9092974268256817i)

0.3.to_c             #=> (0.3+0i)
'0.3-0.5i'.to_c      #=> (0.3-0.5i)
'2/3+3/4i'.to_c      #=> ((2/3)+(3/4)*i)
'1@2'.to_c           #=> (-0.4161468365471424+0.9092974268256817i)

A complex object is either an exact or an inexact number.

Complex(1, 1) / 2    #=> ((1/2)+(1/2)*i)
Complex(1, 1) / 2.0  #=> (0.5+0.5i)

In Files

  • complex.c

Parent

Numeric

Constants

I

The imaginary unit.

Public Class Methods

polar(abs[, arg]) → complex click to toggle source

Returns a complex object which denotes the given polar form.

Complex.polar(3, 0)            #=> (3.0+0.0i)
Complex.polar(3, Math::PI/2)   #=> (1.836909530733566e-16+3.0i)
Complex.polar(3, Math::PI)     #=> (-3.0+3.673819061467132e-16i)
Complex.polar(3, -Math::PI/2)  #=> (1.836909530733566e-16-3.0i)

static VALUE
nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
{
    VALUE abs, arg;

    switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
      case 1:
        nucomp_real_check(abs);
        arg = ZERO;
        break;
      default:
        nucomp_real_check(abs);
        nucomp_real_check(arg);
        break;
    }
    return f_complex_polar(klass, abs, arg);
}
rect(real[, imag]) → complex click to toggle source
rectangular(real[, imag]) → complex

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2)  #=> (1+2i)

static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
    VALUE real, imag;

    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
      case 1:
        nucomp_real_check(real);
        imag = ZERO;
        break;
      default:
        nucomp_real_check(real);
        nucomp_real_check(imag);
        break;
    }

    return nucomp_s_canonicalize_internal(klass, real, imag);
}
rect(real[, imag]) → complex click to toggle source
rectangular(real[, imag]) → complex

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2)  #=> (1+2i)

static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
    VALUE real, imag;

    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
      case 1:
        nucomp_real_check(real);
        imag = ZERO;
        break;
      default:
        nucomp_real_check(real);
        nucomp_real_check(imag);
        break;
    }

    return nucomp_s_canonicalize_internal(klass, real, imag);
}

Public Instance Methods

cmp * numeric → complex click to toggle source

Performs multiplication.

Complex(2, 3)  * Complex(2, 3)   #=> (-5+12i)
Complex(900)   * Complex(1)      #=> (900+0i)
Complex(-2, 9) * Complex(-9, 2)  #=> (0-85i)
Complex(9, 8)  * 4               #=> (36+32i)
Complex(20, 9) * 9.8             #=> (196.0+88.2i)

static VALUE
nucomp_mul(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        VALUE real, imag;

        get_dat2(self, other);

        real = f_sub(f_mul(adat->real, bdat->real),
                     f_mul(adat->imag, bdat->imag));
        imag = f_add(f_mul(adat->real, bdat->imag),
                     f_mul(adat->imag, bdat->real));

        return f_complex_new2(CLASS_OF(self), real, imag);
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        get_dat1(self);

        return f_complex_new2(CLASS_OF(self),
                              f_mul(dat->real, other),
                              f_mul(dat->imag, other));
    }
    return rb_num_coerce_bin(self, other, '*');
}
cmp ** numeric → complex click to toggle source

Performs exponentiation.

Complex('i') ** 2              #=> (-1+0i)
Complex(-8) ** Rational(1, 3)  #=> (1.0000000000000002+1.7320508075688772i)

static VALUE
nucomp_expt(VALUE self, VALUE other)
{
    if (k_numeric_p(other) && k_exact_zero_p(other))
        return f_complex_new_bang1(CLASS_OF(self), ONE);

    if (k_rational_p(other) && f_one_p(f_denominator(other)))
        other = f_numerator(other); /* c14n */

    if (k_complex_p(other)) {
        get_dat1(other);

        if (k_exact_zero_p(dat->imag))
            other = dat->real; /* c14n */
    }

    if (k_complex_p(other)) {
        VALUE r, theta, nr, ntheta;

        get_dat1(other);

        r = f_abs(self);
        theta = f_arg(self);

        nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
                              f_mul(dat->imag, theta)));
        ntheta = f_add(f_mul(theta, dat->real),
                       f_mul(dat->imag, m_log_bang(r)));
        return f_complex_polar(CLASS_OF(self), nr, ntheta);
    }
    if (k_fixnum_p(other)) {
        if (f_gt_p(other, ZERO)) {
            VALUE x, z;
            long n;

            x = self;
            z = x;
            n = FIX2LONG(other) - 1;

            while (n) {
                long q, r;

                while (1) {
                    get_dat1(x);

                    q = n / 2;
                    r = n % 2;

                    if (r)
                        break;

                    x = nucomp_s_new_internal(CLASS_OF(self),
                                       f_sub(f_mul(dat->real, dat->real),
                                             f_mul(dat->imag, dat->imag)),
                                       f_mul(f_mul(TWO, dat->real), dat->imag));
                    n = q;
                }
                z = f_mul(z, x);
                n--;
            }
            return z;
        }
        return f_expt(f_reciprocal(self), f_negate(other));
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        VALUE r, theta;

        if (k_bignum_p(other))
            rb_warn("in a**b, b may be too big");

        r = f_abs(self);
        theta = f_arg(self);

        return f_complex_polar(CLASS_OF(self), f_expt(r, other),
                               f_mul(theta, other));
    }
    return rb_num_coerce_bin(self, other, id_expt);
}
cmp + numeric → complex click to toggle source

Performs addition.

Complex(2, 3)  + Complex(2, 3)   #=> (4+6i)
Complex(900)   + Complex(1)      #=> (901+0i)
Complex(-2, 9) + Complex(-9, 2)  #=> (-11+11i)
Complex(9, 8)  + 4               #=> (13+8i)
Complex(20, 9) + 9.8             #=> (29.8+9i)

static VALUE
nucomp_add(VALUE self, VALUE other)
{
    return f_addsub(self, other, f_add, '+');
}
cmp - numeric → complex click to toggle source

Performs subtraction.

Complex(2, 3)  - Complex(2, 3)   #=> (0+0i)
Complex(900)   - Complex(1)      #=> (899+0i)
Complex(-2, 9) - Complex(-9, 2)  #=> (7+7i)
Complex(9, 8)  - 4               #=> (5+8i)
Complex(20, 9) - 9.8             #=> (10.2+9i)

static VALUE
nucomp_sub(VALUE self, VALUE other)
{
    return f_addsub(self, other, f_sub, '-');
}
-cmp → complex click to toggle source

Returns negation of the value.

-Complex(1, 2)  #=> (-1-2i)

static VALUE
nucomp_negate(VALUE self)
{
  get_dat1(self);
  return f_complex_new2(CLASS_OF(self),
                        f_negate(dat->real), f_negate(dat->imag));
}
cmp / numeric → complex click to toggle source
quo(numeric) → complex

Performs division.

Complex(2, 3)  / Complex(2, 3)   #=> ((1/1)+(0/1)*i)
Complex(900)   / Complex(1)      #=> ((900/1)+(0/1)*i)
Complex(-2, 9) / Complex(-9, 2)  #=> ((36/85)-(77/85)*i)
Complex(9, 8)  / 4               #=> ((9/4)+(2/1)*i)
Complex(20, 9) / 9.8             #=> (2.0408163265306123+0.9183673469387754i)

static VALUE
nucomp_div(VALUE self, VALUE other)
{
    return f_divide(self, other, f_quo, id_quo);
}
cmp == object → true or false click to toggle source

Returns true if cmp equals object numerically.

Complex(2, 3)  == Complex(2, 3)   #=> true
Complex(5)     == 5               #=> true
Complex(0)     == 0.0             #=> true
Complex('1/3') == 0.33            #=> false
Complex('1/2') == '1/2'           #=> false

static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        get_dat2(self, other);

        return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
                          f_eqeq_p(adat->imag, bdat->imag));
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        get_dat1(self);

        return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
    }
    return f_eqeq_p(other, self);
}
abs → real click to toggle source
magnitude → real

Returns the absolute part of its polar form.

Complex(-1).abs         #=> 1
Complex(3.0, -4.0).abs  #=> 5.0

static VALUE
nucomp_abs(VALUE self)
{
    get_dat1(self);

    if (f_zero_p(dat->real)) {
        VALUE a = f_abs(dat->imag);
        if (k_float_p(dat->real) && !k_float_p(dat->imag))
            a = f_to_f(a);
        return a;
    }
    if (f_zero_p(dat->imag)) {
        VALUE a = f_abs(dat->real);
        if (!k_float_p(dat->real) && k_float_p(dat->imag))
            a = f_to_f(a);
        return a;
    }
    return m_hypot(dat->real, dat->imag);
}
abs2 → real click to toggle source

Returns square of the absolute value.

Complex(-1).abs2         #=> 1
Complex(3.0, -4.0).abs2  #=> 25.0

static VALUE
nucomp_abs2(VALUE self)
{
    get_dat1(self);
    return f_add(f_mul(dat->real, dat->real),
                 f_mul(dat->imag, dat->imag));
}
arg → float click to toggle source
angle → float
phase → float

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
arg → float click to toggle source
angle → float
phase → float

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
conj → complex click to toggle source
conjugate → complex

Returns the complex conjugate.

Complex(1, 2).conjugate  #=> (1-2i)

static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
conj → complex click to toggle source
conjugate → complex

Returns the complex conjugate.

Complex(1, 2).conjugate  #=> (1-2i)

static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
denominator → integer click to toggle source

Returns the denominator (lcm of both denominator - real and imag).

See numerator.

static VALUE
nucomp_denominator(VALUE self)
{
    get_dat1(self);
    return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
fdiv(numeric) → complex click to toggle source

Performs division as each part is a float, never returns a float.

Complex(11, 22).fdiv(3)  #=> (3.6666666666666665+7.333333333333333i)

static VALUE
nucomp_fdiv(VALUE self, VALUE other)
{
    return f_divide(self, other, f_fdiv, id_fdiv);
}
imag → real click to toggle source
imaginary → real

Returns the imaginary part.

Complex(7).imaginary      #=> 0
Complex(9, -4).imaginary  #=> -4

static VALUE
nucomp_imag(VALUE self)
{
    get_dat1(self);
    return dat->imag;
}
imag → real click to toggle source
imaginary → real

Returns the imaginary part.

Complex(7).imaginary      #=> 0
Complex(9, -4).imaginary  #=> -4

static VALUE
nucomp_imag(VALUE self)
{
    get_dat1(self);
    return dat->imag;
}
inspect → string click to toggle source

Returns the value as a string for inspection.

Complex(2).inspect                       #=> "(2+0i)"
Complex('-8/6').inspect                  #=> "((-4/3)+0i)"
Complex('1/2i').inspect                  #=> "(0+(1/2)*i)"
Complex(0, Float::INFINITY).inspect      #=> "(0+Infinity*i)"
Complex(Float::NAN, Float::NAN).inspect  #=> "(NaN+NaN*i)"

static VALUE
nucomp_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, f_format(self, f_inspect));
    rb_str_cat2(s, ")");

    return s;
}
abs → real click to toggle source
magnitude → real

Returns the absolute part of its polar form.

Complex(-1).abs         #=> 1
Complex(3.0, -4.0).abs  #=> 5.0

static VALUE
nucomp_abs(VALUE self)
{
    get_dat1(self);

    if (f_zero_p(dat->real)) {
        VALUE a = f_abs(dat->imag);
        if (k_float_p(dat->real) && !k_float_p(dat->imag))
            a = f_to_f(a);
        return a;
    }
    if (f_zero_p(dat->imag)) {
        VALUE a = f_abs(dat->real);
        if (!k_float_p(dat->real) && k_float_p(dat->imag))
            a = f_to_f(a);
        return a;
    }
    return m_hypot(dat->real, dat->imag);
}
numerator → numeric click to toggle source

Returns the numerator.

    1   2       3+4i  <-  numerator
    - + -i  ->  ----
    2   3        6    <-  denominator

c = Complex('1/2+2/3i')  #=> ((1/2)+(2/3)*i)
n = c.numerator          #=> (3+4i)
d = c.denominator        #=> 6
n / d                    #=> ((1/2)+(2/3)*i)
Complex(Rational(n.real, d), Rational(n.imag, d))
                         #=> ((1/2)+(2/3)*i)

See denominator.

static VALUE
nucomp_numerator(VALUE self)
{
    VALUE cd;

    get_dat1(self);

    cd = f_denominator(self);
    return f_complex_new2(CLASS_OF(self),
                          f_mul(f_numerator(dat->real),
                                f_div(cd, f_denominator(dat->real))),
                          f_mul(f_numerator(dat->imag),
                                f_div(cd, f_denominator(dat->imag))));
}
arg → float click to toggle source
angle → float
phase → float

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
polar → array click to toggle source

Returns an array; [cmp.abs, cmp.arg].

Complex(1, 2).polar  #=> [2.23606797749979, 1.1071487177940904]

static VALUE
nucomp_polar(VALUE self)
{
    return rb_assoc_new(f_abs(self), f_arg(self));
}
cmp / numeric → complex click to toggle source
quo(numeric) → complex

Performs division.

Complex(2, 3)  / Complex(2, 3)   #=> ((1/1)+(0/1)*i)
Complex(900)   / Complex(1)      #=> ((900/1)+(0/1)*i)
Complex(-2, 9) / Complex(-9, 2)  #=> ((36/85)-(77/85)*i)
Complex(9, 8)  / 4               #=> ((9/4)+(2/1)*i)
Complex(20, 9) / 9.8             #=> (2.0408163265306123+0.9183673469387754i)

static VALUE
nucomp_div(VALUE self, VALUE other)
{
    return f_divide(self, other, f_quo, id_quo);
}
rationalize([eps]) → rational click to toggle source

Returns the value as a rational if possible (the imaginary part should be exactly zero).

Complex(1.0/3, 0).rationalize  #=> (1/3)
Complex(1, 0.0).rationalize    # RangeError
Complex(1, 2).rationalize      # RangeError

See to_r.

static VALUE
nucomp_rationalize(int argc, VALUE *argv, VALUE self)
{
    get_dat1(self);

    rb_scan_args(argc, argv, "01", NULL);

    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
       VALUE s = f_to_s(self);
       rb_raise(rb_eRangeError, "can't convert %s into Rational",
                StringValuePtr(s));
    }
    return rb_funcall2(dat->real, rb_intern("rationalize"), argc, argv);
}
real → real click to toggle source

Returns the real part.

Complex(7).real      #=> 7
Complex(9, -4).real  #=> 9

static VALUE
nucomp_real(VALUE self)
{
    get_dat1(self);
    return dat->real;
}
real? → false click to toggle source

Returns false.

static VALUE
nucomp_false(VALUE self)
{
    return Qfalse;
}
rect → array click to toggle source
rectangular → array

Returns an array; [cmp.real, cmp.imag].

Complex(1, 2).rectangular  #=> [1, 2]

static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}
rect → array click to toggle source
rectangular → array

Returns an array; [cmp.real, cmp.imag].

Complex(1, 2).rectangular  #=> [1, 2]

static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}
to_c → self click to toggle source

Returns self.

Complex(2).to_c      #=> (2+0i)
Complex(-8, 6).to_c  #=> (-8+6i)

static VALUE
nucomp_to_c(VALUE self)
{
    return self;
}
to_f → float click to toggle source

Returns the value as a float if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_f    #=> 1.0
Complex(1, 0.0).to_f  # RangeError
Complex(1, 2).to_f    # RangeError

static VALUE
nucomp_to_f(VALUE self)
{
    get_dat1(self);

    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
        VALUE s = f_to_s(self);
        rb_raise(rb_eRangeError, "can't convert %s into Float",
                 StringValuePtr(s));
    }
    return f_to_f(dat->real);
}
to_i → integer click to toggle source

Returns the value as an integer if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_i    #=> 1
Complex(1, 0.0).to_i  # RangeError
Complex(1, 2).to_i    # RangeError

static VALUE
nucomp_to_i(VALUE self)
{
    get_dat1(self);

    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
        VALUE s = f_to_s(self);
        rb_raise(rb_eRangeError, "can't convert %s into Integer",
                 StringValuePtr(s));
    }
    return f_to_i(dat->real);
}
to_r → rational click to toggle source

Returns the value as a rational if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_r    #=> (1/1)
Complex(1, 0.0).to_r  # RangeError
Complex(1, 2).to_r    # RangeError

See rationalize.

static VALUE
nucomp_to_r(VALUE self)
{
    get_dat1(self);

    if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
        VALUE s = f_to_s(self);
        rb_raise(rb_eRangeError, "can't convert %s into Rational",
                 StringValuePtr(s));
    }
    return f_to_r(dat->real);
}
to_s → string click to toggle source

Returns the value as a string.

Complex(2).to_s                       #=> "2+0i"
Complex('-8/6').to_s                  #=> "-4/3+0i"
Complex('1/2i').to_s                  #=> "0+1/2i"
Complex(0, Float::INFINITY).to_s      #=> "0+Infinity*i"
Complex(Float::NAN, Float::NAN).to_s  #=> "NaN+NaN*i"

static VALUE
nucomp_to_s(VALUE self)
{
    return f_format(self, f_to_s);
}
conj → complex click to toggle source
conjugate → complex

Returns the complex conjugate.

Complex(1, 2).conjugate  #=> (1-2i)

static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}


class Complex::compatible - Ruby 2.0.0-p576 Core API Reference API Reference

class Complex::compatible

In Files

  • complex.c

Parent

Object


class Continuation - Ruby 2.0.0-p576 Core API Reference API Reference

class Continuation

Continuation objects are generated by Kernel#callcc, after having +require+d continuation. They hold a return address and execution context, allowing a nonlocal return to the end of the callcc block from anywhere within a program. Continuations are somewhat analogous to a structured version of C's setjmp/longjmp (although they contain more state, so you might consider them closer to threads).

For instance:

require "continuation"
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|cc| $cc = cc}
puts(message = arr.shift)
$cc.call unless message =~ /Max/

produces:

Freddie
Herbie
Ron
Max

This (somewhat contrived) example allows the inner loop to abandon processing early:

require "continuation"
callcc {|cont|
  for i in 0..4
    print "\n#{i}: "
    for j in i*5...(i+1)*5
      cont.call() if j == 17
      printf "%3d", j
    end
  end
}
puts

produces:

0:   0  1  2  3  4
1:   5  6  7  8  9
2:  10 11 12 13 14
3:  15 16

In Files

  • cont.c

Parent

Object

Public Instance Methods

call(args, ...) click to toggle source
cont[args, ...]

Invokes the continuation. The program continues from the end of the callcc block. If no arguments are given, the original callcc returns nil. If one argument is given, callcc returns it. Otherwise, an array containing args is returned.

callcc {|cont|  cont.call }           #=> nil
callcc {|cont|  cont.call 1 }         #=> 1
callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]

static VALUE
rb_cont_call(int argc, VALUE *argv, VALUE contval)
{
    rb_context_t *cont;
    rb_thread_t *th = GET_THREAD();
    GetContPtr(contval, cont);

    if (cont->saved_thread.self != th->self) {
        rb_raise(rb_eRuntimeError, "continuation called across threads");
    }
    if (cont->saved_thread.protect_tag != th->protect_tag) {
        rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier");
    }
    if (cont->saved_thread.fiber) {
        rb_fiber_t *fcont;
        GetFiberPtr(cont->saved_thread.fiber, fcont);

        if (th->fiber != cont->saved_thread.fiber) {
            rb_raise(rb_eRuntimeError, "continuation called across fiber");
        }
    }

    cont->argc = argc;
    cont->value = make_passing_arg(argc, argv);

    /* restore `tracing' context. see [Feature #4347] */
    th->trace_arg = cont->saved_thread.trace_arg;

    cont_restore_0(cont, &contval);
    return Qnil; /* unreachable */
}
call(args, ...) click to toggle source
cont[args, ...]

Invokes the continuation. The program continues from the end of the callcc block. If no arguments are given, the original callcc returns nil. If one argument is given, callcc returns it. Otherwise, an array containing args is returned.

callcc {|cont|  cont.call }           #=> nil
callcc {|cont|  cont.call 1 }         #=> 1
callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]

static VALUE
rb_cont_call(int argc, VALUE *argv, VALUE contval)
{
    rb_context_t *cont;
    rb_thread_t *th = GET_THREAD();
    GetContPtr(contval, cont);

    if (cont->saved_thread.self != th->self) {
        rb_raise(rb_eRuntimeError, "continuation called across threads");
    }
    if (cont->saved_thread.protect_tag != th->protect_tag) {
        rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier");
    }
    if (cont->saved_thread.fiber) {
        rb_fiber_t *fcont;
        GetFiberPtr(cont->saved_thread.fiber, fcont);

        if (th->fiber != cont->saved_thread.fiber) {
            rb_raise(rb_eRuntimeError, "continuation called across fiber");
        }
    }

    cont->argc = argc;
    cont->value = make_passing_arg(argc, argv);

    /* restore `tracing' context. see [Feature #4347] */
    th->trace_arg = cont->saved_thread.trace_arg;

    cont_restore_0(cont, &contval);
    return Qnil; /* unreachable */
}


class Data - Ruby 2.0.0-p576 Core API Reference API Reference

class Data

This is a recommended base class for C extensions using Data_Make_Struct or Data_Wrap_Struct, see README.EXT for details.

In Files

  • object.c

Parent

Object


class Dir - Ruby 2.0.0-p576 Core API Reference API Reference

class Dir

Objects of class Dir are directory streams representing directories in the underlying file system. They provide a variety of ways to list directories and their contents. See also File.

The directory used in these examples contains the two regular files (config.h and main.rb), the parent directory (..), and the directory itself (.).

In Files

  • dir.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

Dir[ array ] → array click to toggle source
Dir[ string [, string ...] ] → array

Equivalent to calling Dir.glob(array,0) and Dir.glob([string,...],0).

static VALUE
dir_s_aref(int argc, VALUE *argv, VALUE obj)
{
    if (argc == 1) {
        return rb_push_glob(argv[0], 0);
    }
    return dir_globs(argc, argv, 0);
}
chdir( [ string] ) → 0 click to toggle source
chdir( [ string] ) {| path | block } → anObject

Changes the current working directory of the process to the given string. When called without an argument, changes the directory to the value of the environment variable HOME, or LOGDIR. SystemCallError (probably Errno::ENOENT) if the target directory does not exist.

If a block is given, it is passed the name of the new current directory, and the block is executed with that as the current directory. The original working directory is restored when the block exits. The return value of chdir is the value of the block. chdir blocks can be nested, but in a multi-threaded program an error will be raised if a thread attempts to open a chdir block while another thread has one open.

Dir.chdir("/var/spool/mail")
puts Dir.pwd
Dir.chdir("/tmp") do
  puts Dir.pwd
  Dir.chdir("/usr") do
    puts Dir.pwd
  end
  puts Dir.pwd
end
puts Dir.pwd

produces:

/var/spool/mail
/tmp
/usr
/tmp
/var/spool/mail
static VALUE
dir_s_chdir(int argc, VALUE *argv, VALUE obj)
{
    VALUE path = Qnil;

    rb_secure(2);
    if (rb_scan_args(argc, argv, "01", &path) == 1) {
        FilePathValue(path);
        path = rb_str_encode_ospath(path);
    }
    else {
        const char *dist = getenv("HOME");
        if (!dist) {
            dist = getenv("LOGDIR");
            if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
        }
        path = rb_str_new2(dist);
    }

    if (chdir_blocking > 0) {
        if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
            rb_warn("conflicting chdir during another chdir block");
    }

    if (rb_block_given_p()) {
        struct chdir_data args;

        args.old_path = rb_str_encode_ospath(rb_dir_getwd());
        args.new_path = path;
        args.done = FALSE;
        return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
    }
    dir_chdir(path);

    return INT2FIX(0);
}
chroot( string ) → 0 click to toggle source

Changes this process's idea of the file system root. Only a privileged process may make this call. Not available on all platforms. On Unix systems, see chroot(2) for more information.

static VALUE
dir_s_chroot(VALUE dir, VALUE path)
{
    check_dirname(&path);
    if (chroot(RSTRING_PTR(path)) == -1)
        rb_sys_fail_path(path);

    return INT2FIX(0);
}
delete( string ) → 0 click to toggle source
rmdir( string ) → 0
unlink( string ) → 0

Deletes the named directory. Raises a subclass of SystemCallError if the directory isn't empty.

static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
    check_dirname(&dir);
    if (rmdir(RSTRING_PTR(dir)) < 0)
        rb_sys_fail_path(dir);

    return INT2FIX(0);
}
entries( dirname ) → array click to toggle source

Returns an array containing all of the filenames in the given directory. Will raise a SystemCallError if the named directory doesn't exist.

Dir.entries("testdir")   #=> [".", "..", "config.h", "main.rb"]

static VALUE
dir_entries(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    dir = dir_open_dir(argc, argv);
    return rb_ensure(rb_Array, dir, dir_close, dir);
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Returns true if the named file is a directory, false otherwise.

VALUE
rb_file_directory_p()
{
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Returns true if the named file is a directory, false otherwise.

VALUE
rb_file_directory_p()
{
}
foreach( dirname ) {| filename | block } → nil click to toggle source
foreach( dirname ) → an_enumerator

Calls the block once for each entry in the named directory, passing the filename of each entry as a parameter to the block.

If no block is given, an enumerator is returned instead.

Dir.foreach("testdir") {|x| puts "Got #{x}" }

produces:

Got .
Got ..
Got config.h
Got main.rb
static VALUE
dir_foreach(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    RETURN_ENUMERATOR(io, argc, argv);
    dir = dir_open_dir(argc, argv);
    rb_ensure(dir_each, dir, dir_close, dir);
    return Qnil;
}
getwd → string click to toggle source
pwd → string

Returns the path to the current working directory of this process as a string.

Dir.chdir("/tmp")   #=> 0
Dir.getwd           #=> "/tmp"

static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}
glob( pattern, [flags] ) → array click to toggle source
glob( pattern, [flags] ) {| filename | block } → nil

Returns the filenames found by expanding pattern which is an Array of the patterns or the pattern String, either as an array or as parameters to the block. Note that this pattern is not a regexp (it's closer to a shell glob). See File::fnmatch for the meaning of the flags parameter. Note that case sensitivity depends on your system (so File::FNM_CASEFOLD is ignored), as does the order in which the results are returned.

*

Matches any file. Can be restricted by other values in the glob. * will match all files; c* will match all files beginning with c; *c will match all files ending with c; and *c* will match all files that have c in them (including at the beginning or end). Equivalent to / .* /x in regexp. Note, this will not match Unix-like hidden files (dotfiles). In order to include those in the match results, you must use something like "{*,.*}".

**

Matches directories recursively.

?

Matches any one character. Equivalent to /.{1}/ in regexp.

[set]

Matches any one character in set. Behaves exactly like character sets in Regexp, including set negation ([^a-z]).

{p,q}

Matches either literal p or literal q. Matching literals may be more than one character in length. More than two literals may be specified. Equivalent to pattern alternation in regexp.

\

Escapes the next metacharacter. Note that this means you cannot use backslash in windows as part of a glob, i.e. Dir["c:\foo*"] will not work, use Dir["c:/foo*"] instead.

Dir["config.?"]                     #=> ["config.h"]
Dir.glob("config.?")                #=> ["config.h"]
Dir.glob("*.[a-z][a-z]")            #=> ["main.rb"]
Dir.glob("*.[^r]*")                 #=> ["config.h"]
Dir.glob("*.{rb,h}")                #=> ["main.rb", "config.h"]
Dir.glob("*")                       #=> ["config.h", "main.rb"]
Dir.glob("*", File::FNM_DOTMATCH)   #=> [".", "..", "config.h", "main.rb"]

rbfiles = File.join("**", "*.rb")
Dir.glob(rbfiles)                   #=> ["main.rb",
                                    #    "lib/song.rb",
                                    #    "lib/song/karaoke.rb"]
libdirs = File.join("**", "lib")
Dir.glob(libdirs)                   #=> ["lib"]

librbfiles = File.join("**", "lib", "**", "*.rb")
Dir.glob(librbfiles)                #=> ["lib/song.rb",
                                    #    "lib/song/karaoke.rb"]

librbfiles = File.join("**", "lib", "*.rb")
Dir.glob(librbfiles)                #=> ["lib/song.rb"]

static VALUE
dir_s_glob(int argc, VALUE *argv, VALUE obj)
{
    VALUE str, rflags, ary;
    int flags;

    if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
        flags = NUM2INT(rflags);
    else
        flags = 0;

    ary = rb_check_array_type(str);
    if (NIL_P(ary)) {
        ary = rb_push_glob(str, flags);
    }
    else {
        volatile VALUE v = ary;
        ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
    }

    if (rb_block_given_p()) {
        rb_ary_each(ary);
        return Qnil;
    }
    return ary;
}
home() → "/home/me" click to toggle source
home("root") → "/root"

Returns the home directory of the current user or the named user if given.

static VALUE
dir_s_home(int argc, VALUE *argv, VALUE obj)
{
    VALUE user;
    const char *u = 0;

    rb_scan_args(argc, argv, "01", &user);
    if (!NIL_P(user)) {
        SafeStringValue(user);
        u = StringValueCStr(user);
    }
    return rb_home_dir(u, rb_str_new(0, 0));
}
mkdir( string [, integer] ) → 0 click to toggle source

Makes a new directory named by string, with permissions specified by the optional parameter anInteger. The permissions may be modified by the value of File::umask, and are ignored on NT. Raises a SystemCallError if the directory cannot be created. See also the discussion of permissions in the class documentation for File.

Dir.mkdir(File.join(Dir.home, ".foo"), 0700) #=> 0

static VALUE
dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
{
    VALUE path, vmode;
    int mode;

    if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
        mode = NUM2INT(vmode);
    }
    else {
        mode = 0777;
    }

    check_dirname(&path);
    if (mkdir(RSTRING_PTR(path), mode) == -1)
        rb_sys_fail_path(path);

    return INT2FIX(0);
}
new( string ) → aDir click to toggle source

Returns a new directory object for the named directory.

static VALUE
dir_initialize(int argc, VALUE *argv, VALUE dir)
{
    struct dir_data *dp;
    rb_encoding  *fsenc;
    VALUE dirname, opt, orig;
    static VALUE sym_enc;

    if (!sym_enc) {
        sym_enc = ID2SYM(rb_intern("encoding"));
    }
    fsenc = rb_filesystem_encoding();

    rb_scan_args(argc, argv, "1:", &dirname, &opt);

    if (!NIL_P(opt)) {
        VALUE enc = rb_hash_aref(opt, sym_enc);
        if (!NIL_P(enc)) {
            fsenc = rb_to_encoding(enc);
        }
    }

    GlobPathValue(dirname, FALSE);
    orig = rb_str_dup_frozen(dirname);
    dirname = rb_str_encode_ospath(dirname);
    dirname = rb_str_dup_frozen(dirname);

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp);
    if (dp->dir) closedir(dp->dir);
    dp->dir = NULL;
    dp->path = Qnil;
    dp->enc = fsenc;
    dp->dir = opendir(RSTRING_PTR(dirname));
    if (dp->dir == NULL) {
        if (errno == EMFILE || errno == ENFILE) {
            rb_gc();
            dp->dir = opendir(RSTRING_PTR(dirname));
        }
        if (dp->dir == NULL) {
            rb_sys_fail_path(orig);
        }
    }
    dp->path = orig;

    return dir;
}
open( string ) → aDir click to toggle source
open( string ) {| aDir | block } → anObject

With no block, open is a synonym for Dir::new. If a block is present, it is passed aDir as a parameter. The directory is closed at the end of the block, and Dir::open returns the value of the block.

static VALUE
dir_s_open(int argc, VALUE *argv, VALUE klass)
{
    struct dir_data *dp;
    VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);

    dir_initialize(argc, argv, dir);
    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, dir, dir_close, dir);
    }

    return dir;
}
getwd → string click to toggle source
pwd → string

Returns the path to the current working directory of this process as a string.

Dir.chdir("/tmp")   #=> 0
Dir.getwd           #=> "/tmp"

static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}
delete( string ) → 0 click to toggle source
rmdir( string ) → 0
unlink( string ) → 0

Deletes the named directory. Raises a subclass of SystemCallError if the directory isn't empty.

static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
    check_dirname(&dir);
    if (rmdir(RSTRING_PTR(dir)) < 0)
        rb_sys_fail_path(dir);

    return INT2FIX(0);
}
delete( string ) → 0 click to toggle source
rmdir( string ) → 0
unlink( string ) → 0

Deletes the named directory. Raises a subclass of SystemCallError if the directory isn't empty.

static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
    check_dirname(&dir);
    if (rmdir(RSTRING_PTR(dir)) < 0)
        rb_sys_fail_path(dir);

    return INT2FIX(0);
}

Public Instance Methods

close → nil click to toggle source

Closes the directory stream. Any further attempts to access dir will raise an IOError.

d = Dir.new("testdir")
d.close   #=> nil

static VALUE
dir_close(VALUE dir)
{
    struct dir_data *dirp;

    GetDIR(dir, dirp);
    closedir(dirp->dir);
    dirp->dir = NULL;

    return Qnil;
}
each { |filename| block } → dir click to toggle source
each → an_enumerator

Calls the block once for each entry in this directory, passing the filename of each entry as a parameter to the block.

If no block is given, an enumerator is returned instead.

d = Dir.new("testdir")
d.each  {|x| puts "Got #{x}" }

produces:

Got .
Got ..
Got config.h
Got main.rb
static VALUE
dir_each(VALUE dir)
{
    struct dir_data *dirp;
    struct dirent *dp;
    IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry);

    RETURN_ENUMERATOR(dir, 0, 0);
    GetDIR(dir, dirp);
    rewinddir(dirp->dir);
    while (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) {
        rb_yield(rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc));
        if (dirp->dir == NULL) dir_closed();
    }
    return dir;
}
inspect → string click to toggle source

Return a string describing this Dir object.

static VALUE
dir_inspect(VALUE dir)
{
    struct dir_data *dirp;

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
    if (!NIL_P(dirp->path)) {
        VALUE str = rb_str_new_cstr("#<");
        rb_str_append(str, rb_class_name(CLASS_OF(dir)));
        rb_str_cat2(str, ":");
        rb_str_append(str, dirp->path);
        rb_str_cat2(str, ">");
        return str;
    }
    return rb_funcall(dir, rb_intern("to_s"), 0, 0);
}
path → string or nil click to toggle source

Returns the path parameter passed to dir's constructor.

d = Dir.new("..")
d.path   #=> ".."

static VALUE
dir_path(VALUE dir)
{
    struct dir_data *dirp;

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
    if (NIL_P(dirp->path)) return Qnil;
    return rb_str_dup(dirp->path);
}
pos → integer click to toggle source
tell → integer

Returns the current position in dir. See also Dir#seek.

d = Dir.new("testdir")
d.tell   #=> 0
d.read   #=> "."
d.tell   #=> 12

static VALUE
dir_tell(VALUE dir)
{
    struct dir_data *dirp;
    long pos;

    GetDIR(dir, dirp);
    pos = telldir(dirp->dir);
    return rb_int2inum(pos);
}
pos( integer ) → integer click to toggle source

Synonym for Dir#seek, but returns the position parameter.

d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
d.read                   #=> "."
i = d.pos                #=> 12
d.read                   #=> ".."
d.pos = i                #=> 12
d.read                   #=> ".."

static VALUE
dir_set_pos(VALUE dir, VALUE pos)
{
    dir_seek(dir, pos);
    return pos;
}
read → string or nil click to toggle source

Reads the next entry from dir and returns it as a string. Returns nil at the end of the stream.

d = Dir.new("testdir")
d.read   #=> "."
d.read   #=> ".."
d.read   #=> "config.h"

static VALUE
dir_read(VALUE dir)
{
    struct dir_data *dirp;
    struct dirent *dp;
    IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry);

    GetDIR(dir, dirp);
    errno = 0;
    if (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) {
        return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
    }
    else {
        if (errno != 0) rb_sys_fail(0);
        return Qnil;           /* end of stream */
    }
}
rewind → dir click to toggle source

Repositions dir to the first entry.

d = Dir.new("testdir")
d.read     #=> "."
d.rewind   #=> #<Dir:0x401b3fb0>
d.read     #=> "."

static VALUE
dir_rewind(VALUE dir)
{
    struct dir_data *dirp;

    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(dir)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    GetDIR(dir, dirp);
    rewinddir(dirp->dir);
    return dir;
}
seek( integer ) → dir click to toggle source

Seeks to a particular location in dir. integer must be a value returned by Dir#tell.

d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
d.read                   #=> "."
i = d.tell               #=> 12
d.read                   #=> ".."
d.seek(i)                #=> #<Dir:0x401b3c40>
d.read                   #=> ".."

static VALUE
dir_seek(VALUE dir, VALUE pos)
{
    struct dir_data *dirp;
    long p = NUM2LONG(pos);

    GetDIR(dir, dirp);
    seekdir(dirp->dir, p);
    return dir;
}
pos → integer click to toggle source
tell → integer

Returns the current position in dir. See also Dir#seek.

d = Dir.new("testdir")
d.tell   #=> 0
d.read   #=> "."
d.tell   #=> 12

static VALUE
dir_tell(VALUE dir)
{
    struct dir_data *dirp;
    long pos;

    GetDIR(dir, dirp);
    pos = telldir(dirp->dir);
    return rb_int2inum(pos);
}
path → string or nil click to toggle source

Returns the path parameter passed to dir's constructor.

d = Dir.new("..")
d.path   #=> ".."

static VALUE
dir_path(VALUE dir)
{
    struct dir_data *dirp;

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
    if (NIL_P(dirp->path)) return Qnil;
    return rb_str_dup(dirp->path);
}


class ENV - Ruby 2.0.0-p576 Core API Reference API Reference

class ENV

ENV is a hash-like accessor for environment variables.

In Files

  • hash.c

Parent

Object

Public Class Methods

ENV[name] → value click to toggle source

Retrieves the value for environment variable name as a String. Returns nil if the named variable does not exist.

static VALUE
rb_f_getenv(VALUE obj, VALUE name)
{
    char *nam, *env;

    rb_secure(4);
    SafeStringValue(name);
    nam = RSTRING_PTR(name);
    if (memchr(nam, '\0', RSTRING_LEN(name))) {
        rb_raise(rb_eArgError, "bad environment variable name");
    }
    env = getenv(nam);
    if (env) {
        if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env)) {
#ifdef _WIN32
            VALUE str = rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding());
#else
            VALUE str = rb_filesystem_str_new_cstr(env);
#endif

            rb_obj_freeze(str);
            return str;
        }
        return env_str_new2(env);
    }
    return Qnil;
}
ENV[name] = value click to toggle source
store(name, value) → value

Sets the environment variable name to value. If the value given is nil the environment variable is deleted.

static VALUE
env_aset(VALUE obj, VALUE nm, VALUE val)
{
    char *name, *value;

    if (rb_safe_level() >= 4) {
        rb_raise(rb_eSecurityError, "can't change environment variable");
    }

    if (NIL_P(val)) {
        env_delete(obj, nm);
        return Qnil;
    }
    SafeStringValue(nm);
    SafeStringValue(val);
    name = RSTRING_PTR(nm);
    value = RSTRING_PTR(val);
    if (memchr(name, '\0', RSTRING_LEN(nm)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (memchr(value, '\0', RSTRING_LEN(val)))
        rb_raise(rb_eArgError, "bad environment variable value");

    ruby_setenv(name, value);
    if (ENVMATCH(name, PATH_ENV)) {
        if (OBJ_TAINTED(val)) {
            /* already tainted, no check */
            path_tainted = 1;
            return val;
        }
        else {
            path_tainted_p(value);
        }
    }
    return val;
}
assoc(name) → Array or nil click to toggle source

Returns an Array of the name and value of the environment variable with name or nil if the name cannot be found.

static VALUE
env_assoc(VALUE env, VALUE key)
{
    char *s, *e;

    rb_secure(4);
    SafeStringValue(key);
    s = RSTRING_PTR(key);
    if (memchr(s, '\0', RSTRING_LEN(key)))
        rb_raise(rb_eArgError, "bad environment variable name");
    e = getenv(s);
    if (e) return rb_assoc_new(key, rb_tainted_str_new2(e));
    return Qnil;
}
clear click to toggle source

Removes every environment variable.

VALUE
rb_env_clear(void)
{
    volatile VALUE keys;
    long i;

    keys = env_keys();  /* rb_secure(4); */
    for (i=0; i<RARRAY_LEN(keys); i++) {
        VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
        if (!NIL_P(val)) {
            env_delete(Qnil, RARRAY_PTR(keys)[i]);
        }
    }
    return envtbl;
}
delete(name) → value click to toggle source
delete(name) { |name| } → value

Deletes the environment variable with name and returns the value of the variable. If a block is given it will be called when the named environment does not exist.

static VALUE
env_delete_m(VALUE obj, VALUE name)
{
    VALUE val;

    val = env_delete(obj, name);
    if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
    return val;
}
delete_if { |name, value| } → Hash click to toggle source
delete_if → Enumerator

Deletes every environment variable for which the block evaluates to true.

If no block is given an enumerator is returned instead.

static VALUE
env_delete_if(VALUE ehash)
{
    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    env_reject_bang(ehash);
    return envtbl;
}
each { |name, value| } → Hash click to toggle source
each → Enumerator
each_pair { |name, value| } → Hash
each_pair → Enumerator

Yields each environment variable name and value.

If no block is given an Enumerator is returned.

static VALUE
env_each_pair(VALUE ehash)
{
    char **env;
    VALUE ary;
    long i;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);

    rb_secure(4);
    ary = rb_ary_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_ary_push(ary, env_str_new(*env, s-*env));
            rb_ary_push(ary, env_str_new2(s+1));
        }
        env++;
    }
    FREE_ENVIRON(environ);

    for (i=0; i<RARRAY_LEN(ary); i+=2) {
        rb_yield(rb_assoc_new(RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1]));
    }
    return ehash;
}
each_key { |name| } → Hash click to toggle source
each_key → Enumerator

Yields each environment variable name.

An Enumerator is returned if no block is given.

static VALUE
env_each_key(VALUE ehash)
{
    VALUE keys;
    long i;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    keys = env_keys();  /* rb_secure(4); */
    for (i=0; i<RARRAY_LEN(keys); i++) {
        rb_yield(RARRAY_PTR(keys)[i]);
    }
    return ehash;
}
each { |name, value| } → Hash click to toggle source
each → Enumerator
each_pair { |name, value| } → Hash
each_pair → Enumerator

Yields each environment variable name and value.

If no block is given an Enumerator is returned.

static VALUE
env_each_pair(VALUE ehash)
{
    char **env;
    VALUE ary;
    long i;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);

    rb_secure(4);
    ary = rb_ary_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_ary_push(ary, env_str_new(*env, s-*env));
            rb_ary_push(ary, env_str_new2(s+1));
        }
        env++;
    }
    FREE_ENVIRON(environ);

    for (i=0; i<RARRAY_LEN(ary); i+=2) {
        rb_yield(rb_assoc_new(RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1]));
    }
    return ehash;
}
each_value { |value| } → Hash click to toggle source
each_value → Enumerator

Yields each environment variable value.

An Enumerator is returned if no block was given.

static VALUE
env_each_value(VALUE ehash)
{
    VALUE values;
    long i;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    values = env_values();      /* rb_secure(4); */
    for (i=0; i<RARRAY_LEN(values); i++) {
        rb_yield(RARRAY_PTR(values)[i]);
    }
    return ehash;
}
empty? → true or false click to toggle source

Returns true when there are no environment variables

static VALUE
env_empty_p(void)
{
    char **env;

    rb_secure(4);
    env = GET_ENVIRON(environ);
    if (env[0] == 0) {
        FREE_ENVIRON(environ);
        return Qtrue;
    }
    FREE_ENVIRON(environ);
    return Qfalse;
}
fetch(name) → value click to toggle source
fetch(name, default) → value
fetch(name) { |missing_name| ... } → value

Retrieves the environment variable name.

If the given name does not exist and neither default nor a block a provided an IndexError is raised. If a block is given it is called with the missing name to provide a value. If a default value is given it will be returned when no block is given.

static VALUE
env_fetch(int argc, VALUE *argv)
{
    VALUE key, if_none;
    long block_given;
    char *nam, *env;

    rb_secure(4);
    rb_scan_args(argc, argv, "11", &key, &if_none);
    block_given = rb_block_given_p();
    if (block_given && argc == 2) {
        rb_warn("block supersedes default value argument");
    }
    SafeStringValue(key);
    nam = RSTRING_PTR(key);
    if (memchr(nam, '\0', RSTRING_LEN(key))) {
        rb_raise(rb_eArgError, "bad environment variable name");
    }
    env = getenv(nam);
    if (!env) {
        if (block_given) return rb_yield(key);
        if (argc == 1) {
            rb_raise(rb_eKeyError, "key not found");
        }
        return if_none;
    }
    if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env))
#ifdef _WIN32
        return rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding());
#else
        return rb_filesystem_str_new_cstr(env);
#endif
    return env_str_new2(env);
}
key?(name) → true or false click to toggle source
include?(name) → true or false
has_key?(name) → true or false
member?(name) → true or false

Returns true if there is an environment variable with the given name.

static VALUE
env_has_key(VALUE env, VALUE key)
{
    char *s;

    rb_secure(4);
    SafeStringValue(key);
    s = RSTRING_PTR(key);
    if (memchr(s, '\0', RSTRING_LEN(key)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (getenv(s)) return Qtrue;
    return Qfalse;
}
value?(value) → true or false click to toggle source
has_value?(value) → true or false

Returns true if there is an environment variable with the given value.

static VALUE
env_has_value(VALUE dmy, VALUE obj)
{
    char **env;

    rb_secure(4);
    obj = rb_check_string_type(obj);
    if (NIL_P(obj)) return Qnil;
    rb_check_safe_obj(obj);
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s++) {
            long len = strlen(s);
            if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
                FREE_ENVIRON(environ);
                return Qtrue;
            }
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return Qfalse;
}
key?(name) → true or false click to toggle source
include?(name) → true or false
has_key?(name) → true or false
member?(name) → true or false

Returns true if there is an environment variable with the given name.

static VALUE
env_has_key(VALUE env, VALUE key)
{
    char *s;

    rb_secure(4);
    SafeStringValue(key);
    s = RSTRING_PTR(key);
    if (memchr(s, '\0', RSTRING_LEN(key)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (getenv(s)) return Qtrue;
    return Qfalse;
}
index(value) → key click to toggle source

Deprecated method that is equivalent to ::key

static VALUE
env_index(VALUE dmy, VALUE value)
{
    rb_warn("ENV.index is deprecated; use ENV.key");
    return env_key(dmy, value);
}
inspect → string click to toggle source

Returns the contents of the environment as a String.

static VALUE
env_inspect(void)
{
    char **env;
    VALUE str, i;

    rb_secure(4);
    str = rb_str_buf_new2("{");
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');

        if (env != environ) {
            rb_str_buf_cat2(str, ", ");
        }
        if (s) {
            rb_str_buf_cat2(str, "\"");
            rb_str_buf_cat(str, *env, s-*env);
            rb_str_buf_cat2(str, "\"=>");
            i = rb_inspect(rb_str_new2(s+1));
            rb_str_buf_append(str, i);
        }
        env++;
    }
    FREE_ENVIRON(environ);
    rb_str_buf_cat2(str, "}");
    OBJ_TAINT(str);

    return str;
}
invert → Hash click to toggle source

Returns a new hash created by using environment variable names as values and values as names.

static VALUE
env_invert(void)
{
    return rb_hash_invert(env_to_hash());
}
keep_if { |name, value| } → Hash click to toggle source
keep_if → Enumerator

Deletes every environment variable where the block evaluates to false.

Returns an enumerator if no block was given.

static VALUE
env_keep_if(VALUE ehash)
{
    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    env_select_bang(ehash);
    return envtbl;
}
key(value) → name click to toggle source

Returns the name of the environment variable with value. If the value is not found nil is returned.

static VALUE
env_key(VALUE dmy, VALUE value)
{
    char **env;
    VALUE str;

    rb_secure(4);
    SafeStringValue(value);
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s++) {
            long len = strlen(s);
            if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
                str = env_str_new(*env, s-*env-1);
                FREE_ENVIRON(environ);
                return str;
            }
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return Qnil;
}
key?(name) → true or false click to toggle source
include?(name) → true or false
has_key?(name) → true or false
member?(name) → true or false

Returns true if there is an environment variable with the given name.

static VALUE
env_has_key(VALUE env, VALUE key)
{
    char *s;

    rb_secure(4);
    SafeStringValue(key);
    s = RSTRING_PTR(key);
    if (memchr(s, '\0', RSTRING_LEN(key)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (getenv(s)) return Qtrue;
    return Qfalse;
}
keys → Array click to toggle source

Returns every environment variable name in an Array

static VALUE
env_keys(void)
{
    char **env;
    VALUE ary;

    rb_secure(4);
    ary = rb_ary_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_ary_push(ary, env_str_new(*env, s-*env));
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return ary;
}
length click to toggle source
size

Returns the number of environment variables.

static VALUE
env_size(void)
{
    int i;
    char **env;

    rb_secure(4);
    env = GET_ENVIRON(environ);
    for (i=0; env[i]; i++)
        ;
    FREE_ENVIRON(environ);
    return INT2FIX(i);
}
key?(name) → true or false click to toggle source
include?(name) → true or false
has_key?(name) → true or false
member?(name) → true or false

Returns true if there is an environment variable with the given name.

static VALUE
env_has_key(VALUE env, VALUE key)
{
    char *s;

    rb_secure(4);
    SafeStringValue(key);
    s = RSTRING_PTR(key);
    if (memchr(s, '\0', RSTRING_LEN(key)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (getenv(s)) return Qtrue;
    return Qfalse;
}
rassoc(value) click to toggle source

Returns an Array of the name and value of the environment variable with value or nil if the value cannot be found.

static VALUE
env_rassoc(VALUE dmy, VALUE obj)
{
    char **env;

    rb_secure(4);
    obj = rb_check_string_type(obj);
    if (NIL_P(obj)) return Qnil;
    rb_check_safe_obj(obj);
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s++) {
            long len = strlen(s);
            if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
                VALUE result = rb_assoc_new(rb_tainted_str_new(*env, s-*env-1), obj);
                FREE_ENVIRON(environ);
                return result;
            }
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return Qnil;
}
rehash click to toggle source

Re-hashing the environment variables does nothing. It is provided for compatibility with Hash.

static VALUE
env_none(void)
{
    return Qnil;
}
reject { |name, value| } → Hash click to toggle source
reject → Enumerator

Same as ENV#delete_if, but works on (and returns) a copy of the environment.

static VALUE
env_reject(void)
{
    return rb_hash_delete_if(env_to_hash());
}
reject! { |name, value| } → ENV or nil click to toggle source
reject! → Enumerator

Equivalent to ENV#delete_if but returns nil if no changes were made.

Returns an Enumerator if no block was given.

static VALUE
env_reject_bang(VALUE ehash)
{
    volatile VALUE keys;
    long i;
    int del = 0;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    keys = env_keys();  /* rb_secure(4); */
    RBASIC(keys)->klass = 0;
    for (i=0; i<RARRAY_LEN(keys); i++) {
        VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
        if (!NIL_P(val)) {
            if (RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) {
                FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
                env_delete(Qnil, RARRAY_PTR(keys)[i]);
                del++;
            }
        }
    }
    if (del == 0) return Qnil;
    return envtbl;
}
replace(hash) → env click to toggle source

Replaces the contents of the environment variables with the contents of hash.

static VALUE
env_replace(VALUE env, VALUE hash)
{
    volatile VALUE keys;
    long i;

    keys = env_keys();  /* rb_secure(4); */
    if (env == hash) return env;
    hash = to_hash(hash);
    rb_hash_foreach(hash, env_replace_i, keys);

    for (i=0; i<RARRAY_LEN(keys); i++) {
        env_delete(env, RARRAY_PTR(keys)[i]);
    }
    return env;
}
select { |name, value| } → Hash click to toggle source
select → Enumerator

Returns a copy of the environment for entries where the block returns true.

Returns an Enumerator if no block was given.

static VALUE
env_select(VALUE ehash)
{
    VALUE result;
    VALUE keys;
    long i;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    rb_secure(4);
    result = rb_hash_new();
    keys = env_keys();
    for (i = 0; i < RARRAY_LEN(keys); ++i) {
        VALUE key = RARRAY_PTR(keys)[i];
        VALUE val = rb_f_getenv(Qnil, key);
        if (!NIL_P(val)) {
            if (RTEST(rb_yield_values(2, key, val))) {
                rb_hash_aset(result, key, val);
            }
        }
    }

    return result;
}
select! { |name, value| } → ENV or nil click to toggle source
select! → Enumerator

Equivalent to ENV#keep_if but returns nil if no changes were made.

static VALUE
env_select_bang(VALUE ehash)
{
    volatile VALUE keys;
    long i;
    int del = 0;

    RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
    keys = env_keys();  /* rb_secure(4); */
    RBASIC(keys)->klass = 0;
    for (i=0; i<RARRAY_LEN(keys); i++) {
        VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
        if (!NIL_P(val)) {
            if (!RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) {
                FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
                env_delete(Qnil, RARRAY_PTR(keys)[i]);
                del++;
            }
        }
    }
    if (del == 0) return Qnil;
    return envtbl;
}
shift → Array or nil click to toggle source

Removes an environment variable name-value pair from ENV and returns it as an Array. Returns nil if when the environment is empty.

static VALUE
env_shift(void)
{
    char **env;
    VALUE result = Qnil;

    rb_secure(4);
    env = GET_ENVIRON(environ);
    if (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            VALUE key = env_str_new(*env, s-*env);
            VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
            env_delete(Qnil, key);
            result = rb_assoc_new(key, val);
        }
    }
    FREE_ENVIRON(environ);
    return result;
}
length click to toggle source
size

Returns the number of environment variables.

static VALUE
env_size(void)
{
    int i;
    char **env;

    rb_secure(4);
    env = GET_ENVIRON(environ);
    for (i=0; env[i]; i++)
        ;
    FREE_ENVIRON(environ);
    return INT2FIX(i);
}
ENV[name] = value click to toggle source
store(name, value) → value

Sets the environment variable name to value. If the value given is nil the environment variable is deleted.

static VALUE
env_aset(VALUE obj, VALUE nm, VALUE val)
{
    char *name, *value;

    if (rb_safe_level() >= 4) {
        rb_raise(rb_eSecurityError, "can't change environment variable");
    }

    if (NIL_P(val)) {
        env_delete(obj, nm);
        return Qnil;
    }
    SafeStringValue(nm);
    SafeStringValue(val);
    name = RSTRING_PTR(nm);
    value = RSTRING_PTR(val);
    if (memchr(name, '\0', RSTRING_LEN(nm)))
        rb_raise(rb_eArgError, "bad environment variable name");
    if (memchr(value, '\0', RSTRING_LEN(val)))
        rb_raise(rb_eArgError, "bad environment variable value");

    ruby_setenv(name, value);
    if (ENVMATCH(name, PATH_ENV)) {
        if (OBJ_TAINTED(val)) {
            /* already tainted, no check */
            path_tainted = 1;
            return val;
        }
        else {
            path_tainted_p(value);
        }
    }
    return val;
}
to_a → Array click to toggle source

Converts the environment variables into an array of names and value arrays.

ENV.to_a # => [["TERM", "xterm-color"], ["SHELL", "/bin/bash"], ...]

static VALUE
env_to_a(void)
{
    char **env;
    VALUE ary;

    rb_secure(4);
    ary = rb_ary_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
                                          env_str_new2(s+1)));
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return ary;
}
to_hash → hash click to toggle source
to_h → hash

Creates a hash with a copy of the environment variables.

static VALUE
env_to_hash(void)
{
    char **env;
    VALUE hash;

    rb_secure(4);
    hash = rb_hash_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_hash_aset(hash, env_str_new(*env, s-*env),
                               env_str_new2(s+1));
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return hash;
}
to_hash → hash click to toggle source
to_h → hash

Creates a hash with a copy of the environment variables.

static VALUE
env_to_hash(void)
{
    char **env;
    VALUE hash;

    rb_secure(4);
    hash = rb_hash_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_hash_aset(hash, env_str_new(*env, s-*env),
                               env_str_new2(s+1));
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return hash;
}
to_s → "ENV" click to toggle source

Returns “ENV”

static VALUE
env_to_s(void)
{
    return rb_usascii_str_new2("ENV");
}
update(hash) → Hash click to toggle source
update(hash) { |name, old_value, new_value| } → Hash

Adds the contents of hash to the environment variables. If no block is specified entries with duplicate keys are overwritten, otherwise the value of each duplicate name is determined by calling the block with the key, its value from the environment and its value from the hash.

static VALUE
env_update(VALUE env, VALUE hash)
{
    rb_secure(4);
    if (env == hash) return env;
    hash = to_hash(hash);
    rb_hash_foreach(hash, env_update_i, 0);
    return env;
}
value?(value) → true or false click to toggle source
has_value?(value) → true or false

Returns true if there is an environment variable with the given value.

static VALUE
env_has_value(VALUE dmy, VALUE obj)
{
    char **env;

    rb_secure(4);
    obj = rb_check_string_type(obj);
    if (NIL_P(obj)) return Qnil;
    rb_check_safe_obj(obj);
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s++) {
            long len = strlen(s);
            if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
                FREE_ENVIRON(environ);
                return Qtrue;
            }
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return Qfalse;
}
values → Array click to toggle source

Returns every environment variable value as an Array

static VALUE
env_values(void)
{
    VALUE ary;
    char **env;

    rb_secure(4);
    ary = rb_ary_new();
    env = GET_ENVIRON(environ);
    while (*env) {
        char *s = strchr(*env, '=');
        if (s) {
            rb_ary_push(ary, env_str_new2(s+1));
        }
        env++;
    }
    FREE_ENVIRON(environ);
    return ary;
}
values_at(name, ...) → Array click to toggle source

Returns an array containing the environment variable values associated with the given names. See also ::select.

static VALUE
env_values_at(int argc, VALUE *argv)
{
    VALUE result;
    long i;

    rb_secure(4);
    result = rb_ary_new();
    for (i=0; i<argc; i++) {
        rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
    }
    return result;
}


class EOFError - Ruby 2.0.0-p576 Core API Reference API Reference

class EOFError

Raised by some IO operations when reaching the end of file. Many IO methods exist in two forms,

one that returns nil when the end of file is reached, the other raises EOFError EOFError.

EOFError is a subclass of IOError.

file = File.open("/etc/hosts")
file.read
file.gets     #=> nil
file.readline #=> EOFError: end of file reached

In Files

  • io.c

Parent

IOError


class Encoding - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding

An Encoding instance represents a character encoding usable in Ruby. It is defined as a constant under the Encoding namespace. It has a name and optionally, aliases:

Encoding::ISO_8859_1.name
#=> #<Encoding:ISO-8859-1>

Encoding::ISO_8859_1.names
#=> ["ISO-8859-1", "ISO8859-1"]

Ruby methods dealing with encodings return or accept Encoding instances as arguments (when a method accepts an Encoding instance as an argument, it can be passed an Encoding name or alias instead).

"some string".encoding
#=> #<Encoding:UTF-8>

string = "some string".encode(Encoding::ISO_8859_1)
#=> "some string"
string.encoding
#=> #<Encoding:ISO-8859-1>

"some string".encode "ISO-8859-1"
#=> "some string"

Encoding::ASCII_8BIT is a special encoding that is usually used for a byte string, not a character string. But as the name insists, its characters in the range of ASCII are considered as ASCII characters. This is useful when you use ASCII-8BIT characters with other ASCII compatible characters.

Changing an encoding

The associated Encoding of a String can be changed in two different ways.

First, it is possible to set the Encoding of a string to a new Encoding without changing the internal byte representation of the string, with String#force_encoding. This is how you can tell Ruby the correct encoding of a string.

string
#=> "R\xC3\xA9sum\xC3\xA9"
string.encoding
#=> #<Encoding:ISO-8859-1>
string.force_encoding(Encoding::UTF-8)
#=> "R\u00E9sum\u00E9"

Second, it is possible to transcode a string, i.e. translate its internal byte representation to another encoding. Its associated encoding is also set to the other encoding. See String#encode for the various forms of transcoding, and the Encoding::Converter class for additional control over the transcoding process.

string
#=> "R\u00E9sum\u00E9"
string.encoding
#=> #<Encoding:UTF-8>
string = string.encode!(Encoding::ISO_8859_1)
#=> "R\xE9sum\xE9"
string.encoding
#=> #<Encoding::ISO-8859-1>

Script encoding

All Ruby script code has an associated Encoding which any String literal created in the source code will be associated to.

The default script encoding is Encoding::US-ASCII, but it can be changed by a magic comment on the first line of the source code file (or second line, if there is a shebang line on the first). The comment must contain the word coding or encoding, followed by a colon, space and the Encoding name or alias:

# encoding: UTF-8

"some string".encoding
#=> #<Encoding:UTF-8>

The __ENCODING__ keyword returns the script encoding of the file which the keyword is written:

# encoding: ISO-8859-1

__ENCODING__
#=> #<Encoding:ISO-8859-1>

ruby -K will change the default locale encoding, but this is not recommended. Ruby source files should declare its script encoding by a magic comment even when they only depend on US-ASCII strings or regular expressions.

Locale encoding

The default encoding of the environment. Usually derived from locale.

see ::locale_charmap, ::find('locale')

Filesystem encoding

The default encoding of strings from the filesystem of the environment. This is used for strings of file names or paths.

see ::find('filesystem')

External encoding

Each IO object has an external encoding which indicates the encoding that Ruby will use to read its data. By default Ruby sets the external encoding of an IO object to the default external encoding. The default external encoding is set by locale encoding or the interpreter -E option. ::default_external returns the current value of the external encoding.

ENV["LANG"]
#=> "UTF-8"
Encoding.default_external
#=> #<Encoding:UTF-8>

$ ruby -E ISO-8859-1 -e "p Encoding.default_external"
#<Encoding:ISO-8859-1>

$ LANG=C ruby -e 'p Encoding.default_external'
#<Encoding:US-ASCII>

The default external encoding may also be set through ::default_external=, but you should not do this as strings created before and after the change will have inconsistent encodings. Instead use ruby -E to invoke ruby with the correct external encoding.

When you know that the actual encoding of the data of an IO object is not the default external encoding, you can reset its external encoding with IO#set_encoding or set it at IO object creation (see IO.new options).

Internal encoding

To process the data of an IO object which has an encoding different from its external encoding, you can set its internal encoding. Ruby will use this internal encoding to transcode the data when it is read from the IO object.

Conversely, when data is written to the IO object it is transcoded from the internal encoding to the external encoding of the IO object.

The internal encoding of an IO object can be set with IO#set_encoding or at IO object creation (see IO.new options).

The internal encoding is optional and when not set, the Ruby default internal encoding is used. If not explicitly set this default internal encoding is nil meaning that by default, no transcoding occurs.

The default internal encoding can be set with the interpreter option -E. ::default_internal returns the current internal encoding.

$ ruby -e 'p Encoding.default_internal'
nil

$ ruby -E ISO-8859-1:UTF-8 -e "p [Encoding.default_external, \
  Encoding.default_internal]"
[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>]

The default internal encoding may also be set through ::default_internal=, but you should not do this as strings created before and after the change will have inconsistent encodings. Instead use ruby -E to invoke ruby with the correct internal encoding.

IO encoding example

In the following example a UTF-8 encoded string “Ru00E9sumu00E9” is transcoded for output to ISO-8859-1 encoding, then read back in and transcoded to UTF-8:

string = "R\u00E9sum\u00E9"

open("transcoded.txt", "w:ISO-8859-1") do |io|
  io.write(string)
end

puts "raw text:"
p File.binread("transcoded.txt")
puts

open("transcoded.txt", "r:ISO-8859-1:UTF-8") do |io|
  puts "transcoded text:"
  p io.read
end

While writing the file, the internal encoding is not specified as it is only necessary for reading. While reading the file both the internal and external encoding must be specified to obtain the correct result.

$ ruby t.rb
raw text:
"R\xE9sum\xE9"

transcoded text:
"R\u00E9sum\u00E9"

In Files

  • encoding.c
  • transcode.c

Parent

Object

Public Class Methods

aliases -> {"alias1" => "orig1", "alias2" → "orig2", ...} click to toggle source

Returns the hash of available encoding alias and original encoding name.

Encoding.aliases
#=> {"BINARY"=>"ASCII-8BIT", "ASCII"=>"US-ASCII", "ANSI_X3.4-1986"=>"US-ASCII",
      "SJIS"=>"Shift_JIS", "eucJP"=>"EUC-JP", "CP932"=>"Windows-31J"}

static VALUE
rb_enc_aliases(VALUE klass)
{
    VALUE aliases[2];
    aliases[0] = rb_hash_new();
    aliases[1] = rb_ary_new();
    st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
    return aliases[0];
}
compatible?(obj1, obj2) → enc or nil click to toggle source

Checks the compatibility of two objects.

If the objects are both strings they are compatible when they are concatenatable. The encoding of the concatenated string will be returned if they are compatible, nil if they are not.

Encoding.compatible?("\xa1".force_encoding("iso-8859-1"), "b")
#=> #<Encoding:ISO-8859-1>

Encoding.compatible?(
  "\xa1".force_encoding("iso-8859-1"),
  "\xa1\xa1".force_encoding("euc-jp"))
#=> nil

If the objects are non-strings their encodings are compatible when they have an encoding and:

  • Either encoding is US-ASCII compatible

  • One of the encodings is a 7-bit encoding

static VALUE
enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
{
    rb_encoding *enc;

    if (!enc_capable(str1)) return Qnil;
    if (!enc_capable(str2)) return Qnil;
    enc = rb_enc_compatible(str1, str2);
    if (!enc) return Qnil;
    return rb_enc_from_encoding(enc);
}
default_external → enc click to toggle source

Returns default external encoding.

The default external encoding is used by default for strings created from the following locations:

  • CSV

  • File data read from disk

  • SDBM

  • StringIO

  • Zlib::GzipReader

  • Zlib::GzipWriter

  • String#inspect

  • Regexp#inspect

While strings created from these locations will have this encoding, the encoding may not be valid. Be sure to check String#valid_encoding?.

File data written to disk will be transcoded to the default external encoding when written.

The default external encoding is initialized by the locale or -E option.

static VALUE
get_default_external(VALUE klass)
{
    return rb_enc_default_external();
}
default_external = enc click to toggle source

Sets default external encoding. You should not set ::default_external in ruby code as strings created before changing the value may have a different encoding from strings created after the value was changed., instead you should use ruby -E to invoke ruby with the correct default_external.

See ::default_external for information on how the default external encoding is used.

static VALUE
set_default_external(VALUE klass, VALUE encoding)
{
    rb_warning("setting Encoding.default_external");
    rb_enc_set_default_external(encoding);
    return encoding;
}
default_internal → enc click to toggle source

Returns default internal encoding. Strings will be transcoded to the default internal encoding in the following places if the default internal encoding is not nil:

  • CSV

  • Etc.sysconfdir and Etc.systmpdir

  • File data read from disk

  • File names from Dir

  • Integer#chr

  • String#inspect and Regexp#inspect

  • Strings returned from Curses

  • Strings returned from Readline

  • Strings returned from SDBM

  • Time#zone

  • Values from ENV

  • Values in ARGV including $PROGRAM_NAME

  • __FILE__

Additionally String#encode and String#encode! use the default internal encoding if no encoding is given.

The locale encoding (__ENCODING__), not ::default_internal, is used as the encoding of created strings.

::default_internal is initialized by the source file's internal_encoding or -E option.

static VALUE
get_default_internal(VALUE klass)
{
    return rb_enc_default_internal();
}
default_internal = enc or nil click to toggle source

Sets default internal encoding or removes default internal encoding when passed nil. You should not set ::default_internal in ruby code as strings created before changing the value may have a different encoding from strings created after the change. Instead you should use ruby -E to invoke ruby with the correct default_internal.

See ::default_internal for information on how the default internal encoding is used.

static VALUE
set_default_internal(VALUE klass, VALUE encoding)
{
    rb_warning("setting Encoding.default_internal");
    rb_enc_set_default_internal(encoding);
    return encoding;
}
find(string) → enc click to toggle source

Search the encoding with specified name. name should be a string.

Encoding.find("US-ASCII")  #=> #<Encoding:US-ASCII>

Names which this method accept are encoding names and aliases including following special aliases

“external”

default external encoding

“internal”

default internal encoding

“locale”

locale encoding

“filesystem”

filesystem encoding

An ArgumentError is raised when no encoding with name. Only Encoding.find("internal") however returns nil when no encoding named “internal”, in other words, when Ruby has no default internal encoding.

static VALUE
enc_find(VALUE klass, VALUE enc)
{
    int idx;
    if (RB_TYPE_P(enc, T_DATA) && is_data_encoding(enc))
        return enc;
    idx = str_to_encindex(enc);
    if (idx == UNSPECIFIED_ENCODING) return Qnil;
    return rb_enc_from_encoding_index(idx);
}
list → [enc1, enc2, ...] click to toggle source

Returns the list of loaded encodings.

Encoding.list
#=> [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>,
      #<Encoding:ISO-2022-JP (dummy)>]

Encoding.find("US-ASCII")
#=> #<Encoding:US-ASCII>

Encoding.list
#=> [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>,
      #<Encoding:US-ASCII>, #<Encoding:ISO-2022-JP (dummy)>]

static VALUE
enc_list(VALUE klass)
{
    VALUE ary = rb_ary_new2(0);
    rb_ary_replace(ary, rb_encoding_list);
    return ary;
}
locale_charmap → string click to toggle source

Returns the locale charmap name. It returns nil if no appropriate information.

Debian GNU/Linux
  LANG=C
    Encoding.locale_charmap  #=> "ANSI_X3.4-1968"
  LANG=ja_JP.EUC-JP
    Encoding.locale_charmap  #=> "EUC-JP"

SunOS 5
  LANG=C
    Encoding.locale_charmap  #=> "646"
  LANG=ja
    Encoding.locale_charmap  #=> "eucJP"

The result is highly platform dependent. So ::find may cause an error. If you need some encoding object even for unknown locale, ::find(“locale”) can be used.

VALUE
rb_locale_charmap(VALUE klass)
{
#if defined NO_LOCALE_CHARMAP
    return rb_usascii_str_new2("ASCII-8BIT");
#elif defined _WIN32 || defined __CYGWIN__
    const char *codeset = 0;
    char cp[sizeof(int) * 3 + 4];
# ifdef __CYGWIN__
    const char *nl_langinfo_codeset(void);
    codeset = nl_langinfo_codeset();
# endif
    if (!codeset) {
        UINT codepage = GetConsoleCP();
        if (!codepage) codepage = GetACP();
        snprintf(cp, sizeof(cp), "CP%d", codepage);
        codeset = cp;
    }
    return rb_usascii_str_new2(codeset);
#elif defined HAVE_LANGINFO_H
    char *codeset;
    codeset = nl_langinfo(CODESET);
    return rb_usascii_str_new2(codeset);
#else
    return Qnil;
#endif
}
name_list → ["enc1", "enc2", ...] click to toggle source

Returns the list of available encoding names.

Encoding.name_list
#=> ["US-ASCII", "ASCII-8BIT", "UTF-8",
      "ISO-8859-1", "Shift_JIS", "EUC-JP",
      "Windows-31J",
      "BINARY", "CP932", "eucJP"]

static VALUE
rb_enc_name_list(VALUE klass)
{
    VALUE ary = rb_ary_new2(enc_table.names->num_entries);
    st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
    return ary;
}

Public Instance Methods

ascii_compatible? → true or false click to toggle source

Returns whether ASCII-compatible or not.

Encoding::UTF_8.ascii_compatible?     #=> true
Encoding::UTF_16BE.ascii_compatible?  #=> false

static VALUE
enc_ascii_compatible_p(VALUE enc)
{
    return rb_enc_asciicompat(enc_table.list[must_encoding(enc)].enc) ? Qtrue : Qfalse;
}
dummy? → true or false click to toggle source

Returns true for dummy encodings. A dummy encoding is an encoding for which character handling is not properly implemented. It is used for stateful encodings.

Encoding::ISO_2022_JP.dummy?       #=> true
Encoding::UTF_8.dummy?             #=> false

static VALUE
enc_dummy_p(VALUE enc)
{
    return ENC_DUMMY_P(enc_table.list[must_encoding(enc)].enc) ? Qtrue : Qfalse;
}
inspect → string click to toggle source

Returns a string which represents the encoding for programmers.

Encoding::UTF_8.inspect       #=> "#<Encoding:UTF-8>"
Encoding::ISO_2022_JP.inspect #=> "#<Encoding:ISO-2022-JP (dummy)>"

static VALUE
enc_inspect(VALUE self)
{
    VALUE str = rb_sprintf("#<%s:%s%s>", rb_obj_classname(self),
                      rb_enc_name((rb_encoding*)DATA_PTR(self)),
                      (enc_dummy_p(self) ? " (dummy)" : ""));
    ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
    return str;
}
name → string click to toggle source

Returns the name of the encoding.

Encoding::UTF_8.name      #=> "UTF-8"

static VALUE
enc_name(VALUE self)
{
    return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
}
names → array click to toggle source

Returns the list of name and aliases of the encoding.

Encoding::WINDOWS_31J.names  #=> ["Windows-31J", "CP932", "csWindows31J"]

static VALUE
enc_names(VALUE self)
{
    VALUE args[2];

    args[0] = (VALUE)rb_to_encoding_index(self);
    args[1] = rb_ary_new2(0);
    st_foreach(enc_table.names, enc_names_i, (st_data_t)args);
    return args[1];
}
replicate(name) → encoding click to toggle source

Returns a replicated encoding of enc whose name is name. The new encoding should have the same byte structure of enc. If name is used by another encoding, raise ArgumentError.

static VALUE
enc_replicate(VALUE encoding, VALUE name)
{
    return rb_enc_from_encoding_index(
        rb_enc_replicate(StringValueCStr(name),
                         rb_to_encoding(encoding)));
}
name → string click to toggle source

Returns the name of the encoding.

Encoding::UTF_8.name      #=> "UTF-8"

static VALUE
enc_name(VALUE self)
{
    return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
}


class Encoding::CompatibilityError - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding::CompatibilityError

Raised by Encoding and String methods when the source encoding is incompatible with the target encoding.

In Files

  • encoding.c

Parent

EncodingError


class Encoding::Converter - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding::Converter

In Files

  • encoding.c

Parent

Data

Constants

AFTER_OUTPUT

AFTER_OUTPUT

Stop converting after some output is complete but before all of the input was consumed. See #primitive_convert for an example.

CRLF_NEWLINE_DECORATOR

CRLF_NEWLINE_DECORATOR

Decorator for converting LF to CRLF

CR_NEWLINE_DECORATOR

CR_NEWLINE_DECORATOR

Decorator for converting LF to CR

INVALID_MASK

INVALID_MASK

Mask for invalid byte sequences

INVALID_REPLACE

INVALID_REPLACE

Replace invalid byte sequences

PARTIAL_INPUT

PARTIAL_INPUT

Indicates the source may be part of a larger string. See #primitive_convert for an example.

UNDEF_HEX_CHARREF

UNDEF_HEX_CHARREF

Replace byte sequences that are undefined in the destination encoding with an XML hexadecimal character reference. This is valid for XML conversion.

UNDEF_MASK

UNDEF_MASK

Mask for a valid character in the source encoding but no related character(s) in destination encoding.

UNDEF_REPLACE

UNDEF_REPLACE

Replace byte sequences that are undefined in the destination encoding.

UNIVERSAL_NEWLINE_DECORATOR

UNIVERSAL_NEWLINE_DECORATOR

Decorator for converting CRLF and CR to LF

XML_ATTR_CONTENT_DECORATOR

XML_ATTR_CONTENT_DECORATOR

Escape as XML AttValue

XML_ATTR_QUOTE_DECORATOR

XML_ATTR_QUOTE_DECORATOR

Escape as XML AttValue

XML_TEXT_DECORATOR

XML_TEXT_DECORATOR

Escape as XML CharData

Public Class Methods

Encoding::Converter.asciicompat_encoding(string) → encoding or nil click to toggle source
Encoding::Converter.asciicompat_encoding(encoding) → encoding or nil

Returns the corresponding ASCII compatible encoding.

Returns nil if the argument is an ASCII compatible encoding.

“corresponding ASCII compatible encoding” is an ASCII compatible encoding which can represents exactly the same characters as the given ASCII incompatible encoding. So, no conversion undefined error occurs when converting between the two encodings.

Encoding::Converter.asciicompat_encoding("ISO-2022-JP") #=> #<Encoding:stateless-ISO-2022-JP>
Encoding::Converter.asciicompat_encoding("UTF-16BE") #=> #<Encoding:UTF-8>
Encoding::Converter.asciicompat_encoding("UTF-8") #=> nil

static VALUE
econv_s_asciicompat_encoding(VALUE klass, VALUE arg)
{
    const char *arg_name, *result_name;
    rb_encoding *arg_enc, *result_enc;

    enc_arg(&arg, &arg_name, &arg_enc);

    result_name = rb_econv_asciicompat_encoding(arg_name);

    if (result_name == NULL)
        return Qnil;

    result_enc = make_encoding(result_name);

    return rb_enc_from_encoding(result_enc);
}
Encoding::Converter.new(source_encoding, destination_encoding) click to toggle source
Encoding::Converter.new(source_encoding, destination_encoding, opt)
Encoding::Converter.new(convpath)

possible options elements:

hash form:
  :invalid => nil            # raise error on invalid byte sequence (default)
  :invalid => :replace       # replace invalid byte sequence
  :undef => nil              # raise error on undefined conversion (default)
  :undef => :replace         # replace undefined conversion
  :replace => string         # replacement string ("?" or "\uFFFD" if not specified)
  :newline => :universal     # decorator for converting CRLF and CR to LF
  :newline => :crlf          # decorator for converting LF to CRLF
  :newline => :cr            # decorator for converting LF to CR
  :universal_newline => true # decorator for converting CRLF and CR to LF
  :crlf_newline => true      # decorator for converting LF to CRLF
  :cr_newline => true        # decorator for converting LF to CR
  :xml => :text              # escape as XML CharData.
  :xml => :attr              # escape as XML AttValue
integer form:
  Encoding::Converter::INVALID_REPLACE
  Encoding::Converter::UNDEF_REPLACE
  Encoding::Converter::UNDEF_HEX_CHARREF
  Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR
  Encoding::Converter::CRLF_NEWLINE_DECORATOR
  Encoding::Converter::CR_NEWLINE_DECORATOR
  Encoding::Converter::XML_TEXT_DECORATOR
  Encoding::Converter::XML_ATTR_CONTENT_DECORATOR
  Encoding::Converter::XML_ATTR_QUOTE_DECORATOR

::new creates an instance of Encoding::Converter.

Source_encoding and #destination_encoding should be a string or Encoding object.

opt should be nil, a hash or an integer.

convpath should be an array. convpath may contain

  • two-element arrays which contain encodings or encoding names, or

  • strings representing decorator names.

::new optionally takes an option. The option should be a hash or an integer. The option hash can contain :invalid => nil, etc. The option integer should be logical-or of constants such as Encoding::Converter::INVALID_REPLACE, etc.

:invalid => nil

Raise error on invalid byte sequence. This is a default behavior.

:invalid => :replace

Replace invalid byte sequence by replacement string.

:undef => nil

Raise an error if a character in #source_encoding is not defined in destination_encoding. This is a default behavior.

:undef => :replace

Replace undefined character in #destination_encoding with replacement string.

:replace => string

Specify the replacement string. If not specified, “uFFFD” is used for Unicode encodings and “?” for others.

:universal_newline => true

Convert CRLF and CR to LF.

:crlf_newline => true

Convert LF to CRLF.

:cr_newline => true

Convert LF to CR.

:xml => :text

Escape as XML CharData. This form can be used as a HTML 4.0 #PCDATA.

  • '&' -> '&amp;'

  • '<' -> '&lt;'

  • '>' -> '&gt;'

  • undefined characters in #destination_encoding -> hexadecimal CharRef such as &xHH;

:xml => :attr

Escape as XML AttValue. The converted result is quoted as “…”. This form can be used as a HTML 4.0 attribute value.

  • '&' -> '&amp;'

  • '<' -> '&lt;'

  • '>' -> '&gt;'

  • '“' -> '&quot;'

  • undefined characters in #destination_encoding -> hexadecimal CharRef such as &xHH;

Examples:

# UTF-16BE to UTF-8
ec = Encoding::Converter.new("UTF-16BE", "UTF-8")

# Usually, decorators such as newline conversion are inserted last.
ec = Encoding::Converter.new("UTF-16BE", "UTF-8", :universal_newline => true)
p ec.convpath #=> [[#<Encoding:UTF-16BE>, #<Encoding:UTF-8>],
              #    "universal_newline"]

# But, if the last encoding is ASCII incompatible,
# decorators are inserted before the last conversion.
ec = Encoding::Converter.new("UTF-8", "UTF-16BE", :crlf_newline => true)
p ec.convpath #=> ["crlf_newline",
              #    [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]]

# Conversion path can be specified directly.
ec = Encoding::Converter.new(["universal_newline", ["EUC-JP", "UTF-8"], ["UTF-8", "UTF-16BE"]])
p ec.convpath #=> ["universal_newline",
              #    [#<Encoding:EUC-JP>, #<Encoding:UTF-8>],
              #    [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]]

static VALUE
econv_init(int argc, VALUE *argv, VALUE self)
{
    VALUE ecopts;
    volatile VALUE snamev, dnamev;
    const char *sname, *dname;
    rb_encoding *senc, *denc;
    rb_econv_t *ec;
    int ecflags;
    VALUE convpath;

    if (rb_check_typeddata(self, &econv_data_type)) {
        rb_raise(rb_eTypeError, "already initialized");
    }

    if (argc == 1 && !NIL_P(convpath = rb_check_array_type(argv[0]))) {
        ec = rb_econv_init_by_convpath(self, convpath, &sname, &dname, &senc, &denc);
        ecflags = 0;
        ecopts = Qnil;
    }
    else {
        econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
        ec = rb_econv_open_opts(sname, dname, ecflags, ecopts);
    }

    if (!ec) {
        rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
    }

    if (!DECORATOR_P(sname, dname)) {
        if (!senc)
            senc = make_dummy_encoding(sname);
        if (!denc)
            denc = make_dummy_encoding(dname);
    }

    ec->source_encoding = senc;
    ec->destination_encoding = denc;

    DATA_PTR(self) = ec;

    return self;
}
Encoding::Converter.search_convpath(source_encoding, destination_encoding) → ary click to toggle source
Encoding::Converter.search_convpath(source_encoding, destination_encoding, opt) → ary

Returns a conversion path.

p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP")
#=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
#    [#<Encoding:UTF-8>, #<Encoding:EUC-JP>]]

p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", universal_newline: true)
or
p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", newline: :universal)
#=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
#    [#<Encoding:UTF-8>, #<Encoding:EUC-JP>],
#    "universal_newline"]

p Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", universal_newline: true)
or
p Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", newline: :universal)
#=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
#    "universal_newline",
#    [#<Encoding:UTF-8>, #<Encoding:UTF-32BE>]]

static VALUE
econv_s_search_convpath(int argc, VALUE *argv, VALUE klass)
{
    volatile VALUE snamev, dnamev;
    const char *sname, *dname;
    rb_encoding *senc, *denc;
    int ecflags;
    VALUE ecopts;
    VALUE convpath;

    econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);

    convpath = Qnil;
    transcode_search_path(sname, dname, search_convpath_i, &convpath);

    if (NIL_P(convpath))
        rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));

    if (decorate_convpath(convpath, ecflags) == -1)
        rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));

    return convpath;
}

Public Instance Methods

ec == other → true or false click to toggle source
static VALUE
econv_equal(VALUE self, VALUE other)
{
    rb_econv_t *ec1 = check_econv(self);
    rb_econv_t *ec2;
    int i;

    if (!rb_typeddata_is_kind_of(other, &econv_data_type)) {
        return Qnil;
    }
    ec2 = DATA_PTR(other);
    if (!ec2) return Qfalse;
    if (ec1->source_encoding_name != ec2->source_encoding_name &&
        strcmp(ec1->source_encoding_name, ec2->source_encoding_name))
        return Qfalse;
    if (ec1->destination_encoding_name != ec2->destination_encoding_name &&
        strcmp(ec1->destination_encoding_name, ec2->destination_encoding_name))
        return Qfalse;
    if (ec1->flags != ec2->flags) return Qfalse;
    if (ec1->replacement_enc != ec2->replacement_enc &&
        strcmp(ec1->replacement_enc, ec2->replacement_enc))
        return Qfalse;
    if (ec1->replacement_len != ec2->replacement_len) return Qfalse;
    if (ec1->replacement_str != ec2->replacement_str &&
        memcmp(ec1->replacement_str, ec2->replacement_str, ec2->replacement_len))
        return Qfalse;

    if (ec1->num_trans != ec2->num_trans) return Qfalse;
    for (i = 0; i < ec1->num_trans; i++) {
        if (ec1->elems[i].tc->transcoder != ec2->elems[i].tc->transcoder)
            return Qfalse;
    }
    return Qtrue;
}
convert(source_string) → destination_string click to toggle source

Convert source_string and return destination_string.

source_string is assumed as a part of source. i.e. :partial_input=>true is specified internally. finish method should be used last.

ec = Encoding::Converter.new("utf-8", "euc-jp")
puts ec.convert("\u3042").dump     #=> "\xA4\xA2"
puts ec.finish.dump                #=> ""

ec = Encoding::Converter.new("euc-jp", "utf-8")
puts ec.convert("\xA4").dump       #=> ""
puts ec.convert("\xA2").dump       #=> "\xE3\x81\x82"
puts ec.finish.dump                #=> ""

ec = Encoding::Converter.new("utf-8", "iso-2022-jp")
puts ec.convert("\xE3").dump       #=> "".force_encoding("ISO-2022-JP")
puts ec.convert("\x81").dump       #=> "".force_encoding("ISO-2022-JP")
puts ec.convert("\x82").dump       #=> "\e$B$\"".force_encoding("ISO-2022-JP")
puts ec.finish.dump                #=> "\e(B".force_encoding("ISO-2022-JP")

If a conversion error occur, Encoding::UndefinedConversionError or Encoding::InvalidByteSequenceError is raised. #convert doesn't supply methods to recover or restart from these exceptions. When you want to handle these conversion errors, use #primitive_convert.

static VALUE
econv_convert(VALUE self, VALUE source_string)
{
    VALUE ret, dst;
    VALUE av[5];
    int ac;
    rb_econv_t *ec = check_econv(self);

    StringValue(source_string);

    dst = rb_str_new(NULL, 0);

    av[0] = rb_str_dup(source_string);
    av[1] = dst;
    av[2] = Qnil;
    av[3] = Qnil;
    av[4] = INT2NUM(ECONV_PARTIAL_INPUT);
    ac = 5;

    ret = econv_primitive_convert(ac, av, self);

    if (ret == sym_invalid_byte_sequence ||
        ret == sym_undefined_conversion ||
        ret == sym_incomplete_input) {
        VALUE exc = make_econv_exception(ec);
        rb_exc_raise(exc);
    }

    if (ret == sym_finished) {
        rb_raise(rb_eArgError, "converter already finished");
    }

    if (ret != sym_source_buffer_empty) {
        rb_bug("unexpected result of econv_primitive_convert");
    }

    return dst;
}
convpath → ary click to toggle source

Returns the conversion path of ec.

The result is an array of conversions.

ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP", crlf_newline: true)
p ec.convpath
#=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
#    [#<Encoding:UTF-8>, #<Encoding:EUC-JP>],
#    "crlf_newline"]

Each element of the array is a pair of encodings or a string. A pair means an encoding conversion. A string means a decorator.

In the above example, [#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>] means a converter from ISO-8859-1 to UTF-8. “crlf_newline” means newline converter from LF to CRLF.

static VALUE
econv_convpath(VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    VALUE result;
    int i;

    result = rb_ary_new();
    for (i = 0; i < ec->num_trans; i++) {
        const rb_transcoder *tr = ec->elems[i].tc->transcoder;
        VALUE v;
        if (DECORATOR_P(tr->src_encoding, tr->dst_encoding))
            v = rb_str_new_cstr(tr->dst_encoding);
        else
            v = rb_assoc_new(make_encobj(tr->src_encoding), make_encobj(tr->dst_encoding));
        rb_ary_push(result, v);
    }
    return result;
}
destination_encoding → encoding click to toggle source

Returns the destination encoding as an Encoding object.

static VALUE
econv_destination_encoding(VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    if (!ec->destination_encoding)
        return Qnil;
    return rb_enc_from_encoding(ec->destination_encoding);
}
finish → string click to toggle source

Finishes the converter. It returns the last part of the converted string.

ec = Encoding::Converter.new("utf-8", "iso-2022-jp")
p ec.convert("\u3042")     #=> "\e$B$\""
p ec.finish                #=> "\e(B"

static VALUE
econv_finish(VALUE self)
{
    VALUE ret, dst;
    VALUE av[5];
    int ac;
    rb_econv_t *ec = check_econv(self);

    dst = rb_str_new(NULL, 0);

    av[0] = Qnil;
    av[1] = dst;
    av[2] = Qnil;
    av[3] = Qnil;
    av[4] = INT2NUM(0);
    ac = 5;

    ret = econv_primitive_convert(ac, av, self);

    if (ret == sym_invalid_byte_sequence ||
        ret == sym_undefined_conversion ||
        ret == sym_incomplete_input) {
        VALUE exc = make_econv_exception(ec);
        rb_exc_raise(exc);
    }

    if (ret != sym_finished) {
        rb_bug("unexpected result of econv_primitive_convert");
    }

    return dst;
}
insert_output(string) → nil click to toggle source

Inserts string into the encoding converter. The string will be converted to the destination encoding and output on later conversions.

If the destination encoding is stateful, string is converted according to the state and the state is updated.

This method should be used only when a conversion error occurs.

ec = Encoding::Converter.new("utf-8", "iso-8859-1")
src = "HIRAGANA LETTER A is \u{3042}."
dst = ""
p ec.primitive_convert(src, dst)    #=> :undefined_conversion
puts "[#{dst.dump}, #{src.dump}]"   #=> ["HIRAGANA LETTER A is ", "."]
ec.insert_output("<err>")
p ec.primitive_convert(src, dst)    #=> :finished
puts "[#{dst.dump}, #{src.dump}]"   #=> ["HIRAGANA LETTER A is <err>.", ""]

ec = Encoding::Converter.new("utf-8", "iso-2022-jp")
src = "\u{306F 3041 3068 2661 3002}" # U+2661 is not representable in iso-2022-jp
dst = ""
p ec.primitive_convert(src, dst)    #=> :undefined_conversion
puts "[#{dst.dump}, #{src.dump}]"   #=> ["\e$B$O$!$H".force_encoding("ISO-2022-JP"), "\xE3\x80\x82"]
ec.insert_output "?"                # state change required to output "?".
p ec.primitive_convert(src, dst)    #=> :finished
puts "[#{dst.dump}, #{src.dump}]"   #=> ["\e$B$O$!$H\e(B?\e$B!#\e(B".force_encoding("ISO-2022-JP"), ""]

static VALUE
econv_insert_output(VALUE self, VALUE string)
{
    const char *insert_enc;

    int ret;

    rb_econv_t *ec = check_econv(self);

    StringValue(string);
    insert_enc = rb_econv_encoding_to_insert_output(ec);
    string = rb_str_encode(string, rb_enc_from_encoding(rb_enc_find(insert_enc)), 0, Qnil);

    ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(string), RSTRING_LEN(string), insert_enc);
    if (ret == -1) {
        rb_raise(rb_eArgError, "too big string");
    }

    return Qnil;
}
inspect → string click to toggle source

Returns a printable version of ec

ec = Encoding::Converter.new("iso-8859-1", "utf-8")
puts ec.inspect    #=> #<Encoding::Converter: ISO-8859-1 to UTF-8>

static VALUE
econv_inspect(VALUE self)
{
    const char *cname = rb_obj_classname(self);
    rb_econv_t *ec;

    TypedData_Get_Struct(self, rb_econv_t, &econv_data_type, ec);
    if (!ec)
        return rb_sprintf("#<%s: uninitialized>", cname);
    else {
        const char *sname = ec->source_encoding_name;
        const char *dname = ec->destination_encoding_name;
        VALUE str;
        str = rb_sprintf("#<%s: ", cname);
        econv_description(sname, dname, ec->flags, str);
        rb_str_cat2(str, ">");
        return str;
    }
}
last_error → exception or nil click to toggle source

Returns an exception object for the last conversion. Returns nil if the last conversion did not produce an error.

“error” means that Encoding::InvalidByteSequenceError and Encoding::UndefinedConversionError for #convert and :invalid_byte_sequence, :incomplete_input and :undefined_conversion for #primitive_convert.

ec = Encoding::Converter.new("utf-8", "iso-8859-1")
p ec.primitive_convert(src="\xf1abcd", dst="")       #=> :invalid_byte_sequence
p ec.last_error      #=> #<Encoding::InvalidByteSequenceError: "\xF1" followed by "a" on UTF-8>
p ec.primitive_convert(src, dst, nil, 1)             #=> :destination_buffer_full
p ec.last_error      #=> nil

static VALUE
econv_last_error(VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    VALUE exc;

    exc = make_econv_exception(ec);
    if (NIL_P(exc))
        return Qnil;
    return exc;
}
primitive_convert(source_buffer, destination_buffer) → symbol click to toggle source
primitive_convert(source_buffer, destination_buffer, destination_byteoffset) → symbol
primitive_convert(source_buffer, destination_buffer, destination_byteoffset, destination_bytesize) → symbol
primitive_convert(source_buffer, destination_buffer, destination_byteoffset, destination_bytesize, opt) → symbol

possible opt elements:

hash form:
  :partial_input => true           # source buffer may be part of larger source
  :after_output => true            # stop conversion after output before input
integer form:
  Encoding::Converter::PARTIAL_INPUT
  Encoding::Converter::AFTER_OUTPUT

possible results:

:invalid_byte_sequence
:incomplete_input
:undefined_conversion
:after_output
:destination_buffer_full
:source_buffer_empty
:finished

#primitive_convert converts source_buffer into destination_buffer.

source_buffer should be a string or nil. nil means an empty string.

destination_buffer should be a string.

destination_byteoffset should be an integer or nil. nil means the end of destination_buffer. If it is omitted, nil is assumed.

destination_bytesize should be an integer or nil. nil means unlimited. If it is omitted, nil is assumed.

opt should be nil, a hash or an integer. nil means no flags. If it is omitted, nil is assumed.

#primitive_convert converts the content of source_buffer from beginning and store the result into destination_buffer.

destination_byteoffset and destination_bytesize specify the region which the converted result is stored. destination_byteoffset specifies the start position in destination_buffer in bytes. If destination_byteoffset is nil, destination_buffer.bytesize is used for appending the result. destination_bytesize specifies maximum number of bytes. If destination_bytesize is nil, destination size is unlimited. After conversion, destination_buffer is resized to destination_byteoffset + actually produced number of bytes. Also destination_buffer's encoding is set to destination_encoding.

#primitive_convert drops the converted part of source_buffer. the dropped part is converted in destination_buffer or buffered in Encoding::Converter object.

#primitive_convert stops conversion when one of following condition met.

  • invalid byte sequence found in source buffer (:invalid_byte_sequence) primitive_errinfo and last_error methods returns the detail of the error.

  • unexpected end of source buffer (:incomplete_input) this occur only when :partial_input is not specified. primitive_errinfo and last_error methods returns the detail of the error.

  • character not representable in output encoding (:undefined_conversion) primitive_errinfo and last_error methods returns the detail of the error.

  • after some output is generated, before input is done (:after_output) this occur only when :after_output is specified.

  • destination buffer is full (:destination_buffer_full) this occur only when destination_bytesize is non-nil.

  • source buffer is empty (:source_buffer_empty) this occur only when :partial_input is specified.

  • conversion is finished (:finished)

example:

ec = Encoding::Converter.new("UTF-8", "UTF-16BE")
ret = ec.primitive_convert(src="pi", dst="", nil, 100)
p [ret, src, dst] #=> [:finished, "", "\x00p\x00i"]

ec = Encoding::Converter.new("UTF-8", "UTF-16BE")
ret = ec.primitive_convert(src="pi", dst="", nil, 1)
p [ret, src, dst] #=> [:destination_buffer_full, "i", "\x00"]
ret = ec.primitive_convert(src, dst="", nil, 1)
p [ret, src, dst] #=> [:destination_buffer_full, "", "p"]
ret = ec.primitive_convert(src, dst="", nil, 1)
p [ret, src, dst] #=> [:destination_buffer_full, "", "\x00"]
ret = ec.primitive_convert(src, dst="", nil, 1)
p [ret, src, dst] #=> [:finished, "", "i"]

static VALUE
econv_primitive_convert(int argc, VALUE *argv, VALUE self)
{
    VALUE input, output, output_byteoffset_v, output_bytesize_v, opt, flags_v;
    rb_econv_t *ec = check_econv(self);
    rb_econv_result_t res;
    const unsigned char *ip, *is;
    unsigned char *op, *os;
    long output_byteoffset, output_bytesize;
    unsigned long output_byteend;
    int flags;

    argc = rb_scan_args(argc, argv, "23:", &input, &output, &output_byteoffset_v, &output_bytesize_v, &flags_v, &opt);

    if (NIL_P(output_byteoffset_v))
        output_byteoffset = 0; /* dummy */
    else
        output_byteoffset = NUM2LONG(output_byteoffset_v);

    if (NIL_P(output_bytesize_v))
        output_bytesize = 0; /* dummy */
    else
        output_bytesize = NUM2LONG(output_bytesize_v);

    if (!NIL_P(flags_v)) {
        if (!NIL_P(opt)) {
            rb_error_arity(argc + 1, 2, 5);
        }
        flags = NUM2INT(rb_to_int(flags_v));
    }
    else if (!NIL_P(opt)) {
        VALUE v;
        flags = 0;
        v = rb_hash_aref(opt, sym_partial_input);
        if (RTEST(v))
            flags |= ECONV_PARTIAL_INPUT;
        v = rb_hash_aref(opt, sym_after_output);
        if (RTEST(v))
            flags |= ECONV_AFTER_OUTPUT;
    }
    else {
        flags = 0;
    }

    StringValue(output);
    if (!NIL_P(input))
        StringValue(input);
    rb_str_modify(output);

    if (NIL_P(output_bytesize_v)) {
        output_bytesize = RSTRING_EMBED_LEN_MAX;
        if (!NIL_P(input) && output_bytesize < RSTRING_LEN(input))
            output_bytesize = RSTRING_LEN(input);
    }

  retry:

    if (NIL_P(output_byteoffset_v))
        output_byteoffset = RSTRING_LEN(output);

    if (output_byteoffset < 0)
        rb_raise(rb_eArgError, "negative output_byteoffset");

    if (RSTRING_LEN(output) < output_byteoffset)
        rb_raise(rb_eArgError, "output_byteoffset too big");

    if (output_bytesize < 0)
        rb_raise(rb_eArgError, "negative output_bytesize");

    output_byteend = (unsigned long)output_byteoffset +
                     (unsigned long)output_bytesize;

    if (output_byteend < (unsigned long)output_byteoffset ||
        LONG_MAX < output_byteend)
        rb_raise(rb_eArgError, "output_byteoffset+output_bytesize too big");

    if (rb_str_capacity(output) < output_byteend)
        rb_str_resize(output, output_byteend);

    if (NIL_P(input)) {
        ip = is = NULL;
    }
    else {
        ip = (const unsigned char *)RSTRING_PTR(input);
        is = ip + RSTRING_LEN(input);
    }

    op = (unsigned char *)RSTRING_PTR(output) + output_byteoffset;
    os = op + output_bytesize;

    res = rb_econv_convert(ec, &ip, is, &op, os, flags);
    rb_str_set_len(output, op-(unsigned char *)RSTRING_PTR(output));
    if (!NIL_P(input))
        rb_str_drop_bytes(input, ip - (unsigned char *)RSTRING_PTR(input));

    if (NIL_P(output_bytesize_v) && res == econv_destination_buffer_full) {
        if (LONG_MAX / 2 < output_bytesize)
            rb_raise(rb_eArgError, "too long conversion result");
        output_bytesize *= 2;
        output_byteoffset_v = Qnil;
        goto retry;
    }

    if (ec->destination_encoding) {
        rb_enc_associate(output, ec->destination_encoding);
    }

    return econv_result_to_symbol(res);
}
primitive_errinfo → array click to toggle source

#primitive_errinfo returns important information regarding the last error as a 5-element array:

[result, enc1, enc2, error_bytes, readagain_bytes]

result is the last result of primitive_convert.

Other elements are only meaningful when result is :invalid_byte_sequence, :incomplete_input or :undefined_conversion.

enc1 and enc2 indicate a conversion step as a pair of strings. For example, a converter from EUC-JP to ISO-8859-1 converts a string as follows: EUC-JP -> UTF-8 -> ISO-8859-1. So [enc1, enc2] is either [“EUC-JP”, “UTF-8”] or [“UTF-8”, “ISO-8859-1”].

error_bytes and readagain_bytes indicate the byte sequences which caused the error. error_bytes is discarded portion. readagain_bytes is buffered portion which is read again on next conversion.

Example:

# \xff is invalid as EUC-JP.
ec = Encoding::Converter.new("EUC-JP", "Shift_JIS")
ec.primitive_convert(src="\xff", dst="", nil, 10)
p ec.primitive_errinfo
#=> [:invalid_byte_sequence, "EUC-JP", "UTF-8", "\xFF", ""]

# HIRAGANA LETTER A (\xa4\xa2 in EUC-JP) is not representable in ISO-8859-1.
# Since this error is occur in UTF-8 to ISO-8859-1 conversion,
# error_bytes is HIRAGANA LETTER A in UTF-8 (\xE3\x81\x82).
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
ec.primitive_convert(src="\xa4\xa2", dst="", nil, 10)
p ec.primitive_errinfo
#=> [:undefined_conversion, "UTF-8", "ISO-8859-1", "\xE3\x81\x82", ""]

# partial character is invalid
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
ec.primitive_convert(src="\xa4", dst="", nil, 10)
p ec.primitive_errinfo
#=> [:incomplete_input, "EUC-JP", "UTF-8", "\xA4", ""]

# Encoding::Converter::PARTIAL_INPUT prevents invalid errors by
# partial characters.
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
ec.primitive_convert(src="\xa4", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT)
p ec.primitive_errinfo
#=> [:source_buffer_empty, nil, nil, nil, nil]

# \xd8\x00\x00@ is invalid as UTF-16BE because
# no low surrogate after high surrogate (\xd8\x00).
# It is detected by 3rd byte (\00) which is part of next character.
# So the high surrogate (\xd8\x00) is discarded and
# the 3rd byte is read again later.
# Since the byte is buffered in ec, it is dropped from src.
ec = Encoding::Converter.new("UTF-16BE", "UTF-8")
ec.primitive_convert(src="\xd8\x00\x00@", dst="", nil, 10)
p ec.primitive_errinfo
#=> [:invalid_byte_sequence, "UTF-16BE", "UTF-8", "\xD8\x00", "\x00"]
p src
#=> "@"

# Similar to UTF-16BE, \x00\xd8@\x00 is invalid as UTF-16LE.
# The problem is detected by 4th byte.
ec = Encoding::Converter.new("UTF-16LE", "UTF-8")
ec.primitive_convert(src="\x00\xd8@\x00", dst="", nil, 10)
p ec.primitive_errinfo
#=> [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "@\x00"]
p src
#=> ""

static VALUE
econv_primitive_errinfo(VALUE self)
{
    rb_econv_t *ec = check_econv(self);

    VALUE ary;

    ary = rb_ary_new2(5);

    rb_ary_store(ary, 0, econv_result_to_symbol(ec->last_error.result));
    rb_ary_store(ary, 4, Qnil);

    if (ec->last_error.source_encoding)
        rb_ary_store(ary, 1, rb_str_new2(ec->last_error.source_encoding));

    if (ec->last_error.destination_encoding)
        rb_ary_store(ary, 2, rb_str_new2(ec->last_error.destination_encoding));

    if (ec->last_error.error_bytes_start) {
        rb_ary_store(ary, 3, rb_str_new((const char *)ec->last_error.error_bytes_start, ec->last_error.error_bytes_len));
        rb_ary_store(ary, 4, rb_str_new((const char *)ec->last_error.error_bytes_start + ec->last_error.error_bytes_len, ec->last_error.readagain_len));
    }

    return ary;
}
putback(p1 = v1) click to toggle source

call-seq

ec.putback                    -> string
ec.putback(max_numbytes)      -> string

Put back the bytes which will be converted.

The bytes are caused by invalid_byte_sequence error. When invalid_byte_sequence error, some bytes are discarded and some bytes are buffered to be converted later. The latter bytes can be put back. It can be observed by Encoding::InvalidByteSequenceError#readagain_bytes and #primitive_errinfo.

ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
src = "\x00\xd8\x61\x00"
dst = ""
p ec.primitive_convert(src, dst)   #=> :invalid_byte_sequence
p ec.primitive_errinfo     #=> [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
p ec.putback               #=> "a\x00"
p ec.putback               #=> ""          # no more bytes to put back

static VALUE
econv_putback(int argc, VALUE *argv, VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    int n;
    int putbackable;
    VALUE str, max;

    rb_scan_args(argc, argv, "01", &max);

    if (NIL_P(max))
        n = rb_econv_putbackable(ec);
    else {
        n = NUM2INT(max);
        putbackable = rb_econv_putbackable(ec);
        if (putbackable < n)
            n = putbackable;
    }

    str = rb_str_new(NULL, n);
    rb_econv_putback(ec, (unsigned char *)RSTRING_PTR(str), n);

    if (ec->source_encoding) {
        rb_enc_associate(str, ec->source_encoding);
    }

    return str;
}
replacement → string click to toggle source

Returns the replacement string.

ec = Encoding::Converter.new("euc-jp", "us-ascii")
p ec.replacement    #=> "?"

ec = Encoding::Converter.new("euc-jp", "utf-8")
p ec.replacement    #=> "\uFFFD"

static VALUE
econv_get_replacement(VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    int ret;
    rb_encoding *enc;

    ret = make_replacement(ec);
    if (ret == -1) {
        rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
    }

    enc = rb_enc_find(ec->replacement_enc);
    return rb_enc_str_new((const char *)ec->replacement_str, (long)ec->replacement_len, enc);
}
replacement = string click to toggle source

Sets the replacement string.

ec = Encoding::Converter.new("utf-8", "us-ascii", :undef => :replace)
ec.replacement = "<undef>"
p ec.convert("a \u3042 b")      #=> "a <undef> b"

static VALUE
econv_set_replacement(VALUE self, VALUE arg)
{
    rb_econv_t *ec = check_econv(self);
    VALUE string = arg;
    int ret;
    rb_encoding *enc;

    StringValue(string);
    enc = rb_enc_get(string);

    ret = rb_econv_set_replacement(ec,
            (const unsigned char *)RSTRING_PTR(string),
            RSTRING_LEN(string),
            rb_enc_name(enc));

    if (ret == -1) {
        /* xxx: rb_eInvalidByteSequenceError? */
        rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
    }

    return arg;
}
source_encoding → encoding click to toggle source

Returns the source encoding as an Encoding object.

static VALUE
econv_source_encoding(VALUE self)
{
    rb_econv_t *ec = check_econv(self);
    if (!ec->source_encoding)
        return Qnil;
    return rb_enc_from_encoding(ec->source_encoding);
}


class Encoding::ConverterNotFoundError - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding::ConverterNotFoundError

Raised by transcoding methods when a named encoding does not correspond with a known converter.

In Files

  • encoding.c

Parent

rb_eEncodingError


class Encoding::InvalidByteSequenceError - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding::InvalidByteSequenceError

Raised by Encoding and String methods when the string being transcoded contains a byte invalid for the either the source or target encoding.

In Files

  • encoding.c

Parent

rb_eEncodingError

Public Instance Methods

destination_encoding → string click to toggle source

Returns the destination encoding as an encoding object.

static VALUE
ecerr_destination_encoding(VALUE self)
{
    return rb_attr_get(self, rb_intern("destination_encoding"));
}
destination_encoding_name → string click to toggle source

Returns the destination encoding name as a string.

static VALUE
ecerr_destination_encoding_name(VALUE self)
{
    return rb_attr_get(self, rb_intern("destination_encoding_name"));
}
error_bytes → string click to toggle source

Returns the discarded bytes when Encoding::InvalidByteSequenceError occurs.

ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
begin
  ec.convert("abc\xA1\xFFdef")
rescue Encoding::InvalidByteSequenceError
  p $!      #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "\xFF" on EUC-JP>
  puts $!.error_bytes.dump          #=> "\xA1"
  puts $!.readagain_bytes.dump      #=> "\xFF"
end

static VALUE
ecerr_error_bytes(VALUE self)
{
    return rb_attr_get(self, rb_intern("error_bytes"));
}
incomplete_input? → true or false click to toggle source

Returns true if the invalid byte sequence error is caused by premature end of string.

ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")

begin
  ec.convert("abc\xA1z")
rescue Encoding::InvalidByteSequenceError
  p $!      #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "z" on EUC-JP>
  p $!.incomplete_input?    #=> false
end

begin
  ec.convert("abc\xA1")
  ec.finish
rescue Encoding::InvalidByteSequenceError
  p $!      #=> #<Encoding::InvalidByteSequenceError: incomplete "\xA1" on EUC-JP>
  p $!.incomplete_input?    #=> true
end

static VALUE
ecerr_incomplete_input(VALUE self)
{
    return rb_attr_get(self, rb_intern("incomplete_input"));
}
readagain_bytes → string click to toggle source

Returns the bytes to be read again when Encoding::InvalidByteSequenceError occurs.

static VALUE
ecerr_readagain_bytes(VALUE self)
{
    return rb_attr_get(self, rb_intern("readagain_bytes"));
}
source_encoding → encoding click to toggle source

Returns the source encoding as an encoding object.

Note that the result may not be equal to the source encoding of the encoding converter if the conversion has multiple steps.

ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") # ISO-8859-1 -> UTF-8 -> EUC-JP
begin
  ec.convert("\xa0") # NO-BREAK SPACE, which is available in UTF-8 but not in EUC-JP.
rescue Encoding::UndefinedConversionError
  p $!.source_encoding              #=> #<Encoding:UTF-8>
  p $!.destination_encoding         #=> #<Encoding:EUC-JP>
  p $!.source_encoding_name         #=> "UTF-8"
  p $!.destination_encoding_name    #=> "EUC-JP"
end

static VALUE
ecerr_source_encoding(VALUE self)
{
    return rb_attr_get(self, rb_intern("source_encoding"));
}
source_encoding_name → string click to toggle source

Returns the source encoding name as a string.

static VALUE
ecerr_source_encoding_name(VALUE self)
{
    return rb_attr_get(self, rb_intern("source_encoding_name"));
}


class Encoding::UndefinedConversionError - Ruby 2.0.0-p576 Core API Reference API Reference

class Encoding::UndefinedConversionError

Raised by Encoding and String methods when a transcoding operation fails.

In Files

  • encoding.c

Parent

rb_eEncodingError

Public Instance Methods

destination_encoding → string click to toggle source

Returns the destination encoding as an encoding object.

static VALUE
ecerr_destination_encoding(VALUE self)
{
    return rb_attr_get(self, rb_intern("destination_encoding"));
}
destination_encoding_name → string click to toggle source

Returns the destination encoding name as a string.

static VALUE
ecerr_destination_encoding_name(VALUE self)
{
    return rb_attr_get(self, rb_intern("destination_encoding_name"));
}
error_char → string click to toggle source

Returns the one-character string which cause Encoding::UndefinedConversionError.

ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
begin
  ec.convert("\xa0")
rescue Encoding::UndefinedConversionError
  puts $!.error_char.dump   #=> "\xC2\xA0"
  p $!.error_char.encoding  #=> #<Encoding:UTF-8>
end

static VALUE
ecerr_error_char(VALUE self)
{
    return rb_attr_get(self, rb_intern("error_char"));
}
source_encoding → encoding click to toggle source

Returns the source encoding as an encoding object.

Note that the result may not be equal to the source encoding of the encoding converter if the conversion has multiple steps.

ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") # ISO-8859-1 -> UTF-8 -> EUC-JP
begin
  ec.convert("\xa0") # NO-BREAK SPACE, which is available in UTF-8 but not in EUC-JP.
rescue Encoding::UndefinedConversionError
  p $!.source_encoding              #=> #<Encoding:UTF-8>
  p $!.destination_encoding         #=> #<Encoding:EUC-JP>
  p $!.source_encoding_name         #=> "UTF-8"
  p $!.destination_encoding_name    #=> "EUC-JP"
end

static VALUE
ecerr_source_encoding(VALUE self)
{
    return rb_attr_get(self, rb_intern("source_encoding"));
}
source_encoding_name → string click to toggle source

Returns the source encoding name as a string.

static VALUE
ecerr_source_encoding_name(VALUE self)
{
    return rb_attr_get(self, rb_intern("source_encoding_name"));
}


class EncodingError - Ruby 2.0.0-p576 Core API Reference API Reference

class EncodingError

EncodingError is the base class for encoding errors.

In Files

  • error.c

Parent

StandardError


module Enumerable - Ruby 2.0.0-p576 Core API Reference API Reference

module Enumerable

The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection. If Enumerable#max, #min, or #sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection.

In Files

  • enum.c
  • enumerator.c

Public Instance Methods

all? [{ |obj| block } ] → true or false click to toggle source

Passes each element of the collection to the given block. The method returns true if the block never returns false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } which will cause all? to return true when none of the collection members are false or nil.

%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
%w[ant bear cat].all? { |word| word.length >= 4 } #=> false
[nil, true, 99].all?                              #=> false

static VALUE
enum_all(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qtrue, 0, 0);
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
    return memo->u1.value;
}
any? [{ |obj| block }] → true or false click to toggle source

Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.

%w[ant bear cat].any? { |word| word.length >= 3 } #=> true
%w[ant bear cat].any? { |word| word.length >= 4 } #=> true
[nil, true, 99].any?                              #=> true

static VALUE
enum_any(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qfalse, 0, 0);
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
    return memo->u1.value;
}
chunk { |elt| ... } → an_enumerator click to toggle source
chunk(initial_state) { |elt, state| ... } → an_enumerator

Enumerates over the items, chunking them together based on the return value of the block.

Consecutive elements which return the same block value are chunked together.

For example, consecutive even numbers and odd numbers can be chunked as follows.

[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
  n.even?
}.each { |even, ary|
  p [even, ary]
}
#=> [false, [3, 1]]
#   [true, [4]]
#   [false, [1, 5, 9]]
#   [true, [2, 6]]
#   [false, [5, 3, 5]]

This method is especially useful for sorted series of elements. The following example counts words for each initial letter.

open("/usr/share/dict/words", "r:iso-8859-1") { |f|
  f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] }
}
#=> ["\n", 1]
#   ["A", 1327]
#   ["B", 1372]
#   ["C", 1507]
#   ["D", 791]
#   ...

The following key values have special meaning:

  • nil and :_separator specifies that the elements should be dropped.

  • :_alone specifies that the element should be chunked by itself.

Any other symbols that begin with an underscore will raise an error:

items.chunk { |item| :_underscore }
#=> RuntimeError: symbol begins with an underscore is reserved

nil and :_separator can be used to ignore some elements.

For example, the sequence of hyphens in svn log can be eliminated as follows:

sep = "-"*72 + "\n"
IO.popen("svn log README") { |f|
  f.chunk { |line|
    line != sep || nil
  }.each { |_, lines|
    pp lines
  }
}
#=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
#    "\n",
#    "* README, README.ja: Update the portability section.\n",
#    "\n"]
#   ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
#    "\n",
#    "* README, README.ja: Add a note about default C flags.\n",
#    "\n"]
#   ...

Paragraphs separated by empty lines can be parsed as follows:

File.foreach("README").chunk { |line|
  /\A\s*\z/ !~ line || nil
}.each { |_, lines|
  pp lines
}

:_alone can be used to force items into their own chunk. For example, you can put lines that contain a URL by themselves, and chunk the rest of the lines together, like this:

pattern = /http/
open(filename) { |f|
  f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
    pp lines
  }
}

If the block needs to maintain state over multiple elements, an initial_state argument can be used. If a non-nil value is given, a reference to it is passed as the 2nd argument of the block for the chunk method, so state-changes to it persist across block calls.

static VALUE
enum_chunk(int argc, VALUE *argv, VALUE enumerable)
{
    VALUE initial_state;
    VALUE enumerator;

    if (!rb_block_given_p())
        rb_raise(rb_eArgError, "no block given");
    rb_scan_args(argc, argv, "01", &initial_state);

    enumerator = rb_obj_alloc(rb_cEnumerator);
    rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
    rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
    rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
    rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
    return enumerator;
}
collect { |obj| block } → array click to toggle source
map { |obj| block } → array
collect → an_enumerator
map → an_enumerator

Returns a new array with the results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

(1..4).collect { |i| i*i }  #=> [1, 4, 9, 16]
(1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]

static VALUE
enum_collect(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, collect_i, ary);

    return ary;
}
flat_map { |obj| block } → array click to toggle source
collect_concat { |obj| block } → array
flat_map → an_enumerator
collect_concat → an_enumerator

Returns a new array with the concatenated results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]

static VALUE
enum_flat_map(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);

    return ary;
}
count → int click to toggle source
count(item) → int
count { |obj| block } → int

Returns the number of items in enum through enumeration. If an argument is given, the number of items in enum that are equal to item are counted. If a block is given, it counts the number of elements yielding a true value.

ary = [1, 2, 4, 2]
ary.count               #=> 4
ary.count(2)            #=> 2
ary.count{ |x| x%2==0 } #=> 3

static VALUE
enum_count(int argc, VALUE *argv, VALUE obj)
{
    VALUE item = Qnil;
    NODE *memo;
    rb_block_call_func *func;

    if (argc == 0) {
        if (rb_block_given_p()) {
            func = count_iter_i;
        }
        else {
            func = count_all_i;
        }
    }
    else {
        rb_scan_args(argc, argv, "1", &item);
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        func = count_i;
    }

    memo = NEW_MEMO(item, 0, 0);
    rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
    return INT2NUM(memo->u3.cnt);
}
cycle(n=nil) { |obj| block } → nil click to toggle source
cycle(n=nil) → an_enumerator

Calls block for each element of enum repeatedly n times or forever if none or nil is given. If a non-positive number is given or the collection is empty, does nothing. Returns nil if the loop has finished without getting interrupted.

#cycle saves elements in an internal array so changes to enum after the first pass have no effect.

If no block is given, an enumerator is returned instead.

a = ["a", "b", "c"]
a.cycle { |x| puts x }  # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x }  # print, a, b, c, a, b, c.

static VALUE
enum_cycle(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary;
    VALUE nv = Qnil;
    long n, i, len;

    rb_scan_args(argc, argv, "01", &nv);

    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
    if (NIL_P(nv)) {
        n = -1;
    }
    else {
        n = NUM2LONG(nv);
        if (n <= 0) return Qnil;
    }
    ary = rb_ary_new();
    RBASIC(ary)->klass = 0;
    rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
    len = RARRAY_LEN(ary);
    if (len == 0) return Qnil;
    while (n < 0 || 0 < --n) {
        for (i=0; i<len; i++) {
            rb_yield(RARRAY_PTR(ary)[i]);
        }
    }
    return Qnil;
}
detect(ifnone = nil) { |obj| block } → obj or nil click to toggle source
find(ifnone = nil) { |obj| block } → obj or nil
detect(ifnone = nil) → an_enumerator
find(ifnone = nil) → an_enumerator

Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.

If no block is given, an enumerator is returned instead.

(1..10).detect   { |i| i % 5 == 0 and i % 7 == 0 }   #=> nil
(1..100).find    { |i| i % 5 == 0 and i % 7 == 0 }   #=> 35

static VALUE
enum_find(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    VALUE if_none;

    rb_scan_args(argc, argv, "01", &if_none);
    RETURN_ENUMERATOR(obj, argc, argv);
    memo = NEW_MEMO(Qundef, 0, 0);
    rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
    if (memo->u3.cnt) {
        return memo->u1.value;
    }
    if (!NIL_P(if_none)) {
        return rb_funcall(if_none, id_call, 0, 0);
    }
    return Qnil;
}
drop(n) → array click to toggle source

Drops first n elements from enum, and returns rest elements in an array.

a = [1, 2, 3, 4, 5, 0]
a.drop(3)             #=> [4, 5, 0]

static VALUE
enum_drop(VALUE obj, VALUE n)
{
    VALUE result;
    NODE *memo;
    long len = NUM2LONG(n);

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }

    result = rb_ary_new();
    memo = NEW_MEMO(result, 0, len);
    rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
    return result;
}
drop_while { |arr| block } → array click to toggle source
drop_while → an_enumerator

Drops elements up to, but not including, the first element for which the block returns nil or false and returns an array containing the remaining elements.

If no block is given, an enumerator is returned instead.

a = [1, 2, 3, 4, 5, 0]
a.drop_while { |i| i < 3 }   #=> [3, 4, 5, 0]

static VALUE
enum_drop_while(VALUE obj)
{
    VALUE result;
    NODE *memo;

    RETURN_ENUMERATOR(obj, 0, 0);
    result = rb_ary_new();
    memo = NEW_MEMO(result, 0, FALSE);
    rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
    return result;
}
each_cons(n) { ... } → nil click to toggle source
each_cons(n) → an_enumerator

Iterates the given block for each array of consecutive <n> elements. If no block is given, returns an enumerator.

e.g.:

(1..10).each_cons(3) { |a| p a }
# outputs below
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]

static VALUE
enum_each_cons(VALUE obj, VALUE n)
{
    long size = NUM2LONG(n);
    NODE *memo;

    if (size <= 0) rb_raise(rb_eArgError, "invalid size");
    RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
    memo = NEW_MEMO(rb_ary_new2(size), 0, size);
    rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);

    return Qnil;
}
each_entry { |obj| block } → enum click to toggle source
each_entry → an_enumerator

Calls block once for each element in self, passing that element as a parameter, converting multiple values from yield to an array.

If no block is given, an enumerator is returned instead.

class Foo
  include Enumerable
  def each
    yield 1
    yield 1, 2
    yield
  end
end
Foo.new.each_entry{ |o| p o }

produces:

1
[1, 2]
nil
static VALUE
enum_each_entry(int argc, VALUE *argv, VALUE obj)
{
    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
    rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
    return obj;
}
each_slice(n) { ... } → nil click to toggle source
each_slice(n) → an_enumerator

Iterates the given block for each slice of <n> elements. If no block is given, returns an enumerator.

(1..10).each_slice(3) { |a| p a }
# outputs below
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10]

static VALUE
enum_each_slice(VALUE obj, VALUE n)
{
    long size = NUM2LONG(n);
    VALUE ary;
    NODE *memo;

    if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
    RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
    ary = rb_ary_new2(size);
    memo = NEW_MEMO(ary, 0, size);
    rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
    ary = memo->u1.value;
    if (RARRAY_LEN(ary) > 0) rb_yield(ary);

    return Qnil;
}
each_with_index(*args) { |obj, i| block } → enum click to toggle source
each_with_index(*args) → an_enumerator

Calls block with two arguments, the item and its index, for each item in enum. Given arguments are passed through to each().

If no block is given, an enumerator is returned instead.

hash = Hash.new
%w(cat dog wombat).each_with_index { |item, index|
  hash[item] = index
}
hash   #=> {"cat"=>0, "dog"=>1, "wombat"=>2}

static VALUE
enum_each_with_index(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;

    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

    memo = NEW_MEMO(0, 0, 0);
    rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
    return obj;
}
each_with_object(obj) { |(*args), memo_obj| ... } → obj click to toggle source
each_with_object(obj) → an_enumerator

Iterates the given block for each element with an arbitrary object given, and returns the initially given object.

If no block is given, returns an enumerator.

evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

static VALUE
enum_each_with_object(VALUE obj, VALUE memo)
{
    RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);

    rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);

    return memo;
}
to_a → array click to toggle source
entries → array

Returns an array containing the items in enum.

(1..7).to_a                       #=> [1, 2, 3, 4, 5, 6, 7]
{ 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]

static VALUE
enum_to_a(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary = rb_ary_new();

    rb_block_call(obj, id_each, argc, argv, collect_all, ary);
    OBJ_INFECT(ary, obj);

    return ary;
}
detect(ifnone = nil) { |obj| block } → obj or nil click to toggle source
find(ifnone = nil) { |obj| block } → obj or nil
detect(ifnone = nil) → an_enumerator
find(ifnone = nil) → an_enumerator

Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.

If no block is given, an enumerator is returned instead.

(1..10).detect   { |i| i % 5 == 0 and i % 7 == 0 }   #=> nil
(1..100).find    { |i| i % 5 == 0 and i % 7 == 0 }   #=> 35

static VALUE
enum_find(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    VALUE if_none;

    rb_scan_args(argc, argv, "01", &if_none);
    RETURN_ENUMERATOR(obj, argc, argv);
    memo = NEW_MEMO(Qundef, 0, 0);
    rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
    if (memo->u3.cnt) {
        return memo->u1.value;
    }
    if (!NIL_P(if_none)) {
        return rb_funcall(if_none, id_call, 0, 0);
    }
    return Qnil;
}
find_all { |obj| block } → array click to toggle source
select { |obj| block } → array
find_all → an_enumerator
select → an_enumerator

Returns an array containing all elements of enum for which the given block returns a true value.

If no block is given, an Enumerator is returned instead.

(1..10).find_all { |i|  i % 3 == 0 }   #=> [3, 6, 9]

[1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]

See also #reject.

static VALUE
enum_find_all(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, find_all_i, ary);

    return ary;
}
find_index(value) → int or nil click to toggle source
find_index { |obj| block } → int or nil
find_index → an_enumerator

Compares each entry in enum with value or passes to block. Returns the index for the first for which the evaluated value is non-false. If no object matches, returns nil

If neither block nor argument is given, an enumerator is returned instead.

(1..10).find_index  { |i| i % 5 == 0 and i % 7 == 0 }  #=> nil
(1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 }  #=> 34
(1..100).find_index(50)                                #=> 49

static VALUE
enum_find_index(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo; /* [return value, current index, ] */
    VALUE condition_value = Qnil;
    rb_block_call_func *func;

    if (argc == 0) {
        RETURN_ENUMERATOR(obj, 0, 0);
        func = find_index_iter_i;
    }
    else {
        rb_scan_args(argc, argv, "1", &condition_value);
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        func = find_index_i;
    }

    memo = NEW_MEMO(Qnil, condition_value, 0);
    rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
    return memo->u1.value;
}
first → obj or nil click to toggle source
first(n) → an_array

Returns the first element, or the first n elements, of the enumerable. If the enumerable is empty, the first form returns nil, and the second form returns an empty array.

%w[foo bar baz].first     #=> "foo"
%w[foo bar baz].first(2)  #=> ["foo", "bar"]
%w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
[].first                  #=> nil

static VALUE
enum_first(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    rb_check_arity(argc, 0, 1);
    if (argc > 0) {
        return enum_take(obj, argv[0]);
    }
    else {
        memo = NEW_MEMO(Qnil, 0, 0);
        rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
        return memo->u1.value;
    }
}
flat_map { |obj| block } → array click to toggle source
collect_concat { |obj| block } → array
flat_map → an_enumerator
collect_concat → an_enumerator

Returns a new array with the concatenated results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]

static VALUE
enum_flat_map(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);

    return ary;
}
grep(pattern) → array click to toggle source
grep(pattern) { |obj| block } → array

Returns an array of every element in enum for which Pattern === element. If the optional block is supplied, each matching element is passed to it, and the block's result is stored in the output array.

(1..100).grep 38..44   #=> [38, 39, 40, 41, 42, 43, 44]
c = IO.constants
c.grep(/SEEK/)         #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
res = c.grep(/SEEK/) { |v| IO.const_get(v) }
res                    #=> [0, 1, 2]

static VALUE
enum_grep(VALUE obj, VALUE pat)
{
    VALUE ary = rb_ary_new();
    NODE *memo = NEW_MEMO(pat, ary, 0);

    rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);

    return ary;
}
group_by { |obj| block } → a_hash click to toggle source
group_by → an_enumerator

Groups the collection by result of the block. Returns a hash where the keys are the evaluated result from the block and the values are arrays of elements in the collection that correspond to the key.

If no block is given an enumerator is returned.

(1..6).group_by { |i| i%3 }   #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}

static VALUE
enum_group_by(VALUE obj)
{
    VALUE hash;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    hash = rb_hash_new();
    rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
    OBJ_INFECT(hash, obj);

    return hash;
}
include?(obj) → true or false click to toggle source
member?(obj) → true or false

Returns true if any member of enum equals obj. Equality is tested using ==.

IO.constants.include? :SEEK_SET          #=> true
IO.constants.include? :SEEK_NO_FURTHER   #=> false

static VALUE
enum_member(VALUE obj, VALUE val)
{
    NODE *memo = NEW_MEMO(val, Qfalse, 0);

    rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
    return memo->u2.value;
}
inject(initial, sym) → obj click to toggle source
inject(sym) → obj
inject(initial) { |memo, obj| block } → obj
inject { |memo, obj| block } → obj
reduce(initial, sym) → obj
reduce(sym) → obj
reduce(initial) { |memo, obj| block } → obj
reduce { |memo, obj| block } → obj

Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.

If you specify a block, then for each element in enum the block is passed an accumulator value (memo) and the element. If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.

If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.

# Sum some numbers
(5..10).reduce(:+)                             #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                          #=> 151200
# Same using a block
(5..10).inject(1) { |product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo, word|
   memo.length > word.length ? memo : word
end
longest                                        #=> "sheep"

static VALUE
enum_inject(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    VALUE init, op;
    VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;

    switch (rb_scan_args(argc, argv, "02", &init, &op)) {
      case 0:
        break;
      case 1:
        if (rb_block_given_p()) {
            break;
        }
        op = (VALUE)rb_to_id(init);
        argc = 0;
        init = Qnil;
        iter = inject_op_i;
        break;
      case 2:
        if (rb_block_given_p()) {
            rb_warning("given block not used");
        }
        op = (VALUE)rb_to_id(op);
        iter = inject_op_i;
        break;
    }
    memo = NEW_MEMO(init, argc, op);
    rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
    return memo->u1.value;
}
lazy → lazy_enumerator click to toggle source

Returns a lazy enumerator, whose methods map/collect, flat_map/collect_concat, select/find_all, reject, grep, zip, take, #take_while, drop, and #drop_while enumerate values only on an as-needed basis. However, if a block is given to zip, values are enumerated immediately.

Example

The following program finds pythagorean triples:

def pythagorean_triples
  (1..Float::INFINITY).lazy.flat_map {|z|
    (1..z).flat_map {|x|
      (x..z).select {|y|
        x**2 + y**2 == z**2
      }.map {|y|
        [x, y, z]
      }
    }
  }
end
# show first ten pythagorean triples
p pythagorean_triples.take(10).force # take is lazy, so force is needed
p pythagorean_triples.first(10)      # first is eager
# show pythagorean triples less than 100
p pythagorean_triples.take_while { |*, z| z < 100 }.force

static VALUE
enumerable_lazy(VALUE obj)
{
    VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, enum_size);
    /* Qfalse indicates that the Enumerator::Lazy has no method name */
    rb_ivar_set(result, id_method, Qfalse);
    return result;
}
collect { |obj| block } → array click to toggle source
map { |obj| block } → array
collect → an_enumerator
map → an_enumerator

Returns a new array with the results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

(1..4).collect { |i| i*i }  #=> [1, 4, 9, 16]
(1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]

static VALUE
enum_collect(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, collect_i, ary);

    return ary;
}
max → obj click to toggle source
max { |a, b| block } → obj

Returns the object in enum with the maximum value. The first form assumes all objects implement Comparable; the second uses the block to return a <=> b.

a = %w(albatross dog horse)
a.max                                   #=> "horse"
a.max { |a, b| a.length <=> b.length }  #=> "albatross"

static VALUE
enum_max(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qundef, 0, 0);
    VALUE result;

    if (rb_block_given_p()) {
        rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
    }
    else {
        rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
    }
    result = memo->u1.value;
    if (result == Qundef) return Qnil;
    return result;
}
max_by { |obj| block } → obj click to toggle source
max_by → an_enumerator

Returns the object in enum that gives the maximum value from the given block.

If no block is given, an enumerator is returned instead.

a = %w(albatross dog horse)
a.max_by { |x| x.length }   #=> "albatross"

static VALUE
enum_max_by(VALUE obj)
{
    NODE *memo;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    memo = NEW_MEMO(Qundef, Qnil, 0);
    rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
    return memo->u2.value;
}
include?(obj) → true or false click to toggle source
member?(obj) → true or false

Returns true if any member of enum equals obj. Equality is tested using ==.

IO.constants.include? :SEEK_SET          #=> true
IO.constants.include? :SEEK_NO_FURTHER   #=> false

static VALUE
enum_member(VALUE obj, VALUE val)
{
    NODE *memo = NEW_MEMO(val, Qfalse, 0);

    rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
    return memo->u2.value;
}
min → obj click to toggle source
min { |a, b| block } → obj

Returns the object in enum with the minimum value. The first form assumes all objects implement Comparable; the second uses the block to return a <=> b.

a = %w(albatross dog horse)
a.min                                   #=> "albatross"
a.min { |a, b| a.length <=> b.length }  #=> "dog"

static VALUE
enum_min(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qundef, 0, 0);
    VALUE result;

    if (rb_block_given_p()) {
        rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)memo);
    }
    else {
        rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)memo);
    }
    result = memo->u1.value;
    if (result == Qundef) return Qnil;
    return result;
}
min_by { |obj| block } → obj click to toggle source
min_by → an_enumerator

Returns the object in enum that gives the minimum value from the given block.

If no block is given, an enumerator is returned instead.

a = %w(albatross dog horse)
a.min_by { |x| x.length }   #=> "dog"

static VALUE
enum_min_by(VALUE obj)
{
    NODE *memo;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    memo = NEW_MEMO(Qundef, Qnil, 0);
    rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
    return memo->u2.value;
}
minmax → [min, max] click to toggle source
minmax { |a, b| block } → [min, max]

Returns two elements array which contains the minimum and the maximum value in the enumerable. The first form assumes all objects implement Comparable; the second uses the block to return a <=> b.

a = %w(albatross dog horse)
a.minmax                                  #=> ["albatross", "horse"]
a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]

static VALUE
enum_minmax(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qundef, Qundef, Qundef);
    struct minmax_t *m = (struct minmax_t *)&memo->u1.value;
    VALUE ary = rb_ary_new3(2, Qnil, Qnil);

    m->min = Qundef;
    m->last = Qundef;
    if (rb_block_given_p()) {
        rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)memo);
        if (m->last != Qundef)
            minmax_ii_update(m->last, m->last, m);
    }
    else {
        rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)memo);
        if (m->last != Qundef)
            minmax_i_update(m->last, m->last, m);
    }
    if (m->min != Qundef) {
        rb_ary_store(ary, 0, m->min);
        rb_ary_store(ary, 1, m->max);
    }
    return ary;
}
minmax_by { |obj| block } → [min, max] click to toggle source
minmax_by → an_enumerator

Returns a two element array containing the objects in enum that correspond to the minimum and maximum values respectively from the given block.

If no block is given, an enumerator is returned instead.

a = %w(albatross dog horse)
a.minmax_by { |x| x.length }   #=> ["dog", "albatross"]

static VALUE
enum_minmax_by(VALUE obj)
{
    VALUE memo;
    struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    m->min_bv = Qundef;
    m->max_bv = Qundef;
    m->min = Qnil;
    m->max = Qnil;
    m->last_bv = Qundef;
    m->last = Qundef;
    rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
    if (m->last_bv != Qundef)
        minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
    m = MEMO_FOR(struct minmax_by_t, memo);
    return rb_assoc_new(m->min, m->max);
}
none? [{ |obj| block }] → true or false click to toggle source

Passes each element of the collection to the given block. The method returns true if the block never returns true for all elements. If the block is not given, none? will return true only if none of the collection members is true.

%w{ant bear cat}.none? { |word| word.length == 5 } #=> true
%w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
[].none?                                           #=> true
[nil].none?                                        #=> true
[nil, false].none?                                 #=> true

static VALUE
enum_none(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qtrue, 0, 0);
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
    return memo->u1.value;
}
one? [{ |obj| block }] → true or false click to toggle source

Passes each element of the collection to the given block. The method returns true if the block returns true exactly once. If the block is not given, one? will return true only if exactly one of the collection members is true.

%w{ant bear cat}.one? { |word| word.length == 4 }  #=> true
%w{ant bear cat}.one? { |word| word.length > 4 }   #=> false
%w{ant bear cat}.one? { |word| word.length < 4 }   #=> false
[ nil, true, 99 ].one?                             #=> false
[ nil, true, false ].one?                          #=> true

static VALUE
enum_one(VALUE obj)
{
    NODE *memo = NEW_MEMO(Qundef, 0, 0);
    VALUE result;

    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
    result = memo->u1.value;
    if (result == Qundef) return Qfalse;
    return result;
}
partition { |obj| block } → [ true_array, false_array ] click to toggle source
partition → an_enumerator

Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.

If no block is given, an enumerator is returned instead.

(1..6).partition { |v| v.even? }  #=> [[2, 4, 6], [1, 3, 5]]

static VALUE
enum_partition(VALUE obj)
{
    NODE *memo;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
    rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);

    return rb_assoc_new(memo->u1.value, memo->u2.value);
}
inject(initial, sym) → obj click to toggle source
inject(sym) → obj
inject(initial) { |memo, obj| block } → obj
inject { |memo, obj| block } → obj
reduce(initial, sym) → obj
reduce(sym) → obj
reduce(initial) { |memo, obj| block } → obj
reduce { |memo, obj| block } → obj

Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.

If you specify a block, then for each element in enum the block is passed an accumulator value (memo) and the element. If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.

If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.

# Sum some numbers
(5..10).reduce(:+)                             #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                          #=> 151200
# Same using a block
(5..10).inject(1) { |product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo, word|
   memo.length > word.length ? memo : word
end
longest                                        #=> "sheep"

static VALUE
enum_inject(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    VALUE init, op;
    VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;

    switch (rb_scan_args(argc, argv, "02", &init, &op)) {
      case 0:
        break;
      case 1:
        if (rb_block_given_p()) {
            break;
        }
        op = (VALUE)rb_to_id(init);
        argc = 0;
        init = Qnil;
        iter = inject_op_i;
        break;
      case 2:
        if (rb_block_given_p()) {
            rb_warning("given block not used");
        }
        op = (VALUE)rb_to_id(op);
        iter = inject_op_i;
        break;
    }
    memo = NEW_MEMO(init, argc, op);
    rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
    return memo->u1.value;
}
reject { |obj| block } → array click to toggle source
reject → an_enumerator

Returns an array for all elements of enum for which the given block returns false.

If no block is given, an Enumerator is returned instead.

(1..10).reject { |i|  i % 3 == 0 }   #=> [1, 2, 4, 5, 7, 8, 10]

[1, 2, 3, 4, 5].reject { |num| num.even? } #=> [1, 3, 5]

See also #find_all.

static VALUE
enum_reject(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, reject_i, ary);

    return ary;
}
reverse_each(*args) { |item| block } → enum click to toggle source
reverse_each(*args) → an_enumerator

Builds a temporary array and traverses that array in reverse order.

If no block is given, an enumerator is returned instead.

  (1..3).reverse_each { |v| p v }

produces:

  3
  2
  1

static VALUE
enum_reverse_each(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary;
    long i;

    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

    ary = enum_to_a(argc, argv, obj);

    for (i = RARRAY_LEN(ary); --i >= 0; ) {
        rb_yield(RARRAY_PTR(ary)[i]);
    }

    return obj;
}
find_all { |obj| block } → array click to toggle source
select { |obj| block } → array
find_all → an_enumerator
select → an_enumerator

Returns an array containing all elements of enum for which the given block returns a true value.

If no block is given, an Enumerator is returned instead.

(1..10).find_all { |i|  i % 3 == 0 }   #=> [3, 6, 9]

[1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]

See also #reject.

static VALUE
enum_find_all(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, find_all_i, ary);

    return ary;
}
slice_before(pattern) → an_enumerator click to toggle source
slice_before { |elt| bool } → an_enumerator
slice_before(initial_state) { |elt, state| bool } → an_enumerator

Creates an enumerator for each chunked elements. The beginnings of chunks are defined by pattern and the block.

If pattern === elt returns true or the block returns true for the element, the element is beginning of a chunk.

The === and block is called from the first element to the last element of enum. The result for the first element is ignored.

The result enumerator yields the chunked elements as an array. So each method can be called as follows:

enum.slice_before(pattern).each { |ary| ... }
enum.slice_before { |elt| bool }.each { |ary| ... }
enum.slice_before(initial_state) { |elt, state| bool }.each { |ary| ... }

Other methods of the Enumerator class and Enumerable module, such as map, etc., are also usable.

For example, iteration over ChangeLog entries can be implemented as follows:

# iterate over ChangeLog entries.
open("ChangeLog") { |f|
  f.slice_before(/\A\S/).each { |e| pp e }
}

# same as above.  block is used instead of pattern argument.
open("ChangeLog") { |f|
  f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
}

“svn proplist -R” produces multiline output for each file. They can be chunked as follows:

IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
  f.lines.slice_before(/\AProp/).each { |lines| p lines }
}
#=> ["Properties on '.':\n", "  svn:ignore\n", "  svk:merge\n"]
#   ["Properties on 'goruby.c':\n", "  svn:eol-style\n"]
#   ["Properties on 'complex.c':\n", "  svn:mime-type\n", "  svn:eol-style\n"]
#   ["Properties on 'regparse.c':\n", "  svn:eol-style\n"]
#   ...

If the block needs to maintain state over multiple elements, local variables can be used. For example, three or more consecutive increasing numbers can be squashed as follows:

a = [0, 2, 3, 4, 6, 7, 9]
prev = a[0]
p a.slice_before { |e|
  prev, prev2 = e, prev
  prev2 + 1 != e
}.map { |es|
  es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
}.join(",")
#=> "0,2-4,6,7,9"

However local variables are not appropriate to maintain state if the result enumerator is used twice or more. In such a case, the last state of the 1st each is used in the 2nd each. The initial_state argument can be used to avoid this problem. If non-nil value is given as initial_state, it is duplicated for each each method invocation of the enumerator. The duplicated object is passed to 2nd argument of the block for slice_before method.

# Word wrapping.  This assumes all characters have same width.
def wordwrap(words, maxwidth)
  # if cols is a local variable, 2nd "each" may start with non-zero cols.
  words.slice_before(cols: 0) { |w, h|
    h[:cols] += 1 if h[:cols] != 0
    h[:cols] += w.length
    if maxwidth < h[:cols]
      h[:cols] = w.length
      true
    else
      false
    end
  }
end
text = (1..20).to_a.join(" ")
enum = wordwrap(text.split(/\s+/), 10)
puts "-"*10
enum.each { |ws| puts ws.join(" ") }
puts "-"*10
#=> ----------
#   1 2 3 4 5
#   6 7 8 9 10
#   11 12 13
#   14 15 16
#   17 18 19
#   20
#   ----------

mbox contains series of mails which start with Unix From line. So each mail can be extracted by slice before Unix From line.

# parse mbox
open("mbox") { |f|
  f.slice_before { |line|
    line.start_with? "From "
  }.each { |mail|
    unix_from = mail.shift
    i = mail.index("\n")
    header = mail[0...i]
    body = mail[(i+1)..-1]
    body.pop if body.last == "\n"
    fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
    p unix_from
    pp fields
    pp body
  }
}

# split mails in mbox (slice before Unix From line after an empty line)
open("mbox") { |f|
  f.slice_before(emp: true) { |line, h|
    prevemp = h[:emp]
    h[:emp] = line == "\n"
    prevemp && line.start_with?("From ")
  }.each { |mail|
    mail.pop if mail.last == "\n"
    pp mail
  }
}

static VALUE
enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
{
    VALUE enumerator;

    if (rb_block_given_p()) {
        VALUE initial_state;
        rb_scan_args(argc, argv, "01", &initial_state);
        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
        rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
    }
    else {
        VALUE sep_pat;
        rb_scan_args(argc, argv, "1", &sep_pat);
        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
    }
    rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
    rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
    return enumerator;
}
sort → array click to toggle source
sort { |a, b| block } → array

Returns an array containing the items in enum sorted, either according to their own <=> method, or by using the results of the supplied block. The block should return -1, 0, or +1 depending on the comparison between a and b. As of Ruby 1.8, the method Enumerable#sort_by implements a built-in Schwartzian Transform, useful when key computation or comparison is expensive.

%w(rhea kea flea).sort          #=> ["flea", "kea", "rhea"]
(1..10).sort { |a, b| b <=> a }  #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

static VALUE
enum_sort(VALUE obj)
{
    return rb_ary_sort(enum_to_a(0, 0, obj));
}
sort_by { |obj| block } → array click to toggle source
sort_by → an_enumerator

Sorts enum using a set of keys generated by mapping the values in enum through the given block.

If no block is given, an enumerator is returned instead.

%w{apple pear fig}.sort_by { |word| word.length}
              #=> ["fig", "pear", "apple"]

The current implementation of sort_by generates an array of tuples containing the original collection element and the mapped value. This makes sort_by fairly expensive when the keysets are simple.

require 'benchmark'

a = (1..100000).map { rand(100000) }

Benchmark.bm(10) do |b|
  b.report("Sort")    { a.sort }
  b.report("Sort by") { a.sort_by { |a| a } }
end

produces:

user     system      total        real
Sort        0.180000   0.000000   0.180000 (  0.175469)
Sort by     1.980000   0.040000   2.020000 (  2.013586)

However, consider the case where comparing the keys is a non-trivial operation. The following code sorts some files on modification time using the basic sort method.

files = Dir["*"]
sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
sorted   #=> ["mon", "tues", "wed", "thurs"]

This sort is inefficient: it generates two new File objects during every comparison. A slightly better technique is to use the Kernel#test method to generate the modification times directly.

files = Dir["*"]
sorted = files.sort { |a, b|
  test(M, a) <=> test(M, b)
}
sorted   #=> ["mon", "tues", "wed", "thurs"]

This still generates many unnecessary Time objects. A more efficient technique is to cache the sort keys (modification times in this case) before the sort. Perl users often call this approach a Schwartzian Transform, after Randal Schwartz. We construct a temporary array, where each element is an array containing our sort key along with the filename. We sort this array, and then extract the filename from the result.

sorted = Dir["*"].collect { |f|
   [test(M, f), f]
}.sort.collect { |f| f[1] }
sorted   #=> ["mon", "tues", "wed", "thurs"]

This is exactly what sort_by does internally.

sorted = Dir["*"].sort_by { |f| test(M, f) }
sorted   #=> ["mon", "tues", "wed", "thurs"]

static VALUE
enum_sort_by(VALUE obj)
{
    VALUE ary, buf;
    NODE *memo;
    long i;
    struct sort_by_data *data;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
        ary = rb_ary_new2(RARRAY_LEN(obj)*2);
    }
    else {
        ary = rb_ary_new();
    }
    RBASIC(ary)->klass = 0;
    buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
    rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
    memo = NEW_MEMO(0, 0, 0);
    OBJ_INFECT(memo, obj);
    data = (struct sort_by_data *)&memo->u1;
    data->ary = ary;
    data->buf = buf;
    data->n = 0;
    rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
    ary = data->ary;
    buf = data->buf;
    if (data->n) {
        rb_ary_resize(buf, data->n*2);
        rb_ary_concat(ary, buf);
    }
    if (RARRAY_LEN(ary) > 2) {
        ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
                   sort_by_cmp, (void *)ary);
    }
    if (RBASIC(ary)->klass) {
        rb_raise(rb_eRuntimeError, "sort_by reentered");
    }
    for (i=1; i<RARRAY_LEN(ary); i+=2) {
        RARRAY_PTR(ary)[i/2] = RARRAY_PTR(ary)[i];
    }
    rb_ary_resize(ary, RARRAY_LEN(ary)/2);
    RBASIC(ary)->klass = rb_cArray;
    OBJ_INFECT(ary, memo);

    return ary;
}
take(n) → array click to toggle source

Returns first n elements from enum.

a = [1, 2, 3, 4, 5, 0]
a.take(3)             #=> [1, 2, 3]

static VALUE
enum_take(VALUE obj, VALUE n)
{
    NODE *memo;
    VALUE result;
    long len = NUM2LONG(n);

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }

    if (len == 0) return rb_ary_new2(0);
    result = rb_ary_new2(len);
    memo = NEW_MEMO(result, 0, len);
    rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
    return result;
}
take_while { |arr| block } → array click to toggle source
take_while → an_enumerator

Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements.

If no block is given, an enumerator is returned instead.

a = [1, 2, 3, 4, 5, 0]
a.take_while { |i| i < 3 }   #=> [1, 2]

static VALUE
enum_take_while(VALUE obj)
{
    VALUE ary;

    RETURN_ENUMERATOR(obj, 0, 0);
    ary = rb_ary_new();
    rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
    return ary;
}
to_a → array click to toggle source
entries → array

Returns an array containing the items in enum.

(1..7).to_a                       #=> [1, 2, 3, 4, 5, 6, 7]
{ 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]

static VALUE
enum_to_a(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary = rb_ary_new();

    rb_block_call(obj, id_each, argc, argv, collect_all, ary);
    OBJ_INFECT(ary, obj);

    return ary;
}
zip(arg, ...) → an_array_of_array click to toggle source
zip(arg, ...) { |arr| block } → nil

Takes one element from enum and merges corresponding elements from each args. This generates a sequence of n-element arrays, where n is one more than the count of arguments. The length of the resulting sequence will be enum#size. If the size of any argument is less than enum#size, nil values are supplied. If a block is given, it is invoked for each output array, otherwise an array of arrays is returned.

a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]

[1, 2, 3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b)         #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]

static VALUE
enum_zip(int argc, VALUE *argv, VALUE obj)
{
    int i;
    ID conv;
    NODE *memo;
    VALUE result = Qnil;
    VALUE args = rb_ary_new4(argc, argv);
    int allary = TRUE;

    argv = RARRAY_PTR(args);
    for (i=0; i<argc; i++) {
        VALUE ary = rb_check_array_type(argv[i]);
        if (NIL_P(ary)) {
            allary = FALSE;
            break;
        }
        argv[i] = ary;
    }
    if (!allary) {
        CONST_ID(conv, "to_enum");
        for (i=0; i<argc; i++) {
            if (!rb_respond_to(argv[i], id_each)) {
                rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
                    rb_obj_classname(argv[i]));
            }
            argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
        }
    }
    if (!rb_block_given_p()) {
        result = rb_ary_new();
    }
    /* use NODE_DOT2 as memo(v, v, -) */
    memo = rb_node_newnode(NODE_DOT2, result, args, 0);
    rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);

    return result;
}


class Enumerator - Ruby 2.0.0-p576 Core API Reference API Reference

class Enumerator

A class which allows both internal and external iteration.

An Enumerator can be created by the following methods.

  • Kernel#to_enum

  • Kernel#enum_for

  • ::new

Most methods have two forms: a block form where the contents are evaluated for each item in the enumeration, and a non-block form which returns a new Enumerator wrapping the iteration.

enumerator = %w(one two three).each
puts enumerator.class # => Enumerator

enumerator.each_with_object("foo") do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

enum_with_obj = enumerator.each_with_object("foo")
puts enum_with_obj.class # => Enumerator

enum_with_obj.each do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

This allows you to chain Enumerators together. For example, you can map a list's elements to strings containing the index and the element as a string via:

puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
# => ["0:foo", "1:bar", "2:baz"]

An Enumerator can also be used as an external iterator. For example, #next returns the next value of the iterator or raises StopIteration if the Enumerator is at the end.

e = [1,2,3].each   # returns an enumerator object.
puts e.next   # => 1
puts e.next   # => 2
puts e.next   # => 3
puts e.next   # raises StopIteration

You can use this to implement an internal iterator as follows:

def ext_each(e)
  while true
    begin
      vs = e.next_values
    rescue StopIteration
      return $!.result
    end
    y = yield(*vs)
    e.feed y
  end
end

o = Object.new

def o.each
  puts yield
  puts yield(1)
  puts yield(1, 2)
  3
end

# use o.each as an internal iterator directly.
puts o.each {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

# convert o.each to an external iterator for
# implementing an internal iterator.
puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

In Files

  • enumerator.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

new(size = nil) { |yielder| ... } click to toggle source
new(obj, method = :each, *args)

Creates a new Enumerator object, which can be used as an Enumerable.

In the first form, iteration is defined by the given block, in which a “yielder” object, given as block parameter, can be used to yield a value by calling the yield method (aliased as +<<+):

fib = Enumerator.new do |y|
  a = b = 1
  loop do
    y << a
    a, b = b, a + b
  end
end

p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

The optional parameter can be used to specify how to calculate the size in a lazy fashion (see #size). It can either be a value or a callable object.

In the second, deprecated, form, a generated Enumerator iterates over the given object using the given method with the given arguments passed.

Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum instead.

e = Enumerator.new(ObjectSpace, :each_object)
    #-> ObjectSpace.enum_for(:each_object)

e.select { |obj| obj.is_a?(Class) }  #=> array of all classes

static VALUE
enumerator_initialize(int argc, VALUE *argv, VALUE obj)
{
    VALUE recv, meth = sym_each;
    VALUE size = Qnil;

    if (rb_block_given_p()) {
        rb_check_arity(argc, 0, 1);
        recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
        if (argc) {
            if (NIL_P(argv[0]) || rb_obj_is_proc(argv[0]) ||
                (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) {
                size = argv[0];
            } else {
                size = rb_to_int(argv[0]);
            }
            argc = 0;
        }
    }
    else {
        rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
        rb_warn("Enumerator.new without a block is deprecated; use Object#to_enum");
        recv = *argv++;
        if (--argc) {
            meth = *argv++;
            --argc;
        }
    }

    return enumerator_init(obj, recv, meth, argc, argv, 0, size);
}

Public Instance Methods

each {...} click to toggle source

Iterates over the block according to how this Enumerable was constructed. If no block is given, returns self.

static VALUE
enumerator_each(int argc, VALUE *argv, VALUE obj)
{
    if (argc > 0) {
        struct enumerator *e = enumerator_ptr(obj = rb_obj_dup(obj));
        VALUE args = e->args;
        if (args) {
            args = rb_ary_dup(args);
            rb_ary_cat(args, argv, argc);
        }
        else {
            args = rb_ary_new4(argc, argv);
        }
        e->args = args;
    }
    if (!rb_block_given_p()) return obj;
    return enumerator_block_call(obj, 0, obj);
}
each_with_index {|(*args), idx| ... } click to toggle source
each_with_index

Same as #with_index, i.e. there is no starting offset.

If no block is given, a new Enumerator is returned that includes the index.

static VALUE
enumerator_each_with_index(VALUE obj)
{
    return enumerator_with_index(0, NULL, obj);
}
with_object(obj) {|(*args), obj| ... } click to toggle source
with_object(obj)

Iterates the given block for each element with an arbitrary object, obj, and returns obj

If no block is given, returns a new Enumerator.

Example

to_three = Enumerator.new do |y|
  3.times do |x|
    y << x
  end
end

to_three_with_string = to_three.with_object("foo")
to_three_with_string.each do |x,string|
  puts "#{string}: #{x}"
end

# => foo:0
# => foo:1
# => foo:2

static VALUE
enumerator_with_object(VALUE obj, VALUE memo)
{
    RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_size);
    enumerator_block_call(obj, enumerator_with_object_i, memo);

    return memo;
}
feed obj → nil click to toggle source

Sets the value to be returned by the next yield inside e.

If the value is not set, the yield returns nil.

This value is cleared after being yielded.

o = Object.new
def o.each
  x = yield         # (2) blocks
  p x               # (5) => "foo"
  x = yield         # (6) blocks
  p x               # (8) => nil
  x = yield         # (9) blocks
  p x               # not reached w/o another e.next
end

e = o.to_enum
e.next              # (1)
e.feed "foo"        # (3)
e.next              # (4)
e.next              # (7)
                    # (10)

static VALUE
enumerator_feed(VALUE obj, VALUE v)
{
    struct enumerator *e = enumerator_ptr(obj);

    if (e->feedvalue != Qundef) {
        rb_raise(rb_eTypeError, "feed value already set");
    }
    e->feedvalue = v;

    return Qnil;
}
inspect → string click to toggle source

Creates a printable version of e.

static VALUE
enumerator_inspect(VALUE obj)
{
    return rb_exec_recursive(inspect_enumerator, obj, 0);
}
next → object click to toggle source

Returns the next object in the enumerator, and move the internal position forward. When the position reached at the end, StopIteration is raised.

Example

a = [1,2,3]
e = a.to_enum
p e.next   #=> 1
p e.next   #=> 2
p e.next   #=> 3
p e.next   #raises StopIteration

Note that enumeration sequence by next does not affect other non-external enumeration methods, unless the underlying iteration methods itself has side-effect, e.g. IO#each_line.

static VALUE
enumerator_next(VALUE obj)
{
    VALUE vs = enumerator_next_values(obj);
    return ary2sv(vs, 0);
}
next_values → array click to toggle source

Returns the next object as an array in the enumerator, and move the internal position forward. When the position reached at the end, StopIteration is raised.

This method can be used to distinguish yield and yield nil.

Example

o = Object.new
def o.each
  yield
  yield 1
  yield 1, 2
  yield nil
  yield [1, 2]
end
e = o.to_enum
p e.next_values
p e.next_values
p e.next_values
p e.next_values
p e.next_values
e = o.to_enum
p e.next
p e.next
p e.next
p e.next
p e.next

## yield args       next_values      next
#  yield            []               nil
#  yield 1          [1]              1
#  yield 1, 2       [1, 2]           [1, 2]
#  yield nil        [nil]            nil
#  yield [1, 2]     [[1, 2]]         [1, 2]

Note that next_values does not affect other non-external enumeration methods unless underlying iteration method itself has side-effect, e.g. IO#each_line.

static VALUE
enumerator_next_values(VALUE obj)
{
    struct enumerator *e = enumerator_ptr(obj);
    VALUE vs;

    if (e->lookahead != Qundef) {
        vs = e->lookahead;
        e->lookahead = Qundef;
        return vs;
    }

    return get_next_values(obj, e);
}
peek → object click to toggle source

Returns the next object in the enumerator, but doesn't move the internal position forward. If the position is already at the end, StopIteration is raised.

Example

a = [1,2,3]
e = a.to_enum
p e.next   #=> 1
p e.peek   #=> 2
p e.peek   #=> 2
p e.peek   #=> 2
p e.next   #=> 2
p e.next   #=> 3
p e.peek   #raises StopIteration

static VALUE
enumerator_peek(VALUE obj)
{
    VALUE vs = enumerator_peek_values(obj);
    return ary2sv(vs, 1);
}
peek_values → array click to toggle source

Returns the next object as an array, similar to #next_values, but doesn't move the internal position forward. If the position is already at the end, StopIteration is raised.

Example

o = Object.new
def o.each
  yield
  yield 1
  yield 1, 2
end
e = o.to_enum
p e.peek_values    #=> []
e.next
p e.peek_values    #=> [1]
p e.peek_values    #=> [1]
e.next
p e.peek_values    #=> [1, 2]
e.next
p e.peek_values    # raises StopIteration

static VALUE
enumerator_peek_values_m(VALUE obj)
{
    return rb_ary_dup(enumerator_peek_values(obj));
}
rewind → e click to toggle source

Rewinds the enumeration sequence to the beginning.

If the enclosed object responds to a “rewind” method, it is called.

static VALUE
enumerator_rewind(VALUE obj)
{
    struct enumerator *e = enumerator_ptr(obj);

    rb_check_funcall(e->obj, id_rewind, 0, 0);

    e->fib = 0;
    e->dst = Qnil;
    e->lookahead = Qundef;
    e->feedvalue = Qundef;
    e->stop_exc = Qfalse;
    return obj;
}
size → int, Float::INFINITY or nil click to toggle source

Returns the size of the enumerator, or nil if it can't be calculated lazily.

(1..100).to_a.permutation(4).size # => 94109400
loop.size # => Float::INFINITY
(1..100).drop_while.size # => nil

static VALUE
enumerator_size(VALUE obj)
{
    struct enumerator *e = enumerator_ptr(obj);

    if (e->size_fn) {
        return (*e->size_fn)(e->obj, e->args, obj);
    }
    if (rb_obj_is_proc(e->size)) {
        if (e->args)
            return rb_proc_call(e->size, e->args);
        else
            return rb_proc_call_with_block(e->size, 0, 0, Qnil);
    }
    return e->size;
}
with_index(offset = 0) {|(*args), idx| ... } click to toggle source
with_index(offset = 0)

Iterates the given block for each element with an index, which starts from offset. If no block is given, returns a new Enumerator that includes the index, starting from offset

offset

the starting index to use

static VALUE
enumerator_with_index(int argc, VALUE *argv, VALUE obj)
{
    VALUE memo;

    rb_scan_args(argc, argv, "01", &memo);
    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_size);
    if (NIL_P(memo))
        memo = INT2FIX(0);
    else
        memo = rb_to_int(memo);
    return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)NEW_MEMO(memo, 0, 0));
}
with_object(obj) {|(*args), obj| ... } click to toggle source
with_object(obj)

Iterates the given block for each element with an arbitrary object, obj, and returns obj

If no block is given, returns a new Enumerator.

Example

to_three = Enumerator.new do |y|
  3.times do |x|
    y << x
  end
end

to_three_with_string = to_three.with_object("foo")
to_three_with_string.each do |x,string|
  puts "#{string}: #{x}"
end

# => foo:0
# => foo:1
# => foo:2

static VALUE
enumerator_with_object(VALUE obj, VALUE memo)
{
    RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_size);
    enumerator_block_call(obj, enumerator_with_object_i, memo);

    return memo;
}


class Enumerator::Generator - Ruby 2.0.0-p576 Core API Reference API Reference

class Enumerator::Generator

Lazy

In Files

  • enumerator.c

Parent

Object

Included Modules

  • Enumerable


class Enumerator::Lazy - Ruby 2.0.0-p576 Core API Reference API Reference

class Enumerator::Lazy

Lazy

In Files

  • enumerator.c

Parent

Enumerator

Public Class Methods

new(obj, size=nil) { |yielder, *values| ... } click to toggle source

Creates a new Lazy enumerator. When the enumerator is actually enumerated (e.g. by calling force), obj will be enumerated and each value passed to the given block. The block can yield values back using yielder. For example, to create a method filter_map in both lazy and non-lazy fashions:

module Enumerable
  def filter_map(&block)
    map(&block).compact
  end
end

class Enumerator::Lazy
  def filter_map
    Lazy.new(self) do |yielder, *values|
      result = yield *values
      yielder << result if result
    end
  end
end

(1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
    # => [4, 16, 36, 64, 100]

static VALUE
lazy_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE obj, size = Qnil;
    VALUE generator;

    rb_check_arity(argc, 1, 2);
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy new without a block");
    }
    obj = argv[0];
    if (argc > 1) {
        size = argv[1];
    }
    generator = generator_allocate(rb_cGenerator);
    rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
    enumerator_init(self, generator, sym_each, 0, 0, 0, size);
    rb_ivar_set(self, id_receiver, obj);

    return self;
}

Public Instance Methods

chunk(*args) click to toggle source
static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}
collect() click to toggle source
static VALUE
lazy_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy map without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_map_func, 0),
                           Qnil, lazy_receiver_size);
}
flat_map { |obj| block } → a_lazy_enumerator click to toggle source

Returns a new lazy enumerator with the concatenated results of running block once for every element in lazy.

["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
#=> ["f", "o", "o", "b", "a", "r"]

A value x returned by block is decomposed if either of the following conditions is true:

a) <i>x</i> responds to both each and force, which means that
   <i>x</i> is a lazy enumerator.
b) <i>x</i> is an array or responds to to_ary.

Otherwise, x is contained as-is in the return value.

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force
#=> [{:a=>1}, {:b=>2}]

static VALUE
lazy_flat_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_flat_map_func, 0),
                           Qnil, 0);
}
drop(p1) click to toggle source
static VALUE
lazy_drop(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_drop_func, n),
                           rb_ary_new3(1, n), lazy_drop_size);
}
drop_while() click to toggle source
static VALUE
lazy_drop_while(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
    }
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_drop_while_func, 0),
                           Qnil, 0);
}
to_enum(method = :each, *args) → lazy_enum click to toggle source
enum_for(method = :each, *args) → lazy_enum
to_enum(method = :each, *args) {|*args| block} → lazy_enum
enum_for(method = :each, *args){|*args| block} → lazy_enum

Similar to Kernel#to_enum, except it returns a lazy enumerator. This makes it easy to define Enumerable methods that will naturally remain lazy if called from a lazy enumerator.

For example, continuing from the example in Kernel#to_enum:

# See Kernel#to_enum for the definition of repeat
r = 1..Float::INFINITY
r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
r.repeat(2).class # => Enumerator
r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop!
# works naturally on lazy enumerator:
r.lazy.repeat(2).class # => Enumerator::Lazy
r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]

static VALUE
lazy_to_enum(int argc, VALUE *argv, VALUE self)
{
    VALUE lazy, meth = sym_each;

    if (argc > 0) {
        --argc;
        meth = *argv++;
    }
    lazy = lazy_to_enum_i(self, meth, argc, argv, 0);
    if (rb_block_given_p()) {
        enumerator_ptr(lazy)->size = rb_block_proc();
    }
    return lazy;
}
find_all() click to toggle source
static VALUE
lazy_select(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy select without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_select_func, 0),
                           Qnil, 0);
}
flat_map { |obj| block } → a_lazy_enumerator click to toggle source

Returns a new lazy enumerator with the concatenated results of running block once for every element in lazy.

["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
#=> ["f", "o", "o", "b", "a", "r"]

A value x returned by block is decomposed if either of the following conditions is true:

a) <i>x</i> responds to both each and force, which means that
   <i>x</i> is a lazy enumerator.
b) <i>x</i> is an array or responds to to_ary.

Otherwise, x is contained as-is in the return value.

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force
#=> [{:a=>1}, {:b=>2}]

static VALUE
lazy_flat_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_flat_map_func, 0),
                           Qnil, 0);
}
grep(p1) click to toggle source
static VALUE
lazy_grep(VALUE obj, VALUE pattern)
{
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         rb_block_given_p() ?
                                         lazy_grep_iter : lazy_grep_func,
                                         pattern),
                           rb_ary_new3(1, pattern), 0);
}
lazy() click to toggle source
static VALUE
lazy_lazy(VALUE obj)
{
    return obj;
}
map() click to toggle source
static VALUE
lazy_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy map without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_map_func, 0),
                           Qnil, lazy_receiver_size);
}
reject() click to toggle source
static VALUE
lazy_reject(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy reject without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_reject_func, 0),
                           Qnil, 0);
}
select() click to toggle source
static VALUE
lazy_select(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy select without a block");
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_select_func, 0),
                           Qnil, 0);
}
slice_before(*args) click to toggle source
static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}
take(p1) click to toggle source
static VALUE
lazy_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    VALUE lazy;

    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    if (len == 0) {
        VALUE len = INT2NUM(0);
        lazy = lazy_to_enum_i(obj, sym_cycle, 1, &len, 0);
    }
    else {
        lazy = rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_take_func, n);
    }
    return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size);
}
take_while() click to toggle source
static VALUE
lazy_take_while(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
    }
    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         lazy_take_while_func, 0),
                           Qnil, 0);
}
to_enum(method = :each, *args) → lazy_enum click to toggle source
enum_for(method = :each, *args) → lazy_enum
to_enum(method = :each, *args) {|*args| block} → lazy_enum
enum_for(method = :each, *args){|*args| block} → lazy_enum

Similar to Kernel#to_enum, except it returns a lazy enumerator. This makes it easy to define Enumerable methods that will naturally remain lazy if called from a lazy enumerator.

For example, continuing from the example in Kernel#to_enum:

# See Kernel#to_enum for the definition of repeat
r = 1..Float::INFINITY
r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
r.repeat(2).class # => Enumerator
r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop!
# works naturally on lazy enumerator:
r.lazy.repeat(2).class # => Enumerator::Lazy
r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]

static VALUE
lazy_to_enum(int argc, VALUE *argv, VALUE self)
{
    VALUE lazy, meth = sym_each;

    if (argc > 0) {
        --argc;
        meth = *argv++;
    }
    lazy = lazy_to_enum_i(self, meth, argc, argv, 0);
    if (rb_block_given_p()) {
        enumerator_ptr(lazy)->size = rb_block_proc();
    }
    return lazy;
}
zip(*args) click to toggle source
static VALUE
lazy_zip(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary, v;
    long i;
    rb_block_call_func *func = lazy_zip_arrays_func;

    if (rb_block_given_p()) {
        return rb_call_super(argc, argv);
    }

    ary = rb_ary_new2(argc);
    for (i = 0; i < argc; i++) {
        v = rb_check_array_type(argv[i]);
        if (NIL_P(v)) {
            for (; i < argc; i++) {
                if (!rb_respond_to(argv[i], id_each)) {
                    rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
                        rb_obj_classname(argv[i]));
                }
            }
            ary = rb_ary_new4(argc, argv);
            func = lazy_zip_func;
            break;
        }
        rb_ary_push(ary, v);
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
                                         func, ary),
                           ary, lazy_receiver_size);
}


class Enumerator::Yielder - Ruby 2.0.0-p576 Core API Reference API Reference

class Enumerator::Yielder

Lazy

In Files

  • enumerator.c

Parent

Object


module Errno - Ruby 2.0.0-p576 Core API Reference API Reference

module Errno

Ruby exception objects are subclasses of Exception. However, operating systems typically report errors using plain integers. Module Errno is created dynamically to map these operating system errors to Ruby classes, with each error number generating its own subclass of SystemCallError. As the subclass is created in module Errno, its name will start Errno::.

The names of the Errno:: classes depend on the environment in which Ruby runs. On a typical Unix or Windows platform, there are Errno classes such as Errno::EACCES, Errno::EAGAIN, Errno::EINTR, and so on.

The integer operating system error number corresponding to a particular error is available as the class constant Errno::error::Errno.

Errno::EACCES::Errno   #=> 13
Errno::EAGAIN::Errno   #=> 11
Errno::EINTR::Errno    #=> 4

The full list of operating system errors on your particular platform are available as the constants of Errno.

Errno.constants   #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...

In Files

  • error.c


class Exception - Ruby 2.0.0-p576 Core API Reference API Reference

class Exception

Descendants of class Exception are used to communicate between Kernel#raise and rescue statements in begin ... end blocks. Exception objects carry information about the exception – its type (the exception's class name), an optional descriptive string, and optional traceback information. Exception subclasses may add additional information like NameError#name.

Programs may make subclasses of Exception, typically of StandardError or RuntimeError, to provide custom classes and add additional information. See the subclass list below for defaults for raise and rescue.

When an exception has been raised but not yet handled (in rescue, ensure, at_exit and END blocks) the global variable $! will contain the current exception and $@ contains the current exception's backtrace.

It is recommended that a library should have one subclass of StandardError or RuntimeError and have specific exception types inherit from it. This allows the user to rescue a generic exception type to catch all exceptions the library may raise even if future versions of the library add new exception subclasses.

For example:

class MyLibrary
  class Error < RuntimeError
  end

  class WidgetError < Error
  end

  class FrobError < Error
  end

end

To handle both WidgetError and FrobError the library user can rescue MyLibrary::Error.

The built-in subclasses of Exception are:

  • NoMemoryError

  • ScriptError

    • LoadError

    • NotImplementedError

    • SyntaxError

  • SignalException

    • Interrupt

  • StandardError – default for rescue

    • ArgumentError

    • IndexError

      • StopIteration

    • IOError

      • EOFError

    • LocalJumpError

    • NameError

      • NoMethodError

    • RangeError

      • FloatDomainError

    • RegexpError

    • RuntimeError – default for raise

    • SecurityError

    • SystemCallError

      • Errno::*

    • SystemStackError

    • ThreadError

    • TypeError

    • ZeroDivisionError

  • SystemExit

  • fatal – impossible to rescue

In Files

  • error.c

Parent

Object

Public Class Methods

exception(string) → an_exception or exc click to toggle source

With no argument, or if the argument is the same as the receiver, return the receiver. Otherwise, create a new exception object of the same class as the receiver, but with a message equal to string.to_str.

new(msg = nil) → exception click to toggle source

Construct a new Exception object, optionally passing in a message.

static VALUE
exc_initialize(int argc, VALUE *argv, VALUE exc)
{
    VALUE arg;

    rb_scan_args(argc, argv, "01", &arg);
    rb_iv_set(exc, "mesg", arg);
    rb_iv_set(exc, "bt", Qnil);

    return exc;
}

Public Instance Methods

exc == obj → true or false click to toggle source

Equality—If obj is not an Exception, returns false. Otherwise, returns true if exc and obj share same class, messages, and backtrace.

static VALUE
exc_equal(VALUE exc, VALUE obj)
{
    VALUE mesg, backtrace;
    ID id_mesg;

    if (exc == obj) return Qtrue;
    CONST_ID(id_mesg, "mesg");

    if (rb_obj_class(exc) != rb_obj_class(obj)) {
        int status = 0;
        ID id_message, id_backtrace;
        CONST_ID(id_message, "message");
        CONST_ID(id_backtrace, "backtrace");

        obj = rb_protect(try_convert_to_exception, obj, &status);
        if (status || obj == Qundef) {
            rb_set_errinfo(Qnil);
            return Qfalse;
        }
        if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
        mesg = rb_check_funcall(obj, id_message, 0, 0);
        if (mesg == Qundef) return Qfalse;
        backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
        if (backtrace == Qundef) return Qfalse;
    }
    else {
        mesg = rb_attr_get(obj, id_mesg);
        backtrace = exc_backtrace(obj);
    }

    if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
        return Qfalse;
    if (!rb_equal(exc_backtrace(exc), backtrace))
        return Qfalse;
    return Qtrue;
}
backtrace → array click to toggle source

Returns any backtrace associated with the exception. The backtrace is an array of strings, each containing either “filename:lineNo: in `method''' or “filename:lineNo.''

def a
  raise "boom"
end

def b
  a()
end

begin
  b()
rescue => detail
  print detail.backtrace.join("\n")
end

produces:

prog.rb:2:in `a'
prog.rb:6:in `b'
prog.rb:10
static VALUE
exc_backtrace(VALUE exc)
{
    ID bt;
    VALUE obj;

    CONST_ID(bt, "bt");
    obj = rb_attr_get(exc, bt);

    if (rb_backtrace_p(obj)) {
        obj = rb_backtrace_to_str_ary(obj);
        /* rb_iv_set(exc, "bt", obj); */
    }

    return obj;
}
exception(string) → an_exception or exc click to toggle source

With no argument, or if the argument is the same as the receiver, return the receiver. Otherwise, create a new exception object of the same class as the receiver, but with a message equal to string.to_str.

static VALUE
exc_exception(int argc, VALUE *argv, VALUE self)
{
    VALUE exc;

    if (argc == 0) return self;
    if (argc == 1 && self == argv[0]) return self;
    exc = rb_obj_clone(self);
    exc_initialize(argc, argv, exc);

    return exc;
}
inspect → string click to toggle source

Return this exception's class name and message

static VALUE
exc_inspect(VALUE exc)
{
    VALUE str, klass;

    klass = CLASS_OF(exc);
    exc = rb_obj_as_string(exc);
    if (RSTRING_LEN(exc) == 0) {
        return rb_str_dup(rb_class_name(klass));
    }

    str = rb_str_buf_new2("#<");
    klass = rb_class_name(klass);
    rb_str_buf_append(str, klass);
    rb_str_buf_cat(str, ": ", 2);
    rb_str_buf_append(str, exc);
    rb_str_buf_cat(str, ">", 1);

    return str;
}
message → string click to toggle source

Returns the result of invoking exception.to_s. Normally this returns the exception's message or name. By supplying a to_str method, exceptions are agreeing to be used where Strings are expected.

static VALUE
exc_message(VALUE exc)
{
    return rb_funcall(exc, rb_intern("to_s"), 0, 0);
}
set_backtrace(backtrace) → array click to toggle source

Sets the backtrace information associated with exc. The backtrace must be an array of String objects or a single String in the format described in #backtrace.

static VALUE
exc_set_backtrace(VALUE exc, VALUE bt)
{
    return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
}
to_s → string click to toggle source

Returns exception's message (or the name of the exception if no message is set).

static VALUE
exc_to_s(VALUE exc)
{
    VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
    VALUE r = Qnil;

    if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
    r = rb_String(mesg);
    return r;
}


class FalseClass - Ruby 2.0.0-p576 Core API Reference API Reference

class FalseClass

The global value false is the only instance of class FalseClass and represents a logically false value in boolean expressions. The class provides operators allowing false to participate correctly in logical expressions.

In Files

  • object.c

Parent

Object

Public Instance Methods

false & obj → false click to toggle source
nil & obj → false

And—Returns false. obj is always evaluated as it is the argument to a method call—there is no short-circuit evaluation in this case.

static VALUE
false_and(VALUE obj, VALUE obj2)
{
    return Qfalse;
}
false ^ obj → true or false click to toggle source
nil ^ obj → true or false

Exclusive Or—If obj is nil or false, returns false; otherwise, returns true.

static VALUE
false_xor(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qtrue:Qfalse;
}
inspect() click to toggle source
Alias for: to_s
to_s → "false" click to toggle source

'nuf said…

static VALUE
false_to_s(VALUE obj)
{
    return rb_usascii_str_new2("false");
}
Also aliased as: inspect
false | obj → true or false click to toggle source
nil | obj → true or false

Or—Returns false if obj is nil or false; true otherwise.

static VALUE
false_or(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qtrue:Qfalse;
}


class Fiber - Ruby 2.0.0-p576 Core API Reference API Reference

class Fiber

Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.

As opposed to other stackless light weight concurrency models, each fiber comes with a small 4KB stack. This enables the fiber to be paused from deeply nested function calls within the fiber block.

When a fiber is created it will not run automatically. Rather it must be be explicitly asked to run using the Fiber#resume method. The code running inside the fiber can give up control by calling Fiber.yield in which case it yields control back to caller (the caller of the Fiber#resume).

Upon yielding or termination the Fiber returns the value of the last executed expression

For instance:

fiber = Fiber.new do
  Fiber.yield 1
  2
end

puts fiber.resume
puts fiber.resume
puts fiber.resume

produces

1
2
FiberError: dead fiber called

The Fiber#resume method accepts an arbitrary number of parameters, if it is the first call to resume then they will be passed as block arguments. Otherwise they will be the return value of the call to Fiber.yield

Example:

fiber = Fiber.new do |first|
  second = Fiber.yield first + 2
end

puts fiber.resume 10
puts fiber.resume 14
puts fiber.resume 18

produces

12
14
FiberError: dead fiber called

In Files

  • cont.c

Parent

Object

Public Class Methods

current() → fiber click to toggle source

Returns the current fiber. You need to require 'fiber' before using this method. If you are not running in the context of a fiber this method will return the root fiber.

static VALUE
rb_fiber_s_current(VALUE klass)
{
    return rb_fiber_current();
}
yield(args, ...) → obj click to toggle source

Yields control back to the context that resumed the fiber, passing along any arguments that were passed to it. The fiber will resume processing at this point when resume is called next. Any arguments passed to the next resume will be the value that this Fiber.yield expression evaluates to.

static VALUE
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
{
    return rb_fiber_yield(argc, argv);
}

Public Instance Methods

alive? → true or false click to toggle source

Returns true if the fiber can still be resumed (or transferred to). After finishing execution of the fiber block this method will always return false. You need to require 'fiber' before using this method.

VALUE
rb_fiber_alive_p(VALUE fibval)
{
    rb_fiber_t *fib;
    GetFiberPtr(fibval, fib);
    return fib->status != TERMINATED ? Qtrue : Qfalse;
}
resume(args, ...) → obj click to toggle source

Resumes the fiber from the point at which the last Fiber.yield was called, or starts running it if it is the first call to resume. Arguments passed to resume will be the value of the Fiber.yield expression or will be passed as block parameters to the fiber's block if this is the first resume.

Alternatively, when resume is called it evaluates to the arguments passed to the next Fiber.yield statement inside the fiber's block or to the block value if it runs to completion without any Fiber.yield

static VALUE
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
{
    return rb_fiber_resume(fib, argc, argv);
}
transfer(args, ...) → obj click to toggle source

Transfer control to another fiber, resuming it from where it last stopped or starting it if it was not resumed before. The calling fiber will be suspended much like in a call to Fiber.yield. You need to require 'fiber' before using this method.

The fiber which receives the transfer call is treats it much like a resume call. Arguments passed to transfer are treated like those passed to resume.

You cannot resume a fiber that transferred control to another one. This will cause a double resume error. You need to transfer control back to this fiber before it can yield and resume.

Example:

fiber1 = Fiber.new do
  puts "In Fiber 1"
  Fiber.yield
end

fiber2 = Fiber.new do
  puts "In Fiber 2"
  fiber1.transfer
  puts "Never see this message"
end

fiber3 = Fiber.new do
  puts "In Fiber 3"
end

fiber2.resume
fiber3.resume

<em>produces</em>

In fiber 2
In fiber 1
In fiber 3
static VALUE
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fibval)
{
    rb_fiber_t *fib;
    GetFiberPtr(fibval, fib);
    fib->transfered = 1;
    return rb_fiber_transfer(fibval, argc, argv);
}


class FiberError - Ruby 2.0.0-p576 Core API Reference API Reference

class FiberError

Raised when an invalid operation is attempted on a Fiber, in particular when attempting to call/resume a dead fiber, attempting to yield from the root fiber, or calling a fiber across threads.

fiber = Fiber.new{}
fiber.resume #=> nil
fiber.resume #=> FiberError: dead fiber called

In Files

  • cont.c

Parent

StandardError


class File - Ruby 2.0.0-p576 Core API Reference API Reference

class File

A File is an abstraction of any file object accessible by the program and is closely associated with class IO File includes the methods of module FileTest as class methods, allowing you to write (for example) File.exist?("foo").

In the description of File methods, permission bits are a platform-specific set of bits that indicate permissions of a file. On Unix-based systems, permissions are viewed as a set of three octets, for the owner, the group, and the rest of the world. For each of these entities, permissions may be set to read, write, or execute the file:

The permission bits 0644 (in octal) would thus be interpreted as read/write for owner, and read-only for group and other. Higher-order bits may also be used to indicate the type of file (plain, directory, pipe, socket, and so on) and various other special features. If the permissions are for a directory, the meaning of the execute bit changes; when set the directory can be searched.

On non-Posix operating systems, there may be only the ability to make a file read-only or read-write. In this case, the remaining permission bits will be synthesized to resemble typical values. For instance, on Windows NT the default permission bits are 0644, which means read/write for owner, read-only for all others. The only change that can be made is to make the file read-only, which is reported as 0444.

In Files

  • dir.c
  • file.c
  • io.c

Parent

IO

Constants

ALT_SEPARATOR
PATH_SEPARATOR
SEPARATOR
Separator

Public Class Methods

absolute_path(file_name [, dir_string] ) → abs_file_name click to toggle source

Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point. If the given pathname starts with a “~'' it is NOT expanded, it is treated as a normal directory name.

File.absolute_path("~oracle/bin")       #=> "<relative_path>/~oracle/bin"

VALUE
rb_file_s_absolute_path(int argc, VALUE *argv)
{
    VALUE fname, dname;

    if (argc == 1) {
        return rb_file_absolute_path(argv[0], Qnil);
    }
    rb_scan_args(argc, argv, "11", &fname, &dname);

    return rb_file_absolute_path(fname, dname);
}
atime(file_name) → time click to toggle source

Returns the last access time for the named file as a Time object).

file_name can be an IO object.

File.atime("testfile")   #=> Wed Apr 09 08:51:48 CDT 2003

static VALUE
rb_file_s_atime(VALUE klass, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) {
        FilePathValue(fname);
        rb_sys_fail_path(fname);
    }
    return stat_atime(&st);
}
basename(file_name [, suffix] ) → base_name click to toggle source

Returns the last component of the filename given in file_name, which can be formed using both File::SEPARATOR and File::ALT_SEPARETOR as the separator when File::ALT_SEPARATOR is not nil. If suffix is given and present at the end of file_name, it is removed.

File.basename("/home/gumby/work/ruby.rb")          #=> "ruby.rb"
File.basename("/home/gumby/work/ruby.rb", ".rb")   #=> "ruby"

static VALUE
rb_file_s_basename(int argc, VALUE *argv)
{
    VALUE fname, fext, basename;
    const char *name, *p;
    long f, n;
    rb_encoding *enc;

    if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
        StringValue(fext);
        enc = check_path_encoding(fext);
    }
    FilePathStringValue(fname);
    if (NIL_P(fext) || !(enc = rb_enc_compatible(fname, fext))) {
        enc = rb_enc_get(fname);
        fext = Qnil;
    }
    if ((n = RSTRING_LEN(fname)) == 0 || !*(name = RSTRING_PTR(fname)))
        return rb_str_new_shared(fname);

    p = ruby_enc_find_basename(name, &f, &n, enc);
    if (n >= 0) {
        if (NIL_P(fext)) {
            f = n;
        }
        else {
            const char *fp;
            fp = StringValueCStr(fext);
            if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) {
                f = n;
            }
            RB_GC_GUARD(fext);
        }
        if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname);
    }

    basename = rb_str_new(p, f);
    rb_enc_copy(basename, fname);
    OBJ_INFECT(basename, fname);
    return basename;
}
blockdev?(file_name) → true or false click to toggle source

Returns true if the named file is a block device.

file_name can be an IO object.

static VALUE
rb_file_blockdev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISBLK
#   ifdef S_IFBLK
#       define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#   else
#       define S_ISBLK(m) (0)  /* anytime false */
#   endif
#endif

#ifdef S_ISBLK
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISBLK(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
chardev?(file_name) → true or false click to toggle source

Returns true if the named file is a character device.

file_name can be an IO object.

static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISCHR
#   define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISCHR(st.st_mode)) return Qtrue;

    return Qfalse;
}
chmod(mode_int, file_name, ... ) → integer click to toggle source

Changes permission bits on the named file(s) to the bit pattern represented by mode_int. Actual effects are operating system dependent (see the beginning of this section). On Unix systems, see chmod(2) for details. Returns the number of files processed.

File.chmod(0644, "testfile", "out")   #=> 2

static VALUE
rb_file_s_chmod(int argc, VALUE *argv)
{
    VALUE vmode;
    VALUE rest;
    int mode;
    long n;

    rb_secure(2);
    rb_scan_args(argc, argv, "1*", &vmode, &rest);
    mode = NUM2INT(vmode);

    n = apply2files(chmod_internal, rest, &mode);
    return LONG2FIX(n);
}
chown(owner_int, group_int, file_name,... ) → integer click to toggle source

Changes the owner and group of the named file(s) to the given numeric owner and group id's. Only a process with superuser privileges may change the owner of a file. The current owner of a file may change the file's group to any group to which the owner belongs. A nil or -1 owner or group id is ignored. Returns the number of files processed.

File.chown(nil, 100, "testfile")
static VALUE
rb_file_s_chown(int argc, VALUE *argv)
{
    VALUE o, g, rest;
    struct chown_args arg;
    long n;

    rb_secure(2);
    rb_scan_args(argc, argv, "2*", &o, &g, &rest);
    if (NIL_P(o)) {
        arg.owner = -1;
    }
    else {
        arg.owner = NUM2UIDT(o);
    }
    if (NIL_P(g)) {
        arg.group = -1;
    }
    else {
        arg.group = NUM2GIDT(g);
    }

    n = apply2files(chown_internal, rest, &arg);
    return LONG2FIX(n);
}
ctime(file_name) → time click to toggle source

Returns the change time for the named file (the time at which directory information about the file was changed, not the file itself).

file_name can be an IO object.

Note that on Windows (NTFS), returns creation time (birth time).

File.ctime("testfile")   #=> Wed Apr 09 08:53:13 CDT 2003

static VALUE
rb_file_s_ctime(VALUE klass, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) {
        FilePathValue(fname);
        rb_sys_fail_path(fname);
    }
    return stat_ctime(&st);
}
delete(file_name, ...) → integer click to toggle source
unlink(file_name, ...) → integer

Deletes the named files, returning the number of names passed as arguments. Raises an exception on any error. See also Dir::rmdir.

static VALUE
rb_file_s_unlink(VALUE klass, VALUE args)
{
    long n;

    rb_secure(2);
    n = apply2files(unlink_internal, args, 0);
    return LONG2FIX(n);
}
directory?(file_name) → true or false click to toggle source

Returns true if the named file is a directory, or a symlink that points at a directory, and false otherwise.

file_name can be an IO object.

File.directory?(".")
VALUE
rb_file_directory_p(VALUE obj, VALUE fname)
{
#ifndef S_ISDIR
#   define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISDIR(st.st_mode)) return Qtrue;
    return Qfalse;
}
dirname(file_name) → dir_name click to toggle source

Returns all components of the filename given in file_name except the last one. The filename can be formed using both File::SEPARATOR and File::ALT_SEPARETOR as the separator when File::ALT_SEPARATOR is not nil.

File.dirname("/home/gumby/work/ruby.rb")   #=> "/home/gumby/work"

static VALUE
rb_file_s_dirname(VALUE klass, VALUE fname)
{
    return rb_file_dirname(fname);
}
executable?(file_name) → true or false click to toggle source

Returns true if the named file is executable by the effective user id of this process.

static VALUE
rb_file_executable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
    return Qtrue;
}
executable_real?(file_name) → true or false click to toggle source

Returns true if the named file is executable by the real user id of this process.

static VALUE
rb_file_executable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
    return Qtrue;
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Return true if the named file exists.

file_name can be an IO object.

“file exists” means that stat() or fstat() system call is successful.

static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    return Qtrue;
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Return true if the named file exists.

file_name can be an IO object.

“file exists” means that stat() or fstat() system call is successful.

static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    return Qtrue;
}
expand_path(file_name [, dir_string] ) → abs_file_name click to toggle source

Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point. The given pathname may start with a “~'', which expands to the process owner's home directory (the environment variable HOME must be set correctly). “~user'' expands to the named user's home directory.

File.expand_path("~oracle/bin")           #=> "/home/oracle/bin"
File.expand_path("../../bin", "/tmp/x")   #=> "/bin"

VALUE
rb_file_s_expand_path(int argc, VALUE *argv)
{
    VALUE fname, dname;

    if (argc == 1) {
        return rb_file_expand_path(argv[0], Qnil);
    }
    rb_scan_args(argc, argv, "11", &fname, &dname);

    return rb_file_expand_path(fname, dname);
}
extname(path) → string click to toggle source

Returns the extension (the portion of file name in path starting from the last period).

If path is a dotfile, or starts with a period, then the starting dot is not dealt with the start of the extension.

An empty string will also be returned when the period is the last character in path.

File.extname("test.rb")         #=> ".rb"
File.extname("a/b/d/test.rb")   #=> ".rb"
File.extname("foo.")            #=> ""
File.extname("test")            #=> ""
File.extname(".profile")        #=> ""
File.extname(".profile.sh")     #=> ".sh"

static VALUE
rb_file_s_extname(VALUE klass, VALUE fname)
{
    const char *name, *e;
    long len;
    VALUE extname;

    FilePathStringValue(fname);
    name = StringValueCStr(fname);
    len = RSTRING_LEN(fname);
    e = ruby_enc_find_extname(name, &len, rb_enc_get(fname));
    if (len <= 1)
        return rb_str_new(0, 0);
    extname = rb_str_subseq(fname, e - name, len); /* keep the dot, too! */
    OBJ_INFECT(extname, fname);
    return extname;
}
file?(file_name) → true or false click to toggle source

Returns true if the named file exists and is a regular file.

file_name can be an IO object.

static VALUE
rb_file_file_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISREG(st.st_mode)) return Qtrue;
    return Qfalse;
}
fnmatch( pattern, path, [flags] ) → (true or false) click to toggle source
fnmatch?( pattern, path, [flags] ) → (true or false)

Returns true if path matches against pattern The pattern is not a regular expression; instead it follows rules similar to shell filename globbing. It may contain the following metacharacters:

*

Matches any file. Can be restricted by other values in the glob. * will match all files; c* will match all files beginning with c; *c will match all files ending with c; and *c* will match all files that have c in them (including at the beginning or end). Equivalent to / .* /x in regexp.

**

Matches directories recursively or files expansively.

?

Matches any one character. Equivalent to /.{1}/ in regexp.

[set]

Matches any one character in set. Behaves exactly like character sets in Regexp, including set negation ([^a-z]).

\

Escapes the next metacharacter.

flags is a bitwise OR of the FNM_xxx parameters. The same glob pattern and flags are used by Dir::glob.

File.fnmatch('cat',       'cat')        #=> true  # match entire string
File.fnmatch('cat',       'category')   #=> false # only match partial string
File.fnmatch('c{at,ub}s', 'cats')       #=> false # { } isn't supported

File.fnmatch('c?t',     'cat')          #=> true  # '?' match only 1 character
File.fnmatch('c??t',    'cat')          #=> false # ditto
File.fnmatch('c*',      'cats')         #=> true  # '*' match 0 or more characters
File.fnmatch('c*t',     'c/a/b/t')      #=> true  # ditto
File.fnmatch('ca[a-z]', 'cat')          #=> true  # inclusive bracket expression
File.fnmatch('ca[^t]',  'cat')          #=> false # exclusive bracket expression ('^' or '!')

File.fnmatch('cat', 'CAT')                     #=> false # case sensitive
File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true  # case insensitive

File.fnmatch('?',   '/', File::FNM_PATHNAME)  #=> false # wildcard doesn't match '/' on FNM_PATHNAME
File.fnmatch('*',   '/', File::FNM_PATHNAME)  #=> false # ditto
File.fnmatch('[/]', '/', File::FNM_PATHNAME)  #=> false # ditto

File.fnmatch('\?',   '?')                       #=> true  # escaped wildcard becomes ordinary
File.fnmatch('\a',   'a')                       #=> true  # escaped ordinary remains ordinary
File.fnmatch('\a',   '\a', File::FNM_NOESCAPE)  #=> true  # FNM_NOESCAPE makes '\' ordinary
File.fnmatch('[\?]', '?')                       #=> true  # can escape inside bracket expression

File.fnmatch('*',   '.profile')                      #=> false # wildcard doesn't match leading
File.fnmatch('*',   '.profile', File::FNM_DOTMATCH)  #=> true  # period by default.
File.fnmatch('.*',  '.profile')                      #=> true

rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
File.fnmatch(rbfiles, 'main.rb')                    #=> false
File.fnmatch(rbfiles, './main.rb')                  #=> false
File.fnmatch(rbfiles, 'lib/song.rb')                #=> true
File.fnmatch('**.rb', 'main.rb')                    #=> true
File.fnmatch('**.rb', './main.rb')                  #=> false
File.fnmatch('**.rb', 'lib/song.rb')                #=> true
File.fnmatch('*',           'dave/.profile')                      #=> true

pattern = '*' '/' '*'
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME)  #=> false
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true

pattern = '**' '/' 'foo'
File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME)     #=> true
File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME)    #=> true
File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME)  #=> true
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME)    #=> false
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true

static VALUE
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
{
    VALUE pattern, path;
    VALUE rflags;
    int flags;

    if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
        flags = NUM2INT(rflags);
    else
        flags = 0;

    StringValue(pattern);
    FilePathStringValue(path);

    if (flags & FNM_EXTGLOB) {
        struct brace_args args;

        args.value = path;
        args.flags = flags;
        if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
                              (VALUE)&args, rb_enc_get(pattern)) > 0)
            return Qtrue;
    }
    else {
        rb_encoding *enc = rb_enc_compatible(pattern, path);
        if (!enc) return Qfalse;
        if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
            return Qtrue;
    }
    RB_GC_GUARD(pattern);

    return Qfalse;
}
fnmatch( pattern, path, [flags] ) → (true or false) click to toggle source
fnmatch?( pattern, path, [flags] ) → (true or false)

Returns true if path matches against pattern The pattern is not a regular expression; instead it follows rules similar to shell filename globbing. It may contain the following metacharacters:

*

Matches any file. Can be restricted by other values in the glob. * will match all files; c* will match all files beginning with c; *c will match all files ending with c; and *c* will match all files that have c in them (including at the beginning or end). Equivalent to / .* /x in regexp.

**

Matches directories recursively or files expansively.

?

Matches any one character. Equivalent to /.{1}/ in regexp.

[set]

Matches any one character in set. Behaves exactly like character sets in Regexp, including set negation ([^a-z]).

\

Escapes the next metacharacter.

flags is a bitwise OR of the FNM_xxx parameters. The same glob pattern and flags are used by Dir::glob.

File.fnmatch('cat',       'cat')        #=> true  # match entire string
File.fnmatch('cat',       'category')   #=> false # only match partial string
File.fnmatch('c{at,ub}s', 'cats')       #=> false # { } isn't supported

File.fnmatch('c?t',     'cat')          #=> true  # '?' match only 1 character
File.fnmatch('c??t',    'cat')          #=> false # ditto
File.fnmatch('c*',      'cats')         #=> true  # '*' match 0 or more characters
File.fnmatch('c*t',     'c/a/b/t')      #=> true  # ditto
File.fnmatch('ca[a-z]', 'cat')          #=> true  # inclusive bracket expression
File.fnmatch('ca[^t]',  'cat')          #=> false # exclusive bracket expression ('^' or '!')

File.fnmatch('cat', 'CAT')                     #=> false # case sensitive
File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true  # case insensitive

File.fnmatch('?',   '/', File::FNM_PATHNAME)  #=> false # wildcard doesn't match '/' on FNM_PATHNAME
File.fnmatch('*',   '/', File::FNM_PATHNAME)  #=> false # ditto
File.fnmatch('[/]', '/', File::FNM_PATHNAME)  #=> false # ditto

File.fnmatch('\?',   '?')                       #=> true  # escaped wildcard becomes ordinary
File.fnmatch('\a',   'a')                       #=> true  # escaped ordinary remains ordinary
File.fnmatch('\a',   '\a', File::FNM_NOESCAPE)  #=> true  # FNM_NOESCAPE makes '\' ordinary
File.fnmatch('[\?]', '?')                       #=> true  # can escape inside bracket expression

File.fnmatch('*',   '.profile')                      #=> false # wildcard doesn't match leading
File.fnmatch('*',   '.profile', File::FNM_DOTMATCH)  #=> true  # period by default.
File.fnmatch('.*',  '.profile')                      #=> true

rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
File.fnmatch(rbfiles, 'main.rb')                    #=> false
File.fnmatch(rbfiles, './main.rb')                  #=> false
File.fnmatch(rbfiles, 'lib/song.rb')                #=> true
File.fnmatch('**.rb', 'main.rb')                    #=> true
File.fnmatch('**.rb', './main.rb')                  #=> false
File.fnmatch('**.rb', 'lib/song.rb')                #=> true
File.fnmatch('*',           'dave/.profile')                      #=> true

pattern = '*' '/' '*'
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME)  #=> false
File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true

pattern = '**' '/' 'foo'
File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME)     #=> true
File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME)    #=> true
File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME)  #=> true
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME)    #=> false
File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true

static VALUE
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
{
    VALUE pattern, path;
    VALUE rflags;
    int flags;

    if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
        flags = NUM2INT(rflags);
    else
        flags = 0;

    StringValue(pattern);
    FilePathStringValue(path);

    if (flags & FNM_EXTGLOB) {
        struct brace_args args;

        args.value = path;
        args.flags = flags;
        if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
                              (VALUE)&args, rb_enc_get(pattern)) > 0)
            return Qtrue;
    }
    else {
        rb_encoding *enc = rb_enc_compatible(pattern, path);
        if (!enc) return Qfalse;
        if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
            return Qtrue;
    }
    RB_GC_GUARD(pattern);

    return Qfalse;
}
ftype(file_name) → string click to toggle source

Identifies the type of the named file; the return string is one of “file'', “directory'', “characterSpecial'', “blockSpecial'', “fifo'', “link'', “socket'', or “unknown''.

File.ftype("testfile")            #=> "file"
File.ftype("/dev/tty")            #=> "characterSpecial"
File.ftype("/tmp/.X11-unix/X0")   #=> "socket"

static VALUE
rb_file_s_ftype(VALUE klass, VALUE fname)
{
    struct stat st;

    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (lstat(StringValueCStr(fname), &st) == -1) {
        rb_sys_fail_path(fname);
    }

    return rb_file_ftype(&st);
}
grpowned?(file_name) → true or false click to toggle source

Returns true if the named file exists and the effective group id of the calling process is the owner of the file. Returns false on Windows.

file_name can be an IO object.

static VALUE
rb_file_grpowned_p(VALUE obj, VALUE fname)
{
#ifndef _WIN32
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (rb_group_member(st.st_gid)) return Qtrue;
#endif
    return Qfalse;
}
identical?(file_1, file_2) → true or false click to toggle source

Returns true if the named files are identical.

file_1 and file_2 can be an IO object.

open("a", "w") {}
p File.identical?("a", "a")      #=> true
p File.identical?("a", "./a")    #=> true
File.link("a", "b")
p File.identical?("a", "b")      #=> true
File.symlink("a", "c")
p File.identical?("a", "c")      #=> true
open("d", "w") {}
p File.identical?("a", "d")      #=> false

static VALUE
rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
{
#ifndef DOSISH
    struct stat st1, st2;

    if (rb_stat(fname1, &st1) < 0) return Qfalse;
    if (rb_stat(fname2, &st2) < 0) return Qfalse;
    if (st1.st_dev != st2.st_dev) return Qfalse;
    if (st1.st_ino != st2.st_ino) return Qfalse;
#else
# ifdef _WIN32
    BY_HANDLE_FILE_INFORMATION st1, st2;
    HANDLE f1 = 0, f2 = 0;
# endif

    rb_secure(2);
# ifdef _WIN32
    f1 = w32_io_info(&fname1, &st1);
    if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
    f2 = w32_io_info(&fname2, &st2);
    if (f1) CloseHandle(f1);
    if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
    if (f2) CloseHandle(f2);

    if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
        st1.nFileIndexHigh == st2.nFileIndexHigh &&
        st1.nFileIndexLow == st2.nFileIndexLow)
        return Qtrue;
    if (!f1 || !f2) return Qfalse;
# else
    FilePathValue(fname1);
    fname1 = rb_str_new4(fname1);
    fname1 = rb_str_encode_ospath(fname1);
    FilePathValue(fname2);
    fname2 = rb_str_encode_ospath(fname2);
    if (access(RSTRING_PTR(fname1), 0)) return Qfalse;
    if (access(RSTRING_PTR(fname2), 0)) return Qfalse;
# endif
    fname1 = rb_file_expand_path(fname1, Qnil);
    fname2 = rb_file_expand_path(fname2, Qnil);
    if (RSTRING_LEN(fname1) != RSTRING_LEN(fname2)) return Qfalse;
    if (rb_memcicmp(RSTRING_PTR(fname1), RSTRING_PTR(fname2), RSTRING_LEN(fname1)))
        return Qfalse;
#endif
    return Qtrue;
}
join(string, ...) → path click to toggle source

Returns a new string formed by joining the strings using File::SEPARATOR.

File.join("usr", "mail", "gumby")   #=> "usr/mail/gumby"

static VALUE
rb_file_s_join(VALUE klass, VALUE args)
{
    return rb_file_join(args, separator);
}
lchmod(mode_int, file_name, ...) → integer click to toggle source

Equivalent to File::chmod, but does not follow symbolic links (so it will change the permissions associated with the link, not the file referenced by the link). Often not available.

static VALUE
rb_file_s_lchmod(int argc, VALUE *argv)
{
    VALUE vmode;
    VALUE rest;
    long mode, n;

    rb_secure(2);
    rb_scan_args(argc, argv, "1*", &vmode, &rest);
    mode = NUM2INT(vmode);

    n = apply2files(lchmod_internal, rest, (void *)(long)mode);
    return LONG2FIX(n);
}
lchown(owner_int, group_int, file_name,..) → integer click to toggle source

Equivalent to File::chown, but does not follow symbolic links (so it will change the owner associated with the link, not the file referenced by the link). Often not available. Returns number of files in the argument list.

static VALUE
rb_file_s_lchown(int argc, VALUE *argv)
{
    VALUE o, g, rest;
    struct chown_args arg;
    long n;

    rb_secure(2);
    rb_scan_args(argc, argv, "2*", &o, &g, &rest);
    if (NIL_P(o)) {
        arg.owner = -1;
    }
    else {
        arg.owner = NUM2UIDT(o);
    }
    if (NIL_P(g)) {
        arg.group = -1;
    }
    else {
        arg.group = NUM2GIDT(g);
    }

    n = apply2files(lchown_internal, rest, &arg);
    return LONG2FIX(n);
}
link(old_name, new_name) → 0 click to toggle source

Creates a new name for an existing file using a hard link. Will not overwrite new_name if it already exists (raising a subclass of SystemCallError). Not available on all platforms.

File.link("testfile", ".testfile")   #=> 0
IO.readlines(".testfile")[0]         #=> "This is line one\n"

static VALUE
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
{
    rb_secure(2);
    FilePathValue(from);
    FilePathValue(to);
    from = rb_str_encode_ospath(from);
    to = rb_str_encode_ospath(to);

    if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
        sys_fail2(from, to);
    }
    return INT2FIX(0);
}
lstat(file_name) → stat click to toggle source

Same as File::stat, but does not follow the last symbolic link. Instead, reports on the link itself.

File.symlink("testfile", "link2test")   #=> 0
File.stat("testfile").size              #=> 66
File.lstat("link2test").size            #=> 8
File.stat("link2test").size             #=> 66

static VALUE
rb_file_s_lstat(VALUE klass, VALUE fname)
{
#ifdef HAVE_LSTAT
    struct stat st;

    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (lstat(StringValueCStr(fname), &st) == -1) {
        rb_sys_fail_path(fname);
    }
    return stat_new(&st);
#else
    return rb_file_s_stat(klass, fname);
#endif
}
mtime(file_name) → time click to toggle source

Returns the modification time for the named file as a Time object.

file_name can be an IO object.

File.mtime("testfile")   #=> Tue Apr 08 12:58:04 CDT 2003

static VALUE
rb_file_s_mtime(VALUE klass, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) {
        FilePathValue(fname);
        rb_sys_fail_path(fname);
    }
    return stat_mtime(&st);
}
new(filename, mode="r" [, opt]) → file click to toggle source
new(filename [, mode [, perm]] [, opt]) → file

Opens the file named by filename according to the given mode and returns a new File object.

See IO.new for a description of mode and opt.

If a file is being created, permission bits may be given in perm. These mode and permission bits are platform dependent; on Unix systems, see open(2) and chmod(2) man pages for details.

Examples

f = File.new("testfile", "r")
f = File.new("newfile",  "w+")
f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
static VALUE
rb_file_initialize(int argc, VALUE *argv, VALUE io)
{
    if (RFILE(io)->fptr) {
        rb_raise(rb_eRuntimeError, "reinitializing File");
    }
    if (0 < argc && argc < 3) {
        VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");

        if (!NIL_P(fd)) {
            argv[0] = fd;
            return rb_io_initialize(argc, argv, io);
        }
    }
    rb_open_file(argc, argv, io);

    return io;
}
open(filename, mode="r" [, opt]) → file click to toggle source
open(filename [, mode [, perm]] [, opt]) → file
open(filename, mode="r" [, opt]) {|file| block } → obj
open(filename [, mode [, perm]] [, opt]) {|file| block } → obj

With no associated block, File.open is a synonym for ::new. If the optional code block is given, it will be passed the opened file as an argument and the File object will automatically be closed when the block terminates. The value of the block will be returned from File.open.

If a file is being created, its initial permissions may be set using the perm parameter. See ::new for further discussion.

See IO.new for a description of the mode and opt parameters.

static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_class_new_instance(argc, argv, klass);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, io, io_close, io);
    }

    return io;
}
owned?(file_name) → true or false click to toggle source

Returns true if the named file exists and the effective used id of the calling process is the owner of the file.

file_name can be an IO object.

static VALUE
rb_file_owned_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (st.st_uid == geteuid()) return Qtrue;
    return Qfalse;
}
path(path) → string click to toggle source

Returns the string representation of the path

File.path("/dev/null")          #=> "/dev/null"
File.path(Pathname.new("/tmp")) #=> "/tmp"

static VALUE
rb_file_s_path(VALUE klass, VALUE fname)
{
    return rb_get_path(fname);
}
pipe?(file_name) → true or false click to toggle source

Returns true if the named file is a pipe.

file_name can be an IO object.

static VALUE
rb_file_pipe_p(VALUE obj, VALUE fname)
{
#ifdef S_IFIFO
#  ifndef S_ISFIFO
#    define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#  endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISFIFO(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
readable?(file_name) → true or false click to toggle source

Returns true if the named file is readable by the effective user id of this process.

static VALUE
rb_file_readable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
    return Qtrue;
}
readable_real?(file_name) → true or false click to toggle source

Returns true if the named file is readable by the real user id of this process.

static VALUE
rb_file_readable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
    return Qtrue;
}
readlink(link_name) → file_name click to toggle source

Returns the name of the file referenced by the given link. Not available on all platforms.

File.symlink("testfile", "link2test")   #=> 0
File.readlink("link2test")              #=> "testfile"

static VALUE
rb_file_s_readlink(VALUE klass, VALUE path)
{
    return rb_readlink(path);
}
realdirpath(pathname [, dir_string]) → real_pathname click to toggle source

Returns the real (absolute) pathname of pathname in the actual filesystem. The real pathname doesn't contain symlinks or useless dots.

If dir_string is given, it is used as a base directory for interpreting relative pathname instead of the current directory.

The last component of the real pathname can be nonexistent.

static VALUE
rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass)
{
    VALUE path, basedir;
    rb_scan_args(argc, argv, "11", &path, &basedir);
    return rb_realpath_internal(basedir, path, 0);
}
realpath(pathname [, dir_string]) → real_pathname click to toggle source

Returns the real (absolute) pathname of pathname in the actual filesystem not containing symlinks or useless dots.

If dir_string is given, it is used as a base directory for interpreting relative pathname instead of the current directory.

All components of the pathname must exist when this method is called.

static VALUE
rb_file_s_realpath(int argc, VALUE *argv, VALUE klass)
{
    VALUE path, basedir;
    rb_scan_args(argc, argv, "11", &path, &basedir);
    return rb_realpath_internal(basedir, path, 1);
}
rename(old_name, new_name) → 0 click to toggle source

Renames the given file to the new name. Raises a SystemCallError if the file cannot be renamed.

File.rename("afile", "afile.bak")   #=> 0

static VALUE
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
{
    const char *src, *dst;
    VALUE f, t;

    rb_secure(2);
    FilePathValue(from);
    FilePathValue(to);
    f = rb_str_encode_ospath(from);
    t = rb_str_encode_ospath(to);
    src = StringValueCStr(f);
    dst = StringValueCStr(t);
#if defined __CYGWIN__
    errno = 0;
#endif
    if (rename(src, dst) < 0) {
#if defined DOSISH
        switch (errno) {
          case EEXIST:
#if defined (__EMX__)
          case EACCES:
#endif
            if (chmod(dst, 0666) == 0 &&
                unlink(dst) == 0 &&
                rename(src, dst) == 0)
                return INT2FIX(0);
        }
#endif
        sys_fail2(from, to);
    }

    return INT2FIX(0);
}
setgid?(file_name) → true or false click to toggle source

Returns true if the named file has the setgid bit set.

static VALUE
rb_file_sgid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISGID
    return check3rdbyte(fname, S_ISGID);
#else
    return Qfalse;
#endif
}
setuid?(file_name) → true or false click to toggle source

Returns true if the named file has the setuid bit set.

static VALUE
rb_file_suid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISUID
    return check3rdbyte(fname, S_ISUID);
#else
    return Qfalse;
#endif
}
size(file_name) → integer click to toggle source

Returns the size of file_name.

file_name can be an IO object.

static VALUE
rb_file_s_size(VALUE klass, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) {
        FilePathValue(fname);
        rb_sys_fail_path(fname);
    }
    return OFFT2NUM(st.st_size);
}
size?(file_name) → Integer or nil click to toggle source

Returns nil if file_name doesn't exist or has zero size, the size of the file otherwise.

file_name can be an IO object.

static VALUE
rb_file_size_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if (st.st_size == 0) return Qnil;
    return OFFT2NUM(st.st_size);
}
socket?(file_name) → true or false click to toggle source

Returns true if the named file is a socket.

file_name can be an IO object.

static VALUE
rb_file_socket_p(VALUE obj, VALUE fname)
{
#ifndef S_ISSOCK
#  ifdef _S_ISSOCK
#    define S_ISSOCK(m) _S_ISSOCK(m)
#  else
#    ifdef _S_IFSOCK
#      define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
#    else
#      ifdef S_IFSOCK
#        define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#      endif
#    endif
#  endif
#endif

#ifdef S_ISSOCK
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISSOCK(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
split(file_name) → array click to toggle source

Splits the given string into a directory and a file component and returns them in a two-element array. See also File::dirname and File::basename.

File.split("/home/gumby/.profile")   #=> ["/home/gumby", ".profile"]

static VALUE
rb_file_s_split(VALUE klass, VALUE path)
{
    FilePathStringValue(path);          /* get rid of converting twice */
    return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
}
stat(file_name) → stat click to toggle source

Returns a File::Stat object for the named file (see File::Stat).

File.stat("testfile").mtime   #=> Tue Apr 08 12:58:04 CDT 2003

static VALUE
rb_file_s_stat(VALUE klass, VALUE fname)
{
    struct stat st;

    rb_secure(4);
    FilePathValue(fname);
    if (rb_stat(fname, &st) < 0) {
        rb_sys_fail_path(fname);
    }
    return stat_new(&st);
}
sticky?(file_name) → true or false click to toggle source

Returns true if the named file has the sticky bit set.

static VALUE
rb_file_sticky_p(VALUE obj, VALUE fname)
{
#ifdef S_ISVTX
    return check3rdbyte(fname, S_ISVTX);
#else
    return Qnil;
#endif
}
symlink(old_name, new_name) → 0 click to toggle source

Creates a symbolic link called new_name for the existing file old_name. Raises a NotImplemented exception on platforms that do not support symbolic links.

File.symlink("testfile", "link2test")   #=> 0

static VALUE
rb_file_s_symlink(VALUE klass, VALUE from, VALUE to)
{
    rb_secure(2);
    FilePathValue(from);
    FilePathValue(to);
    from = rb_str_encode_ospath(from);
    to = rb_str_encode_ospath(to);

    if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
        sys_fail2(from, to);
    }
    return INT2FIX(0);
}
symlink?(file_name) → true or false click to toggle source

Returns true if the named file is a symbolic link.

static VALUE
rb_file_symlink_p(VALUE obj, VALUE fname)
{
#ifndef S_ISLNK
#  ifdef _S_ISLNK
#    define S_ISLNK(m) _S_ISLNK(m)
#  else
#    ifdef _S_IFLNK
#      define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
#    else
#      ifdef S_IFLNK
#        define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#      endif
#    endif
#  endif
#endif

#ifdef S_ISLNK
    struct stat st;

    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
    if (S_ISLNK(st.st_mode)) return Qtrue;
#endif

    return Qfalse;
}
truncate(file_name, integer) → 0 click to toggle source

Truncates the file file_name to be at most integer bytes long. Not available on all platforms.

f = File.new("out", "w")
f.write("1234567890")     #=> 10
f.close                   #=> nil
File.truncate("out", 5)   #=> 0
File.size("out")          #=> 5

static VALUE
rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
{
    off_t pos;

    rb_secure(2);
    pos = NUM2OFFT(len);
    FilePathValue(path);
    path = rb_str_encode_ospath(path);
#ifdef HAVE_TRUNCATE
    if (truncate(StringValueCStr(path), pos) < 0)
        rb_sys_fail_path(path);
#else /* defined(HAVE_CHSIZE) */
    {
        int tmpfd;

        if ((tmpfd = rb_cloexec_open(StringValueCStr(path), 0, 0)) < 0) {
            rb_sys_fail_path(path);
        }
        rb_update_max_fd(tmpfd);
        if (chsize(tmpfd, pos) < 0) {
            close(tmpfd);
            rb_sys_fail_path(path);
        }
        close(tmpfd);
    }
#endif
    return INT2FIX(0);
}
umask() → integer click to toggle source
umask(integer) → integer

Returns the current umask value for this process. If the optional argument is given, set the umask to that value and return the previous value. Umask values are subtracted from the default permissions, so a umask of 0222 would make a file read-only for everyone.

File.umask(0006)   #=> 18
File.umask         #=> 6

static VALUE
rb_file_s_umask(int argc, VALUE *argv)
{
    int omask = 0;

    rb_secure(2);
    if (argc == 0) {
        omask = umask(0);
        umask(omask);
    }
    else if (argc == 1) {
        omask = umask(NUM2INT(argv[0]));
    }
    else {
        rb_check_arity(argc, 0, 1);
    }
    return INT2FIX(omask);
}
delete(file_name, ...) → integer click to toggle source
unlink(file_name, ...) → integer

Deletes the named files, returning the number of names passed as arguments. Raises an exception on any error. See also Dir::rmdir.

static VALUE
rb_file_s_unlink(VALUE klass, VALUE args)
{
    long n;

    rb_secure(2);
    n = apply2files(unlink_internal, args, 0);
    return LONG2FIX(n);
}
utime(atime, mtime, file_name,...) → integer click to toggle source

Sets the access and modification times of each named file to the first two arguments. Returns the number of file names in the argument list.

static VALUE
rb_file_s_utime(int argc, VALUE *argv)
{
    VALUE rest;
    struct utime_args args;
    struct timespec tss[2], *tsp = NULL;
    long n;

    rb_secure(2);
    rb_scan_args(argc, argv, "2*", &args.atime, &args.mtime, &rest);

    if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
        tsp = tss;
        tsp[0] = rb_time_timespec(args.atime);
        tsp[1] = rb_time_timespec(args.mtime);
    }
    args.tsp = tsp;

    n = apply2files(utime_internal, rest, &args);
    return LONG2FIX(n);
}
world_readable?(file_name) → fixnum or nil click to toggle source

If file_name is readable by others, returns an integer representing the file permission bits of file_name. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

file_name can be an IO object.

File.world_readable?("/etc/passwd")           #=> 420
m = File.world_readable?("/etc/passwd")
sprintf("%o", m)                              #=> "644"

static VALUE
rb_file_world_readable_p(VALUE obj, VALUE fname)
{
#ifdef S_IROTH
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if ((st.st_mode & (S_IROTH)) == S_IROTH) {
        return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
#endif
    return Qnil;
}
world_writable?(file_name) → fixnum or nil click to toggle source

If file_name is writable by others, returns an integer representing the file permission bits of file_name. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

file_name can be an IO object.

File.world_writable?("/tmp")                  #=> 511
m = File.world_writable?("/tmp")
sprintf("%o", m)                              #=> "777"

static VALUE
rb_file_world_writable_p(VALUE obj, VALUE fname)
{
#ifdef S_IWOTH
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
        return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
#endif
    return Qnil;
}
writable?(file_name) → true or false click to toggle source

Returns true if the named file is writable by the effective user id of this process.

static VALUE
rb_file_writable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
    return Qtrue;
}
writable_real?(file_name) → true or false click to toggle source

Returns true if the named file is writable by the real user id of this process.

static VALUE
rb_file_writable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
    return Qtrue;
}
zero?(file_name) → true or false click to toggle source

Returns true if the named file exists and has a zero size.

file_name can be an IO object.

static VALUE
rb_file_zero_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (st.st_size == 0) return Qtrue;
    return Qfalse;
}

Public Instance Methods

atime → time click to toggle source

Returns the last access time (a Time object)

for <i>file</i>, or epoch if <i>file</> has not been accessed.

  File.new("testfile").atime   #=> Wed Dec 31 18:00:00 CST 1969

static VALUE
rb_file_atime(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return stat_atime(&st);
}
chmod(mode_int) → 0 click to toggle source

Changes permission bits on file to the bit pattern represented by mode_int. Actual effects are platform dependent; on Unix systems, see chmod(2) for details. Follows symbolic links. Also see File#lchmod.

f = File.new("out", "w");
f.chmod(0644)   #=> 0

static VALUE
rb_file_chmod(VALUE obj, VALUE vmode)
{
    rb_io_t *fptr;
    int mode;
#ifndef HAVE_FCHMOD
    VALUE path;
#endif

    rb_secure(2);
    mode = NUM2INT(vmode);

    GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
    if (fchmod(fptr->fd, mode) == -1)
        rb_sys_fail_path(fptr->pathv);
#else
    if (NIL_P(fptr->pathv)) return Qnil;
    path = rb_str_encode_ospath(fptr->pathv);
    if (chmod(RSTRING_PTR(path), mode) == -1)
        rb_sys_fail_path(fptr->pathv);
#endif

    return INT2FIX(0);
}
chown(owner_int, group_int ) → 0 click to toggle source

Changes the owner and group of file to the given numeric owner and group id's. Only a process with superuser privileges may change the owner of a file. The current owner of a file may change the file's group to any group to which the owner belongs. A nil or -1 owner or group id is ignored. Follows symbolic links. See also File#lchown.

File.new("testfile").chown(502, 1000)
static VALUE
rb_file_chown(VALUE obj, VALUE owner, VALUE group)
{
    rb_io_t *fptr;
    int o, g;
#ifndef HAVE_FCHOWN
    VALUE path;
#endif

    rb_secure(2);
    o = NIL_P(owner) ? -1 : NUM2INT(owner);
    g = NIL_P(group) ? -1 : NUM2INT(group);
    GetOpenFile(obj, fptr);
#ifndef HAVE_FCHOWN
    if (NIL_P(fptr->pathv)) return Qnil;
    path = rb_str_encode_ospath(fptr->pathv);
    if (chown(RSTRING_PTR(path), o, g) == -1)
        rb_sys_fail_path(fptr->pathv);
#else
    if (fchown(fptr->fd, o, g) == -1)
        rb_sys_fail_path(fptr->pathv);
#endif

    return INT2FIX(0);
}
ctime → time click to toggle source

Returns the change time for file (that is, the time directory information about the file was changed, not the file itself).

Note that on Windows (NTFS), returns creation time (birth time).

File.new("testfile").ctime   #=> Wed Apr 09 08:53:14 CDT 2003

static VALUE
rb_file_ctime(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return stat_ctime(&st);
}
flock(locking_constant) → 0 or false click to toggle source

Locks or unlocks a file according to locking_constant (a logical or of the values in the table below). Returns false if File::LOCK_NB is specified and the operation would otherwise have blocked. Not available on all platforms.

Locking constants (in class File):

LOCK_EX   | Exclusive lock. Only one process may hold an
          | exclusive lock for a given file at a time.
----------+------------------------------------------------
LOCK_NB   | Don't block when locking. May be combined
          | with other lock options using logical or.
----------+------------------------------------------------
LOCK_SH   | Shared lock. Multiple processes may each hold a
          | shared lock for a given file at the same time.
----------+------------------------------------------------
LOCK_UN   | Unlock.

Example:

# update a counter using write lock
# don't use "w" because it truncates the file before lock.
File.open("counter", File::RDWR|File::CREAT, 0644) {|f|
  f.flock(File::LOCK_EX)
  value = f.read.to_i + 1
  f.rewind
  f.write("#{value}\n")
  f.flush
  f.truncate(f.pos)
}

# read the counter using read lock
File.open("counter", "r") {|f|
  f.flock(File::LOCK_SH)
  p f.read
}

static VALUE
rb_file_flock(VALUE obj, VALUE operation)
{
    rb_io_t *fptr;
    int op[2], op1;
    struct timeval time;

    rb_secure(2);
    op[1] = op1 = NUM2INT(operation);
    GetOpenFile(obj, fptr);
    op[0] = fptr->fd;

    if (fptr->mode & FMODE_WRITABLE) {
        rb_io_flush(obj);
    }
    while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
        switch (errno) {
          case EAGAIN:
          case EACCES:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
          case EWOULDBLOCK:
#endif
            if (op1 & LOCK_NB) return Qfalse;

            time.tv_sec = 0;
            time.tv_usec = 100 * 1000; /* 0.1 sec */
            rb_thread_wait_for(time);
            rb_io_check_closed(fptr);
            continue;

          case EINTR:
#if defined(ERESTART)
          case ERESTART:
#endif
            break;

          default:
            rb_sys_fail_path(fptr->pathv);
        }
    }
    return INT2FIX(0);
}
lstat → stat click to toggle source

Same as IO#stat, but does not follow the last symbolic link. Instead, reports on the link itself.

File.symlink("testfile", "link2test")   #=> 0
File.stat("testfile").size              #=> 66
f = File.new("link2test")
f.lstat.size                            #=> 8
f.stat.size                             #=> 66

static VALUE
rb_file_lstat(VALUE obj)
{
#ifdef HAVE_LSTAT
    rb_io_t *fptr;
    struct stat st;
    VALUE path;

    rb_secure(2);
    GetOpenFile(obj, fptr);
    if (NIL_P(fptr->pathv)) return Qnil;
    path = rb_str_encode_ospath(fptr->pathv);
    if (lstat(RSTRING_PTR(path), &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return stat_new(&st);
#else
    return rb_io_stat(obj);
#endif
}
mtime → time click to toggle source

Returns the modification time for file.

File.new("testfile").mtime   #=> Wed Apr 09 08:53:14 CDT 2003

static VALUE
rb_file_mtime(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return stat_mtime(&st);
}
path → filename click to toggle source

Returns the pathname used to create file as a string. Does not normalize the name.

File.new("testfile").path               #=> "testfile"
File.new("/tmp/../tmp/xxx", "w").path   #=> "/tmp/../tmp/xxx"

static VALUE
rb_file_path(VALUE obj)
{
    rb_io_t *fptr;

    fptr = RFILE(rb_io_taint_check(obj))->fptr;
    rb_io_check_initialized(fptr);
    if (NIL_P(fptr->pathv)) return Qnil;
    return rb_obj_taint(rb_str_dup(fptr->pathv));
}
size → integer click to toggle source

Returns the size of file in bytes.

File.new("testfile").size   #=> 66

static VALUE
rb_file_size(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fptr->mode & FMODE_WRITABLE) {
        rb_io_flush(obj);
    }
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return OFFT2NUM(st.st_size);
}
path → filename click to toggle source

Returns the pathname used to create file as a string. Does not normalize the name.

File.new("testfile").path               #=> "testfile"
File.new("/tmp/../tmp/xxx", "w").path   #=> "/tmp/../tmp/xxx"

static VALUE
rb_file_path(VALUE obj)
{
    rb_io_t *fptr;

    fptr = RFILE(rb_io_taint_check(obj))->fptr;
    rb_io_check_initialized(fptr);
    if (NIL_P(fptr->pathv)) return Qnil;
    return rb_obj_taint(rb_str_dup(fptr->pathv));
}
truncate(integer) → 0 click to toggle source

Truncates file to at most integer bytes. The file must be opened for writing. Not available on all platforms.

f = File.new("out", "w")
f.syswrite("1234567890")   #=> 10
f.truncate(5)              #=> 0
f.close()                  #=> nil
File.size("out")           #=> 5

static VALUE
rb_file_truncate(VALUE obj, VALUE len)
{
    rb_io_t *fptr;
    off_t pos;

    rb_secure(2);
    pos = NUM2OFFT(len);
    GetOpenFile(obj, fptr);
    if (!(fptr->mode & FMODE_WRITABLE)) {
        rb_raise(rb_eIOError, "not opened for writing");
    }
    rb_io_flush(obj);
#ifdef HAVE_FTRUNCATE
    if (ftruncate(fptr->fd, pos) < 0)
        rb_sys_fail_path(fptr->pathv);
#else /* defined(HAVE_CHSIZE) */
    if (chsize(fptr->fd, pos) < 0)
        rb_sys_fail_path(fptr->pathv);
#endif
    return INT2FIX(0);
}


module File::Constants - Ruby 2.0.0-p576 Core API Reference API Reference

module File::Constants

File::Constants provides file-related constants. All possible file constants are listed in the documentation but they may not all be present on your platform.

If the underlying platform doesn't define a constant the corresponding Ruby constant is not defined.

Your platform documentations (e.g. man open(2)) may describe more detailed information.

In Files

  • dir.c

Constants

APPEND

append on each write

BINARY

disable line code conversion

CREAT

create file if it does not exist

DIRECT

Try to minimize cache effects of the I/O to and from this file.

DSYNC

any write operation perform synchronously except some meta data

EXCL

error if CREAT and the file exists

LOCK_EX

exclusive lock. see File#flock

LOCK_NB

non-blocking lock. used with LOCK_SH or LOCK_EX. see File#flock

LOCK_SH

shared lock. see File#flock

LOCK_UN

unlock. see File#flock

NOATIME

do not change atime

NOCTTY

not to make opened IO the controlling terminal device

NOFOLLOW

do not follow symlinks

NONBLOCK

do not block on open or for data to become available

NULL

Name of the null device

RDONLY

open for reading only

RDWR

open for reading and writing

RSYNC

any read operation perform synchronously. used with SYNC or DSYNC.

SYNC

any write operation perform synchronously

TRUNC

truncate size to 0

WRONLY

open for writing only


class File::Stat - Ruby 2.0.0-p576 Core API Reference API Reference

class File::Stat

Objects of class File::Stat encapsulate common status information for File objects. The information is recorded at the moment the File::Stat object is created; changes made to the file after that point will not be reflected. File::Stat objects are returned by IO#stat, File::stat, File#lstat, and File::lstat. Many of these methods return platform-specific values, and not all values are meaningful on all systems. See also Kernel#test.

In Files

  • dir.c

Parent

Object

Included Modules

  • Comparable

Public Class Methods

File::Stat.new(file_name) → stat click to toggle source

Create a File::Stat object for the given file name (raising an exception if the file doesn't exist).

static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
    struct stat st, *nst;

    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (STAT(StringValueCStr(fname), &st) == -1) {
        rb_sys_fail_path(fname);
    }
    if (DATA_PTR(obj)) {
        xfree(DATA_PTR(obj));
        DATA_PTR(obj) = NULL;
    }
    nst = ALLOC(struct stat);
    *nst = st;
    DATA_PTR(obj) = nst;

    return Qnil;
}

Public Instance Methods

stat <=> other_stat → -1, 0, 1, nil click to toggle source

Compares File::Stat objects by comparing their respective modification times.

nil is returned if the two values are incomparable.

f1 = File.new("f1", "w")
sleep 1
f2 = File.new("f2", "w")
f1.stat <=> f2.stat   #=> -1

static VALUE
rb_stat_cmp(VALUE self, VALUE other)
{
    if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
        struct timespec ts1 = stat_mtimespec(get_stat(self));
        struct timespec ts2 = stat_mtimespec(get_stat(other));
        if (ts1.tv_sec == ts2.tv_sec) {
            if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0);
            if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1);
            return INT2FIX(1);
        }
        if (ts1.tv_sec < ts2.tv_sec) return INT2FIX(-1);
        return INT2FIX(1);
    }
    return Qnil;
}
atime → time click to toggle source

Returns the last access time for this file as an object of class Time.

File.stat("testfile").atime   #=> Wed Dec 31 18:00:00 CST 1969

static VALUE
rb_stat_atime(VALUE self)
{
    return stat_atime(get_stat(self));
}
blksize → integer or nil click to toggle source

Returns the native file system's block size. Will return nil on platforms that don't support this information.

File.stat("testfile").blksize   #=> 4096

static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_ST_BLKSIZE
    return ULONG2NUM(get_stat(self)->st_blksize);
#else
    return Qnil;
#endif
}
blockdev? → true or false click to toggle source

Returns true if the file is a block device, false if it isn't or if the operating system doesn't support this feature.

File.stat("testfile").blockdev?    #=> false
File.stat("/dev/hda1").blockdev?   #=> true

static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
    if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}
blocks → integer or nil click to toggle source

Returns the number of native file system blocks allocated for this file, or nil if the operating system doesn't support this feature.

File.stat("testfile").blocks   #=> 2

static VALUE
rb_stat_blocks(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
    return ULL2NUM(get_stat(self)->st_blocks);
# else
    return ULONG2NUM(get_stat(self)->st_blocks);
# endif
#else
    return Qnil;
#endif
}
chardev? → true or false click to toggle source

Returns true if the file is a character device, false if it isn't or if the operating system doesn't support this feature.

File.stat("/dev/tty").chardev?   #=> true

static VALUE
rb_stat_c(VALUE obj)
{
    if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;

    return Qfalse;
}
ctime → aTime click to toggle source

Returns the change time for stat (that is, the time directory information about the file was changed, not the file itself).

Note that on Windows (NTFS), returns creation time (birth time).

File.stat("testfile").ctime   #=> Wed Apr 09 08:53:14 CDT 2003

static VALUE
rb_stat_ctime(VALUE self)
{
    return stat_ctime(get_stat(self));
}
dev → fixnum click to toggle source

Returns an integer representing the device on which stat resides.

File.stat("testfile").dev   #=> 774

static VALUE
rb_stat_dev(VALUE self)
{
    return DEVT2NUM(get_stat(self)->st_dev);
}
dev_major → fixnum click to toggle source

Returns the major part of File_Stat#dev or nil.

File.stat("/dev/fd1").dev_major   #=> 2
File.stat("/dev/tty").dev_major   #=> 5

static VALUE
rb_stat_dev_major(VALUE self)
{
#if defined(major)
    return INT2NUM(major(get_stat(self)->st_dev));
#else
    return Qnil;
#endif
}
dev_minor → fixnum click to toggle source

Returns the minor part of File_Stat#dev or nil.

File.stat("/dev/fd1").dev_minor   #=> 1
File.stat("/dev/tty").dev_minor   #=> 0

static VALUE
rb_stat_dev_minor(VALUE self)
{
#if defined(minor)
    return INT2NUM(minor(get_stat(self)->st_dev));
#else
    return Qnil;
#endif
}
directory?(file_name) → true or false click to toggle source

Returns true if the named file is a directory, or a symlink that points at a directory, and false otherwise.

file_name can be an IO object.

File.directory?(".")
static VALUE
rb_stat_d(VALUE obj)
{
    if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
    return Qfalse;
}
executable? → true or false click to toggle source

Returns true if stat is executable or if the operating system doesn't distinguish executable files from nonexecutable files. The tests are made using the effective owner of the process.

File.stat("testfile").executable?   #=> false

static VALUE
rb_stat_x(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (geteuid() == 0) {
        return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
    }
#endif
#ifdef S_IXUSR
    if (rb_stat_owned(obj))
        return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IXGRP
    if (rb_stat_grpowned(obj))
        return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IXOTH
    if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
    return Qtrue;
}
executable_real? → true or false click to toggle source

Same as executable?, but tests using the real owner of the process.

static VALUE
rb_stat_X(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (getuid() == 0) {
        return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
    }
#endif
#ifdef S_IXUSR
    if (rb_stat_rowned(obj))
        return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IXGRP
    if (rb_group_member(get_stat(obj)->st_gid))
        return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IXOTH
    if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
    return Qtrue;
}
file? → true or false click to toggle source

Returns true if stat is a regular file (not a device file, pipe, socket, etc.).

File.stat("testfile").file?   #=> true

static VALUE
rb_stat_f(VALUE obj)
{
    if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
    return Qfalse;
}
ftype → string click to toggle source

Identifies the type of stat. The return string is one of: “file'', “directory'', “characterSpecial'', “blockSpecial'', “fifo'', “link'', “socket'', or “unknown''.

File.stat("/dev/tty").ftype   #=> "characterSpecial"

static VALUE
rb_stat_ftype(VALUE obj)
{
    return rb_file_ftype(get_stat(obj));
}
gid → fixnum click to toggle source

Returns the numeric group id of the owner of stat.

File.stat("testfile").gid   #=> 500

static VALUE
rb_stat_gid(VALUE self)
{
    return GIDT2NUM(get_stat(self)->st_gid);
}
grpowned? → true or false click to toggle source

Returns true if the effective group id of the process is the same as the group id of stat. On Windows NT, returns false.

File.stat("testfile").grpowned?      #=> true
File.stat("/etc/passwd").grpowned?   #=> false

static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
    if (rb_group_member(get_stat(obj)->st_gid)) return Qtrue;
#endif
    return Qfalse;
}
ino → fixnum click to toggle source

Returns the inode number for stat.

File.stat("testfile").ino   #=> 1083669

static VALUE
rb_stat_ino(VALUE self)
{
#if SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
    return ULL2NUM(get_stat(self)->st_ino);
#else
    return ULONG2NUM(get_stat(self)->st_ino);
#endif
}
inspect → string click to toggle source

Produce a nicely formatted description of stat.

File.stat("/etc/passwd").inspect
   #=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644,
   #    nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
   #    blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
   #    mtime=Fri Sep 12 15:41:41 CDT 2003,
   #    ctime=Mon Oct 27 11:20:27 CST 2003>"

static VALUE
rb_stat_inspect(VALUE self)
{
    VALUE str;
    size_t i;
    static const struct {
        const char *name;
        VALUE (*func)(VALUE);
    } member[] = {
        {"dev",            rb_stat_dev},
        {"ino",            rb_stat_ino},
        {"mode",    rb_stat_mode},
        {"nlink",   rb_stat_nlink},
        {"uid",            rb_stat_uid},
        {"gid",            rb_stat_gid},
        {"rdev",    rb_stat_rdev},
        {"size",    rb_stat_size},
        {"blksize", rb_stat_blksize},
        {"blocks",  rb_stat_blocks},
        {"atime",   rb_stat_atime},
        {"mtime",   rb_stat_mtime},
        {"ctime",   rb_stat_ctime},
    };

    struct stat* st;
    TypedData_Get_Struct(self, struct stat, &stat_data_type, st);
    if (!st) {
        return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
    }

    str = rb_str_buf_new2("#<");
    rb_str_buf_cat2(str, rb_obj_classname(self));
    rb_str_buf_cat2(str, " ");

    for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
        VALUE v;

        if (i > 0) {
            rb_str_buf_cat2(str, ", ");
        }
        rb_str_buf_cat2(str, member[i].name);
        rb_str_buf_cat2(str, "=");
        v = (*member[i].func)(self);
        if (i == 2) {          /* mode */
            rb_str_catf(str, "0%lo", (unsigned long)NUM2ULONG(v));
        }
        else if (i == 0 || i == 6) { /* dev/rdev */
            rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
        }
        else {
            rb_str_append(str, rb_inspect(v));
        }
    }
    rb_str_buf_cat2(str, ">");
    OBJ_INFECT(str, self);

    return str;
}
mode → fixnum click to toggle source

Returns an integer representing the permission bits of stat. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

File.chmod(0644, "testfile")   #=> 1
s = File.stat("testfile")
sprintf("%o", s.mode)          #=> "100644"

static VALUE
rb_stat_mode(VALUE self)
{
    return UINT2NUM(ST2UINT(get_stat(self)->st_mode));
}
mtime → aTime click to toggle source

Returns the modification time of stat.

File.stat("testfile").mtime   #=> Wed Apr 09 08:53:14 CDT 2003

static VALUE
rb_stat_mtime(VALUE self)
{
    return stat_mtime(get_stat(self));
}
nlink → fixnum click to toggle source

Returns the number of hard links to stat.

File.stat("testfile").nlink             #=> 1
File.link("testfile", "testfile.bak")   #=> 0
File.stat("testfile").nlink             #=> 2

static VALUE
rb_stat_nlink(VALUE self)
{
    return UINT2NUM(get_stat(self)->st_nlink);
}
owned? → true or false click to toggle source

Returns true if the effective user id of the process is the same as the owner of stat.

File.stat("testfile").owned?      #=> true
File.stat("/etc/passwd").owned?   #=> false

static VALUE
rb_stat_owned(VALUE obj)
{
    if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
    return Qfalse;
}
pipe? → true or false click to toggle source

Returns true if the operating system supports pipes and stat is a pipe; false otherwise.

static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
    if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}
rdev → fixnum or nil click to toggle source

Returns an integer representing the device type on which stat resides. Returns nil if the operating system doesn't support this feature.

File.stat("/dev/fd1").rdev   #=> 513
File.stat("/dev/tty").rdev   #=> 1280

static VALUE
rb_stat_rdev(VALUE self)
{
#ifdef HAVE_ST_RDEV
    return DEVT2NUM(get_stat(self)->st_rdev);
#else
    return Qnil;
#endif
}
rdev_major → fixnum click to toggle source

Returns the major part of File_Stat#rdev or nil.

File.stat("/dev/fd1").rdev_major   #=> 2
File.stat("/dev/tty").rdev_major   #=> 5

static VALUE
rb_stat_rdev_major(VALUE self)
{
#if defined(HAVE_ST_RDEV) && defined(major)
    return DEVT2NUM(major(get_stat(self)->st_rdev));
#else
    return Qnil;
#endif
}
rdev_minor → fixnum click to toggle source

Returns the minor part of File_Stat#rdev or nil.

File.stat("/dev/fd1").rdev_minor   #=> 1
File.stat("/dev/tty").rdev_minor   #=> 0

static VALUE
rb_stat_rdev_minor(VALUE self)
{
#if defined(HAVE_ST_RDEV) && defined(minor)
    return DEVT2NUM(minor(get_stat(self)->st_rdev));
#else
    return Qnil;
#endif
}
readable? → true or false click to toggle source

Returns true if stat is readable by the effective user id of this process.

File.stat("testfile").readable?   #=> true

static VALUE
rb_stat_r(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
    if (rb_stat_owned(obj))
        return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IRGRP
    if (rb_stat_grpowned(obj))
        return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IROTH
    if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
    return Qtrue;
}
readable_real? → true or false click to toggle source

Returns true if stat is readable by the real user id of this process.

File.stat("testfile").readable_real?   #=> true

static VALUE
rb_stat_R(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
    if (rb_stat_rowned(obj))
        return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IRGRP
    if (rb_group_member(get_stat(obj)->st_gid))
        return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IROTH
    if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
    return Qtrue;
}
setgid? → true or false click to toggle source

Returns true if stat has the set-group-id permission bit set, false if it doesn't or if the operating system doesn't support this feature.

File.stat("/usr/sbin/lpc").setgid?   #=> true

static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
    if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
#endif
    return Qfalse;
}
setuid? → true or false click to toggle source

Returns true if stat has the set-user-id permission bit set, false if it doesn't or if the operating system doesn't support this feature.

File.stat("/bin/su").setuid?   #=> true

static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
    if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
#endif
    return Qfalse;
}
size → fixnum click to toggle source

Returns the size of stat in bytes.

File.stat("testfile").size   #=> 66

static VALUE
rb_stat_size(VALUE self)
{
    return OFFT2NUM(get_stat(self)->st_size);
}
size → integer click to toggle source

Returns the size of stat in bytes.

File.stat("testfile").size   #=> 66

static VALUE
rb_stat_s(VALUE obj)
{
    off_t size = get_stat(obj)->st_size;

    if (size == 0) return Qnil;
    return OFFT2NUM(size);
}
socket? → true or false click to toggle source

Returns true if stat is a socket, false if it isn't or if the operating system doesn't support this feature.

File.stat("testfile").socket?   #=> false

static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
    if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}
sticky? → true or false click to toggle source

Returns true if stat has its sticky bit set, false if it doesn't or if the operating system doesn't support this feature.

File.stat("testfile").sticky?   #=> false

static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
    if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
#endif
    return Qfalse;
}
symlink? → true or false click to toggle source

Returns true if stat is a symbolic link, false if it isn't or if the operating system doesn't support this feature. As File::stat automatically follows symbolic links, symlink? will always be false for an object returned by File::stat.

File.symlink("testfile", "alink")   #=> 0
File.stat("alink").symlink?         #=> false
File.lstat("alink").symlink?        #=> true

static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
    if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
#endif
    return Qfalse;
}
uid → fixnum click to toggle source

Returns the numeric user id of the owner of stat.

File.stat("testfile").uid   #=> 501

static VALUE
rb_stat_uid(VALUE self)
{
    return UIDT2NUM(get_stat(self)->st_uid);
}
world_readable? → fixnum or nil click to toggle source

If stat is readable by others, returns an integer representing the file permission bits of stat. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

m = File.stat("/etc/passwd").world_readable?  #=> 420
sprintf("%o", m)                              #=> "644"

static VALUE
rb_stat_wr(VALUE obj)
{
#ifdef S_IROTH
    if ((get_stat(obj)->st_mode & (S_IROTH)) == S_IROTH) {
        return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
    else {
        return Qnil;
    }
#endif
}
world_writable? → fixnum or nil click to toggle source

If stat is writable by others, returns an integer representing the file permission bits of stat. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

m = File.stat("/tmp").world_writable?         #=> 511
sprintf("%o", m)                              #=> "777"

static VALUE
rb_stat_ww(VALUE obj)
{
#ifdef S_IROTH
    if ((get_stat(obj)->st_mode & (S_IWOTH)) == S_IWOTH) {
        return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
    else {
        return Qnil;
    }
#endif
}
writable? → true or false click to toggle source

Returns true if stat is writable by the effective user id of this process.

File.stat("testfile").writable?   #=> true

static VALUE
rb_stat_w(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
    if (rb_stat_owned(obj))
        return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IWGRP
    if (rb_stat_grpowned(obj))
        return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IWOTH
    if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
    return Qtrue;
}
writable_real? → true or false click to toggle source

Returns true if stat is writable by the real user id of this process.

File.stat("testfile").writable_real?   #=> true

static VALUE
rb_stat_W(VALUE obj)
{
    struct stat *st = get_stat(obj);

#ifdef USE_GETEUID
    if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
    if (rb_stat_rowned(obj))
        return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IWGRP
    if (rb_group_member(get_stat(obj)->st_gid))
        return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IWOTH
    if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
    return Qtrue;
}
zero? → true or false click to toggle source

Returns true if stat is a zero-length file; false otherwise.

File.stat("testfile").zero?   #=> false

static VALUE
rb_stat_z(VALUE obj)
{
    if (get_stat(obj)->st_size == 0) return Qtrue;
    return Qfalse;
}


module FileTest - Ruby 2.0.0-p576 Core API Reference API Reference

module FileTest

FileTest implements file test operations similar to those used in File::Stat. It exists as a standalone module, and its methods are also insinuated into the File class. (Note that this is not done by inclusion: the interpreter cheats).

In Files

  • file.c

Public Instance Methods

blockdev?(file_name) → true or false click to toggle source

Returns true if the named file is a block device.

file_name can be an IO object.

static VALUE
rb_file_blockdev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISBLK
#   ifdef S_IFBLK
#       define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#   else
#       define S_ISBLK(m) (0)  /* anytime false */
#   endif
#endif

#ifdef S_ISBLK
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISBLK(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
chardev?(file_name) → true or false click to toggle source

Returns true if the named file is a character device.

file_name can be an IO object.

static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISCHR
#   define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISCHR(st.st_mode)) return Qtrue;

    return Qfalse;
}
directory?(file_name) → true or false click to toggle source

Returns true if the named file is a directory, or a symlink that points at a directory, and false otherwise.

file_name can be an IO object.

File.directory?(".")
VALUE
rb_file_directory_p(VALUE obj, VALUE fname)
{
#ifndef S_ISDIR
#   define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISDIR(st.st_mode)) return Qtrue;
    return Qfalse;
}
executable?(file_name) → true or false click to toggle source

Returns true if the named file is executable by the effective user id of this process.

static VALUE
rb_file_executable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
    return Qtrue;
}
executable_real?(file_name) → true or false click to toggle source

Returns true if the named file is executable by the real user id of this process.

static VALUE
rb_file_executable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
    return Qtrue;
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Return true if the named file exists.

file_name can be an IO object.

“file exists” means that stat() or fstat() system call is successful.

static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    return Qtrue;
}
exist?(file_name) → true or false click to toggle source
exists?(file_name) → true or false

Return true if the named file exists.

file_name can be an IO object.

“file exists” means that stat() or fstat() system call is successful.

static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    return Qtrue;
}
file?(file_name) → true or false click to toggle source

Returns true if the named file exists and is a regular file.

file_name can be an IO object.

static VALUE
rb_file_file_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISREG(st.st_mode)) return Qtrue;
    return Qfalse;
}
grpowned?(file_name) → true or false click to toggle source

Returns true if the named file exists and the effective group id of the calling process is the owner of the file. Returns false on Windows.

file_name can be an IO object.

static VALUE
rb_file_grpowned_p(VALUE obj, VALUE fname)
{
#ifndef _WIN32
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (rb_group_member(st.st_gid)) return Qtrue;
#endif
    return Qfalse;
}
identical?(file_1, file_2) → true or false click to toggle source

Returns true if the named files are identical.

file_1 and file_2 can be an IO object.

open("a", "w") {}
p File.identical?("a", "a")      #=> true
p File.identical?("a", "./a")    #=> true
File.link("a", "b")
p File.identical?("a", "b")      #=> true
File.symlink("a", "c")
p File.identical?("a", "c")      #=> true
open("d", "w") {}
p File.identical?("a", "d")      #=> false

static VALUE
rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
{
#ifndef DOSISH
    struct stat st1, st2;

    if (rb_stat(fname1, &st1) < 0) return Qfalse;
    if (rb_stat(fname2, &st2) < 0) return Qfalse;
    if (st1.st_dev != st2.st_dev) return Qfalse;
    if (st1.st_ino != st2.st_ino) return Qfalse;
#else
# ifdef _WIN32
    BY_HANDLE_FILE_INFORMATION st1, st2;
    HANDLE f1 = 0, f2 = 0;
# endif

    rb_secure(2);
# ifdef _WIN32
    f1 = w32_io_info(&fname1, &st1);
    if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
    f2 = w32_io_info(&fname2, &st2);
    if (f1) CloseHandle(f1);
    if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
    if (f2) CloseHandle(f2);

    if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
        st1.nFileIndexHigh == st2.nFileIndexHigh &&
        st1.nFileIndexLow == st2.nFileIndexLow)
        return Qtrue;
    if (!f1 || !f2) return Qfalse;
# else
    FilePathValue(fname1);
    fname1 = rb_str_new4(fname1);
    fname1 = rb_str_encode_ospath(fname1);
    FilePathValue(fname2);
    fname2 = rb_str_encode_ospath(fname2);
    if (access(RSTRING_PTR(fname1), 0)) return Qfalse;
    if (access(RSTRING_PTR(fname2), 0)) return Qfalse;
# endif
    fname1 = rb_file_expand_path(fname1, Qnil);
    fname2 = rb_file_expand_path(fname2, Qnil);
    if (RSTRING_LEN(fname1) != RSTRING_LEN(fname2)) return Qfalse;
    if (rb_memcicmp(RSTRING_PTR(fname1), RSTRING_PTR(fname2), RSTRING_LEN(fname1)))
        return Qfalse;
#endif
    return Qtrue;
}
owned?(file_name) → true or false click to toggle source

Returns true if the named file exists and the effective used id of the calling process is the owner of the file.

file_name can be an IO object.

static VALUE
rb_file_owned_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (st.st_uid == geteuid()) return Qtrue;
    return Qfalse;
}
pipe?(file_name) → true or false click to toggle source

Returns true if the named file is a pipe.

file_name can be an IO object.

static VALUE
rb_file_pipe_p(VALUE obj, VALUE fname)
{
#ifdef S_IFIFO
#  ifndef S_ISFIFO
#    define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#  endif

    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISFIFO(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
readable?(file_name) → true or false click to toggle source

Returns true if the named file is readable by the effective user id of this process.

static VALUE
rb_file_readable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
    return Qtrue;
}
readable_real?(file_name) → true or false click to toggle source

Returns true if the named file is readable by the real user id of this process.

static VALUE
rb_file_readable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
    return Qtrue;
}
setgid?(file_name) → true or false click to toggle source

Returns true if the named file has the setgid bit set.

static VALUE
rb_file_sgid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISGID
    return check3rdbyte(fname, S_ISGID);
#else
    return Qfalse;
#endif
}
setuid?(file_name) → true or false click to toggle source

Returns true if the named file has the setuid bit set.

static VALUE
rb_file_suid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISUID
    return check3rdbyte(fname, S_ISUID);
#else
    return Qfalse;
#endif
}
size(file_name) → integer click to toggle source

Returns the size of file_name.

file_name can be an IO object.

static VALUE
rb_file_s_size(VALUE klass, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) {
        FilePathValue(fname);
        rb_sys_fail_path(fname);
    }
    return OFFT2NUM(st.st_size);
}
size?(file_name) → Integer or nil click to toggle source

Returns nil if file_name doesn't exist or has zero size, the size of the file otherwise.

file_name can be an IO object.

static VALUE
rb_file_size_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if (st.st_size == 0) return Qnil;
    return OFFT2NUM(st.st_size);
}
socket?(file_name) → true or false click to toggle source

Returns true if the named file is a socket.

file_name can be an IO object.

static VALUE
rb_file_socket_p(VALUE obj, VALUE fname)
{
#ifndef S_ISSOCK
#  ifdef _S_ISSOCK
#    define S_ISSOCK(m) _S_ISSOCK(m)
#  else
#    ifdef _S_IFSOCK
#      define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
#    else
#      ifdef S_IFSOCK
#        define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#      endif
#    endif
#  endif
#endif

#ifdef S_ISSOCK
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (S_ISSOCK(st.st_mode)) return Qtrue;

#endif
    return Qfalse;
}
sticky?(file_name) → true or false click to toggle source

Returns true if the named file has the sticky bit set.

static VALUE
rb_file_sticky_p(VALUE obj, VALUE fname)
{
#ifdef S_ISVTX
    return check3rdbyte(fname, S_ISVTX);
#else
    return Qnil;
#endif
}
symlink?(file_name) → true or false click to toggle source

Returns true if the named file is a symbolic link.

static VALUE
rb_file_symlink_p(VALUE obj, VALUE fname)
{
#ifndef S_ISLNK
#  ifdef _S_ISLNK
#    define S_ISLNK(m) _S_ISLNK(m)
#  else
#    ifdef _S_IFLNK
#      define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
#    else
#      ifdef S_IFLNK
#        define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#      endif
#    endif
#  endif
#endif

#ifdef S_ISLNK
    struct stat st;

    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
    if (S_ISLNK(st.st_mode)) return Qtrue;
#endif

    return Qfalse;
}
world_readable?(file_name) → fixnum or nil click to toggle source

If file_name is readable by others, returns an integer representing the file permission bits of file_name. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

file_name can be an IO object.

File.world_readable?("/etc/passwd")           #=> 420
m = File.world_readable?("/etc/passwd")
sprintf("%o", m)                              #=> "644"

static VALUE
rb_file_world_readable_p(VALUE obj, VALUE fname)
{
#ifdef S_IROTH
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if ((st.st_mode & (S_IROTH)) == S_IROTH) {
        return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
#endif
    return Qnil;
}
world_writable?(file_name) → fixnum or nil click to toggle source

If file_name is writable by others, returns an integer representing the file permission bits of file_name. Returns nil otherwise. The meaning of the bits is platform dependent; on Unix systems, see stat(2).

file_name can be an IO object.

File.world_writable?("/tmp")                  #=> 511
m = File.world_writable?("/tmp")
sprintf("%o", m)                              #=> "777"

static VALUE
rb_file_world_writable_p(VALUE obj, VALUE fname)
{
#ifdef S_IWOTH
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qnil;
    if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
        return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
    }
#endif
    return Qnil;
}
writable?(file_name) → true or false click to toggle source

Returns true if the named file is writable by the effective user id of this process.

static VALUE
rb_file_writable_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
    return Qtrue;
}
writable_real?(file_name) → true or false click to toggle source

Returns true if the named file is writable by the real user id of this process.

static VALUE
rb_file_writable_real_p(VALUE obj, VALUE fname)
{
    rb_secure(2);
    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
    return Qtrue;
}
zero?(file_name) → true or false click to toggle source

Returns true if the named file exists and has a zero size.

file_name can be an IO object.

static VALUE
rb_file_zero_p(VALUE obj, VALUE fname)
{
    struct stat st;

    if (rb_stat(fname, &st) < 0) return Qfalse;
    if (st.st_size == 0) return Qtrue;
    return Qfalse;
}


class Fixnum - Ruby 2.0.0-p576 Core API Reference API Reference

class Fixnum

A Fixnum holds Integer values that can be represented in a native machine word (minus 1 bit). If any operation on a Fixnum exceeds this range, the value is automatically converted to a Bignum.

Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias Fixnum objects. There is effectively only one Fixnum object instance for any given integer value, so, for example, you cannot add a singleton method to a Fixnum.

In Files

  • numeric.c

Parent

Integer

Public Instance Methods

fix % other → real click to toggle source
modulo(other) → real

Returns fix modulo other. See numeric.divmod for more information.

static VALUE
fix_mod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
        return LONG2NUM(mod);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_modulo(x, y);
      case T_FLOAT:
        return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
}
fix & integer → integer_result click to toggle source

Bitwise AND.

static VALUE
fix_and(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long val = FIX2LONG(x) & FIX2LONG(y);
        return LONG2NUM(val);
    }

    if (RB_TYPE_P(y, T_BIGNUM)) {
        return rb_big_and(y, x);
    }

    bit_coerce(&x, &y, TRUE);
    return rb_funcall(x, rb_intern("&"), 1, y);
}
fix * numeric → numeric_result click to toggle source

Performs multiplication: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

static VALUE
fix_mul(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
#ifdef __HP_cc
/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
        volatile
#endif
        long a, b;
#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
        LONG_LONG d;
#else
        VALUE r;
#endif

        a = FIX2LONG(x);
        b = FIX2LONG(y);

#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
        d = (LONG_LONG)a * b;
        if (FIXABLE(d)) return LONG2FIX(d);
        return rb_ll2inum(d);
#else
        if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
            return LONG2FIX(a*b);
        if (a == 0) return x;
        if (MUL_OVERFLOW_FIXNUM_P(a, b))
            r = rb_big_mul(rb_int2big(a), rb_int2big(b));
        else
            r = LONG2FIX(a * b);
        return r;
#endif
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_mul(y, x);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '*');
    }
}
fix ** numeric → numeric_result click to toggle source

Raises fix to the numeric power, which may be negative or fractional.

2 ** 3      #=> 8
2 ** -1     #=> (1/2)
2 ** 0.5    #=> 1.4142135623731

static VALUE
fix_pow(VALUE x, VALUE y)
{
    long a = FIX2LONG(x);

    if (FIXNUM_P(y)) {
        long b = FIX2LONG(y);

        if (a == 1) return INT2FIX(1);
        if (a == -1) {
            if (b % 2 == 0)
                return INT2FIX(1);
            else
                return INT2FIX(-1);
        }
        if (b < 0)
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);

        if (b == 0) return INT2FIX(1);
        if (b == 1) return x;
        if (a == 0) {
            if (b > 0) return INT2FIX(0);
            return DBL2NUM(INFINITY);
        }
        return int_pow(a, b);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        if (a == 1) return INT2FIX(1);
        if (a == -1) {
            if (int_even_p(y)) return INT2FIX(1);
            else return INT2FIX(-1);
        }
        if (negative_int_p(y))
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
        if (a == 0) return INT2FIX(0);
        x = rb_int2big(FIX2LONG(x));
        return rb_big_pow(x, y);
      case T_FLOAT:
        if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0);
        if (a == 0) {
            return DBL2NUM(RFLOAT_VALUE(y) < 0 ? INFINITY : 0.0);
        }
        if (a == 1) return DBL2NUM(1.0);
        {
            double dy = RFLOAT_VALUE(y);
            if (a < 0 && dy != round(dy))
                return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
            return DBL2NUM(pow((double)a, dy));
        }
      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
}
fix + numeric → numeric_result click to toggle source

Performs addition: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

static VALUE
fix_plus(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long a, b, c;
        VALUE r;

        a = FIX2LONG(x);
        b = FIX2LONG(y);
        c = a + b;
        r = LONG2NUM(c);

        return r;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_plus(y, x);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
fix - numeric → numeric_result click to toggle source

Performs subtraction: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

static VALUE
fix_minus(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long a, b, c;
        VALUE r;

        a = FIX2LONG(x);
        b = FIX2LONG(y);
        c = a - b;
        r = LONG2NUM(c);

        return r;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_minus(x, y);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
-fix → integer click to toggle source

Negates fix (which might return a Bignum).

static VALUE
fix_uminus(VALUE num)
{
    return LONG2NUM(-FIX2LONG(num));
}
fix / numeric → numeric_result click to toggle source

Performs division: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

static VALUE
fix_div(VALUE x, VALUE y)
{
    return fix_divide(x, y, '/');
}
fix < real → true or false click to toggle source

Returns true if the value of fix is less than that of real.

static VALUE
fix_lt(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return rb_integer_float_cmp(x, y) == INT2FIX(-1) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, '<');
    }
}
fix << count → integer click to toggle source

Shifts fix left count positions (right if count is negative).

static VALUE
rb_fix_lshift(VALUE x, VALUE y)
{
    long val, width;

    val = NUM2LONG(x);
    if (!FIXNUM_P(y))
        return rb_big_lshift(rb_int2big(val), y);
    width = FIX2LONG(y);
    if (width < 0)
        return fix_rshift(val, (unsigned long)-width);
    return fix_lshift(val, width);
}
fix <= real → true or false click to toggle source

Returns true if the value of fix is less than or equal to that of real.

static VALUE
fix_le(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        {
          VALUE rel = rb_integer_float_cmp(x, y);
          return rel == INT2FIX(-1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
        }
      default:
        return rb_num_coerce_relop(x, y, rb_intern("<="));
    }
}
fix <=> numeric → -1, 0, +1 or nil click to toggle source

Comparison—Returns -1, 0, +1 or nil depending on whether fix is less than, equal to, or greater than numeric. This is the basis for the tests in Comparable.

nil is returned if the two values are incomparable.

static VALUE
fix_cmp(VALUE x, VALUE y)
{
    if (x == y) return INT2FIX(0);
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
        return INT2FIX(-1);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
      case T_FLOAT:
        return rb_integer_float_cmp(x, y);
      default:
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }
}
fix == other → true or false click to toggle source

Return true if fix equals other numerically.

1 == 2      #=> false
1 == 1.0    #=> true

static VALUE
fix_equal(VALUE x, VALUE y)
{
    if (x == y) return Qtrue;
    if (FIXNUM_P(y)) return Qfalse;
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_eq(y, x);
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return num_equal(x, y);
    }
}
fix == other → true or false click to toggle source

Return true if fix equals other numerically.

1 == 2      #=> false
1 == 1.0    #=> true

static VALUE
fix_equal(VALUE x, VALUE y)
{
    if (x == y) return Qtrue;
    if (FIXNUM_P(y)) return Qfalse;
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_eq(y, x);
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return num_equal(x, y);
    }
}
fix > real → true or false click to toggle source

Returns true if the value of fix is greater than that of real.

static VALUE
fix_gt(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return rb_integer_float_cmp(x, y) == INT2FIX(1) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, '>');
    }
}
fix >= real → true or false click to toggle source

Returns true if the value of fix is greater than or equal to that of real.

static VALUE
fix_ge(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        {
          VALUE rel = rb_integer_float_cmp(x, y);
          return rel == INT2FIX(1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
        }
      default:
        return rb_num_coerce_relop(x, y, rb_intern(">="));
    }
}
fix >> count → integer click to toggle source

Shifts fix right count positions (left if count is negative).

static VALUE
rb_fix_rshift(VALUE x, VALUE y)
{
    long i, val;

    val = FIX2LONG(x);
    if (!FIXNUM_P(y))
        return rb_big_rshift(rb_int2big(val), y);
    i = FIX2LONG(y);
    if (i == 0) return x;
    if (i < 0)
        return fix_lshift(val, (unsigned long)-i);
    return fix_rshift(val, i);
}
fix[n] → 0, 1 click to toggle source

Bit Reference—Returns the nth bit in the binary representation of fix, where fix is the least significant bit.

a = 0b11001100101010
30.downto(0) do |n| print a[n] end

produces:

0000000000000000011001100101010
static VALUE
fix_aref(VALUE fix, VALUE idx)
{
    long val = FIX2LONG(fix);
    long i;

    idx = rb_to_int(idx);
    if (!FIXNUM_P(idx)) {
        idx = rb_big_norm(idx);
        if (!FIXNUM_P(idx)) {
            if (!RBIGNUM_SIGN(idx) || val >= 0)
                return INT2FIX(0);
            return INT2FIX(1);
        }
    }
    i = FIX2LONG(idx);

    if (i < 0) return INT2FIX(0);
    if (SIZEOF_LONG*CHAR_BIT-1 < i) {
        if (val < 0) return INT2FIX(1);
        return INT2FIX(0);
    }
    if (val & (1L<<i))
        return INT2FIX(1);
    return INT2FIX(0);
}
fix ^ integer → integer_result click to toggle source

Bitwise EXCLUSIVE OR.

static VALUE
fix_xor(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long val = FIX2LONG(x) ^ FIX2LONG(y);
        return LONG2NUM(val);
    }

    if (RB_TYPE_P(y, T_BIGNUM)) {
        return rb_big_xor(y, x);
    }

    bit_coerce(&x, &y, TRUE);
    return rb_funcall(x, rb_intern("^"), 1, y);
}
abs → integer click to toggle source
magnitude → integer

Returns the absolute value of fix.

-12345.abs   #=> 12345
12345.abs    #=> 12345

static VALUE
fix_abs(VALUE fix)
{
    long i = FIX2LONG(fix);

    if (i < 0) i = -i;

    return LONG2NUM(i);
}
div(numeric) → integer click to toggle source

Performs integer division: returns integer value.

static VALUE
fix_idiv(VALUE x, VALUE y)
{
    return fix_divide(x, y, rb_intern("div"));
}
divmod(numeric) → array click to toggle source

See Numeric#divmod.

static VALUE
fix_divmod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long div, mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);

        return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_divmod(x, y);
      case T_FLOAT:
        {
            double div, mod;
            volatile VALUE a, b;

            flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
            a = dbl2ival(div);
            b = DBL2NUM(mod);
            return rb_assoc_new(a, b);
        }
      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
}
even? → true or false click to toggle source

Returns true if fix is an even number.

static VALUE
fix_even_p(VALUE num)
{
    if (num & 2) {
        return Qfalse;
    }
    return Qtrue;
}
fdiv(numeric) → float click to toggle source

Returns the floating point result of dividing fix by numeric.

654321.fdiv(13731)      #=> 47.6528293642124
654321.fdiv(13731.24)   #=> 47.6519964693647

static VALUE
fix_fdiv(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_fdiv(rb_int2big(FIX2LONG(x)), y);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
    }
}
inspect(p1 = v1) click to toggle source
Alias for: to_s
abs → integer click to toggle source
magnitude → integer

Returns the absolute value of fix.

-12345.abs   #=> 12345
12345.abs    #=> 12345

static VALUE
fix_abs(VALUE fix)
{
    long i = FIX2LONG(fix);

    if (i < 0) i = -i;

    return LONG2NUM(i);
}
fix % other → real click to toggle source
modulo(other) → real

Returns fix modulo other. See numeric.divmod for more information.

static VALUE
fix_mod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
        return LONG2NUM(mod);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_modulo(x, y);
      case T_FLOAT:
        return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
}
odd? → true or false click to toggle source

Returns true if fix is an odd number.

static VALUE
fix_odd_p(VALUE num)
{
    if (num & 2) {
        return Qtrue;
    }
    return Qfalse;
}
size → fixnum click to toggle source

Returns the number of bytes in the machine representation of a Fixnum.

1.size            #=> 4
-1.size           #=> 4
2147483647.size   #=> 4

static VALUE
fix_size(VALUE fix)
{
    return INT2FIX(sizeof(long));
}
next → integer click to toggle source
succ → integer

Returns the Integer equal to int + 1.

1.next      #=> 2
(-1).next   #=> 0

static VALUE
fix_succ(VALUE num)
{
    long i = FIX2LONG(num) + 1;
    return LONG2NUM(i);
}
to_f → float click to toggle source

Converts fix to a Float.

static VALUE
fix_to_f(VALUE num)
{
    double val;

    val = (double)FIX2LONG(num);

    return DBL2NUM(val);
}
to_s(base=10) → string click to toggle source

Returns a string containing the representation of fix radix base (between 2 and 36).

12345.to_s       #=> "12345"
12345.to_s(2)    #=> "11000000111001"
12345.to_s(8)    #=> "30071"
12345.to_s(10)   #=> "12345"
12345.to_s(16)   #=> "3039"
12345.to_s(36)   #=> "9ix"

static VALUE
fix_to_s(int argc, VALUE *argv, VALUE x)
{
    int base;

    if (argc == 0) base = 10;
    else {
        VALUE b;

        rb_scan_args(argc, argv, "01", &b);
        base = NUM2INT(b);
    }

    return rb_fix2str(x, base);
}
Also aliased as: inspect
zero? → true or false click to toggle source

Returns true if fix is zero.

static VALUE
fix_zero_p(VALUE num)
{
    if (FIX2LONG(num) == 0) {
        return Qtrue;
    }
    return Qfalse;
}
fix | integer → integer_result click to toggle source

Bitwise OR.

static VALUE
fix_or(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long val = FIX2LONG(x) | FIX2LONG(y);
        return LONG2NUM(val);
    }

    if (RB_TYPE_P(y, T_BIGNUM)) {
        return rb_big_or(y, x);
    }

    bit_coerce(&x, &y, TRUE);
    return rb_funcall(x, rb_intern("|"), 1, y);
}
~fix → integer click to toggle source

One's complement: returns a number where each bit is flipped.

static VALUE
fix_rev(VALUE num)
{
    return ~num | FIXNUM_FLAG;
}


class Float - Ruby 2.0.0-p576 Core API Reference API Reference

class Float

Float objects represent inexact real numbers using the native architecture's double-precision floating point representation.

Floating point has a different arithmetic and is a inexact number. So you should know its esoteric system. see following:

  • docs.sun.com/source/806-3568/ncg_goldberg.html

  • wiki.github.com/rdp/ruby_tutorials_core/ruby-talk-faq#wiki-floats_imprecise

  • en.wikipedia.org/wiki/Floating_point#Accuracy_problems

In Files

  • complex.c
  • numeric.c
  • rational.c

Parent

Numeric

Constants

DIG

The number of decimal digits in a double-precision floating point.

Usually defaults to 15.

EPSILON

The difference between 1 and the smallest double-precision floating point number.

Usually defaults to 2.2204460492503131e-16.

INFINITY

An expression representing positive infinity.

MANT_DIG

The number of base digits for the double data type.

Usually defaults to 53.

MAX

The largest possible integer in a double-precision floating point number.

Usually defaults to 1.7976931348623157e+308.

MAX_10_EXP

The largest positive exponent in a double-precision floating point where 10 raised to this power minus 1.

Usually defaults to 308.

MAX_EXP

The largest possible exponent value in a double-precision floating point.

Usually defaults to 1024.

MIN

The smallest positive integer in a double-precision floating point.

Usually defaults to 2.2250738585072014e-308.

MIN_10_EXP

The smallest negative exponent in a double-precision floating point where 10 raised to this power minus 1.

Usually defaults to -307.

MIN_EXP

The smallest posable exponent value in a double-precision floating point.

Usually defaults to -1021.

NAN

An expression representing a value which is “not a number”.

RADIX

The base of the floating point, or number of unique digits used to represent the number.

Usually defaults to 2 on most systems, which would represent a base-10 decimal.

ROUNDS

Rounding towards negative infinity

Public Instance Methods

float % other → float click to toggle source
modulo(other) → float

Return the modulo after division of float by other.

6543.21.modulo(137)      #=> 104.21
6543.21.modulo(137.24)   #=> 92.9299999999996

static VALUE
flo_mod(VALUE x, VALUE y)
{
    double fy;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
}
float * other → float click to toggle source

Returns a new float which is the product of float and other.

static VALUE
flo_mul(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '*');
    }
}
flt ** other → float click to toggle source

Raises float the other power.

2.0**3      #=> 8.0

static VALUE
flo_pow(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(pow(RFLOAT_VALUE(x), (double)FIX2LONG(y)));
      case T_BIGNUM:
        return DBL2NUM(pow(RFLOAT_VALUE(x), rb_big2dbl(y)));
      case T_FLOAT:
        {
            double dx = RFLOAT_VALUE(x);
            double dy = RFLOAT_VALUE(y);
            if (dx < 0 && dy != round(dy))
                return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
            return DBL2NUM(pow(dx, dy));
        }
      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
}
float + other → float click to toggle source

Returns a new float which is the sum of float and other.

static VALUE
flo_plus(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
float - other → float click to toggle source

Returns a new float which is the difference of float and other.

static VALUE
flo_minus(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
      case T_BIGNUM:
        return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
-float → float click to toggle source

Returns float, negated.

static VALUE
flo_uminus(VALUE flt)
{
    return DBL2NUM(-RFLOAT_VALUE(flt));
}
float / other → float click to toggle source

Returns a new float which is the result of dividing float by other.

static VALUE
flo_div(VALUE x, VALUE y)
{
    long f_y;
    double d;

    switch (TYPE(y)) {
      case T_FIXNUM:
        f_y = FIX2LONG(y);
        return DBL2NUM(RFLOAT_VALUE(x) / (double)f_y);
      case T_BIGNUM:
        d = rb_big2dbl(y);
        return DBL2NUM(RFLOAT_VALUE(x) / d);
      case T_FLOAT:
        return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '/');
    }
}
flt < real → true or false click to toggle source

true if flt is less than real. The result of NaN < NaN is undefined, so the implementation-dependent value is returned.

static VALUE
flo_lt(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) < 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, '<');
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a < b)?Qtrue:Qfalse;
}
flt <= real → true or false click to toggle source

true if flt is less than or equal to real. The result of NaN <= NaN is undefined, so the implementation-dependent value is returned.

static VALUE
flo_le(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) <= 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, rb_intern("<="));
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a <= b)?Qtrue:Qfalse;
}
float <=> real → -1, 0, +1 or nil click to toggle source

Returns -1, 0, +1 or nil depending on whether float is less than, equal to, or greater than real. This is the basis for the tests in Comparable.

The result of NaN <=> NaN is undefined, so the implementation-dependent value is returned.

nil is returned if the two values are incomparable.

static VALUE
flo_cmp(VALUE x, VALUE y)
{
    double a, b;
    VALUE i;

    a = RFLOAT_VALUE(x);
    if (isnan(a)) return Qnil;
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return INT2FIX(-FIX2INT(rel));
        return rel;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
        break;

      default:
        if (isinf(a) && (i = rb_check_funcall(y, rb_intern("infinite?"), 0, 0)) != Qundef) {
            if (RTEST(i)) {
                int j = rb_cmpint(i, x, y);
                j = (a > 0.0) ? (j > 0 ? 0 : +1) : (j < 0 ? 0 : -1);
                return INT2FIX(j);
            }
            if (a > 0.0) return INT2FIX(1);
            return INT2FIX(-1);
        }
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }
    return rb_dbl_cmp(a, b);
}
flt == obj → true or false click to toggle source

Returns true only if obj has the same value as flt. Contrast this with Float#eql?, which requires obj to be a Float. The result of NaN == NaN is undefined, so the implementation-dependent value is returned.

1.0 == 1   #=> true

static VALUE
flo_eq(VALUE x, VALUE y)
{
    volatile double a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
        return rb_integer_float_eq(y, x);
      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;
      default:
        return num_equal(x, y);
    }
    a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a == b)?Qtrue:Qfalse;
}
flt == obj → true or false click to toggle source

Returns true only if obj has the same value as flt. Contrast this with Float#eql?, which requires obj to be a Float. The result of NaN == NaN is undefined, so the implementation-dependent value is returned.

1.0 == 1   #=> true

static VALUE
flo_eq(VALUE x, VALUE y)
{
    volatile double a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
        return rb_integer_float_eq(y, x);
      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;
      default:
        return num_equal(x, y);
    }
    a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a == b)?Qtrue:Qfalse;
}
flt > real → true or false click to toggle source

true if flt is greater than real. The result of NaN > NaN is undefined, so the implementation-dependent value is returned.

static VALUE
flo_gt(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) > 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, '>');
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a > b)?Qtrue:Qfalse;
}
flt >= real → true or false click to toggle source

true if flt is greater than or equal to real. The result of NaN >= NaN is undefined, so the implementation-dependent value is returned.

static VALUE
flo_ge(VALUE x, VALUE y)
{
    double a, b;

    a = RFLOAT_VALUE(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
      case T_BIGNUM:
      {
        VALUE rel = rb_integer_float_cmp(y, x);
        if (FIXNUM_P(rel))
            return -FIX2INT(rel) >= 0 ? Qtrue : Qfalse;
        return Qfalse;
      }

      case T_FLOAT:
        b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(b)) return Qfalse;
#endif
        break;

      default:
        return rb_num_coerce_relop(x, y, rb_intern(">="));
    }
#if defined(_MSC_VER) && _MSC_VER < 1300
    if (isnan(a)) return Qfalse;
#endif
    return (a >= b)?Qtrue:Qfalse;
}
abs → float click to toggle source
magnitude → float

Returns the absolute value of flt.

(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56

static VALUE
flo_abs(VALUE flt)
{
    double val = fabs(RFLOAT_VALUE(flt));
    return DBL2NUM(val);
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
ceil → integer click to toggle source

Returns the smallest Integer greater than or equal to flt.

1.2.ceil      #=> 2
2.0.ceil      #=> 2
(-1.2).ceil   #=> -1
(-2.0).ceil   #=> -2

static VALUE
flo_ceil(VALUE num)
{
    double f = ceil(RFLOAT_VALUE(num));
    long val;

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
coerce(numeric) → array click to toggle source

Returns an array with both aNumeric and flt represented as Float objects. This is achieved by converting aNumeric to a Float.

1.2.coerce(3)       #=> [3.0, 1.2]
2.5.coerce(1.1)     #=> [1.1, 2.5]

static VALUE
flo_coerce(VALUE x, VALUE y)
{
    return rb_assoc_new(rb_Float(y), x);
}
denominator → integer click to toggle source

Returns the denominator (always positive). The result is machine dependent.

See numerator.

static VALUE
float_denominator(VALUE self)
{
    double d = RFLOAT_VALUE(self);
    if (isinf(d) || isnan(d))
        return INT2FIX(1);
    return rb_call_super(0, 0);
}
divmod(numeric) → array click to toggle source

See Numeric#divmod.

42.0.divmod 6 #=> [7, 0.0]
42.0.divmod 5 #=> [8, 2.0]

static VALUE
flo_divmod(VALUE x, VALUE y)
{
    double fy, div, mod;
    volatile VALUE a, b;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
    flodivmod(RFLOAT_VALUE(x), fy, &div, &mod);
    a = dbl2ival(div);
    b = DBL2NUM(mod);
    return rb_assoc_new(a, b);
}
eql?(obj) → true or false click to toggle source

Returns true only if obj is a Float with the same value as flt. Contrast this with Float#==, which performs type conversions. The result of NaN.eql?(NaN) is undefined, so the implementation-dependent value is returned.

1.0.eql?(1)   #=> false

static VALUE
flo_eql(VALUE x, VALUE y)
{
    if (RB_TYPE_P(y, T_FLOAT)) {
        double a = RFLOAT_VALUE(x);
        double b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
        if (isnan(a) || isnan(b)) return Qfalse;
#endif
        if (a == b)
            return Qtrue;
    }
    return Qfalse;
}
quo(numeric) → float click to toggle source

Returns float / numeric.

static VALUE
flo_quo(VALUE x, VALUE y)
{
    return rb_funcall(x, '/', 1, y);
}
finite? → true or false click to toggle source

Returns true if flt is a valid IEEE floating point number (it is not infinite, and nan? is false).

static VALUE
flo_is_finite_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

#if HAVE_ISFINITE
    if (!isfinite(value))
        return Qfalse;
#else
    if (isinf(value) || isnan(value))
        return Qfalse;
#endif

    return Qtrue;
}
floor → integer click to toggle source

Returns the largest integer less than or equal to flt.

1.2.floor      #=> 1
2.0.floor      #=> 2
(-1.2).floor   #=> -2
(-2.0).floor   #=> -2

static VALUE
flo_floor(VALUE num)
{
    double f = floor(RFLOAT_VALUE(num));
    long val;

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
hash → integer click to toggle source

Returns a hash code for this float.

static VALUE
flo_hash(VALUE num)
{
    double d;
    st_index_t hash;

    d = RFLOAT_VALUE(num);
    /* normalize -0.0 to 0.0 */
    if (d == 0.0) d = 0.0;
    hash = rb_memhash(&d, sizeof(d));
    return LONG2FIX(hash);
}
infinite? → nil, -1, +1 click to toggle source

Returns nil, -1, or +1 depending on whether flt is finite, -infinity, or +infinity.

(0.0).infinite?        #=> nil
(-1.0/0.0).infinite?   #=> -1
(+1.0/0.0).infinite?   #=> 1

static VALUE
flo_is_infinite_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

    if (isinf(value)) {
        return INT2FIX( value < 0 ? -1 : 1 );
    }

    return Qnil;
}
inspect() click to toggle source
Alias for: to_s
abs → float click to toggle source
magnitude → float

Returns the absolute value of flt.

(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56

static VALUE
flo_abs(VALUE flt)
{
    double val = fabs(RFLOAT_VALUE(flt));
    return DBL2NUM(val);
}
float % other → float click to toggle source
modulo(other) → float

Return the modulo after division of float by other.

6543.21.modulo(137)      #=> 104.21
6543.21.modulo(137.24)   #=> 92.9299999999996

static VALUE
flo_mod(VALUE x, VALUE y)
{
    double fy;

    switch (TYPE(y)) {
      case T_FIXNUM:
        fy = (double)FIX2LONG(y);
        break;
      case T_BIGNUM:
        fy = rb_big2dbl(y);
        break;
      case T_FLOAT:
        fy = RFLOAT_VALUE(y);
        break;
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
}
nan? → true or false click to toggle source

Returns true if flt is an invalid IEEE floating point number.

a = -1.0      #=> -1.0
a.nan?        #=> false
a = 0.0/0.0   #=> NaN
a.nan?        #=> true

static VALUE
flo_is_nan_p(VALUE num)
{
    double value = RFLOAT_VALUE(num);

    return isnan(value) ? Qtrue : Qfalse;
}
numerator → integer click to toggle source

Returns the numerator. The result is machine dependent.

n = 0.3.numerator    #=> 5404319552844595
d = 0.3.denominator  #=> 18014398509481984
n.fdiv(d)            #=> 0.3

static VALUE
float_numerator(VALUE self)
{
    double d = RFLOAT_VALUE(self);
    if (isinf(d) || isnan(d))
        return self;
    return rb_call_super(0, 0);
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
float_arg(VALUE self)
{
    if (isnan(RFLOAT_VALUE(self)))
        return self;
    if (f_tpositive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
quo(numeric) → float click to toggle source

Returns float / numeric.

static VALUE
flo_quo(VALUE x, VALUE y)
{
    return rb_funcall(x, '/', 1, y);
}
rationalize([eps]) → rational click to toggle source

Returns a simpler approximation of the value (flt-|eps| <= result <= flt+|eps|). if the optional eps is not given, it will be chosen automatically.

0.3.rationalize          #=> (3/10)
1.333.rationalize        #=> (1333/1000)
1.333.rationalize(0.01)  #=> (4/3)

See to_r.

static VALUE
float_rationalize(int argc, VALUE *argv, VALUE self)
{
    VALUE e, a, b, p, q;

    if (f_negative_p(self))
        return f_negate(float_rationalize(argc, argv, f_abs(self)));

    rb_scan_args(argc, argv, "01", &e);

    if (argc != 0) {
        e = f_abs(e);
        a = f_sub(self, e);
        b = f_add(self, e);
    }
    else {
        VALUE f, n;

        float_decode_internal(self, &f, &n);
        if (f_zero_p(f) || f_positive_p(n))
            return rb_rational_new1(f_lshift(f, n));

#if FLT_RADIX == 2
        {
            VALUE two_times_f, den;

            two_times_f = f_mul(TWO, f);
            den = f_lshift(ONE, f_sub(ONE, n));

            a = rb_rational_new2(f_sub(two_times_f, ONE), den);
            b = rb_rational_new2(f_add(two_times_f, ONE), den);
        }
#else
        {
            VALUE radix_times_f, den;

            radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
            den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));

            a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
            b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
        }
#endif
    }

    if (f_eqeq_p(a, b))
        return f_to_r(self);

    nurat_rationalize_internal(a, b, &p, &q);
    return rb_rational_new2(p, q);
}
round([ndigits]) → integer or float click to toggle source

Rounds flt to a given precision in decimal digits (default 0 digits). Precision may be negative. Returns a floating point number when ndigits is more than zero.

1.4.round      #=> 1
1.5.round      #=> 2
1.6.round      #=> 2
(-1.5).round   #=> -2

1.234567.round(2)  #=> 1.23
1.234567.round(3)  #=> 1.235
1.234567.round(4)  #=> 1.2346
1.234567.round(5)  #=> 1.23457

34567.89.round(-5) #=> 0
34567.89.round(-4) #=> 30000
34567.89.round(-3) #=> 35000
34567.89.round(-2) #=> 34600
34567.89.round(-1) #=> 34570
34567.89.round(0)  #=> 34568
34567.89.round(1)  #=> 34567.9
34567.89.round(2)  #=> 34567.89
34567.89.round(3)  #=> 34567.89

static VALUE
flo_round(int argc, VALUE *argv, VALUE num)
{
    VALUE nd;
    double number, f;
    int ndigits = 0;
    int binexp;
    enum {float_dig = DBL_DIG+2};

    if (argc > 0 && rb_scan_args(argc, argv, "01", &nd) == 1) {
        ndigits = NUM2INT(nd);
    }
    if (ndigits < 0) {
        return int_round_0(flo_truncate(num), ndigits);
    }
    number  = RFLOAT_VALUE(num);
    if (ndigits == 0) {
        return dbl2ival(number);
    }
    frexp(number, &binexp);

/* Let `exp` be such that `number` is written as:"0.#{digits}e#{exp}",
   i.e. such that  10 ** (exp - 1) <= |number| < 10 ** exp
   Recall that up to float_dig digits can be needed to represent a double,
   so if ndigits + exp >= float_dig, the intermediate value (number * 10 ** ndigits)
   will be an integer and thus the result is the original number.
   If ndigits + exp <= 0, the result is 0 or "1e#{exp}", so
   if ndigits + exp < 0, the result is 0.
   We have:
        2 ** (binexp-1) <= |number| < 2 ** binexp
        10 ** ((binexp-1)/log_2(10)) <= |number| < 10 ** (binexp/log_2(10))
        If binexp >= 0, and since log_2(10) = 3.322259:
           10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
           floor(binexp/4) <= exp <= ceil(binexp/3)
        If binexp <= 0, swap the /4 and the /3
        So if ndigits + floor(binexp/(4 or 3)) >= float_dig, the result is number
        If ndigits + ceil(binexp/(3 or 4)) < 0 the result is 0
*/
    if (isinf(number) || isnan(number) ||
        (ndigits >= float_dig - (binexp > 0 ? binexp / 4 : binexp / 3 - 1))) {
        return num;
    }
    if (ndigits < - (binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
        return DBL2NUM(0);
    }
    f = pow(10, ndigits);
    return DBL2NUM(round(number * f) / f);
}
to_f → self click to toggle source

As flt is already a float, returns self.

static VALUE
flo_to_f(VALUE num)
{
    return num;
}
to_i → integer click to toggle source
to_int → integer
truncate → integer

Returns flt truncated to an Integer.

static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
to_i → integer click to toggle source
to_int → integer
truncate → integer

Returns flt truncated to an Integer.

static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
to_r → rational click to toggle source

Returns the value as a rational.

NOTE: 0.3.to_r isn't the same as '0.3'.to_r. The latter is equivalent to '3/10'.#to_r, but the former isn't so.

2.0.to_r    #=> (2/1)
2.5.to_r    #=> (5/2)
-0.75.to_r  #=> (-3/4)
0.0.to_r    #=> (0/1)

See rationalize.

static VALUE
float_to_r(VALUE self)
{
    VALUE f, n;

    float_decode_internal(self, &f, &n);
#if FLT_RADIX == 2
    {
        long ln = FIX2LONG(n);

        if (ln == 0)
            return f_to_r(f);
        if (ln > 0)
            return f_to_r(f_lshift(f, n));
        ln = -ln;
        return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
    }
#else
    return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
#endif
}
to_s → string click to toggle source

Returns a string containing a representation of self. As well as a fixed or exponential form of the number, the call may return “NaN'', “Infinity'', and “-Infinity''.

static VALUE
flo_to_s(VALUE flt)
{
    char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
    enum {decimal_mant = DBL_MANT_DIG-DBL_DIG};
    enum {float_dig = DBL_DIG+1};
    char buf[float_dig + (decimal_mant + CHAR_BIT - 1) / CHAR_BIT + 10];
    double value = RFLOAT_VALUE(flt);
    VALUE s;
    char *p, *e;
    int sign, decpt, digs;

    if (isinf(value))
        return rb_usascii_str_new2(value < 0 ? "-Infinity" : "Infinity");
    else if (isnan(value))
        return rb_usascii_str_new2("NaN");

    p = ruby_dtoa(value, 0, 0, &decpt, &sign, &e);
    s = sign ? rb_usascii_str_new_cstr("-") : rb_usascii_str_new(0, 0);
    if ((digs = (int)(e - p)) >= (int)sizeof(buf)) digs = (int)sizeof(buf) - 1;
    memcpy(buf, p, digs);
    xfree(p);
    if (decpt > 0) {
        if (decpt < digs) {
            memmove(buf + decpt + 1, buf + decpt, digs - decpt);
            buf[decpt] = '.';
            rb_str_cat(s, buf, digs + 1);
        }
        else if (decpt <= DBL_DIG) {
            long len;
            char *ptr;
            rb_str_cat(s, buf, digs);
            rb_str_resize(s, (len = RSTRING_LEN(s)) + decpt - digs + 2);
            ptr = RSTRING_PTR(s) + len;
            if (decpt > digs) {
                memset(ptr, '0', decpt - digs);
                ptr += decpt - digs;
            }
            memcpy(ptr, ".0", 2);
        }
        else {
            goto exp;
        }
    }
    else if (decpt > -4) {
        long len;
        char *ptr;
        rb_str_cat(s, "0.", 2);
        rb_str_resize(s, (len = RSTRING_LEN(s)) - decpt + digs);
        ptr = RSTRING_PTR(s);
        memset(ptr += len, '0', -decpt);
        memcpy(ptr -= decpt, buf, digs);
    }
    else {
      exp:
        if (digs > 1) {
            memmove(buf + 2, buf + 1, digs - 1);
        }
        else {
            buf[2] = '0';
            digs++;
        }
        buf[1] = '.';
        rb_str_cat(s, buf, digs + 1);
        rb_str_catf(s, "e%+03d", decpt - 1);
    }
    return s;
}
Also aliased as: inspect
to_i → integer click to toggle source
to_int → integer
truncate → integer

Returns flt truncated to an Integer.

static VALUE
flo_truncate(VALUE num)
{
    double f = RFLOAT_VALUE(num);
    long val;

    if (f > 0.0) f = floor(f);
    if (f < 0.0) f = ceil(f);

    if (!FIXABLE(f)) {
        return rb_dbl2big(f);
    }
    val = (long)f;
    return LONG2FIX(val);
}
zero? → true or false click to toggle source

Returns true if flt is 0.0.

static VALUE
flo_zero_p(VALUE num)
{
    if (RFLOAT_VALUE(num) == 0.0) {
        return Qtrue;
    }
    return Qfalse;
}


class FloatDomainError - Ruby 2.0.0-p576 Core API Reference API Reference

class FloatDomainError

Raised when attempting to convert special float values (in particular infinite or NaN) to numerical classes which don't support them.

Float::INFINITY.to_r

raises the exception:

FloatDomainError: Infinity

In Files

  • numeric.c

Parent

RangeError


module GC - Ruby 2.0.0-p576 Core API Reference API Reference

module GC

The GC module provides an interface to Ruby's mark and sweep garbage collection mechanism.

Some of the underlying methods are also available via the ObjectSpace module.

You may obtain information about the operation of the GC through GC::Profiler.

In Files

  • gc.c

Public Class Methods

count → Integer click to toggle source

The number of times GC occurred.

It returns the number of times GC occurred since the process started.

static VALUE
gc_count(VALUE self)
{
    return UINT2NUM(rb_objspace.count);
}
disable → true or false click to toggle source

Disables garbage collection, returning true if garbage collection was already disabled.

GC.disable   #=> false
GC.disable   #=> true

VALUE
rb_gc_disable(void)
{
    rb_objspace_t *objspace = &rb_objspace;
    int old = dont_gc;

    rest_sweep(objspace);

    dont_gc = TRUE;
    return old ? Qtrue : Qfalse;
}
enable → true or false click to toggle source

Enables garbage collection, returning true if garbage collection was previously disabled.

GC.disable   #=> false
GC.enable    #=> true
GC.enable    #=> false

VALUE
rb_gc_enable(void)
{
    rb_objspace_t *objspace = &rb_objspace;
    int old = dont_gc;

    dont_gc = FALSE;
    return old ? Qtrue : Qfalse;
}
malloc_allocated_size → Integer click to toggle source

Returns the size of memory allocated by malloc().

Only available if ruby was built with CALC_EXACT_MALLOC_SIZE.

static VALUE
gc_malloc_allocated_size(VALUE self)
{
    return UINT2NUM(rb_objspace.malloc_params.allocated_size);
}
malloc_allocations → Integer click to toggle source

Returns the number of malloc() allocations.

Only available if ruby was built with CALC_EXACT_MALLOC_SIZE.

static VALUE
gc_malloc_allocations(VALUE self)
{
    return UINT2NUM(rb_objspace.malloc_params.allocations);
}
start → nil click to toggle source
garbage_collect → nil
garbage_collect → nil

Initiates garbage collection, unless manually disabled.

VALUE
rb_gc_start(void)
{
    rb_gc();
    return Qnil;
}
stat → Hash click to toggle source

Returns a Hash containing information about the GC.

The hash includes information about internal statistics about GC such as:

{
    :count=>0,
    :heap_used=>12,
    :heap_length=>12,
    :heap_increment=>0,
    :heap_live_num=>7539,
    :heap_free_num=>88,
    :heap_final_num=>0,
    :total_allocated_object=>7630,
    :total_freed_object=>88
}

The contents of the hash are implementation specific and may be changed in the future.

This method is only expected to work on C Ruby.

static VALUE
gc_stat(int argc, VALUE *argv, VALUE self)
{
    rb_objspace_t *objspace = &rb_objspace;
    VALUE hash;
    static VALUE sym_count;
    static VALUE sym_heap_used, sym_heap_length, sym_heap_increment;
    static VALUE sym_heap_live_num, sym_heap_free_num, sym_heap_final_num;
    static VALUE sym_total_allocated_object, sym_total_freed_object;
    if (sym_count == 0) {
        sym_count = ID2SYM(rb_intern_const("count"));
        sym_heap_used = ID2SYM(rb_intern_const("heap_used"));
        sym_heap_length = ID2SYM(rb_intern_const("heap_length"));
        sym_heap_increment = ID2SYM(rb_intern_const("heap_increment"));
        sym_heap_live_num = ID2SYM(rb_intern_const("heap_live_num"));
        sym_heap_free_num = ID2SYM(rb_intern_const("heap_free_num"));
        sym_heap_final_num = ID2SYM(rb_intern_const("heap_final_num"));
        sym_total_allocated_object = ID2SYM(rb_intern_const("total_allocated_object"));
        sym_total_freed_object = ID2SYM(rb_intern_const("total_freed_object"));
    }

    if (rb_scan_args(argc, argv, "01", &hash) == 1) {
        if (!RB_TYPE_P(hash, T_HASH))
            rb_raise(rb_eTypeError, "non-hash given");
    }

    if (hash == Qnil) {
        hash = rb_hash_new();
    }

    rest_sweep(objspace);

    rb_hash_aset(hash, sym_count, SIZET2NUM(objspace->count));
    /* implementation dependent counters */
    rb_hash_aset(hash, sym_heap_used, SIZET2NUM(objspace->heap.used));
    rb_hash_aset(hash, sym_heap_length, SIZET2NUM(objspace->heap.length));
    rb_hash_aset(hash, sym_heap_increment, SIZET2NUM(objspace->heap.increment));
    rb_hash_aset(hash, sym_heap_live_num, SIZET2NUM(objspace_live_num(objspace)));
    rb_hash_aset(hash, sym_heap_free_num, SIZET2NUM(objspace->heap.free_num));
    rb_hash_aset(hash, sym_heap_final_num, SIZET2NUM(objspace->heap.final_num));
    rb_hash_aset(hash, sym_total_allocated_object, SIZET2NUM(objspace->total_allocated_object_num));
    rb_hash_aset(hash, sym_total_freed_object, SIZET2NUM(objspace->total_freed_object_num));

    return hash;
}
stress → true or false click to toggle source

Returns current status of GC stress mode.

static VALUE
gc_stress_get(VALUE self)
{
    rb_objspace_t *objspace = &rb_objspace;
    return ruby_gc_stress ? Qtrue : Qfalse;
}
stress = bool → bool click to toggle source

Updates the GC stress mode.

When stress mode is enabled, the GC is invoked at every GC opportunity: all memory and object allocations.

Enabling stress mode will degrade performance, it is only for debugging.

static VALUE
gc_stress_set(VALUE self, VALUE flag)
{
    rb_objspace_t *objspace = &rb_objspace;
    rb_secure(2);
    ruby_gc_stress = RTEST(flag);
    return flag;
}

Public Instance Methods

start → nil click to toggle source
garbage_collect → nil
garbage_collect → nil

Initiates garbage collection, unless manually disabled.

VALUE
rb_gc_start(void)
{
    rb_gc();
    return Qnil;
}


module GC::Profiler - Ruby 2.0.0-p576 Core API Reference API Reference

module GC::Profiler

The GC profiler provides access to information on GC runs including time, length and object space size.

Example:

GC::Profiler.enable

require 'rdoc/rdoc'

GC::Profiler.report

GC::Profiler.disable

See also GC.count, GC.malloc_allocated_size and GC.malloc_allocations

In Files

  • gc.c

Public Class Methods

GC::Profiler.clear → nil click to toggle source

Clears the GC profiler data.

static VALUE
gc_profile_clear(void)
{
    rb_objspace_t *objspace = &rb_objspace;

    if (GC_PROFILE_RECORD_DEFAULT_SIZE * 2 < objspace->profile.size) {
        objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE * 2;
        objspace->profile.record = realloc(objspace->profile.record, sizeof(gc_profile_record) * objspace->profile.size);
        if (!objspace->profile.record) {
            rb_memerror();
        }
    }
    MEMZERO(objspace->profile.record, gc_profile_record, objspace->profile.size);
    objspace->profile.count = 0;
    return Qnil;
}
GC::Profiler.disable → nil click to toggle source

Stops the GC profiler.

static VALUE
gc_profile_disable(void)
{
    rb_objspace_t *objspace = &rb_objspace;

    objspace->profile.run = FALSE;
    return Qnil;
}
GC::Profiler.enable → nil click to toggle source

Starts the GC profiler.

static VALUE
gc_profile_enable(void)
{
    rb_objspace_t *objspace = &rb_objspace;

    objspace->profile.run = TRUE;
    return Qnil;
}
GC::Profiler.enabled? → true or false click to toggle source

The current status of GC profile mode.

static VALUE
gc_profile_enable_get(VALUE self)
{
    rb_objspace_t *objspace = &rb_objspace;
    return objspace->profile.run ? Qtrue : Qfalse;
}
GC::Profiler.raw_data → [Hash, ...] click to toggle source

Returns an Array of individual raw profile data Hashes ordered from earliest to latest by :GC_INVOKE_TIME.

For example:

[
  {
     :GC_TIME=>1.3000000000000858e-05,
     :GC_INVOKE_TIME=>0.010634999999999999,
     :HEAP_USE_SIZE=>289640,
     :HEAP_TOTAL_SIZE=>588960,
     :HEAP_TOTAL_OBJECTS=>14724,
     :GC_IS_MARKED=>false
  },
  # ...
]

The keys mean:

:GC_TIME

Time elapsed in seconds for this GC run

:GC_INVOKE_TIME

Time elapsed in seconds from startup to when the GC was invoked

:HEAP_USE_SIZE

Total bytes of heap used

:HEAP_TOTAL_SIZE

Total size of heap in bytes

:HEAP_TOTAL_OBJECTS

Total number of objects

:GC_IS_MARKED

Returns true if the GC is in mark phase

If ruby was built with GC_PROFILE_MORE_DETAIL, you will also have access to the following hash keys:

:GC_MARK_TIME
:GC_SWEEP_TIME
:ALLOCATE_INCREASE
:ALLOCATE_LIMIT
:HEAP_USE_SLOTS
:HEAP_LIVE_OBJECTS
:HEAP_FREE_OBJECTS
:HAVE_FINALIZE
static VALUE
gc_profile_record_get(void)
{
    VALUE prof;
    VALUE gc_profile = rb_ary_new();
    size_t i;
    rb_objspace_t *objspace = (&rb_objspace);

    if (!objspace->profile.run) {
        return Qnil;
    }

    for (i =0; i < objspace->profile.count; i++) {
        prof = rb_hash_new();
        rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(objspace->profile.record[i].gc_time));
        rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(objspace->profile.record[i].gc_invoke_time));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(objspace->profile.record[i].heap_use_size));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), SIZET2NUM(objspace->profile.record[i].heap_total_size));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_total_objects));
        rb_hash_aset(prof, ID2SYM(rb_intern("GC_IS_MARKED")), objspace->profile.record[i].is_marked);
#if GC_PROFILE_MORE_DETAIL
        rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(objspace->profile.record[i].gc_mark_time));
        rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(objspace->profile.record[i].gc_sweep_time));
        rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(objspace->profile.record[i].allocate_increase));
        rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(objspace->profile.record[i].allocate_limit));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SLOTS")), SIZET2NUM(objspace->profile.record[i].heap_use_slots));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_live_objects));
        rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_free_objects));
        rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), objspace->profile.record[i].have_finalize);
#endif
        rb_ary_push(gc_profile, prof);
    }

    return gc_profile;
}
GC::Profiler.report click to toggle source
GC::Profiler.report(io)

Writes the ::result to $stdout or the given IO object.

static VALUE
gc_profile_report(int argc, VALUE *argv, VALUE self)
{
    VALUE out;

    if (argc == 0) {
        out = rb_stdout;
    }
    else {
        rb_scan_args(argc, argv, "01", &out);
    }
    gc_profile_dump_on(out, rb_io_write);

    return Qnil;
}
GC::Profiler.result → String click to toggle source

Returns a profile data report such as:

GC 1 invokes.
Index    Invoke Time(sec)       Use Size(byte)     Total Size(byte)         Total Object                    GC time(ms)
    1               0.012               159240               212940                10647         0.00000000000001530000
static VALUE
gc_profile_result(void)
{
        VALUE str = rb_str_buf_new(0);
        gc_profile_dump_on(str, rb_str_buf_append);
        return str;
}
GC::Profiler.total_time → float click to toggle source

The total time used for garbage collection in seconds

static VALUE
gc_profile_total_time(VALUE self)
{
    double time = 0;
    rb_objspace_t *objspace = &rb_objspace;
    size_t i;

    if (objspace->profile.run && objspace->profile.count) {
        for (i = 0; i < objspace->profile.count; i++) {
            time += objspace->profile.record[i].gc_time;
        }
    }
    return DBL2NUM(time);
}


class Hash - Ruby 2.0.0-p576 Core API Reference API Reference

class Hash

A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.

Hashes enumerate their values in the order that the corresponding keys were inserted.

A Hash can be easily created by using its implicit form:

grades = { "Jane Doe" => 10, "Jim Doe" => 6 }

Hashes allow an alternate syntax form when your keys are always symbols. Instead of

options = { :font_size => 10, :font_family => "Arial" }

You could write it as:

options = { font_size: 10, font_family: "Arial" }

Each named key is a symbol you can access in hash:

options[:font_size]  # => 10

A Hash can also be created through its ::new method:

grades = Hash.new
grades["Dorothy Doe"] = 9

Hashes have a default value that is returned when accessing keys that do not exist in the hash. If no default is set nil is used. You can set the default value by sending it as an argument to ::new:

grades = Hash.new(0)

Or by using the default= method:

grades = {"Timmy Doe" => 8}
grades.default = 0

Accessing a value in a Hash requires using its key:

puts grades["Jane Doe"] # => 10

Common Uses

Hashes are an easy way to represent data structures, such as

books         = {}
books[:matz]  = "The Ruby Language"
books[:black] = "The Well-Grounded Rubyist"

Hashes are also commonly used as a way to have named parameters in functions. Note that no brackets are used below. If a hash is the last argument on a method call, no braces are needed, thus creating a really clean interface:

Person.create(name: "John Doe", age: 27)

def self.create(params)
  @name = params[:name]
  @age  = params[:age]
end

Hash Keys

Two objects refer to the same hash key when their hash value is identical and the two objects are eql? to each other.

A user-defined class may be used as a hash key if the hash and eql? methods are overridden to provide meaningful behavior. By default, separate instances refer to separate hash keys.

A typical implementation of hash is based on the object's data while eql? is usually aliased to the overridden == method:

class Book
  attr_reader :author, :title

  def initialize(author, title)
    @author = author
    @title = title
  end

  def ==(other)
    self.class === other and
      other.author == @author and
      other.title == @title
  end

  alias eql? ==

  def hash
    @author.hash ^ @title.hash # XOR
  end
end

book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'

reviews = {}

reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'

reviews.length #=> 1

See also Object#hash and Object#eql?

In Files

  • hash.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

Hash[ key, value, ... ] → new_hash click to toggle source
Hash[ [ [key, value], ... ] ] → new_hash
Hash[ object ] → new_hash

Creates a new hash populated with the given objects. Equivalent to the literal { key => value, ... }. In the first form, keys and values occur in pairs, so there must be an even number of arguments. The second and third form take a single argument which is either an array of key-value pairs or an object convertible to a hash.

Hash["a", 100, "b", 200]             #=> {"a"=>100, "b"=>200}
Hash[ [ ["a", 100], ["b", 200] ] ]   #=> {"a"=>100, "b"=>200}
Hash["a" => 100, "b" => 200]         #=> {"a"=>100, "b"=>200}

static VALUE
rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
{
    VALUE hash, tmp;
    int i;

    if (argc == 1) {
        tmp = rb_hash_s_try_convert(Qnil, argv[0]);
        if (!NIL_P(tmp)) {
            hash = hash_alloc(klass);
            if (RHASH(tmp)->ntbl) {
                RHASH(hash)->ntbl = st_copy(RHASH(tmp)->ntbl);
            }
            return hash;
        }

        tmp = rb_check_array_type(argv[0]);
        if (!NIL_P(tmp)) {
            long i;

            hash = hash_alloc(klass);
            for (i = 0; i < RARRAY_LEN(tmp); ++i) {
                VALUE e = RARRAY_PTR(tmp)[i];
                VALUE v = rb_check_array_type(e);
                VALUE key, val = Qnil;

                if (NIL_P(v)) {
#if 0 /* refix in the next release */
                    rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
                             rb_builtin_class_name(e), i);

#else
                    rb_warn("wrong element type %s at %ld (expected array)",
                            rb_builtin_class_name(e), i);
                    rb_warn("ignoring wrong elements is deprecated, remove them explicitly");
                    rb_warn("this causes ArgumentError in the next release");
                    continue;
#endif
                }
                switch (RARRAY_LEN(v)) {
                  default:
                    rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
                             RARRAY_LEN(v));
                  case 2:
                    val = RARRAY_PTR(v)[1];
                  case 1:
                    key = RARRAY_PTR(v)[0];
                    rb_hash_aset(hash, key, val);
                }
            }
            return hash;
        }
    }
    if (argc % 2 != 0) {
        rb_raise(rb_eArgError, "odd number of arguments for Hash");
    }

    hash = hash_alloc(klass);
    for (i=0; i<argc; i+=2) {
        rb_hash_aset(hash, argv[i], argv[i + 1]);
    }

    return hash;
}
new → new_hash click to toggle source
new(obj) → new_hash
new {|hash, key| block } → new_hash

Returns a new, empty hash. If this hash is subsequently accessed by a key that doesn't correspond to a hash entry, the value returned depends on the style of new used to create the hash. In the first form, the access returns nil. If obj is specified, this single object will be used for all default values. If a block is specified, it will be called with the hash object and the key, and should return the default value. It is the block's responsibility to store the value in the hash if required.

h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"]           #=> 100
h["c"]           #=> "Go Fish"
# The following alters the single default object
h["c"].upcase!   #=> "GO FISH"
h["d"]           #=> "GO FISH"
h.keys           #=> ["a", "b"]

# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"]           #=> "Go Fish: c"
h["c"].upcase!   #=> "GO FISH: C"
h["d"]           #=> "Go Fish: d"
h.keys           #=> ["c", "d"]

static VALUE
rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
{
    VALUE ifnone;

    rb_hash_modify(hash);
    if (rb_block_given_p()) {
        rb_check_arity(argc, 0, 0);
        ifnone = rb_block_proc();
        default_proc_arity_check(ifnone);
        RHASH_IFNONE(hash) = ifnone;
        FL_SET(hash, HASH_PROC_DEFAULT);
    }
    else {
        rb_scan_args(argc, argv, "01", &ifnone);
        RHASH_IFNONE(hash) = ifnone;
    }

    return hash;
}
try_convert(obj) → hash or nil click to toggle source

Try to convert obj into a hash, using #to_hash method. Returns converted hash or nil if obj cannot be converted for any reason.

Hash.try_convert({1=>2})   # => {1=>2}
Hash.try_convert("1=>2")   # => nil

static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
    return rb_check_hash_type(hash);
}

Public Instance Methods

hsh == other_hash → true or false click to toggle source

Equality—Two hashes are equal if they each contain the same number of keys and if each key-value pair is equal to (according to Object#==) the corresponding elements in the other hash.

h1 = { "a" => 1, "c" => 2 }
h2 = { 7 => 35, "c" => 2, "a" => 1 }
h3 = { "a" => 1, "c" => 2, 7 => 35 }
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h1 == h2   #=> false
h2 == h3   #=> true
h3 == h4   #=> false

static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}
hsh[key] → value click to toggle source

Element Reference—Retrieves the value object corresponding to the key object. If not found, returns the default value (see Hash::new for details).

h = { "a" => 100, "b" => 200 }
h["a"]   #=> 100
h["c"]   #=> nil

VALUE
rb_hash_aref(VALUE hash, VALUE key)
{
    st_data_t val;

    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
        return hash_default_value(hash, key);
    }
    return (VALUE)val;
}
hsh[key] = value → value click to toggle source
store(key, value) → value

Element Assignment

Associates the value given by value with the key given by key.

h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h   #=> {"a"=>9, "b"=>200, "c"=>4}

key should not have its value changed while it is in use as a key (an unfrozen String passed as a key will be duplicated and frozen).

a = "a"
b = "b".freeze
h = { a => 100, b => 200 }
h.key(100).equal? a #=> false
h.key(200).equal? b #=> true

VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    int iter_lev = RHASH_ITER_LEV(hash);
    st_table *tbl = RHASH(hash)->ntbl;

    rb_hash_modify(hash);
    if (!tbl) {
        if (iter_lev > 0) no_new_key();
        tbl = RHASH_TBL(hash);
    }
    if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
    }
    else {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
    }
    return val;
}
assoc(obj) → an_array or nil click to toggle source

Searches through the hash comparing obj with the key using ==. Returns the key-value pair (two elements array) or nil if no match is found. See Array#assoc.

h = {"colors"  => ["red", "blue", "green"],
     "letters" => ["a", "b", "c" ]}
h.assoc("letters")  #=> ["letters", ["a", "b", "c"]]
h.assoc("foo")      #=> nil

VALUE
rb_hash_assoc(VALUE hash, VALUE obj)
{
    VALUE args[2];

    args[0] = obj;
    args[1] = Qnil;
    rb_hash_foreach(hash, assoc_i, (VALUE)args);
    return args[1];
}
clear → hsh click to toggle source

Removes all key-value pairs from hsh.

h = { "a" => 100, "b" => 200 }   #=> {"a"=>100, "b"=>200}
h.clear                          #=> {}

VALUE
rb_hash_clear(VALUE hash)
{
    rb_hash_modify_check(hash);
    if (!RHASH(hash)->ntbl)
        return hash;
    if (RHASH(hash)->ntbl->num_entries > 0) {
        if (RHASH_ITER_LEV(hash) > 0)
            rb_hash_foreach(hash, clear_i, 0);
        else
            st_clear(RHASH(hash)->ntbl);
    }

    return hash;
}
compare_by_identity → hsh click to toggle source

Makes hsh compare its keys by their identity, i.e. it will consider exact same objects as same keys.

h1 = { "a" => 100, "b" => 200, :c => "c" }
h1["a"]        #=> 100
h1.compare_by_identity
h1.compare_by_identity? #=> true
h1["a"]        #=> nil  # different objects.
h1[:c]         #=> "c"  # same symbols are all same.

static VALUE
rb_hash_compare_by_id(VALUE hash)
{
    rb_hash_modify(hash);
    RHASH(hash)->ntbl->type = &identhash;
    rb_hash_rehash(hash);
    return hash;
}
compare_by_identity? → true or false click to toggle source

Returns true if hsh will compare its keys by their identity. Also see Hash#compare_by_identity.

static VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    if (!RHASH(hash)->ntbl)
        return Qfalse;
    if (RHASH(hash)->ntbl->type == &identhash) {
        return Qtrue;
    }
    return Qfalse;
}
default(key=nil) → obj click to toggle source

Returns the default value, the value that would be returned by hsh if key did not exist in hsh. See also Hash::new and Hash#default=.

h = Hash.new                            #=> {}
h.default                               #=> nil
h.default(2)                            #=> nil

h = Hash.new("cat")                     #=> {}
h.default                               #=> "cat"
h.default(2)                            #=> "cat"

h = Hash.new {|h,k| h[k] = k.to_i*10}   #=> {}
h.default                               #=> nil
h.default(2)                            #=> 20

static VALUE
rb_hash_default(int argc, VALUE *argv, VALUE hash)
{
    VALUE key, ifnone;

    rb_scan_args(argc, argv, "01", &key);
    ifnone = RHASH_IFNONE(hash);
    if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
        if (argc == 0) return Qnil;
        return rb_funcall(ifnone, id_yield, 2, hash, key);
    }
    return ifnone;
}
default = obj → obj click to toggle source

Sets the default value, the value returned for a key that does not exist in the hash. It is not possible to set the default to a Proc that will be executed on each key lookup.

h = { "a" => 100, "b" => 200 }
h.default = "Go fish"
h["a"]     #=> 100
h["z"]     #=> "Go fish"
# This doesn't do what you might hope...
h.default = proc do |hash, key|
  hash[key] = key + key
end
h[2]       #=> #<Proc:0x401b3948@-:6>
h["cat"]   #=> #<Proc:0x401b3948@-:6>

static VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
    rb_hash_modify_check(hash);
    RHASH_IFNONE(hash) = ifnone;
    FL_UNSET(hash, HASH_PROC_DEFAULT);
    return ifnone;
}
default_proc → anObject click to toggle source

If Hash::new was invoked with a block, return that block, otherwise return nil.

h = Hash.new {|h,k| h[k] = k*k }   #=> {}
p = h.default_proc                 #=> #<Proc:0x401b3d08@-:1>
a = []                             #=> []
p.call(a, 2)
a                                  #=> [nil, nil, 4]

static VALUE
rb_hash_default_proc(VALUE hash)
{
    if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
        return RHASH_IFNONE(hash);
    }
    return Qnil;
}
default_proc = proc_obj or nil click to toggle source

Sets the default proc to be executed on each failed key lookup.

h.default_proc = proc do |hash, key|
  hash[key] = key + key
end
h[2]       #=> 4
h["cat"]   #=> "catcat"

static VALUE
rb_hash_set_default_proc(VALUE hash, VALUE proc)
{
    VALUE b;

    rb_hash_modify_check(hash);
    if (NIL_P(proc)) {
        FL_UNSET(hash, HASH_PROC_DEFAULT);
        RHASH_IFNONE(hash) = proc;
        return proc;
    }
    b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
    if (NIL_P(b) || !rb_obj_is_proc(b)) {
        rb_raise(rb_eTypeError,
                 "wrong default_proc type %s (expected Proc)",
                 rb_obj_classname(proc));
    }
    proc = b;
    default_proc_arity_check(proc);
    RHASH_IFNONE(hash) = proc;
    FL_SET(hash, HASH_PROC_DEFAULT);
    return proc;
}
delete(key) → value click to toggle source
delete(key) {| key | block } → value

Deletes the key-value pair and returns the value from hsh whose key is equal to key. If the key is not found, returns the default value. If the optional code block is given and the key is not found, pass in the key and return the result of block.

h = { "a" => 100, "b" => 200 }
h.delete("a")                              #=> 100
h.delete("z")                              #=> nil
h.delete("z") { |el| "#{el} not found" }   #=> "z not found"

VALUE
rb_hash_delete(VALUE hash, VALUE key)
{
    VALUE val;

    rb_hash_modify_check(hash);
    val = rb_hash_delete_key(hash, key);
    if (val != Qundef) return val;
    if (rb_block_given_p()) {
        return rb_yield(key);
    }
    return Qnil;
}
delete_if {| key, value | block } → hsh click to toggle source
delete_if → an_enumerator

Deletes every key-value pair from hsh for which block evaluates to true.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200, "c" => 300 }
h.delete_if {|key, value| key >= "b" }   #=> {"a"=>100}

VALUE
rb_hash_delete_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_modify_check(hash);
    if (RHASH(hash)->ntbl)
        rb_hash_foreach(hash, delete_if_i, hash);
    return hash;
}
each {| key, value | block } → hsh click to toggle source
each_pair {| key, value | block } → hsh
each → an_enumerator
each_pair → an_enumerator

Calls block once for each key in hsh, passing the key-value pair as parameters.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

produces:

a is 100
b is 200
static VALUE
rb_hash_each_pair(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_foreach(hash, each_pair_i, 0);
    return hash;
}
each_key {| key | block } → hsh click to toggle source
each_key → an_enumerator

Calls block once for each key in hsh, passing the key as a parameter.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200 }
h.each_key {|key| puts key }

produces:

a
b
static VALUE
rb_hash_each_key(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_foreach(hash, each_key_i, 0);
    return hash;
}
each {| key, value | block } → hsh click to toggle source
each_pair {| key, value | block } → hsh
each → an_enumerator
each_pair → an_enumerator

Calls block once for each key in hsh, passing the key-value pair as parameters.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

produces:

a is 100
b is 200
static VALUE
rb_hash_each_pair(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_foreach(hash, each_pair_i, 0);
    return hash;
}
each_value {| value | block } → hsh click to toggle source
each_value → an_enumerator

Calls block once for each key in hsh, passing the value as a parameter.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200 }
h.each_value {|value| puts value }

produces:

100
200
static VALUE
rb_hash_each_value(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_foreach(hash, each_value_i, 0);
    return hash;
}
empty? → true or false click to toggle source

Returns true if hsh contains no key-value pairs.

{}.empty?   #=> true

static VALUE
rb_hash_empty_p(VALUE hash)
{
    return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
}
eql?(other) → true or false click to toggle source

Returns true if hash and other are both hashes with the same content.

static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}
fetch(key [, default] ) → obj click to toggle source
fetch(key) {| key | block } → obj

Returns a value from the hash for the given key. If the key can't be found, there are several options: With no other arguments, it will raise an KeyError exception; if default is given, then that will be returned; if the optional code block is specified, then that will be run and its result returned.

h = { "a" => 100, "b" => 200 }
h.fetch("a")                            #=> 100
h.fetch("z", "go fish")                 #=> "go fish"
h.fetch("z") { |el| "go fish, #{el}"}   #=> "go fish, z"

The following example shows that an exception is raised if the key is not found and a default value is not supplied.

h = { "a" => 100, "b" => 200 }
h.fetch("z")

produces:

prog.rb:2:in `fetch': key not found (KeyError)
 from prog.rb:2
static VALUE
rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
{
    VALUE key, if_none;
    st_data_t val;
    long block_given;

    rb_scan_args(argc, argv, "11", &key, &if_none);

    block_given = rb_block_given_p();
    if (block_given && argc == 2) {
        rb_warn("block supersedes default value argument");
    }
    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
        if (block_given) return rb_yield(key);
        if (argc == 1) {
            volatile VALUE desc = rb_protect(rb_inspect, key, 0);
            if (NIL_P(desc)) {
                desc = rb_any_to_s(key);
            }
            desc = rb_str_ellipsize(desc, 65);
            rb_raise(rb_eKeyError, "key not found: %s", RSTRING_PTR(desc));
        }
        return if_none;
    }
    return (VALUE)val;
}
flatten → an_array click to toggle source
flatten(level) → an_array

Returns a new array that is a one-dimensional flattening of this hash. That is, for every key or value that is an array, extract its elements into the new array. Unlike Array#flatten, this method does not flatten recursively by default. The optional level argument determines the level of recursion to flatten.

a =  {1=> "one", 2 => [2,"two"], 3 => "three"}
a.flatten    # => [1, "one", 2, [2, "two"], 3, "three"]
a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]

static VALUE
rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
{
    VALUE ary, tmp;

    ary = rb_hash_to_a(hash);
    if (argc == 0) {
        argc = 1;
        tmp = INT2FIX(1);
        argv = &tmp;
    }
    rb_funcall2(ary, rb_intern("flatten!"), argc, argv);
    return ary;
}
has_key?(key) → true or false click to toggle source
include?(key) → true or false
key?(key) → true or false
member?(key) → true or false

Returns true if the given key is present in hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

static VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (!RHASH(hash)->ntbl)
        return Qfalse;
    if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
        return Qtrue;
    }
    return Qfalse;
}
has_value?(value) → true or false click to toggle source
value?(value) → true or false

Returns true if the given value is present for some key in hsh.

h = { "a" => 100, "b" => 200 }
h.has_value?(100)   #=> true
h.has_value?(999)   #=> false

static VALUE
rb_hash_has_value(VALUE hash, VALUE val)
{
    VALUE data[2];

    data[0] = Qfalse;
    data[1] = val;
    rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
    return data[0];
}
hash → fixnum click to toggle source

Compute a hash-code for this hash. Two hashes with the same content will have the same hash code (and will compare using eql?).

static VALUE
rb_hash_hash(VALUE hash)
{
    return rb_exec_recursive_outer(recursive_hash, hash, 0);
}
has_key?(key) → true or false click to toggle source
include?(key) → true or false
key?(key) → true or false
member?(key) → true or false

Returns true if the given key is present in hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

static VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (!RHASH(hash)->ntbl)
        return Qfalse;
    if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
        return Qtrue;
    }
    return Qfalse;
}
initialize_copy(p1) click to toggle source
static VALUE
rb_hash_initialize_copy(VALUE hash, VALUE hash2)
{
    st_table *ntbl;

    rb_hash_modify_check(hash);
    hash2 = to_hash(hash2);

    Check_Type(hash2, T_HASH);

    if (hash == hash2) return hash;

    ntbl = RHASH(hash)->ntbl;
    if (RHASH(hash2)->ntbl) {
        if (ntbl) st_free_table(ntbl);
        RHASH(hash)->ntbl = st_copy(RHASH(hash2)->ntbl);
        if (RHASH(hash)->ntbl->num_entries)
            rb_hash_rehash(hash);
    }
    else if (ntbl) {
        st_clear(ntbl);
    }

    if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
        FL_SET(hash, HASH_PROC_DEFAULT);
    }
    else {
        FL_UNSET(hash, HASH_PROC_DEFAULT);
    }
    RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);

    return hash;
}
to_s → string click to toggle source
inspect → string

Return the contents of this hash as a string.

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
h.to_s   #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"

static VALUE
rb_hash_inspect(VALUE hash)
{
    if (RHASH_EMPTY_P(hash))
        return rb_usascii_str_new2("{}");
    return rb_exec_recursive(inspect_hash, hash, 0);
}
Also aliased as: to_s
invert → new_hash click to toggle source

Returns a new hash created by using hsh's values as keys, and the keys as values.

h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert   #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}

static VALUE
rb_hash_invert(VALUE hash)
{
    VALUE h = rb_hash_new();

    rb_hash_foreach(hash, rb_hash_invert_i, h);
    return h;
}
keep_if {| key, value | block } → hsh click to toggle source
keep_if → an_enumerator

Deletes every key-value pair from hsh for which block evaluates to false.

If no block is given, an enumerator is returned instead.

VALUE
rb_hash_keep_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_modify_check(hash);
    if (RHASH(hash)->ntbl)
        rb_hash_foreach(hash, keep_if_i, hash);
    return hash;
}
key(value) → key click to toggle source

Returns the key of an occurrence of a given value. If the value is not found, returns nil.

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
h.key(200)   #=> "b"
h.key(300)   #=> "c"
h.key(999)   #=> nil

static VALUE
rb_hash_key(VALUE hash, VALUE value)
{
    VALUE args[2];

    args[0] = value;
    args[1] = Qnil;

    rb_hash_foreach(hash, key_i, (VALUE)args);

    return args[1];
}
has_key?(key) → true or false click to toggle source
include?(key) → true or false
key?(key) → true or false
member?(key) → true or false

Returns true if the given key is present in hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

static VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (!RHASH(hash)->ntbl)
        return Qfalse;
    if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
        return Qtrue;
    }
    return Qfalse;
}
keys → array click to toggle source

Returns a new array populated with the keys from this hash. See also Hash#values.

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
h.keys   #=> ["a", "b", "c", "d"]

static VALUE
rb_hash_keys(VALUE hash)
{
    VALUE ary;

    ary = rb_ary_new();
    rb_hash_foreach(hash, keys_i, ary);

    return ary;
}
length → fixnum click to toggle source
size → fixnum

Returns the number of key-value pairs in the hash.

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.length        #=> 4
h.delete("a")   #=> 200
h.length        #=> 3

static VALUE
rb_hash_size(VALUE hash)
{
    if (!RHASH(hash)->ntbl)
        return INT2FIX(0);
    return INT2FIX(RHASH(hash)->ntbl->num_entries);
}
has_key?(key) → true or false click to toggle source
include?(key) → true or false
key?(key) → true or false
member?(key) → true or false

Returns true if the given key is present in hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

static VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (!RHASH(hash)->ntbl)
        return Qfalse;
    if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
        return Qtrue;
    }
    return Qfalse;
}
merge(other_hash) → new_hash click to toggle source
merge(other_hash){|key, oldval, newval| block} → new_hash

Returns a new hash containing the contents of other_hash and the contents of hsh. If no block is specified, the value for entries with duplicate keys will be that of other_hash. Otherwise the value for each duplicate key is determined by calling the block with the key, its value in hsh and its value in other_hash.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
h1.merge(h2){|key, oldval, newval| newval - oldval}
               #=> {"a"=>100, "b"=>54,  "c"=>300}
h1             #=> {"a"=>100, "b"=>200}

static VALUE
rb_hash_merge(VALUE hash1, VALUE hash2)
{
    return rb_hash_update(rb_obj_dup(hash1), hash2);
}
merge!(other_hash) → hsh click to toggle source
update(other_hash) → hsh
merge!(other_hash){|key, oldval, newval| block} → hsh
update(other_hash){|key, oldval, newval| block} → hsh

Adds the contents of other_hash to hsh. If no block is specified, entries with duplicate keys are overwritten with the values from other_hash, otherwise the value of each duplicate key is determined by calling the block with the key, its value in hsh and its value in other_hash.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) { |key, v1, v2| v1 }
                #=> {"a"=>100, "b"=>200, "c"=>300}

static VALUE
rb_hash_update(VALUE hash1, VALUE hash2)
{
    rb_hash_modify(hash1);
    hash2 = to_hash(hash2);
    if (rb_block_given_p()) {
        rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
    }
    else {
        rb_hash_foreach(hash2, rb_hash_update_i, hash1);
    }
    return hash1;
}
rassoc(obj) → an_array or nil click to toggle source

Searches through the hash comparing obj with the value using ==. Returns the first key-value pair (two-element array) that matches. See also Array#rassoc.

a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
a.rassoc("two")    #=> [2, "two"]
a.rassoc("four")   #=> nil

VALUE
rb_hash_rassoc(VALUE hash, VALUE obj)
{
    VALUE args[2];

    args[0] = obj;
    args[1] = Qnil;
    rb_hash_foreach(hash, rassoc_i, (VALUE)args);
    return args[1];
}
rehash → hsh click to toggle source

Rebuilds the hash based on the current hash values for each key. If values of key objects have changed since they were inserted, this method will reindex hsh. If Hash#rehash is called while an iterator is traversing the hash, an RuntimeError will be raised in the iterator.

a = [ "a", "b" ]
c = [ "c", "d" ]
h = { a => 100, c => 300 }
h[a]       #=> 100
a[0] = "z"
h[a]       #=> nil
h.rehash   #=> {["z", "b"]=>100, ["c", "d"]=>300}
h[a]       #=> 100

static VALUE
rb_hash_rehash(VALUE hash)
{
    VALUE tmp;
    st_table *tbl;

    if (RHASH_ITER_LEV(hash) > 0) {
        rb_raise(rb_eRuntimeError, "rehash during iteration");
    }
    rb_hash_modify_check(hash);
    if (!RHASH(hash)->ntbl)
        return hash;
    tmp = hash_alloc(0);
    tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
    RHASH(tmp)->ntbl = tbl;

    rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
    st_free_table(RHASH(hash)->ntbl);
    RHASH(hash)->ntbl = tbl;
    RHASH(tmp)->ntbl = 0;

    return hash;
}
reject {| key, value | block } → a_hash click to toggle source
reject → an_enumerator

Same as Hash#delete_if, but works on (and returns) a copy of the hsh. Equivalent to hsh.dup.delete_if.

static VALUE
rb_hash_reject(VALUE hash)
{
    return rb_hash_delete_if(rb_obj_dup(hash));
}
reject! {| key, value | block } → hsh or nil click to toggle source
reject! → an_enumerator

Equivalent to Hash#delete_if, but returns nil if no changes were made.

VALUE
rb_hash_reject_bang(VALUE hash)
{
    st_index_t n;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_modify(hash);
    if (!RHASH(hash)->ntbl)
        return Qnil;
    n = RHASH(hash)->ntbl->num_entries;
    rb_hash_foreach(hash, delete_if_i, hash);
    if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
    return hash;
}
replace(other_hash) → hsh click to toggle source

Replaces the contents of hsh with the contents of other_hash.

h = { "a" => 100, "b" => 200 }
h.replace({ "c" => 300, "d" => 400 })   #=> {"c"=>300, "d"=>400}

static VALUE
rb_hash_replace(VALUE hash, VALUE hash2)
{
    rb_hash_modify_check(hash);
    hash2 = to_hash(hash2);
    if (hash == hash2) return hash;
    rb_hash_clear(hash);
    if (RHASH(hash2)->ntbl) {
        rb_hash_tbl(hash);
        RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
    }
    rb_hash_foreach(hash2, replace_i, hash);
    RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
    if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
        FL_SET(hash, HASH_PROC_DEFAULT);
    }
    else {
        FL_UNSET(hash, HASH_PROC_DEFAULT);
    }

    return hash;
}
select {|key, value| block} → a_hash click to toggle source
select → an_enumerator

Returns a new hash consisting of entries for which the block returns true.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200, "c" => 300 }
h.select {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}
h.select {|k,v| v < 200}  #=> {"a" => 100}

VALUE
rb_hash_select(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    result = rb_hash_new();
    rb_hash_foreach(hash, select_i, result);
    return result;
}
select! {| key, value | block } → hsh or nil click to toggle source
select! → an_enumerator

Equivalent to Hash#keep_if, but returns nil if no changes were made.

VALUE
rb_hash_select_bang(VALUE hash)
{
    st_index_t n;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size);
    rb_hash_modify_check(hash);
    if (!RHASH(hash)->ntbl)
        return Qnil;
    n = RHASH(hash)->ntbl->num_entries;
    rb_hash_foreach(hash, keep_if_i, hash);
    if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
    return hash;
}
shift → anArray or obj click to toggle source

Removes a key-value pair from hsh and returns it as the two-item array [ key, value ], or the hash's default value if the hash is empty.

h = { 1 => "a", 2 => "b", 3 => "c" }
h.shift   #=> [1, "a"]
h         #=> {2=>"b", 3=>"c"}

static VALUE
rb_hash_shift(VALUE hash)
{
    struct shift_var var;

    rb_hash_modify_check(hash);
    if (RHASH(hash)->ntbl) {
        var.key = Qundef;
        rb_hash_foreach(hash, RHASH_ITER_LEV(hash) > 0 ? shift_i_safe : shift_i,
                        (VALUE)&var);

        if (var.key != Qundef) {
            if (RHASH_ITER_LEV(hash) > 0) {
                rb_hash_delete_key(hash, var.key);
            }
            return rb_assoc_new(var.key, var.val);
        }
    }
    return hash_default_value(hash, Qnil);
}
length → fixnum click to toggle source
size → fixnum

Returns the number of key-value pairs in the hash.

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.length        #=> 4
h.delete("a")   #=> 200
h.length        #=> 3

static VALUE
rb_hash_size(VALUE hash)
{
    if (!RHASH(hash)->ntbl)
        return INT2FIX(0);
    return INT2FIX(RHASH(hash)->ntbl->num_entries);
}
hsh[key] = value → value click to toggle source
store(key, value) → value

Element Assignment

Associates the value given by value with the key given by key.

h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h   #=> {"a"=>9, "b"=>200, "c"=>4}

key should not have its value changed while it is in use as a key (an unfrozen String passed as a key will be duplicated and frozen).

a = "a"
b = "b".freeze
h = { a => 100, b => 200 }
h.key(100).equal? a #=> false
h.key(200).equal? b #=> true

VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    int iter_lev = RHASH_ITER_LEV(hash);
    st_table *tbl = RHASH(hash)->ntbl;

    rb_hash_modify(hash);
    if (!tbl) {
        if (iter_lev > 0) no_new_key();
        tbl = RHASH_TBL(hash);
    }
    if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
    }
    else {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
    }
    return val;
}
to_a → array click to toggle source

Converts hsh to a nested array of [ key, value ] arrays.

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
h.to_a   #=> [["c", 300], ["a", 100], ["d", 400]]

static VALUE
rb_hash_to_a(VALUE hash)
{
    VALUE ary;

    ary = rb_ary_new();
    rb_hash_foreach(hash, to_a_i, ary);
    OBJ_INFECT(ary, hash);

    return ary;
}
to_h → hsh or new_hash click to toggle source

Returns self. If called on a subclass of Hash, converts the receiver to a Hash object.

static VALUE
rb_hash_to_h(VALUE hash)
{
    if (rb_obj_class(hash) != rb_cHash) {
        VALUE ret = rb_hash_new();
        if (!RHASH_EMPTY_P(hash))
            RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl);
        if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
            FL_SET(ret, HASH_PROC_DEFAULT);
        }
        RHASH_IFNONE(ret) = RHASH_IFNONE(hash);
        return ret;
    }
    return hash;
}
to_hash → hsh click to toggle source

Returns self.

static VALUE
rb_hash_to_hash(VALUE hash)
{
    return hash;
}
to_s() click to toggle source
Alias for: inspect
merge!(other_hash) → hsh click to toggle source
update(other_hash) → hsh
merge!(other_hash){|key, oldval, newval| block} → hsh
update(other_hash){|key, oldval, newval| block} → hsh

Adds the contents of other_hash to hsh. If no block is specified, entries with duplicate keys are overwritten with the values from other_hash, otherwise the value of each duplicate key is determined by calling the block with the key, its value in hsh and its value in other_hash.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) { |key, v1, v2| v1 }
                #=> {"a"=>100, "b"=>200, "c"=>300}

static VALUE
rb_hash_update(VALUE hash1, VALUE hash2)
{
    rb_hash_modify(hash1);
    hash2 = to_hash(hash2);
    if (rb_block_given_p()) {
        rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
    }
    else {
        rb_hash_foreach(hash2, rb_hash_update_i, hash1);
    }
    return hash1;
}
has_value?(value) → true or false click to toggle source
value?(value) → true or false

Returns true if the given value is present for some key in hsh.

h = { "a" => 100, "b" => 200 }
h.has_value?(100)   #=> true
h.has_value?(999)   #=> false

static VALUE
rb_hash_has_value(VALUE hash, VALUE val)
{
    VALUE data[2];

    data[0] = Qfalse;
    data[1] = val;
    rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
    return data[0];
}
values → array click to toggle source

Returns a new array populated with the values from hsh. See also Hash#keys.

h = { "a" => 100, "b" => 200, "c" => 300 }
h.values   #=> [100, 200, 300]

static VALUE
rb_hash_values(VALUE hash)
{
    VALUE ary;

    ary = rb_ary_new();
    rb_hash_foreach(hash, values_i, ary);

    return ary;
}
values_at(key, ...) → array click to toggle source

Return an array containing the values associated with the given keys. Also see Hash.select.

h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
h.values_at("cow", "cat")  #=> ["bovine", "feline"]

VALUE
rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
{
    VALUE result = rb_ary_new2(argc);
    long i;

    for (i=0; i<argc; i++) {
        rb_ary_push(result, rb_hash_aref(hash, argv[i]));
    }
    return result;
}


class IO - Ruby 2.0.0-p576 Core API Reference API Reference

class IO

The IO class is the basis for all input and output in Ruby. An I/O stream may be duplexed (that is, bidirectional), and so may use more than one native operating system stream.

Many of the examples in this section use the File class, the only standard subclass of IO. The two classes are closely associated. Like the File class, the Socket library subclasses from IO (such as TCPSocket or UDPSocket).

The Kernel#open method can create an IO (or File) object for these types of arguments:

  • A plain string represents a filename suitable for the underlying operating system.

  • A string starting with "|" indicates a subprocess. The remainder of the string following the "|" is invoked as a process with appropriate input/output channels connected to it.

  • A string equal to "|-" will create another Ruby instance as a subprocess.

The IO may be opened with different file modes (read-only, write-only) and encodings for proper conversion. See ::new for these options. See Kernel#open for details of the various command formats described above.

::popen, the Open3 library, or Process#spawn may also be used to communicate with subprocesses through an IO.

Ruby will convert pathnames between different operating system conventions if possible. For instance, on a Windows system the filename "/gumby/ruby/test.rb" will be opened as "\gumby\ruby\test.rb". When specifying a Windows-style filename in a Ruby string, remember to escape the backslashes:

"c:\\gumby\\ruby\\test.rb"

Our examples here will use the Unix-style forward slashes; File::ALT_SEPARATOR can be used to get the platform-specific separator character.

The global constant ARGF (also accessible as $<) provides an IO-like stream which allows access to all files mentioned on the command line (or STDIN if no files are mentioned). ARGF#path and its alias ARGF#filename are provided to access the name of the file currently being read.

io/console

The io/console extension provides methods for interacting with the console. The console can be accessed from IO.console or the standard input/output/error IO objects.

Requiring io/console adds the following methods:

  • IO::console

  • IO#raw

  • IO#raw!

  • IO#cooked

  • IO#cooked!

  • IO#getch

  • IO#echo=

  • IO#echo?

  • IO#noecho

  • IO#winsize

  • IO#winsize=

  • IO#iflush

  • IO#ioflush

  • IO#oflush

Example:

require 'io/console'
rows, columns = $stdin.winsize
puts "Your screen is #{columns} wide and #{rows} tall"

In Files

  • file.c
  • io.c

Parent

Object

Included Modules

  • File::Constants
  • Enumerable

Constants

SEEK_CUR
SEEK_END
SEEK_SET

Public Class Methods

binread(name, [length [, offset]] ) → string click to toggle source

Opens the file, optionally seeks to the given offset, then returns length bytes (defaulting to the rest of the file). binread ensures the file is closed before returning. The open mode would be “rb:ASCII-8BIT”.

IO.binread("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
IO.binread("testfile", 20)       #=> "This is line one\nThi"
IO.binread("testfile", 20, 10)   #=> "ne one\nThis is line "

static VALUE
rb_io_s_binread(int argc, VALUE *argv, VALUE io)
{
    VALUE offset;
    struct foreach_arg arg;

    rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
    FilePathValue(argv[0]);
    arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
    if (NIL_P(arg.io)) return Qnil;
    arg.argv = argv+1;
    arg.argc = (argc > 1) ? 1 : 0;
    if (!NIL_P(offset)) {
        rb_io_seek(arg.io, offset, SEEK_SET);
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
binwrite(name, string, [offset] ) → fixnum click to toggle source
binwrite(name, string, [offset], open_args ) → fixnum

Same as IO.write except opening the file in binary mode and ASCII-8BIT encoding (“wb:ASCII-8BIT”).

static VALUE
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, 1);
}
copy_stream(src, dst) click to toggle source
copy_stream(src, dst, copy_length)
copy_stream(src, dst, copy_length, src_offset)

::copy_stream copies src to dst. src and dst is either a filename or an IO.

This method returns the number of bytes copied.

If optional arguments are not given, the start position of the copy is the beginning of the filename or the current file offset of the IO. The end position of the copy is the end of file.

If copy_length is given, No more than copy_length bytes are copied.

If src_offset is given, it specifies the start position of the copy.

When src_offset is specified and src is an IO, ::copy_stream doesn't move the current file offset.

static VALUE
rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
{
    VALUE src, dst, length, src_offset;
    struct copy_stream_struct st;

    MEMZERO(&st, struct copy_stream_struct, 1);

    rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);

    st.src = src;
    st.dst = dst;

    if (NIL_P(length))
        st.copy_length = (off_t)-1;
    else
        st.copy_length = NUM2OFFT(length);

    if (NIL_P(src_offset))
        st.src_offset = (off_t)-1;
    else
        st.src_offset = NUM2OFFT(src_offset);

    rb_fd_init(&st.fds);
    rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);

    return OFFT2NUM(st.total);
}
for_fd(fd, mode [, opt]) → io click to toggle source

Synonym for IO.new.

static VALUE
rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_obj_alloc(klass);
    rb_io_initialize(argc, argv, io);
    return io;
}
foreach(name, sep=$/ [, open_args]) {|line| block } → nil click to toggle source
foreach(name, limit [, open_args]) {|line| block } → nil
foreach(name, sep, limit [, open_args]) {|line| block } → nil
foreach(...) → an_enumerator

Executes the block for every line in the named I/O port, where lines are separated by sep.

If no block is given, an enumerator is returned instead.

IO.foreach("testfile") {|x| print "GOT ", x }

produces:

GOT This is line one
GOT This is line two
GOT This is line three
GOT And so on...

If the last argument is a hash, it's the keyword argument to open. See IO.read for detail.

static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
    VALUE opt;
    int orig_argc = argc;
    struct foreach_arg arg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
    RETURN_ENUMERATOR(self, orig_argc, argv);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
}
new(fd [, mode] [, opt]) → io click to toggle source

Returns a new IO object (a stream) for the given integer file descriptor fd and mode string. opt may be used to specify parts of mode in a more readable fashion. See also ::sysopen and ::for_fd.

::new is called by various File and IO opening methods such as ::open, Kernel#open, and File.open.

Open Mode

When mode is an integer it must be combination of the modes defined in File::Constants (+File::RDONLY+, +File::WRONLY | File::CREAT+). See the open(2) man page for more information.

When mode is a string it must be in one of the following forms:

fmode
fmode ":" ext_enc
fmode ":" ext_enc ":" int_enc
fmode ":" "BOM|UTF-*"

fmode is an IO open mode string, ext_enc is the external encoding for the IO and int_enc is the internal encoding.

IO Open Mode

Ruby allows the following open modes:

"r"  Read-only, starts at beginning of file  (default mode).

"r+" Read-write, starts at beginning of file.

"w"  Write-only, truncates existing file
     to zero length or creates a new file for writing.

"w+" Read-write, truncates existing file to zero length
     or creates a new file for reading and writing.

"a"  Write-only, each write call appends data at end of file.
     Creates a new file for writing if file does not exist.

"a+" Read-write, each write call appends data at end of file.
     Creates a new file for reading and writing if file does
     not exist.

The following modes must be used separately, and along with one or more of the modes seen above.

"b"  Binary file mode
     Suppresses EOL <-> CRLF conversion on Windows. And
     sets external encoding to ASCII-8BIT unless explicitly
     specified.

"t"  Text file mode

When the open mode of original IO is read only, the mode cannot be changed to be writable. Similarly, the open mode cannot be changed from write only to readable.

When such a change is attempted the error is raised in different locations according to the platform.

IO Encoding

When ext_enc is specified, strings read will be tagged by the encoding when reading, and strings output will be converted to the specified encoding when writing.

When ext_enc and int_enc are specified read strings will be converted from ext_enc to int_enc upon input, and written strings will be converted from int_enc to ext_enc upon output. See Encoding for further details of transcoding on input and output.

If “BOM|UTF-8”, “BOM|UTF-16LE” or “BOM|UTF16-BE” are used, ruby checks for a Unicode BOM in the input document to help determine the encoding. For UTF-16 encodings the file open mode must be binary. When present, the BOM is stripped and the external encoding from the BOM is used. When the BOM is missing the given Unicode encoding is used as ext_enc. (The BOM-set encoding option is case insensitive, so “bom|utf-8” is also valid.)

Options

opt can be used instead of mode for improved readability. The following keys are supported:

:mode

Same as mode parameter

:external_encoding

External encoding for the IO. “-” is a synonym for the default external encoding.

:internal_encoding

Internal encoding for the IO. “-” is a synonym for the default internal encoding.

If the value is nil no conversion occurs.

:encoding

Specifies external and internal encodings as “extern:intern”.

:textmode

If the value is truth value, same as “t” in argument mode.

:binmode

If the value is truth value, same as “b” in argument mode.

:autoclose

If the value is false, the fd will be kept open after this IO instance gets finalized.

Also, opt can have same keys in String#encode for controlling conversion between the external encoding and the internal encoding.

Example 1

fd = IO.sysopen("/dev/tty", "w")
a = IO.new(fd,"w")
$stderr.puts "Hello"
a.puts "World"

Produces:

Hello
World

Example 2

require 'fcntl'

fd = STDERR.fcntl(Fcntl::F_DUPFD)
io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
io.puts "Hello, World!"

fd = STDERR.fcntl(Fcntl::F_DUPFD)
io = IO.new(fd, mode: 'w', cr_newline: true,
            external_encoding: Encoding::UTF_16LE)
io.puts "Hello, World!"

Both of above print “Hello, World!” in UTF-16LE to standard error output with converting EOL generated by puts to CR.

static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
    VALUE fnum, vmode;
    rb_io_t *fp;
    int fd, fmode, oflags = O_RDONLY;
    convconfig_t convconfig;
    VALUE opt;
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    int ofmode;
#else
    struct stat st;
#endif

    rb_secure(4);

    argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
    rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);

    fd = NUM2INT(fnum);
    if (rb_reserved_fd_p(fd)) {
        rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
    }
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    oflags = fcntl(fd, F_GETFL);
    if (oflags == -1) rb_sys_fail(0);
#else
    if (fstat(fd, &st) == -1) rb_sys_fail(0);
#endif
    rb_update_max_fd(fd);
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    ofmode = rb_io_oflags_fmode(oflags);
    if (NIL_P(vmode)) {
        fmode = ofmode;
    }
    else if ((~ofmode & fmode) & FMODE_READWRITE) {
        VALUE error = INT2FIX(EINVAL);
        rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
    }
#endif
    if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
        fmode |= FMODE_PREP;
    }
    MakeOpenFile(io, fp);
    fp->fd = fd;
    fp->mode = fmode;
    fp->encs = convconfig;
    clear_codeconv(fp);
    io_check_tty(fp);
    if (fileno(stdin) == fd)
        fp->stdio_file = stdin;
    else if (fileno(stdout) == fd)
        fp->stdio_file = stdout;
    else if (fileno(stderr) == fd)
        fp->stdio_file = stderr;

    if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
    return io;
}
open(fd, mode="r" [, opt]) → io click to toggle source
open(fd, mode="r" [, opt]) { |io| block } → obj

With no associated block, IO.open is a synonym for ::new. If the optional code block is given, it will be passed io as an argument, and the IO object will automatically be closed when the block terminates. In this instance, ::open returns the value of the block.

See ::new for a description of the fd, mode and opt parameters.

static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_class_new_instance(argc, argv, klass);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, io, io_close, io);
    }

    return io;
}
pipe → [read_io, write_io] click to toggle source
pipe(ext_enc) → [read_io, write_io]
pipe("ext_enc:int_enc" [, opt]) → [read_io, write_io]
pipe(ext_enc, int_enc [, opt]) → [read_io, write_io]
pipe(...) {|read_io, write_io| ... }

Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element array of IO objects: [ read_io, write_io ].

If a block is given, the block is called and returns the value of the block. read_io and write_io are sent to the block as arguments. If read_io and write_io are not closed when the block exits, they are closed. i.e. closing read_io and/or write_io doesn't cause an error.

Not available on all platforms.

If an encoding (encoding name or encoding object) is specified as an optional argument, read string from pipe is tagged with the encoding specified. If the argument is a colon separated two encoding names “A:B”, the read string is converted from encoding A (external encoding) to encoding B (internal encoding), then tagged with B. If two optional arguments are specified, those must be encoding objects or encoding names, and the first one is the external encoding, and the second one is the internal encoding. If the external encoding and the internal encoding is specified, optional hash argument specify the conversion option.

In the example below, the two processes close the ends of the pipe that they are not using. This is not just a cosmetic nicety. The read end of a pipe will not generate an end of file condition if there are any writers with the pipe still open. In the case of the parent process, the rd.read will never return if it does not first issue a wr.close.

rd, wr = IO.pipe

if fork
  wr.close
  puts "Parent got: <#{rd.read}>"
  rd.close
  Process.wait
else
  rd.close
  puts "Sending message to parent"
  wr.write "Hi Dad"
  wr.close
end

produces:

Sending message to parent
Parent got: <Hi Dad>
static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
    int pipes[2], state;
    VALUE r, w, args[3], v1, v2;
    VALUE opt;
    rb_io_t *fptr, *fptr2;
    int fmode = 0;
    VALUE ret;

    argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
    if (rb_pipe(pipes) == -1)
        rb_sys_fail(0);

    args[0] = klass;
    args[1] = INT2NUM(pipes[0]);
    args[2] = INT2FIX(O_RDONLY);
    r = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[0]);
        close(pipes[1]);
        rb_jump_tag(state);
    }
    GetOpenFile(r, fptr);
    io_encoding_set(fptr, v1, v2, opt);
    args[1] = INT2NUM(pipes[1]);
    args[2] = INT2FIX(O_WRONLY);
    w = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[1]);
        if (!NIL_P(r)) rb_io_close(r);
        rb_jump_tag(state);
    }
    GetOpenFile(w, fptr2);
    rb_io_synchronized(fptr2);

    extract_binmode(opt, &fmode);
#if DEFAULT_TEXTMODE
    if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr->mode &= ~FMODE_TEXTMODE;
        setmode(fptr->fd, O_BINARY);
    }
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
        fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
    }
#endif
#endif
    fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
    if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr2->mode &= ~FMODE_TEXTMODE;
        setmode(fptr2->fd, O_BINARY);
    }
#endif
    fptr2->mode |= fmode;

    ret = rb_assoc_new(r, w);
    if (rb_block_given_p()) {
        VALUE rw[2];
        rw[0] = r;
        rw[1] = w;
        return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
    }
    return ret;
}
popen([env,] cmd, mode="r" [, opt]) → io click to toggle source
popen([env,] cmd, mode="r" [, opt]) {|io| block } → obj

Runs the specified command as a subprocess; the subprocess's standard input and output will be connected to the returned IO object.

The PID of the started process can be obtained by #pid method.

cmd is a string or an array as follows.

cmd:
  "-"                                      : fork
  commandline                              : command line string which is passed to a shell
  [env, cmdname, arg1, ..., opts]          : command name and zero or more arguments (no shell)
  [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
(env and opts are optional.)

If cmd is a String “-'', then a new instance of Ruby is started as the subprocess.

If cmd is an Array of String, then it will be used as the subprocess's argv bypassing a shell. The array can contains a hash at first for environments and a hash at last for options similar to spawn.

The default mode for the new file object is “r'', but mode may be set to any of the modes listed in the description for class IO. The last argument opt qualifies mode.

# set IO encoding
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# merge standard output and standard error using
# spawn option.  See the document of Kernel.spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

# spawn options can be mixed with IO options
IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
  ls_result_with_error = ls_io.read
}

Raises exceptions which IO.pipe and Kernel.spawn raise.

If a block is given, Ruby will run the command as a child connected to Ruby with a pipe. Ruby's end of the pipe will be passed as a parameter to the block. At the end of block, Ruby close the pipe and sets $?. In this case IO.popen returns the value of the block.

If a block is given with a cmd of “-'', the block will be run in two separate processes: once in the parent, and once in a child. The parent process will be passed the pipe object as a parameter to the block, the child version of the block will be passed nil, and the child's standard in and standard out will be connected to the parent through the pipe. Not available on all platforms.

f = IO.popen("uname")
p f.readlines
f.close
puts "Parent is #{Process.pid}"
IO.popen("date") { |f| puts f.gets }
IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
p $?
IO.popen(%wsed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
  f.puts "bar"; f.close_write; puts f.gets
}

produces:

["Linux\n"]
Parent is 21346
Thu Jan 15 22:41:19 JST 2009
21346 is here, f is #<IO:fd 3>
21352 is here, f is nil
#<Process::Status: pid 21352 exit 0>
<foo>bar;zot;
static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
    const char *modestr;
    VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
    int oflags, fmode;
    convconfig_t convconfig;

    if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
    if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
    switch (argc) {
      case 2:
        pmode = argv[1];
      case 1:
        pname = argv[0];
        break;
      default:
        {
            int ex = !NIL_P(opt);
            rb_error_arity(argc + ex, 1 + ex, 2 + ex);
        }
    }

    tmp = rb_check_array_type(pname);
    if (!NIL_P(tmp)) {
        long len = RARRAY_LEN(tmp);
#if SIZEOF_LONG > SIZEOF_INT
        if (len > INT_MAX) {
            rb_raise(rb_eArgError, "too many arguments");
        }
#endif
        tmp = rb_ary_dup(tmp);
        RBASIC(tmp)->klass = 0;
        execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
        rb_ary_clear(tmp);
    }
    else {
        SafeStringValue(pname);
        execarg_obj = Qnil;
        if (!is_popen_fork(pname))
            execarg_obj = rb_execarg_new(1, &pname, TRUE);
    }
    if (!NIL_P(execarg_obj)) {
        if (!NIL_P(opt))
            opt = rb_execarg_extract_options(execarg_obj, opt);
        if (!NIL_P(env))
            rb_execarg_setenv(execarg_obj, env);
    }
    rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
    modestr = rb_io_oflags_modestr(oflags);

    port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
    if (NIL_P(port)) {
        /* child */
        if (rb_block_given_p()) {
            rb_yield(Qnil);
            rb_io_flush(rb_stdout);
            rb_io_flush(rb_stderr);
            _exit(0);
        }
        return Qnil;
    }
    RBASIC(port)->klass = klass;
    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, port, io_close, port);
    }
    return port;
}
read(name, [length [, offset]] ) → string click to toggle source
read(name, [length [, offset]], open_args) → string

Opens the file, optionally seeks to the given offset, then returns length bytes (defaulting to the rest of the file). read ensures the file is closed before returning.

If the last argument is a hash, it specifies option for internal open(). The key would be the following. open_args: is exclusive to others.

encoding

string or encoding

specifies encoding of the read string. encoding will be ignored if length is specified.

mode

string

specifies mode argument for open(). It should start with “r” otherwise it will cause an error.

open_args

array of strings

specifies arguments for open() as an array.

Examples:

IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
IO.read("testfile", 20)       #=> "This is line one\nThi"
IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "

static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
    VALUE opt, offset;
    struct foreach_arg arg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    if (!NIL_P(offset)) {
        struct seek_arg sarg;
        int state = 0;
        sarg.io = arg.io;
        sarg.offset = offset;
        sarg.mode = SEEK_SET;
        rb_protect(seek_before_access, (VALUE)&sarg, &state);
        if (state) {
            rb_io_close(arg.io);
            rb_jump_tag(state);
        }
        if (arg.argc == 2) arg.argc = 1;
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
readlines(name, sep=$/ [, open_args]) → array click to toggle source
readlines(name, limit [, open_args]) → array
readlines(name, sep, limit [, open_args]) → array

Reads the entire file specified by name as individual lines, and returns those lines in an array. Lines are separated by sep.

a = IO.readlines("testfile")
a[0]   #=> "This is line one\n"

If the last argument is a hash, it's the keyword argument to open. See IO.read for detail.

static VALUE
rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
{
    VALUE opt;
    struct foreach_arg arg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
}
select(read_array click to toggle source
[, write_array
[, error_array
[, timeout]]]) → array or nil

Calls select(2) system call. It monitors given arrays of IO objects, waits one or more of IO objects ready for reading, are ready for writing, and have pending exceptions respectably, and returns an array that contains arrays of those IO objects. It will return nil if optional timeout value is given and no IO object is ready in timeout seconds.

Parameters

read_array

an array of IO objects that wait until ready for read

write_array

an array of IO objects that wait until ready for write

error_array

an array of IO objects that wait for exceptions

timeout

a numeric value in second

Example

rp, wp = IO.pipe
mesg = "ping "
100.times {
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

produces:

ping pong
ping pong
ping pong
(snipped)
ping
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
    VALUE timeout;
    struct select_args args;
    struct timeval timerec;
    int i;

    rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
    if (NIL_P(timeout)) {
        args.timeout = 0;
    }
    else {
        timerec = rb_time_interval(timeout);
        args.timeout = &timerec;
    }

    for (i = 0; i < numberof(args.fdsets); ++i)
        rb_fd_init(&args.fdsets[i]);

    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}
sysopen(path, [mode, [perm]]) → fixnum click to toggle source

Opens the given path, returning the underlying file descriptor as a Fixnum.

IO.sysopen("testfile")   #=> 3

static VALUE
rb_io_s_sysopen(int argc, VALUE *argv)
{
    VALUE fname, vmode, vperm;
    VALUE intmode;
    int oflags, fd;
    mode_t perm;

    rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
    FilePathValue(fname);

    if (NIL_P(vmode))
        oflags = O_RDONLY;
    else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
        oflags = NUM2INT(intmode);
    else {
        SafeStringValue(vmode);
        oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
    }
    if (NIL_P(vperm)) perm = 0666;
    else              perm = NUM2MODET(vperm);

    RB_GC_GUARD(fname) = rb_str_new4(fname);
    fd = rb_sysopen(fname, oflags, perm);
    return INT2NUM(fd);
}
try_convert(obj) → io or nil click to toggle source

Try to convert obj into an IO, using #to_io method. Returns converted IO or nil if obj cannot be converted for any reason.

IO.try_convert(STDOUT)     #=> STDOUT
IO.try_convert("STDOUT")   #=> nil

require 'zlib'
f = open("/tmp/zz.gz")       #=> #<File:/tmp/zz.gz>
z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
IO.try_convert(z)            #=> #<File:/tmp/zz.gz>

static VALUE
rb_io_s_try_convert(VALUE dummy, VALUE io)
{
    return rb_io_check_io(io);
}
write(name, string, [offset] ) → fixnum click to toggle source
write(name, string, [offset], open_args ) → fixnum

Opens the file, optionally seeks to the given offset, writes string, then returns the length written. write ensures the file is closed before returning. If offset is not given, the file is truncated. Otherwise, it is not truncated.

If the last argument is a hash, it specifies option for internal open(). The key would be the following. open_args: is exclusive to others.

encoding: string or encoding

 specifies encoding of the read string.  encoding will be ignored
 if length is specified.

mode: string

 specifies mode argument for open().  it should start with "w" or "a" or "r+"
 otherwise it would cause error.

perm: fixnum

 specifies perm argument for open().

open_args: array

 specifies arguments for open() as an array.

  IO.write("testfile", "0123456789", 20) # => 10
  # File could contain:  "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
  IO.write("testfile", "0123456789")      #=> 10
  # File would now read: "0123456789"

static VALUE
rb_io_s_write(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, 0);
}

Public Instance Methods

ios << obj → ios click to toggle source

String Output—Writes obj to ios. obj will be converted to a string using to_s.

$stdout << "Hello " << "world!\n"

produces:

Hello world!
VALUE
rb_io_addstr(VALUE io, VALUE str)
{
    rb_io_write(io, str);
    return io;
}
advise(advice, offset=0, len=0) → nil click to toggle source
Announce an intention to access data from the current file in a
specific pattern. On platforms that do not support the
<em>posix_fadvise(2)</em> system call, this method is a no-op.

advice is one of the following symbols:

* :normal - No advice to give; the default assumption for an open file.
* :sequential - The data will be accessed sequentially:
   with lower offsets read before higher ones.
* :random - The data will be accessed in random order.
* :willneed - The data will be accessed in the near future.
* :dontneed - The data will not be accessed in the near future.
* :noreuse - The data will only be accessed once.

The semantics of a piece of advice are platform-dependent. See man 2 posix_fadvise for details.

"data" means the region of the current file that begins at
_offset_ and extends for _len_ bytes. If _len_ is 0, the region
ends at the last byte of the file. By default, both _offset_ and
_len_ are 0, meaning that the advice applies to the entire file.

If an error occurs, one of the following exceptions will be raised:

* <code>IOError</code> - The <code>IO</code> stream is closed.
* <code>Errno::EBADF</code> - The file descriptor of the current file is
  invalid.
* <code>Errno::EINVAL</code> - An invalid value for _advice_ was given.
* <code>Errno::ESPIPE</code> - The file descriptor of the current
* file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code>
* in this case).
* <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the
  other arguments was not an <code>Integer</code>.
* <code>RangeError</code> - One of the arguments given was too big/small.
This list is not exhaustive; other Errno

exceptions are also possible.

static VALUE
rb_io_advise(int argc, VALUE *argv, VALUE io)
{
    VALUE advice, offset, len;
    off_t off, l;
    rb_io_t *fptr;

    rb_scan_args(argc, argv, "12", &advice, &offset, &len);
    advice_arg_check(advice);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
    l   = NIL_P(len)    ? 0 : NUM2OFFT(len);

#ifdef HAVE_POSIX_FADVISE
    return do_io_advise(fptr, advice, off, l);
#else
    ((void)off, (void)l);       /* Ignore all hint */
    return Qnil;
#endif
}
autoclose = bool → true or false click to toggle source

Sets auto-close flag.

f = open("/dev/null")
IO.for_fd(f.fileno)
# ...
f.gets # may cause IOError

f = open("/dev/null")
IO.for_fd(f.fileno).autoclose = true
# ...
f.gets # won't cause IOError
static VALUE
rb_io_set_autoclose(VALUE io, VALUE autoclose)
{
    rb_io_t *fptr;
    rb_secure(4);
    GetOpenFile(io, fptr);
    if (!RTEST(autoclose))
        fptr->mode |= FMODE_PREP;
    else
        fptr->mode &= ~FMODE_PREP;
    return io;
}
autoclose? → true or false click to toggle source

Returns true if the underlying file descriptor of ios will be closed automatically at its finalization, otherwise false.

static VALUE
rb_io_autoclose_p(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;
    rb_secure(4);
    rb_io_check_closed(fptr);
    return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
}
binmode → ios click to toggle source

Puts ios into binary mode. Once a stream is in binary mode, it cannot be reset to nonbinary mode.

  • newline conversion disabled

  • encoding conversion disabled

  • content is treated as ASCII-8BIT

static VALUE
rb_io_binmode_m(VALUE io)
{
    VALUE write_io;

    rb_io_ascii8bit_binmode(io);

    write_io = GetWriteIO(io);
    if (write_io != io)
        rb_io_ascii8bit_binmode(write_io);
    return io;
}
binmode? → true or false click to toggle source

Returns true if ios is binmode.

static VALUE
rb_io_binmode_p(VALUE io)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
}
bytes() click to toggle source

This is a deprecated alias for each_byte.

static VALUE
rb_io_bytes(VALUE io)
{
    rb_warn("IO#bytes is deprecated; use #each_byte instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
    return rb_io_each_byte(io);
}
chars() click to toggle source

This is a deprecated alias for each_char.

static VALUE
rb_io_chars(VALUE io)
{
    rb_warn("IO#chars is deprecated; use #each_char instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
    return rb_io_each_char(io);
}
close → nil click to toggle source

Closes ios and flushes any pending writes to the operating system. The stream is unavailable for any further data operations; an IOError is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector.

If ios is opened by IO.popen, close sets $?.

static VALUE
rb_io_close_m(VALUE io)
{
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    rb_io_check_closed(RFILE(io)->fptr);
    rb_io_close(io);
    return Qnil;
}
close_on_exec = bool → true or false click to toggle source

Sets a close-on-exec flag.

f = open("/dev/null")
f.close_on_exec = true
system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
f.closed?                #=> false

Ruby sets close-on-exec flags of all file descriptors by default since Ruby 2.0.0. So you don't need to set by yourself. Also, unsetting a close-on-exec flag can cause file descriptor leak if another thread use fork() and exec() (via system() method for example). If you really needs file descriptor inheritance to child process, use spawn()'s argument such as fd=>fd.

static VALUE
rb_io_set_close_on_exec(VALUE io, VALUE arg)
{
    int flag = RTEST(arg) ? FD_CLOEXEC : 0;
    rb_io_t *fptr;
    VALUE write_io;
    int fd, ret;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        GetOpenFile(write_io, fptr);
        if (fptr && 0 <= (fd = fptr->fd)) {
            if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
            if ((ret & FD_CLOEXEC) != flag) {
                ret = (ret & ~FD_CLOEXEC) | flag;
                ret = fcntl(fd, F_SETFD, ret);
                if (ret == -1) rb_sys_fail_path(fptr->pathv);
            }
        }

    }

    GetOpenFile(io, fptr);
    if (fptr && 0 <= (fd = fptr->fd)) {
        if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
        if ((ret & FD_CLOEXEC) != flag) {
            ret = (ret & ~FD_CLOEXEC) | flag;
            ret = fcntl(fd, F_SETFD, ret);
            if (ret == -1) rb_sys_fail_path(fptr->pathv);
        }
    }
    return Qnil;
}
close_on_exec? → true or false click to toggle source

Returns true if ios will be closed on exec.

f = open("/dev/null")
f.close_on_exec?                 #=> false
f.close_on_exec = true
f.close_on_exec?                 #=> true
f.close_on_exec = false
f.close_on_exec?                 #=> false

static VALUE
rb_io_close_on_exec_p(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;
    int fd, ret;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        GetOpenFile(write_io, fptr);
        if (fptr && 0 <= (fd = fptr->fd)) {
            if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
            if (!(ret & FD_CLOEXEC)) return Qfalse;
        }
    }

    GetOpenFile(io, fptr);
    if (fptr && 0 <= (fd = fptr->fd)) {
        if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
        if (!(ret & FD_CLOEXEC)) return Qfalse;
    }
    return Qtrue;
}
close_read → nil click to toggle source

Closes the read end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an IOError if the stream is not duplexed.

f = IO.popen("/bin/sh","r+")
f.close_read
f.readlines

produces:

prog.rb:3:in `readlines': not opened for reading (IOError)
 from prog.rb:3
static VALUE
rb_io_close_read(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;

    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    GetOpenFile(io, fptr);
    if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_RD
# define SHUT_RD 0
#endif
        if (shutdown(fptr->fd, SHUT_RD) < 0)
            rb_sys_fail_path(fptr->pathv);
        fptr->mode &= ~FMODE_READABLE;
        if (!(fptr->mode & FMODE_WRITABLE))
            return rb_io_close(io);
        return Qnil;
    }

    write_io = GetWriteIO(io);
    if (io != write_io) {
        rb_io_t *wfptr;
        GetOpenFile(write_io, wfptr);
        wfptr->pid = fptr->pid;
        fptr->pid = 0;
        RFILE(io)->fptr = wfptr;
        /* bind to write_io temporarily to get rid of memory/fd leak */
        fptr->tied_io_for_writing = 0;
        fptr->mode &= ~FMODE_DUPLEX;
        RFILE(write_io)->fptr = fptr;
        rb_io_fptr_cleanup(fptr, FALSE);
        /* should not finalize fptr because another thread may be reading it */
        return Qnil;
    }

    if (fptr->mode & FMODE_WRITABLE) {
        rb_raise(rb_eIOError, "closing non-duplex IO for reading");
    }
    return rb_io_close(io);
}
close_write → nil click to toggle source

Closes the write end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an IOError if the stream is not duplexed.

f = IO.popen("/bin/sh","r+")
f.close_write
f.print "nowhere"

produces:

prog.rb:3:in `write': not opened for writing (IOError)
 from prog.rb:3:in `print'
 from prog.rb:3
static VALUE
rb_io_close_write(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;

    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    write_io = GetWriteIO(io);
    GetOpenFile(write_io, fptr);
    if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_WR
# define SHUT_WR 1
#endif
        if (shutdown(fptr->fd, SHUT_WR) < 0)
            rb_sys_fail_path(fptr->pathv);
        fptr->mode &= ~FMODE_WRITABLE;
        if (!(fptr->mode & FMODE_READABLE))
            return rb_io_close(write_io);
        return Qnil;
    }

    if (fptr->mode & FMODE_READABLE) {
        rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    }

    if (io != write_io) {
        GetOpenFile(io, fptr);
        fptr->tied_io_for_writing = 0;
        fptr->mode &= ~FMODE_DUPLEX;
    }
    rb_io_close(write_io);
    return Qnil;
}
closed? → true or false click to toggle source

Returns true if ios is completely closed (for duplex streams, both reader and writer), false otherwise.

f = File.new("testfile")
f.close         #=> nil
f.closed?       #=> true
f = IO.popen("/bin/sh","r+")
f.close_write   #=> nil
f.closed?       #=> false
f.close_read    #=> nil
f.closed?       #=> true

static VALUE
rb_io_closed(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;
    rb_io_t *write_fptr;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        write_fptr = RFILE(write_io)->fptr;
        if (write_fptr && 0 <= write_fptr->fd) {
            return Qfalse;
        }
    }

    fptr = RFILE(io)->fptr;
    rb_io_check_initialized(fptr);
    return 0 <= fptr->fd ? Qfalse : Qtrue;
}
codepoints() click to toggle source

This is a deprecated alias for each_codepoint.

static VALUE
rb_io_codepoints(VALUE io)
{
    rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
    return rb_io_each_codepoint(io);
}
each(sep=$/) {|line| block } → ios click to toggle source
each(limit) {|line| block } → ios
each(sep,limit) {|line| block } → ios
each(...) → an_enumerator
each_line(sep=$/) {|line| block } → ios
each_line(limit) {|line| block } → ios
each_line(sep,limit) {|line| block } → ios
each_line(...) → an_enumerator

Executes the block for every line in ios, where lines are separated by sep. ios must be opened for reading or an IOError will be raised.

If no block is given, an enumerator is returned instead.

f = File.new("testfile")
f.each {|line| puts "#{f.lineno}: #{line}" }

produces:

1: This is line one
2: This is line two
3: This is line three
4: And so on...
static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str, rs;
    long limit;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &rs, &limit, io);
    if (limit == 0)
        rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
        rb_yield(str);
    }
    return io;
}
each_byte {|byte| block } → ios click to toggle source
each_byte → an_enumerator

Calls the given block once for each byte (0..255) in ios, passing the byte as an argument. The stream must be opened for reading or an IOError will be raised.

If no block is given, an enumerator is returned instead.

f = File.new("testfile")
checksum = 0
f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
checksum                           #=> 12

static VALUE
rb_io_each_byte(VALUE io)
{
    rb_io_t *fptr;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);

    for (;;) {
        while (fptr->rbuf.len > 0) {
            char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
            fptr->rbuf.len--;
            rb_yield(INT2FIX(*p & 0xff));
            errno = 0;
        }
        rb_io_check_byte_readable(fptr);
        READ_CHECK(fptr);
        if (io_fillbuf(fptr) < 0) {
            break;
        }
    }
    return io;
}
each_char {|c| block } → ios click to toggle source
each_char → an_enumerator

Calls the given block once for each character in ios, passing the character as an argument. The stream must be opened for reading or an IOError will be raised.

If no block is given, an enumerator is returned instead.

f = File.new("testfile")
f.each_char {|c| print c, ' ' }   #=> #<File:testfile>

static VALUE
rb_io_each_char(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;
    VALUE c;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    enc = io_input_encoding(fptr);
    READ_CHECK(fptr);
    while (!NIL_P(c = io_getc(fptr, enc))) {
        rb_yield(c);
    }
    return io;
}
each_codepoint {|c| block } → ios click to toggle source
codepoints {|c| block } → ios
each_codepoint → an_enumerator
codepoints → an_enumerator

Passes the Integer ordinal of each character in ios, passing the codepoint as an argument. The stream must be opened for reading or an IOError will be raised.

If no block is given, an enumerator is returned instead.

static VALUE
rb_io_each_codepoint(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;
    unsigned int c;
    int r, n;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    READ_CHECK(fptr);
    if (NEED_READCONV(fptr)) {
        SET_BINARY_MODE(fptr);
        for (;;) {
            make_readconv(fptr, 0);
            for (;;) {
                if (fptr->cbuf.len) {
                    if (fptr->encs.enc)
                        r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
                                                  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
                                                  fptr->encs.enc);
                    else
                        r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
                    if (!MBCLEN_NEEDMORE_P(r))
                        break;
                    if (fptr->cbuf.len == fptr->cbuf.capa) {
                        rb_raise(rb_eIOError, "too long character");
                    }
                }
                if (more_char(fptr) == MORE_CHAR_FINISHED) {
                    clear_readconv(fptr);
                    /* ignore an incomplete character before EOF */
                    return io;
                }
            }
            if (MBCLEN_INVALID_P(r)) {
                rb_raise(rb_eArgError, "invalid byte sequence in %s",
                         rb_enc_name(fptr->encs.enc));
            }
            n = MBCLEN_CHARFOUND_LEN(r);
            if (fptr->encs.enc) {
                c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
                                     fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
                                     fptr->encs.enc);
            }
            else {
                c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
            }
            fptr->cbuf.off += n;
            fptr->cbuf.len -= n;
            rb_yield(UINT2NUM(c));
        }
    }
    NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
    enc = io_input_encoding(fptr);
    for (;;) {
        if (io_fillbuf(fptr) < 0) {
            return io;
        }
        r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
                                  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
        if (MBCLEN_CHARFOUND_P(r) &&
            (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
            c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
                                 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
            fptr->rbuf.off += n;
            fptr->rbuf.len -= n;
            rb_yield(UINT2NUM(c));
        }
        else if (MBCLEN_INVALID_P(r)) {
            rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
        }
        else {
            continue;
        }
    }
    return io;
}
each(sep=$/) {|line| block } → ios click to toggle source
each(limit) {|line| block } → ios
each(sep,limit) {|line| block } → ios
each(...) → an_enumerator
each_line(sep=$/) {|line| block } → ios
each_line(limit) {|line| block } → ios
each_line(sep,limit) {|line| block } → ios
each_line(...) → an_enumerator

Executes the block for every line in ios, where lines are separated by sep. ios must be opened for reading or an IOError will be raised.

If no block is given, an enumerator is returned instead.

f = File.new("testfile")
f.each {|line| puts "#{f.lineno}: #{line}" }

produces:

1: This is line one
2: This is line two
3: This is line three
4: And so on...
static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str, rs;
    long limit;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &rs, &limit, io);
    if (limit == 0)
        rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
        rb_yield(str);
    }
    return io;
}
eof → true or false click to toggle source
eof? → true or false

Returns true if ios is at end of file that means there are no more data to read. The stream must be opened for reading or an IOError will be raised.

f = File.new("testfile")
dummy = f.readlines
f.eof   #=> true

If ios is a stream such as pipe or socket, IO#eof? blocks until the other end sends some data or closes it.

r, w = IO.pipe
Thread.new { sleep 1; w.close }
r.eof?  #=> true after 1 second blocking

r, w = IO.pipe
Thread.new { sleep 1; w.puts "a" }
r.eof?  #=> false after 1 second blocking

r, w = IO.pipe
r.eof?  # blocks forever

Note that IO#eof? reads data to the input byte buffer. So IO#sysread may not behave as you intend with IO#eof?, unless you call IO#rewind first (which is not available for some streams).

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
        return eof(fptr->fd) ? Qtrue : Qfalse;
    }
#endif
    if (io_fillbuf(fptr) < 0) {
        return Qtrue;
    }
    return Qfalse;
}
eof → true or false click to toggle source
eof? → true or false

Returns true if ios is at end of file that means there are no more data to read. The stream must be opened for reading or an IOError will be raised.

f = File.new("testfile")
dummy = f.readlines
f.eof   #=> true

If ios is a stream such as pipe or socket, IO#eof? blocks until the other end sends some data or closes it.

r, w = IO.pipe
Thread.new { sleep 1; w.close }
r.eof?  #=> true after 1 second blocking

r, w = IO.pipe
Thread.new { sleep 1; w.puts "a" }
r.eof?  #=> false after 1 second blocking

r, w = IO.pipe
r.eof?  # blocks forever

Note that IO#eof? reads data to the input byte buffer. So IO#sysread may not behave as you intend with IO#eof?, unless you call IO#rewind first (which is not available for some streams).

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
        return eof(fptr->fd) ? Qtrue : Qfalse;
    }
#endif
    if (io_fillbuf(fptr) < 0) {
        return Qtrue;
    }
    return Qfalse;
}
external_encoding → encoding click to toggle source

Returns the Encoding object that represents the encoding of the file. If io is write mode and no encoding is specified, returns nil.

static VALUE
rb_io_external_encoding(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (fptr->encs.enc2) {
        return rb_enc_from_encoding(fptr->encs.enc2);
    }
    if (fptr->mode & FMODE_WRITABLE) {
        if (fptr->encs.enc)
            return rb_enc_from_encoding(fptr->encs.enc);
        return Qnil;
    }
    return rb_enc_from_encoding(io_read_encoding(fptr));
}
fcntl(integer_cmd, arg) → integer click to toggle source

Provides a mechanism for issuing low-level commands to control or query file-oriented I/O streams. Arguments and results are platform dependent. If arg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes (Array#pack might be a useful way to build this string). On Unix platforms, see fcntl(2) for details. Not implemented on all platforms.

static VALUE
rb_io_fcntl(int argc, VALUE *argv, VALUE io)
{
    VALUE req, arg;

    rb_scan_args(argc, argv, "11", &req, &arg);
    return rb_fcntl(io, req, arg);
}
fdatasync → 0 or nil click to toggle source

Immediately writes all buffered data in ios to disk.

If the underlying operating system does not support fdatasync(2), IO#fsync is called instead (which might raise a NotImplementedError).

static VALUE
rb_io_fdatasync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    if (io_fflush(fptr) < 0)
        rb_sys_fail(0);

    if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
        return INT2FIX(0);

    /* fall back */
    return rb_io_fsync(io);
}
fileno → fixnum click to toggle source
to_i → fixnum

Returns an integer representing the numeric file descriptor for ios.

$stdin.fileno    #=> 0
$stdout.fileno   #=> 1

static VALUE
rb_io_fileno(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;
    int fd;

    rb_io_check_closed(fptr);
    fd = fptr->fd;
    return INT2FIX(fd);
}
Also aliased as: to_i
flush → ios click to toggle source

Flushes any buffered data within ios to the underlying operating system (note that this is Ruby internal buffering only; the OS may buffer the data as well).

$stdout.print "no newline"
$stdout.flush

produces:

no newline
VALUE
rb_io_flush(VALUE io)
{
    rb_io_t *fptr;

    if (!RB_TYPE_P(io, T_FILE)) {
        return rb_funcall(io, id_flush, 0);
    }

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    if (fptr->mode & FMODE_WRITABLE) {
        if (io_fflush(fptr) < 0)
            rb_sys_fail(0);
#ifdef _WIN32
        if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
            rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd);
        }
#endif
    }
    if (fptr->mode & FMODE_READABLE) {
        io_unread(fptr);
    }

    return io;
}
fsync → 0 or nil click to toggle source

Immediately writes all buffered data in ios to disk. Note that fsync differs from using IO#sync=. The latter ensures that data is flushed from Ruby's buffers, but does not guarantee that the underlying operating system actually writes it to disk.

NotImplementedError is raised if the underlying operating system does not support fsync(2).

static VALUE
rb_io_fsync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    if (io_fflush(fptr) < 0)
        rb_sys_fail(0);
# ifndef _WIN32 /* already called in io_fflush() */
    if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
        rb_sys_fail_path(fptr->pathv);
# endif
    return INT2FIX(0);
}
getbyte → fixnum or nil click to toggle source

Gets the next 8-bit byte (0..255) from ios. Returns nil if called at end of file.

f = File.new("testfile")
f.getbyte   #=> 84
f.getbyte   #=> 104

VALUE
rb_io_getbyte(VALUE io)
{
    rb_io_t *fptr;
    int c;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    READ_CHECK(fptr);
    if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
        rb_io_t *ofp;
        GetOpenFile(rb_stdout, ofp);
        if (ofp->mode & FMODE_TTY) {
            rb_io_flush(rb_stdout);
        }
    }
    if (io_fillbuf(fptr) < 0) {
        return Qnil;
    }
    fptr->rbuf.off++;
    fptr->rbuf.len--;
    c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
    return INT2FIX(c & 0xff);
}
getc → string or nil click to toggle source

Reads a one-character string from ios. Returns nil if called at end of file.

f = File.new("testfile")
f.getc   #=> "h"
f.getc   #=> "e"

static VALUE
rb_io_getc(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    enc = io_input_encoding(fptr);
    READ_CHECK(fptr);
    return io_getc(fptr, enc);
}
gets(sep=$/) → string or nil click to toggle source
gets(limit) → string or nil
gets(sep, limit) → string or nil

Reads the next “line'' from the I/O stream; lines are separated by sep. A separator of nil reads the entire contents, and a zero-length separator reads the input a paragraph at a time (two successive newlines in the input separate paragraphs). The stream must be opened for reading or an IOError will be raised. The line read in will be returned and also assigned to $_. Returns nil if called at end of file. If the first argument is an integer, or optional second argument is given, the returning string would not be longer than the given value in bytes.

File.new("testfile").gets   #=> "This is line one\n"
$_                          #=> "This is line one\n"

static VALUE
rb_io_gets_m(int argc, VALUE *argv, VALUE io)
{
    VALUE str;

    str = rb_io_getline(argc, argv, io);
    rb_lastline_set(str);

    return str;
}
inspect → string click to toggle source

Return a string describing this IO object.

static VALUE
rb_io_inspect(VALUE obj)
{
    rb_io_t *fptr;
    VALUE result;
    static const char closed[] = " (closed)";

    fptr = RFILE(taint_check(obj))->fptr;
    if (!fptr) return rb_any_to_s(obj);
    result = rb_str_new_cstr("#<");
    rb_str_append(result, rb_class_name(CLASS_OF(obj)));
    rb_str_cat2(result, ":");
    if (NIL_P(fptr->pathv)) {
        if (fptr->fd < 0) {
            rb_str_cat(result, closed+1, strlen(closed)-1);
        }
        else {
            rb_str_catf(result, "fd %d", fptr->fd);
        }
    }
    else {
        rb_str_append(result, fptr->pathv);
        if (fptr->fd < 0) {
            rb_str_cat(result, closed, strlen(closed));
        }
    }
    return rb_str_cat2(result, ">");
}
internal_encoding → encoding click to toggle source

Returns the Encoding of the internal string if conversion is specified. Otherwise returns nil.

static VALUE
rb_io_internal_encoding(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (!fptr->encs.enc2) return Qnil;
    return rb_enc_from_encoding(io_read_encoding(fptr));
}
ioctl(integer_cmd, arg) → integer click to toggle source

Provides a mechanism for issuing low-level commands to control or query I/O devices. Arguments and results are platform dependent. If arg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes. On Unix platforms, see ioctl(2) for details. Not implemented on all platforms.

static VALUE
rb_io_ioctl(int argc, VALUE *argv, VALUE io)
{
    VALUE req, arg;

    rb_scan_args(argc, argv, "11", &req, &arg);
    return rb_ioctl(io, req, arg);
}
isatty → true or false click to toggle source
tty? → true or false

Returns true if ios is associated with a terminal device (tty), false otherwise.

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true

static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
        return Qfalse;
    return Qtrue;
}
lineno → integer click to toggle source

Returns the current line number in ios. The stream must be opened for reading. lineno counts the number of times gets is called rather than the number of newlines encountered. The two values will differ if gets is called with a separator other than newline.

Methods that use $/ like each, lines and readline will also increment lineno.

See also the $. variable.

f = File.new("testfile")
f.lineno   #=> 0
f.gets     #=> "This is line one\n"
f.lineno   #=> 1
f.gets     #=> "This is line two\n"
f.lineno   #=> 2

static VALUE
rb_io_lineno(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    return INT2NUM(fptr->lineno);
}
lineno = integer → integer click to toggle source

Manually sets the current line number to the given value. $. is updated only on the next read.

f = File.new("testfile")
f.gets                     #=> "This is line one\n"
$.                         #=> 1
f.lineno = 1000
f.lineno                   #=> 1000
$.                         #=> 1         # lineno of last read
f.gets                     #=> "This is line two\n"
$.                         #=> 1001      # lineno of last read

static VALUE
rb_io_set_lineno(VALUE io, VALUE lineno)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    fptr->lineno = NUM2INT(lineno);
    return lineno;
}
lines(*args) click to toggle source

This is a deprecated alias for each_line.

static VALUE
rb_io_lines(int argc, VALUE *argv, VALUE io)
{
    rb_warn("IO#lines is deprecated; use #each_line instead");
    if (!rb_block_given_p())
        return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
    return rb_io_each_line(argc, argv, io);
}
pid → fixnum click to toggle source

Returns the process ID of a child process associated with ios. This will be set by IO.popen.

pipe = IO.popen("-")
if pipe
  $stderr.puts "In parent, child pid is #{pipe.pid}"
else
  $stderr.puts "In child, pid is #{$$}"
end

produces:

In child, pid is 26209
In parent, child pid is 26209
static VALUE
rb_io_pid(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (!fptr->pid)
        return Qnil;
    return PIDT2NUM(fptr->pid);
}
pos → integer click to toggle source
tell → integer

Returns the current offset (in bytes) of ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17

static VALUE
rb_io_tell(VALUE io)
{
    rb_io_t *fptr;
    off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    pos -= fptr->rbuf.len;
    return OFFT2NUM(pos);
}
pos = integer → integer click to toggle source

Seeks to the given position (in bytes) in ios. It is not guranteed that seeking to the right position when ios is textmode.

f = File.new("testfile")
f.pos = 17
f.gets   #=> "This is line two\n"

static VALUE
rb_io_set_pos(VALUE io, VALUE offset)
{
    rb_io_t *fptr;
    off_t pos;

    pos = NUM2OFFT(offset);
    GetOpenFile(io, fptr);
    pos = io_seek(fptr, pos, SEEK_SET);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);

    return OFFT2NUM(pos);
}
print() → nil click to toggle source
print(obj, ...) → nil

Writes the given object(s) to ios. The stream must be opened for writing. If the output field separator ($,) is not nil, it will be inserted between each object. If the output record separator ($\</code>) is not <code>nil, it will be appended to the output. If no arguments are given, prints $_. Objects that aren't strings will be converted by calling their to_s method. With no argument, prints the contents of the variable $_. Returns nil.

$stdout.print("This is ", 100, " percent.\n")

produces:

This is 100 percent.
VALUE
rb_io_print(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print `$_' */
    if (argc == 0) {
        argc = 1;
        line = rb_lastline_get();
        argv = &line;
    }
    for (i=0; i<argc; i++) {
        if (!NIL_P(rb_output_fs) && i>0) {
            rb_io_write(out, rb_output_fs);
        }
        rb_io_write(out, argv[i]);
    }
    if (argc > 0 && !NIL_P(rb_output_rs)) {
        rb_io_write(out, rb_output_rs);
    }

    return Qnil;
}
printf(format_string [, obj, ...]) → nil click to toggle source

Formats and writes to ios, converting parameters under control of the format string. See Kernel#sprintf for details.

VALUE
rb_io_printf(int argc, VALUE *argv, VALUE out)
{
    rb_io_write(out, rb_f_sprintf(argc, argv));
    return Qnil;
}
putc(obj) → obj click to toggle source

If obj is Numeric, write the character whose code is the least-significant byte of obj, otherwise write the first byte of the string representation of obj to ios. Note: This method is not safe for use with multi-byte characters as it will truncate them.

$stdout.putc "A"
$stdout.putc 65

produces:

AA
static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
    VALUE str;
    if (RB_TYPE_P(ch, T_STRING)) {
        str = rb_str_substr(ch, 0, 1);
    }
    else {
        char c = NUM2CHR(ch);
        str = rb_str_new(&c, 1);
    }
    rb_io_write(io, str);
    return ch;
}
puts(obj, ...) → nil click to toggle source

Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line. If called without arguments, outputs a single record separator.

$stdout.puts("this", "is", "a", "test")

produces:

this
is
a
test
VALUE
rb_io_puts(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print newline. */
    if (argc == 0) {
        rb_io_write(out, rb_default_rs);
        return Qnil;
    }
    for (i=0; i<argc; i++) {
        if (RB_TYPE_P(argv[i], T_STRING)) {
            line = argv[i];
            goto string;
        }
        if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
            continue;
        }
        line = rb_obj_as_string(argv[i]);
      string:
        rb_io_write(out, line);
        if (RSTRING_LEN(line) == 0 ||
            !str_end_with_asciichar(line, '\n')) {
            rb_io_write(out, rb_default_rs);
        }
    }

    return Qnil;
}
read([length [, outbuf]]) → string, outbuf, or nil click to toggle source

Reads length bytes from the I/O stream.

length must be a non-negative integer or nil.

If length is a positive integer, it try to read length bytes without any conversion (binary mode). It returns nil or a string whose length is 1 to length bytes. nil means it met EOF at beginning. The 1 to length-1 bytes string means it met EOF after reading the result. The length bytes string means it doesn't meet EOF. The resulted string is always ASCII-8BIT encoding.

If length is omitted or is nil, it reads until EOF and the encoding conversion is applied. It returns a string even if EOF is met at beginning.

If length is zero, it returns "".

If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning.

At end of file, it returns nil or ""
depend on length. ios.read() and
ios.read(nil) returns "".
ios.read(positive-integer) returns
nil.

f = File.new("testfile")
f.read(16)   #=> "This is line one"

# reads whole file
open("file") {|f|
  data = f.read # This returns a string even if the file is empty.
  ...
}

# iterate over fixed length records.
open("fixed-record-file") {|f|
  while record = f.read(256)
    ...
  end
}

# iterate over variable length records.
# record is prefixed by 32-bit length.
open("variable-record-file") {|f|
  while len = f.read(4)
    len = len.unpack("N")[0] # 32-bit length
    record = f.read(len) # This returns a string even if len is 0.
  end
}

Note that this method behaves like fread() function in C. This means it retry to invoke read(2) system call to read data with the specified length (or until EOF). This behavior is preserved even if ios is non-blocking mode. (This method is non-blocking flag insensitive as other methods.) If you need the behavior like single read(2) system call, consider readpartial, #read_nonblock and sysread.

static VALUE
io_read(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    long n, len;
    VALUE length, str;
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    int previous_mode;
#endif

    rb_scan_args(argc, argv, "02", &length, &str);

    if (NIL_P(length)) {
        GetOpenFile(io, fptr);
        rb_io_check_char_readable(fptr);
        return read_all(fptr, remain_size(fptr), str);
    }
    len = NUM2LONG(length);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative length %ld given", len);
    }

    io_setstrbuf(&str,len);

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    if (len == 0) {
        io_set_read_length(str, 0);
        return str;
    }

    READ_CHECK(fptr);
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    previous_mode = set_binary_mode_with_seek_cur(fptr);
#endif
    n = io_fread(str, 0, len, fptr);
    io_set_read_length(str, n);
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    if (previous_mode == O_TEXT) {
        setmode(fptr->fd, O_TEXT);
    }
#endif
    if (n == 0) return Qnil;
    OBJ_TAINT(str);

    return str;
}
read_nonblock(maxlen) → string click to toggle source
read_nonblock(maxlen, outbuf) → outbuf

Reads at most maxlen bytes from ios using the read(2) system call after O_NONBLOCK is set for the underlying file descriptor.

If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning.

#read_nonblock just calls the read(2) system call. It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. The caller should care such errors.

If the exception is Errno::EWOULDBLOCK or Errno::AGAIN, it is extended by IO::WaitReadable. So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.

#read_nonblock causes EOFError on EOF.

If the read byte buffer is not empty, #read_nonblock reads from the buffer like readpartial. In this case, the read(2) system call is not called.

When #read_nonblock raises an exception kind of IO::WaitReadable, #read_nonblock should not be called until io is readable for avoiding busy loop. This can be done as follows.

# emulates blocking read (readpartial).
begin
  result = io.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io])
  retry
end

Although #read_nonblock doesn't raise IO::WaitWritable. OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable. If IO and SSL should be used polymorphically, IO::WaitWritable should be rescued too. See the document of OpenSSL::Buffering#read_nonblock for sample code.

Note that this method is identical to readpartial except the non-blocking flag is set.

static VALUE
io_read_nonblock(int argc, VALUE *argv, VALUE io)
{
    VALUE ret;

    ret = io_getpartial(argc, argv, io, 1);
    if (NIL_P(ret))
        rb_eof_error();
    return ret;
}
readbyte → fixnum click to toggle source

Reads a byte as with IO#getbyte, but raises an EOFError on end of file.

static VALUE
rb_io_readbyte(VALUE io)
{
    VALUE c = rb_io_getbyte(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}
readchar → string click to toggle source

Reads a one-character string from ios. Raises an EOFError on end of file.

f = File.new("testfile")
f.readchar   #=> "h"
f.readchar   #=> "e"

static VALUE
rb_io_readchar(VALUE io)
{
    VALUE c = rb_io_getc(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}
readline(sep=$/) → string click to toggle source
readline(limit) → string
readline(sep, limit) → string

Reads a line as with IO#gets, but raises an EOFError on end of file.

static VALUE
rb_io_readline(int argc, VALUE *argv, VALUE io)
{
    VALUE line = rb_io_gets_m(argc, argv, io);

    if (NIL_P(line)) {
        rb_eof_error();
    }
    return line;
}
readlines(sep=$/) → array click to toggle source
readlines(limit) → array
readlines(sep, limit) → array

Reads all of the lines in ios, and returns them in anArray. Lines are separated by the optional sep. If sep is nil, the rest of the stream is returned as a single record. If the first argument is an integer, or optional second argument is given, the returning string would not be longer than the given value in bytes. The stream must be opened for reading or an IOError will be raised.

f = File.new("testfile")
f.readlines[0]   #=> "This is line one\n"

static VALUE
rb_io_readlines(int argc, VALUE *argv, VALUE io)
{
    VALUE line, ary, rs;
    long limit;

    prepare_getline_args(argc, argv, &rs, &limit, io);
    if (limit == 0)
        rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
    ary = rb_ary_new();
    while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
        rb_ary_push(ary, line);
    }
    return ary;
}
readpartial(maxlen) → string click to toggle source
readpartial(maxlen, outbuf) → outbuf

Reads at most maxlen bytes from the I/O stream. It blocks only if ios has no data immediately available. It doesn't block if some data available. If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning. It raises EOFError on end of file.

readpartial is designed for streams such as pipe, socket, tty, etc. It blocks only when no data immediately available. This means that it blocks only when following all conditions hold.

  • the byte buffer in the IO object is empty.

  • the content of the stream is empty.

  • the stream is not reached to EOF.

When readpartial blocks, it waits data or EOF on the stream. If some data is reached, readpartial returns with the data. If EOF is reached, readpartial raises EOFError.

When readpartial doesn't blocks, it returns or raises immediately. If the byte buffer is not empty, it returns the data in the buffer. Otherwise if the stream has some content, it returns the data in the stream. Otherwise if the stream is reached to EOF, it raises EOFError.

r, w = IO.pipe           #               buffer          pipe content
w << "abc"               #               ""              "abc".
r.readpartial(4096)      #=> "abc"       ""              ""
r.readpartial(4096)      # blocks because buffer and pipe is empty.

r, w = IO.pipe           #               buffer          pipe content
w << "abc"               #               ""              "abc"
w.close                  #               ""              "abc" EOF
r.readpartial(4096)      #=> "abc"       ""              EOF
r.readpartial(4096)      # raises EOFError

r, w = IO.pipe           #               buffer          pipe content
w << "abc\ndef\n"        #               ""              "abc\ndef\n"
r.gets                   #=> "abc\n"     "def\n"         ""
w << "ghi\n"             #               "def\n"         "ghi\n"
r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
r.readpartial(4096)      #=> "ghi\n"     ""              ""

Note that readpartial behaves similar to sysread. The differences are:

  • If the byte buffer is not empty, read from the byte buffer instead of “sysread for buffered IO (IOError)”.

  • It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.

The later means that readpartial is nonblocking-flag insensitive. It blocks on the situation #sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.

static VALUE
io_readpartial(int argc, VALUE *argv, VALUE io)
{
    VALUE ret;

    ret = io_getpartial(argc, argv, io, 0);
    if (NIL_P(ret))
        rb_eof_error();
    return ret;
}
reopen(other_IO) → ios click to toggle source
reopen(path, mode_str) → ios

Reassociates ios with the I/O stream given in other_IO or to a new stream opened on path. This may dynamically change the actual class of this stream.

f1 = File.new("testfile")
f2 = File.new("testfile")
f2.readlines[0]   #=> "This is line one\n"
f2.reopen(f1)     #=> #<File:testfile>
f2.readlines[0]   #=> "This is line one\n"

static VALUE
rb_io_reopen(int argc, VALUE *argv, VALUE file)
{
    VALUE fname, nmode, opt;
    int oflags;
    rb_io_t *fptr;

    rb_secure(4);
    if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
        VALUE tmp = rb_io_check_io(fname);
        if (!NIL_P(tmp)) {
            return io_reopen(file, tmp);
        }
    }

    FilePathValue(fname);
    rb_io_taint_check(file);
    fptr = RFILE(file)->fptr;
    if (!fptr) {
        fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
        MEMZERO(fptr, rb_io_t, 1);
    }

    if (!NIL_P(nmode) || !NIL_P(opt)) {
        int fmode;
        convconfig_t convconfig;

        rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
        if (IS_PREP_STDIO(fptr) &&
            ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
            (fptr->mode & FMODE_READWRITE)) {
            rb_raise(rb_eArgError,
                     "%s can't change access mode from \"%s\" to \"%s\"",
                     PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
                     rb_io_fmode_modestr(fmode));
        }
        fptr->mode = fmode;
        fptr->encs = convconfig;
    }
    else {
        oflags = rb_io_fmode_oflags(fptr->mode);
    }

    fptr->pathv = rb_str_new_frozen(fname);
    if (fptr->fd < 0) {
        fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
        fptr->stdio_file = 0;
        return file;
    }

    if (fptr->mode & FMODE_WRITABLE) {
        if (io_fflush(fptr) < 0)
            rb_sys_fail(0);
    }
    fptr->rbuf.off = fptr->rbuf.len = 0;

    if (fptr->stdio_file) {
        if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
            rb_sys_fail_path(fptr->pathv);
        }
        fptr->fd = fileno(fptr->stdio_file);
        rb_fd_fix_cloexec(fptr->fd);
#ifdef USE_SETVBUF
        if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
            rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
#endif
        if (fptr->stdio_file == stderr) {
            if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
                rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
        }
        else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
            if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
                rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
        }
    }
    else {
        int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
        int err = 0;
        if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
            err = errno;
        (void)close(tmpfd);
        if (err) {
            rb_sys_fail_path(fptr->pathv);
        }
    }

    return file;
}
rewind → 0 click to toggle source

Positions ios to the beginning of input, resetting lineno to zero.

f = File.new("testfile")
f.readline   #=> "This is line one\n"
f.rewind     #=> 0
f.lineno     #=> 0
f.readline   #=> "This is line one\n"

Note that it cannot be used with streams such as pipes, ttys, and sockets.

static VALUE
rb_io_rewind(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
#ifdef _WIN32
    if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
        fsync(fptr->fd);
    }
#endif
    if (io == ARGF.current_file) {
        ARGF.lineno -= fptr->lineno;
    }
    fptr->lineno = 0;
    if (fptr->readconv) {
        clear_readconv(fptr);
    }

    return INT2FIX(0);
}
seek(amount, whence=IO::SEEK_SET) → 0 click to toggle source

Seeks to a given offset anInteger in the stream according to the value of whence:

IO::SEEK_CUR  | Seeks to _amount_ plus current position
--------------+----------------------------------------------------
IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
              | want a negative value for _amount_)
--------------+----------------------------------------------------
IO::SEEK_SET  | Seeks to the absolute location given by _amount_

Example:

f = File.new("testfile")
f.seek(-13, IO::SEEK_END)   #=> 0
f.readline                  #=> "And so on...\n"

static VALUE
rb_io_seek_m(int argc, VALUE *argv, VALUE io)
{
    VALUE offset, ptrname;
    int whence = SEEK_SET;

    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
        whence = NUM2INT(ptrname);
    }

    return rb_io_seek(io, offset, whence);
}
set_encoding(ext_enc) → io click to toggle source
set_encoding("ext_enc:int_enc") → io
set_encoding(ext_enc, int_enc) → io
set_encoding("ext_enc:int_enc", opt) → io
set_encoding(ext_enc, int_enc, opt) → io

If single argument is specified, read string from io is tagged with the encoding specified. If encoding is a colon separated two encoding names “A:B”, the read string is converted from encoding A (external encoding) to encoding B (internal encoding), then tagged with B. If two arguments are specified, those must be encoding objects or encoding names, and the first one is the external encoding, and the second one is the internal encoding. If the external encoding and the internal encoding is specified, optional hash argument specify the conversion option.

static VALUE
rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    VALUE v1, v2, opt;

    if (!RB_TYPE_P(io, T_FILE)) {
        return rb_funcall2(io, id_set_encoding, argc, argv);
    }

    argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
    GetOpenFile(io, fptr);
    io_encoding_set(fptr, v1, v2, opt);
    return io;
}
stat → stat click to toggle source

Returns status information for ios as an object of type File::Stat.

f = File.new("testfile")
s = f.stat
"%o" % s.mode   #=> "100644"
s.blksize       #=> 4096
s.atime         #=> Wed Apr 09 08:53:54 CDT 2003

static VALUE
rb_io_stat(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return stat_new(&st);
}
sync → true or false click to toggle source

Returns the current “sync mode'' of ios. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered by Ruby internally. See also IO#fsync.

f = File.new("testfile")
f.sync   #=> false

static VALUE
rb_io_sync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
}
sync = boolean → boolean click to toggle source

Sets the “sync mode'' to true or false. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered internally. Returns the new state. See also IO#fsync.

f = File.new("testfile")
f.sync = true

(produces no output)

static VALUE
rb_io_set_sync(VALUE io, VALUE sync)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    if (RTEST(sync)) {
        fptr->mode |= FMODE_SYNC;
    }
    else {
        fptr->mode &= ~FMODE_SYNC;
    }
    return sync;
}
sysread(maxlen[, outbuf]) → string click to toggle source

Reads maxlen bytes from ios using a low-level read and returns them as a string. Do not mix with other methods that read from ios or you may get unpredictable results. If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning. Raises SystemCallError on error and EOFError at end of file.

f = File.new("testfile")
f.sysread(16)   #=> "This is line one"

static VALUE
rb_io_sysread(int argc, VALUE *argv, VALUE io)
{
    VALUE len, str;
    rb_io_t *fptr;
    long n, ilen;
    struct read_internal_arg arg;

    rb_scan_args(argc, argv, "11", &len, &str);
    ilen = NUM2LONG(len);

    io_setstrbuf(&str,ilen);
    if (ilen == 0) return str;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);

    if (READ_DATA_BUFFERED(fptr)) {
        rb_raise(rb_eIOError, "sysread for buffered IO");
    }

    n = fptr->fd;

    /*
     * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
     * on non-blocking IOs.  However, it's still currently possible
     * for sysread to raise Errno::EAGAIN if another thread read()s
     * the IO after we return from rb_thread_wait_fd() but before
     * we call read()
     */
    rb_thread_wait_fd(fptr->fd);

    rb_io_check_closed(fptr);

    io_setstrbuf(&str, ilen);
    rb_str_locktmp(str);
    arg.fd = fptr->fd;
    arg.str_ptr = RSTRING_PTR(str);
    arg.len = ilen;
    rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
    n = arg.len;

    if (n == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    io_set_read_length(str, n);
    if (n == 0 && ilen > 0) {
        rb_eof_error();
    }
    OBJ_TAINT(str);

    return str;
}
sysseek(offset, whence=IO::SEEK_SET) → integer click to toggle source

Seeks to a given offset in the stream according to the value of whence (see IO#seek for values of whence). Returns the new offset into the file.

f = File.new("testfile")
f.sysseek(-13, IO::SEEK_END)   #=> 53
f.sysread(10)                  #=> "And so on."

static VALUE
rb_io_sysseek(int argc, VALUE *argv, VALUE io)
{
    VALUE offset, ptrname;
    int whence = SEEK_SET;
    rb_io_t *fptr;
    off_t pos;

    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
        whence = NUM2INT(ptrname);
    }
    pos = NUM2OFFT(offset);
    GetOpenFile(io, fptr);
    if ((fptr->mode & FMODE_READABLE) &&
        (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
        rb_raise(rb_eIOError, "sysseek for buffered IO");
    }
    if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
        rb_warn("sysseek for buffered IO");
    }
    errno = 0;
    pos = lseek(fptr->fd, pos, whence);
    if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);

    return OFFT2NUM(pos);
}
syswrite(string) → integer click to toggle source

Writes the given string to ios using a low-level write. Returns the number of bytes written. Do not mix with other methods that write to ios or you may get unpredictable results. Raises SystemCallError on error.

f = File.new("out", "w")
f.syswrite("ABCDEF")   #=> 6

static VALUE
rb_io_syswrite(VALUE io, VALUE str)
{
    rb_io_t *fptr;
    long n;

    rb_secure(4);
    if (!RB_TYPE_P(str, T_STRING))
        str = rb_obj_as_string(str);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);

    str = rb_str_new_frozen(str);

    if (fptr->wbuf.len) {
        rb_warn("syswrite for buffered IO");
    }

    n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
    RB_GC_GUARD(str);

    if (n == -1) rb_sys_fail_path(fptr->pathv);

    return LONG2FIX(n);
}
pos → integer click to toggle source
tell → integer

Returns the current offset (in bytes) of ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17

static VALUE
rb_io_tell(VALUE io)
{
    rb_io_t *fptr;
    off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    pos -= fptr->rbuf.len;
    return OFFT2NUM(pos);
}
to_i() click to toggle source
Alias for: fileno
to_io → ios click to toggle source

Returns ios.

static VALUE
rb_io_to_io(VALUE io)
{
    return io;
}
isatty → true or false click to toggle source
tty? → true or false

Returns true if ios is associated with a terminal device (tty), false otherwise.

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true

static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
        return Qfalse;
    return Qtrue;
}
ungetbyte(string) → nil click to toggle source
ungetbyte(integer) → nil

Pushes back bytes (passed as a parameter) onto ios, such that a subsequent buffered read will return it. Only one byte may be pushed back before a subsequent read operation (that is, you will be able to read only the last of several bytes that have been pushed back). Has no effect with unbuffered reads (such as IO#sysread).

f = File.new("testfile")   #=> #<File:testfile>
b = f.getbyte              #=> 0x38
f.ungetbyte(b)             #=> nil
f.getbyte                  #=> 0x38

VALUE
rb_io_ungetbyte(VALUE io, VALUE b)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    if (NIL_P(b)) return Qnil;
    if (FIXNUM_P(b)) {
        char cc = FIX2INT(b);
        b = rb_str_new(&cc, 1);
    }
    else {
        SafeStringValue(b);
    }
    io_ungetbyte(b, fptr);
    return Qnil;
}
ungetc(string) → nil click to toggle source

Pushes back one character (passed as a parameter) onto ios, such that a subsequent buffered character read will return it. Only one character may be pushed back before a subsequent read operation (that is, you will be able to read only the last of several characters that have been pushed back). Has no effect with unbuffered reads (such as IO#sysread).

f = File.new("testfile")   #=> #<File:testfile>
c = f.getc                 #=> "8"
f.ungetc(c)                #=> nil
f.getc                     #=> "8"

VALUE
rb_io_ungetc(VALUE io, VALUE c)
{
    rb_io_t *fptr;
    long len;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    if (NIL_P(c)) return Qnil;
    if (FIXNUM_P(c)) {
        c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
    }
    else if (RB_TYPE_P(c, T_BIGNUM)) {
        c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
    }
    else {
        SafeStringValue(c);
    }
    if (NEED_READCONV(fptr)) {
        SET_BINARY_MODE(fptr);
        len = RSTRING_LEN(c);
#if SIZEOF_LONG > SIZEOF_INT
        if (len > INT_MAX)
            rb_raise(rb_eIOError, "ungetc failed");
#endif
        make_readconv(fptr, (int)len);
        if (fptr->cbuf.capa - fptr->cbuf.len < len)
            rb_raise(rb_eIOError, "ungetc failed");
        if (fptr->cbuf.off < len) {
            MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
                    fptr->cbuf.ptr+fptr->cbuf.off,
                    char, fptr->cbuf.len);
            fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
        }
        fptr->cbuf.off -= (int)len;
        fptr->cbuf.len += (int)len;
        MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
    }
    else {
        NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
        io_ungetbyte(c, fptr);
    }
    return Qnil;
}
write(string) → integer click to toggle source

Writes the given string to ios. The stream must be opened for writing. If the argument is not a string, it will be converted to a string using to_s. Returns the number of bytes written.

count = $stdout.write("This is a test\n")
puts "That was #{count} bytes of data"

produces:

This is a test
That was 15 bytes of data
static VALUE
io_write_m(VALUE io, VALUE str)
{
    return io_write(io, str, 0);
}
write_nonblock(string) → integer click to toggle source

Writes the given string to ios using the write(2) system call after O_NONBLOCK is set for the underlying file descriptor.

It returns the number of bytes written.

#write_nonblock just calls the write(2) system call. It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. The result may also be smaller than string.length (partial write). The caller should care such errors and partial write.

If the exception is Errno::EWOULDBLOCK or Errno::AGAIN, it is extended by IO::WaitWritable. So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.

# Creates a pipe.
r, w = IO.pipe

# write_nonblock writes only 65536 bytes and return 65536.
# (The pipe size is 65536 bytes on this environment.)
s = "a" * 100000
p w.write_nonblock(s)     #=> 65536

# write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
p w.write_nonblock("b")   # Resource temporarily unavailable (Errno::EAGAIN)

If the write buffer is not empty, it is flushed at first.

When #write_nonblock raises an exception kind of IO::WaitWritable, #write_nonblock should not be called until io is writable for avoiding busy loop. This can be done as follows.

begin
  result = io.write_nonblock(string)
rescue IO::WaitWritable, Errno::EINTR
  IO.select(nil, [io])
  retry
end

Note that this doesn't guarantee to write all data in string. The length written is reported as result and it should be checked later.

On some platforms such as Windows, #write_nonblock is not supported according to the kind of the IO object. In such cases, #write_nonblock raises Errno::EBADF.

static VALUE
rb_io_write_nonblock(VALUE io, VALUE str)
{
    rb_io_t *fptr;
    long n;

    rb_secure(4);
    if (!RB_TYPE_P(str, T_STRING))
        str = rb_obj_as_string(str);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);

    if (io_fflush(fptr) < 0)
        rb_sys_fail(0);

    rb_io_set_nonblock(fptr);
    n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));

    if (n == -1) {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
            rb_mod_sys_fail(rb_mWaitWritable, "write would block");
        rb_sys_fail_path(fptr->pathv);
    }

    return LONG2FIX(n);
}


module IO::WaitReadable - Ruby 2.0.0-p576 Core API Reference API Reference

module IO::WaitReadable

In Files

  • file.c


module IO::WaitWritable - Ruby 2.0.0-p576 Core API Reference API Reference

module IO::WaitWritable

In Files

  • file.c


class IOError - Ruby 2.0.0-p576 Core API Reference API Reference

class IOError

Raised when an IO operation fails.

File.open("/etc/hosts") {|f| f << "example"}
  #=> IOError: not opened for writing

File.open("/etc/hosts") {|f| f.close; f.read }
  #=> IOError: closed stream

Note that some IO failures raise +SystemCallError+s and these are not subclasses of IOError:

File.open("does/not/exist")
  #=> Errno::ENOENT: No such file or directory - does/not/exist

In Files

  • io.c

Parent

StandardError


class IndexError - Ruby 2.0.0-p576 Core API Reference API Reference

class IndexError

Raised when the given index is invalid.

a = [:foo, :bar]
a.fetch(0)   #=> :foo
a[4]         #=> nil
a.fetch(4)   #=> IndexError: index 4 outside of array bounds: -2...2

In Files

  • error.c

Parent

StandardError


class Integer - Ruby 2.0.0-p576 Core API Reference API Reference

class Integer

Integer is the basis for the two concrete classes that hold whole numbers, Bignum and Fixnum.

In Files

  • numeric.c
  • rational.c

Parent

Numeric

Public Instance Methods

to_i → integer click to toggle source
to_int → integer
floor → integer
ceil → integer
truncate → integer

As int is already an Integer, all these methods simply return the receiver.

static VALUE
int_to_i(VALUE num)
{
    return num;
}
chr([encoding]) → string click to toggle source

Returns a string containing the character represented by the receiver's value according to encoding.

65.chr    #=> "A"
230.chr   #=> "\346"
255.chr(Encoding::UTF_8)   #=> "\303\277"

static VALUE
int_chr(int argc, VALUE *argv, VALUE num)
{
    char c;
    unsigned int i;
    rb_encoding *enc;

    if (rb_num_to_uint(num, &i) == 0) {
    }
    else if (FIXNUM_P(num)) {
        rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(num));
    }
    else {
        rb_raise(rb_eRangeError, "bignum out of char range");
    }

    switch (argc) {
      case 0:
        if (0xff < i) {
            enc = rb_default_internal_encoding();
            if (!enc) {
                rb_raise(rb_eRangeError, "%d out of char range", i);
            }
            goto decode;
        }
        c = (char)i;
        if (i < 0x80) {
            return rb_usascii_str_new(&c, 1);
        }
        else {
            return rb_str_new(&c, 1);
        }
      case 1:
        break;
      default:
        rb_check_arity(argc, 0, 1);
        break;
    }
    enc = rb_to_encoding(argv[0]);
    if (!enc) enc = rb_ascii8bit_encoding();
  decode:
    return rb_enc_uint_chr(i, enc);
}
denominator → 1 click to toggle source

Returns 1.

static VALUE
integer_denominator(VALUE self)
{
    return INT2FIX(1);
}
downto(limit) {|i| block } → self click to toggle source
downto(limit) → an_enumerator

Iterates block, passing decreasing values from int down to and including limit.

If no block is given, an enumerator is returned instead.

5.downto(1) { |n| print n, ".. " }
print "  Liftoff!\n"

produces:

5.. 4.. 3.. 2.. 1..   Liftoff!
static VALUE
int_downto(VALUE from, VALUE to)
{
    RETURN_SIZED_ENUMERATOR(from, 1, &to, int_downto_size);
    if (FIXNUM_P(from) && FIXNUM_P(to)) {
        long i, end;

        end = FIX2LONG(to);
        for (i=FIX2LONG(from); i >= end; i--) {
            rb_yield(LONG2FIX(i));
        }
    }
    else {
        VALUE i = from, c;

        while (!(c = rb_funcall(i, '<', 1, to))) {
            rb_yield(i);
            i = rb_funcall(i, '-', 1, INT2FIX(1));
        }
        if (NIL_P(c)) rb_cmperr(i, to);
    }
    return from;
}
even? → true or false click to toggle source

Returns true if int is an even number.

static VALUE
int_even_p(VALUE num)
{
    if (rb_funcall(num, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
        return Qtrue;
    }
    return Qfalse;
}
to_i → integer click to toggle source
to_int → integer
floor → integer
ceil → integer
truncate → integer

As int is already an Integer, all these methods simply return the receiver.

static VALUE
int_to_i(VALUE num)
{
    return num;
}
gcd(int2) → integer click to toggle source

Returns the greatest common divisor (always positive). 0.gcd(x) and x.gcd(0) return abs(x).

2.gcd(2)                    #=> 2
3.gcd(-7)                   #=> 1
((1<<31)-1).gcd((1<<61)-1)  #=> 1

VALUE
rb_gcd(VALUE self, VALUE other)
{
    other = nurat_int_value(other);
    return f_gcd(self, other);
}
gcdlcm(int2) → array click to toggle source

Returns an array; [int.gcd(int2), int.lcm(int2)].

2.gcdlcm(2)                    #=> [2, 2]
3.gcdlcm(-7)                   #=> [1, 21]
((1<<31)-1).gcdlcm((1<<61)-1)  #=> [1, 4951760154835678088235319297]

VALUE
rb_gcdlcm(VALUE self, VALUE other)
{
    other = nurat_int_value(other);
    return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
}
integer? → true click to toggle source

Always returns true.

static VALUE
int_int_p(VALUE num)
{
    return Qtrue;
}
lcm(int2) → integer click to toggle source

Returns the least common multiple (always positive). 0.lcm(x) and x.lcm(0) return zero.

2.lcm(2)                    #=> 2
3.lcm(-7)                   #=> 21
((1<<31)-1).lcm((1<<61)-1)  #=> 4951760154835678088235319297

VALUE
rb_lcm(VALUE self, VALUE other)
{
    other = nurat_int_value(other);
    return f_lcm(self, other);
}
next → integer click to toggle source
succ → integer

Returns the Integer equal to int + 1.

1.next      #=> 2
(-1).next   #=> 0

VALUE
rb_int_succ(VALUE num)
{
    if (FIXNUM_P(num)) {
        long i = FIX2LONG(num) + 1;
        return LONG2NUM(i);
    }
    return rb_funcall(num, '+', 1, INT2FIX(1));
}
numerator → self click to toggle source

Returns self.

static VALUE
integer_numerator(VALUE self)
{
    return self;
}
odd? → true or false click to toggle source

Returns true if int is an odd number.

static VALUE
int_odd_p(VALUE num)
{
    if (rb_funcall(num, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
        return Qtrue;
    }
    return Qfalse;
}
ord → self click to toggle source

Returns the int itself.

a.ord    #=> 97

This method is intended for compatibility to character constant in Ruby 1.9. For example, ?a.ord returns 97 both in 1.8 and 1.9.

static VALUE
int_ord(VALUE num)
{
    return num;
}
pred → integer click to toggle source

Returns the Integer equal to int - 1.

1.pred      #=> 0
(-1).pred   #=> -2

VALUE
rb_int_pred(VALUE num)
{
    if (FIXNUM_P(num)) {
        long i = FIX2LONG(num) - 1;
        return LONG2NUM(i);
    }
    return rb_funcall(num, '-', 1, INT2FIX(1));
}
rationalize([eps]) → rational click to toggle source

Returns the value as a rational. The optional argument eps is always ignored.

static VALUE
integer_rationalize(int argc, VALUE *argv, VALUE self)
{
    rb_scan_args(argc, argv, "01", NULL);
    return integer_to_r(self);
}
round([ndigits]) → integer or float click to toggle source

Rounds flt to a given precision in decimal digits (default 0 digits). Precision may be negative. Returns a floating point number when ndigits is positive, self for zero, and round down for negative.

1.round        #=> 1
1.round(2)     #=> 1.0
15.round(-1)   #=> 20

static VALUE
int_round(int argc, VALUE* argv, VALUE num)
{
    VALUE n;
    int ndigits;

    if (argc == 0) return num;
    rb_scan_args(argc, argv, "1", &n);
    ndigits = NUM2INT(n);
    if (ndigits > 0) {
        return rb_Float(num);
    }
    if (ndigits == 0) {
        return num;
    }
    return int_round_0(num, ndigits);
}
next → integer click to toggle source
succ → integer

Returns the Integer equal to int + 1.

1.next      #=> 2
(-1).next   #=> 0

VALUE
rb_int_succ(VALUE num)
{
    if (FIXNUM_P(num)) {
        long i = FIX2LONG(num) + 1;
        return LONG2NUM(i);
    }
    return rb_funcall(num, '+', 1, INT2FIX(1));
}
times {|i| block } → self click to toggle source
times → an_enumerator

Iterates block int times, passing in values from zero to int - 1.

If no block is given, an enumerator is returned instead.

5.times do |i|
  print i, " "
end

produces:

0 1 2 3 4
static VALUE
int_dotimes(VALUE num)
{
    RETURN_SIZED_ENUMERATOR(num, 0, 0, int_dotimes_size);

    if (FIXNUM_P(num)) {
        long i, end;

        end = FIX2LONG(num);
        for (i=0; i<end; i++) {
            rb_yield(LONG2FIX(i));
        }
    }
    else {
        VALUE i = INT2FIX(0);

        for (;;) {
            if (!RTEST(rb_funcall(i, '<', 1, num))) break;
            rb_yield(i);
            i = rb_funcall(i, '+', 1, INT2FIX(1));
        }
    }
    return num;
}
to_i → integer click to toggle source
to_int → integer
floor → integer
ceil → integer
truncate → integer

As int is already an Integer, all these methods simply return the receiver.

static VALUE
int_to_i(VALUE num)
{
    return num;
}
to_i → integer click to toggle source
to_int → integer
floor → integer
ceil → integer
truncate → integer

As int is already an Integer, all these methods simply return the receiver.

static VALUE
int_to_i(VALUE num)
{
    return num;
}
to_r → rational click to toggle source

Returns the value as a rational.

1.to_r        #=> (1/1)
(1<<64).to_r  #=> (18446744073709551616/1)

static VALUE
integer_to_r(VALUE self)
{
    return rb_rational_new1(self);
}
to_i → integer click to toggle source
to_int → integer
floor → integer
ceil → integer
truncate → integer

As int is already an Integer, all these methods simply return the receiver.

static VALUE
int_to_i(VALUE num)
{
    return num;
}
upto(limit) {|i| block } → self click to toggle source
upto(limit) → an_enumerator

Iterates block, passing in integer values from int up to and including limit.

If no block is given, an enumerator is returned instead.

5.upto(10) { |i| print i, " " }

produces:

5 6 7 8 9 10
static VALUE
int_upto(VALUE from, VALUE to)
{
    RETURN_SIZED_ENUMERATOR(from, 1, &to, int_upto_size);
    if (FIXNUM_P(from) && FIXNUM_P(to)) {
        long i, end;

        end = FIX2LONG(to);
        for (i = FIX2LONG(from); i <= end; i++) {
            rb_yield(LONG2FIX(i));
        }
    }
    else {
        VALUE i = from, c;

        while (!(c = rb_funcall(i, '>', 1, to))) {
            rb_yield(i);
            i = rb_funcall(i, '+', 1, INT2FIX(1));
        }
        if (NIL_P(c)) rb_cmperr(i, to);
    }
    return from;
}


class Interrupt - Ruby 2.0.0-p576 Core API Reference API Reference

class Interrupt

Raised with the interrupt signal is received, typically because the user pressed on Control-C (on most posix platforms). As such, it is a subclass of SignalException.

begin
  puts "Press ctrl-C when you get bored"
  loop {}
rescue Interrupt => e
  puts "Note: You will typically use Signal.trap instead."
end

produces:

Press ctrl-C when you get bored

then waits until it is interrupted with Control-C and then prints:

Note: You will typically use Signal.trap instead.

In Files

  • error.c
  • signal.c

Parent

SignalException


module Kernel - Ruby 2.0.0-p576 Core API Reference API Reference

module Kernel

The Kernel module is included by class Object, so its methods are available in every Ruby object.

The Kernel instance methods are documented in class Object while the module methods are documented here. These methods are called without a receiver and thus can be called in functional form:

sprintf "%.1f", 1.234 #=> "1.2"

In Files

  • complex.c
  • cont.c
  • error.c
  • eval.c
  • eval_jump.c
  • file.c
  • io.c
  • load.c
  • object.c
  • proc.c
  • process.c
  • random.c
  • rational.c
  • ruby.c
  • signal.c
  • vm_backtrace.c
  • vm_eval.c
  • vm_trace.c

Public Instance Methods

Array(arg) → array click to toggle source

Returns arg as an Array.

First tries to call Array#to_ary on arg, then Array#to_a.

Array(1..5)   #=> [1, 2, 3, 4, 5]

static VALUE
rb_f_array(VALUE obj, VALUE arg)
{
    return rb_Array(arg);
}
Complex(x[, y]) → numeric click to toggle source

Returns x+i*y;

Complex(1, 2)    #=> (1+2i)
Complex('1+2i')  #=> (1+2i)

Syntax of string form:

string form = extra spaces , complex , extra spaces ;
complex = real part | [ sign ] , imaginary part
        | real part , sign , imaginary part
        | rational , "@" , rational ;
real part = rational ;
imaginary part = imaginary unit | unsigned rational , imaginary unit ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
imaginary unit = "i" | "I" | "j" | "J" ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit };
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ;

See String#to_c.

static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
{
    return rb_funcall2(rb_cComplex, id_convert, argc, argv);
}
Float(arg) → float click to toggle source

Returns arg converted to a float. Numeric types are converted directly, the rest are converted using arg.to_f. As of Ruby 1.8, converting nil generates a TypeError.

Float(1)           #=> 1.0
Float("123.456")   #=> 123.456

static VALUE
rb_f_float(VALUE obj, VALUE arg)
{
    return rb_Float(arg);
}
Hash(arg) → hash click to toggle source

Converts arg to a Hash by calling arg.to_hash. Returns an empty Hash when arg is nil or [].

Hash([])          #=> {}
Hash(nil)         #=> nil
Hash(key: :value) #=> {:key => :value}
Hash([1, 2, 3])   #=> TypeError

static VALUE
rb_f_hash(VALUE obj, VALUE arg)
{
    return rb_Hash(arg);
}
Integer(arg,base=0) → integer click to toggle source

Converts arg to a Fixnum or Bignum. Numeric types are converted directly (with floating point numbers being truncated). base (0, or between 2 and 36) is a base for integer string representation. If arg is a String, when base is omitted or equals to zero, radix indicators (0, 0b, and 0x) are honored. In any case, strings should be strictly conformed to numeric representation. This behavior is different from that of String#to_i. Non string values will be converted using to_int, and to_i.

Integer(123.999)    #=> 123
Integer("0x1a")     #=> 26
Integer(Time.new)   #=> 1204973019
Integer("0930", 10) #=> 930
Integer("111", 2)   #=> 7

static VALUE
rb_f_integer(int argc, VALUE *argv, VALUE obj)
{
    VALUE arg = Qnil;
    int base = 0;

    switch (argc) {
      case 2:
        base = NUM2INT(argv[1]);
      case 1:
        arg = argv[0];
        break;
      default:
        /* should cause ArgumentError */
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    return rb_convert_to_integer(arg, base);
}
Rational(x[, y]) → numeric click to toggle source

Returns x/y;

Rational(1, 2)   #=> (1/2)
Rational('1/2')  #=> (1/2)

Syntax of string form:

string form = extra spaces , rational , extra spaces ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ;

See String#to_r.

static VALUE
nurat_f_rational(int argc, VALUE *argv, VALUE klass)
{
    return rb_funcall2(rb_cRational, id_convert, argc, argv);
}
String(arg) → string click to toggle source

Converts arg to a String by calling its to_s method.

String(self)        #=> "main"
String(self.class)  #=> "Object"
String(123456)      #=> "123456"

static VALUE
rb_f_string(VALUE obj, VALUE arg)
{
    return rb_String(arg);
}
__callee__() click to toggle source
static VALUE
rb_f_callee_name(void)
{
    ID fname = rb_frame_callee(); /* need *callee* ID */

    if (fname) {
        return ID2SYM(fname);
    }
    else {
        return Qnil;
    }
}
__dir__ → string click to toggle source

Returns the canonicalized absolute path of the directory of the file from which this method is called. It means symlinks in the path is resolved. If __FILE__ is nil, it returns nil. The return value equals to File.dirname(File.realpath(__FILE__)).

static VALUE
f_current_dirname(void)
{
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        return Qnil;
    }
    base = rb_file_dirname(base);
    return base;
}
__method__ → symbol click to toggle source
__callee__ → symbol

Returns the name of the current method as a Symbol. If called outside of a method, it returns nil.

static VALUE
rb_f_method_name(void)
{
    ID fname = rb_frame_caller(); /* need *caller* ID */

    if (fname) {
        return ID2SYM(fname);
    }
    else {
        return Qnil;
    }
}
`cmd` → string click to toggle source

Returns the standard output of running cmd in a subshell. The built-in syntax %x{...} uses this method. Sets $? to the process status.

%xdate`                   #=> "Wed Apr  9 08:56:30 CDT 2003\n"
%xls testdir`.split[1]    #=> "main.rb"
%xecho oops && exit 99`   #=> "oops\n"
$?.exitstatus            #=> 99

static VALUE
rb_f_backquote(VALUE obj, VALUE str)
{
    volatile VALUE port;
    VALUE result;
    rb_io_t *fptr;

    SafeStringValue(str);
    rb_last_status_clear();
    port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
    if (NIL_P(port)) return rb_str_new(0,0);

    GetOpenFile(port, fptr);
    result = read_all(fptr, remain_size(fptr), Qnil);
    rb_io_close(port);

    return result;
}
abort click to toggle source
Kernel::abort([msg])
Process::abort([msg])

Terminate execution immediately, effectively by calling Kernel.exit(false). If msg is given, it is written to STDERR prior to terminating.

VALUE
rb_f_abort(int argc, VALUE *argv)
{
    rb_secure(4);
    if (argc == 0) {
        if (!NIL_P(GET_THREAD()->errinfo)) {
            ruby_error_print();
        }
        rb_exit(EXIT_FAILURE);
    }
    else {
        VALUE args[2];

        rb_scan_args(argc, argv, "1", &args[1]);
        StringValue(argv[0]);
        rb_io_puts(argc, argv, rb_stderr);
        args[0] = INT2NUM(EXIT_FAILURE);
        rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
    }

    UNREACHABLE;
}
at_exit { block } → proc click to toggle source

Converts block to a Proc object (and therefore binds it at the point of call) and registers it for execution when the program exits. If multiple handlers are registered, they are executed in reverse order of registration.

def do_at_exit(str1)
  at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit

produces:

goodbye cruel world
static VALUE
rb_f_at_exit(void)
{
    VALUE proc;

    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "called without a block");
    }
    proc = rb_block_proc();
    rb_set_end_proc(rb_call_end_proc, proc);
    return proc;
}
autoload(module, filename) → nil click to toggle source

Registers filename to be loaded (using Kernel::require) the first time that module (which may be a String or a symbol) is accessed.

autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
static VALUE
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
    VALUE klass = rb_class_real(rb_vm_cbase());
    if (NIL_P(klass)) {
        rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
    }
    return rb_mod_autoload(klass, sym, file);
}
autoload?(name) → String or nil click to toggle source

Returns filename to be loaded if name is registered as autoload.

autoload(:B, "b")
autoload?(:B)            #=> "b"

static VALUE
rb_f_autoload_p(VALUE obj, VALUE sym)
{
    /* use rb_vm_cbase() as same as rb_f_autoload. */
    VALUE klass = rb_vm_cbase();
    if (NIL_P(klass)) {
        return Qnil;
    }
    return rb_mod_autoload_p(klass, sym);
}
binding → a_binding click to toggle source

Returns a Binding object, describing the variable and method bindings at the point of call. This object can be used when calling eval to execute the evaluated command in this environment. See also the description of class Binding.

def get_binding(param)
  return binding
end
b = get_binding("hello")
eval("param", b)   #=> "hello"

static VALUE
rb_f_binding(VALUE self)
{
    return rb_binding_new();
}
block_given? → true or false click to toggle source
iterator? → true or false

Returns true if yield would execute a block in the current context. The iterator? form is mildly deprecated.

def try
  if block_given?
    yield
  else
    "no block"
  end
end
try                  #=> "no block"
try { "hello" }      #=> "hello"
try do "hello" end   #=> "hello"

VALUE
rb_f_block_given_p(void)
{
    rb_thread_t *th = GET_THREAD();
    rb_control_frame_t *cfp = th->cfp;
    cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));

    if (cfp != 0 && VM_CF_BLOCK_PTR(cfp)) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}
callcc {|cont| block } → obj click to toggle source

Generates a Continuation object, which it passes to the associated block. You need to require 'continuation' before using this method. Performing a cont.call will cause the callcc to return (as will falling through the end of the block). The value returned by the callcc is the value of the block, or the value passed to cont.call. See class Continuation for more details. Also see #throw for an alternative mechanism for unwinding a call stack.

static VALUE
rb_callcc(VALUE self)
{
    volatile int called;
    volatile VALUE val = cont_capture(&called);

    if (called) {
        return val;
    }
    else {
        return rb_yield(val);
    }
}
caller(start=1, length=nil) → array or nil click to toggle source
caller(range) → array or nil

Returns the current execution stack—an array containing strings in the form file:line or file:line: in `method'.

The optional start parameter determines the number of initial stack entries to omit from the top of the stack.

A second optional length parameter can be used to limit how many entries are returned from the stack.

Returns nil if start is greater than the size of current execution stack.

Optionally you can pass a range, which will return an array containing the entries within the specified range.

def a(skip)
  caller(skip)
end
def b(skip)
  a(skip)
end
def c(skip)
  b(skip)
end
c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
c(2)   #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
c(3)   #=> ["prog:13:in `<main>'"]
c(4)   #=> []
c(5)   #=> nil

static VALUE
rb_f_caller(int argc, VALUE *argv)
{
    return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 1);
}
caller_locations(start=1, length=nil) → array or nil click to toggle source
caller_locations(range) → array or nil

Returns the current execution stack—an array containing backtrace location objects.

See Thread::Backtrace::Location for more information.

The optional start parameter determines the number of initial stack entries to omit from the top of the stack.

A second optional length parameter can be used to limit how many entries are returned from the stack.

Returns nil if start is greater than the size of current execution stack.

Optionally you can pass a range, which will return an array containing the entries within the specified range.

static VALUE
rb_f_caller_locations(int argc, VALUE *argv)
{
    return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
}
catch([arg]) {|tag| block } → obj click to toggle source

catch executes its block. If a throw is executed, Ruby searches up its stack for a catch block with a tag corresponding to the throw's tag. If found, that block is terminated, and catch returns the value given to throw. If throw is not called, the block terminates normally, and the value of catch is the value of the last expression evaluated. catch expressions may be nested, and the throw call need not be in lexical scope.

def routine(n)
  puts n
  throw :done if n <= 0
  routine(n-1)
end

catch(:done) { routine(3) }

produces:

3
2
1
0

when arg is given, catch yields it as is, or when no arg is given, catch assigns a new unique object to throw. this is useful for nested catch. arg can be an arbitrary object, not only Symbol.

static VALUE
rb_f_catch(int argc, VALUE *argv)
{
    VALUE tag;

    if (argc == 0) {
        tag = rb_obj_alloc(rb_cObject);
    }
    else {
        rb_scan_args(argc, argv, "01", &tag);
    }
    return rb_catch_obj(tag, catch_i, 0);
}
chomp → $_ click to toggle source
chomp(string) → $_

Equivalent to $_ = $_.chomp(string). See String#chomp. Available only when -p/-n command line option specified.

static VALUE
rb_f_chomp(int argc, VALUE *argv)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
    rb_lastline_set(str);
    return str;
}
chop → string click to toggle source

Equivalent to ($_.dup).chop!, except nil is never returned. See String#chop!. Available only when -p/-n command line option specified.

static VALUE
rb_f_chop(void)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
    rb_lastline_set(str);
    return str;
}
eval(string [, binding [, filename [,lineno]]]) → obj click to toggle source

Evaluates the Ruby expression(s) in string. If binding is given, which must be a Binding object, the evaluation is performed in its context. If the optional filename and lineno parameters are present, they will be used when reporting syntax errors.

def get_binding(str)
  return binding
end
str = "hello"
eval "str + ' Fred'"                      #=> "hello Fred"
eval "str + ' Fred'", get_binding("bye")  #=> "bye Fred"

VALUE
rb_f_eval(int argc, VALUE *argv, VALUE self)
{
    VALUE src, scope, vfile, vline;
    VALUE file = Qundef;
    int line = 1;

    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
    if (rb_safe_level() >= 4) {
        StringValue(src);
        if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
            rb_raise(rb_eSecurityError,
                     "Insecure: can't modify trusted binding");
        }
    }
    else {
        SafeStringValue(src);
    }
    if (argc >= 3) {
        StringValue(vfile);
    }
    if (argc >= 4) {
        line = NUM2INT(vline);
    }

    if (!NIL_P(vfile))
        file = vfile;
    return eval_string(self, src, scope, file, line);
}
exec([env,] command... [,options]) click to toggle source

Replaces the current process by running the given external command. command… is one of following forms.

commandline                 : command line string which is passed to the standard shell
cmdname, arg1, ...          : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)

If single string is given as the command, it is taken as a command line that is subject to shell expansion before being executed.

The standard shell means always "/bin/sh" on Unix-like systems, ENV["RUBYSHELL"] or ENV["COMSPEC"] on Windows NT series, and similar.

If two or more string given, the first is taken as a command name and the rest are passed as parameters to command with no shell expansion.

If a two-element array at the beginning of the command, the first element is the command to be executed, and the second argument is used as the argv[0] value, which may show up in process listings.

In order to execute the command, one of the exec(2) system calls is used, so the running command may inherit some of the environment of the original program (including open file descriptors). This behavior is modified by env and options. See spawn for details.

Raises SystemCallError if the command couldn't execute (typically Errno::ENOENT when it was not found).

This method modifies process attributes according to options (details described in spawn) before exec(2) system call. The modified attributes may be retained when exec(2) system call fails. For example, hard resource limits is not restorable. If it is not acceptable, consider to create a child process using spawn or system.

exec "echo *"       # echoes list of files in current directory
# never get here

exec "echo", "*"    # echoes an asterisk
# never get here
VALUE
rb_f_exec(int argc, VALUE *argv)
{
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;
#define CHILD_ERRMSG_BUFLEN 80
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

#if defined(__APPLE__) || defined(__HAIKU__)
    rb_exec_without_timer_thread(eargp, errmsg, sizeof(errmsg));
#else
    rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
#endif
    RB_GC_GUARD(execarg_obj);
    if (errmsg[0])
        rb_sys_fail(errmsg);
    rb_sys_fail_str(fail_str);
    return Qnil;                /* dummy */
}
exit(status=true) click to toggle source
Kernel::exit(status=true)
Process::exit(status=true)

Initiates the termination of the Ruby script by raising the SystemExit exception. This exception may be caught. The optional parameter is used to return a status code to the invoking environment. true and FALSE of status means success and failure respectively. The interpretation of other integer values are system dependent.

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end
puts "after begin block"

produces:

rescued a SystemExit exception
after begin block

Just prior to termination, Ruby executes any at_exit functions (see Kernel::at_exit) and runs any object finalizers (see ObjectSpace.define_finalizer).

at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
exit

produces:

at_exit function
in finalizer
VALUE
rb_f_exit(int argc, VALUE *argv)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
        istatus = exit_status_code(status);
    }
    else {
        istatus = EXIT_SUCCESS;
    }
    rb_exit(istatus);

    UNREACHABLE;
}
exit!(status=false) click to toggle source

Exits the process immediately. No exit handlers are run. status is returned to the underlying system as the exit status.

Process.exit!(true)
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
        istatus = exit_status_code(status);
    }
    else {
        istatus = EXIT_FAILURE;
    }
    _exit(istatus);

    UNREACHABLE;
}
raise click to toggle source
raise(string)
raise(exception [, string [, array]])
fail
fail(string)
fail(exception [, string [, array]])

With no arguments, raises the exception in $! or raises a RuntimeError if $! is nil. With a single String argument, raises a RuntimeError with the string as a message. Otherwise, the first parameter should be the name of an Exception class (or an object that returns an Exception object when sent an exception message). The optional second parameter sets the message associated with the exception, and the third parameter is an array of callback information. Exceptions are caught by the rescue clause of begin...end blocks.

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
static VALUE
rb_f_raise(int argc, VALUE *argv)
{
    VALUE err;
    if (argc == 0) {
        err = get_errinfo();
        if (!NIL_P(err)) {
            argc = 1;
            argv = &err;
        }
    }
    rb_raise_jump(rb_make_exception(argc, argv));

    UNREACHABLE;
}
fork [{ block }] → fixnum or nil click to toggle source
fork [{ block }] → fixnum or nil

Creates a subprocess. If a block is specified, that block is run in the subprocess, and the subprocess terminates with a status of zero. Otherwise, the fork call returns twice, once in the parent, returning the process ID of the child, and once in the child, returning nil. The child process can exit using Kernel.exit! to avoid running any at_exit functions. The parent process should use Process.wait to collect the termination statuses of its children or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

The thread calling fork is the only thread in the created child process. fork doesn't copy other threads.

If fork is not usable, Process.respond_to?(:fork) returns false.

static VALUE
rb_f_fork(VALUE obj)
{
    rb_pid_t pid;

    rb_secure(2);

    switch (pid = rb_fork_ruby(NULL)) {
      case 0:
        rb_thread_atfork();
        if (rb_block_given_p()) {
            int status;

            rb_protect(rb_yield, Qundef, &status);
            ruby_stop(status);
        }
        return Qnil;

      case -1:
        rb_sys_fail("fork(2)");
        return Qnil;

      default:
        return PIDT2NUM(pid);
    }
}
format(format_string [, arguments...] ) → string click to toggle source
sprintf(format_string [, arguments...] ) → string

Returns the string resulting from applying format_string to any additional arguments. Within the format string, any characters other than format sequences are copied to the result.

The syntax of a format sequence is follows.

%[flags][width][.precision]type

A format sequence consists of a percent sign, followed by optional flags, width, and precision indicators, then terminated with a field type character. The field type controls how the corresponding sprintf argument is to be interpreted, while the flags modify that interpretation.

The field type characters are:

Field |  Integer Format
------+--------------------------------------------------------------
  b   | Convert argument as a binary number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..1'.
  B   | Equivalent to `b', but uses an uppercase 0B for prefix
      | in the alternative format by #.
  d   | Convert argument as a decimal number.
  i   | Identical to `d'.
  o   | Convert argument as an octal number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..7'.
  u   | Identical to `d'.
  x   | Convert argument as a hexadecimal number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..f' (representing an infinite string of
      | leading 'ff's).
  X   | Equivalent to `x', but uses uppercase letters.

Field |  Float Format
------+--------------------------------------------------------------
  e   | Convert floating point argument into exponential notation
      | with one digit before the decimal point as [-]d.dddddde[+-]dd.
      | The precision specifies the number of digits after the decimal
      | point (defaulting to six).
  E   | Equivalent to `e', but uses an uppercase E to indicate
      | the exponent.
  f   | Convert floating point argument as [-]ddd.dddddd,
      | where the precision specifies the number of digits after
      | the decimal point.
  g   | Convert a floating point number using exponential form
      | if the exponent is less than -4 or greater than or
      | equal to the precision, or in dd.dddd form otherwise.
      | The precision specifies the number of significant digits.
  G   | Equivalent to `g', but use an uppercase `E' in exponent form.
  a   | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
      | which is consisted from optional sign, "0x", fraction part
      | as hexadecimal, "p", and exponential part as decimal.
  A   | Equivalent to `a', but use uppercase `X' and `P'.

Field |  Other Format
------+--------------------------------------------------------------
  c   | Argument is the numeric code for a single character or
      | a single character string itself.
  p   | The valuing of argument.inspect.
  s   | Argument is a string to be substituted.  If the format
      | sequence contains a precision, at most that many characters
      | will be copied.
  %   | A percent sign itself will be displayed.  No argument taken.

The flags modifies the behavior of the formats. The flag characters are:

Flag     | Applies to    | Meaning
---------+---------------+-----------------------------------------
space    | bBdiouxX      | Leave a space at the start of
         | aAeEfgG       | non-negative numbers.
         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
         |               | a minus sign with absolute value for
         |               | negative values.
---------+---------------+-----------------------------------------
(digit)$ | all           | Specifies the absolute argument number
         |               | for this field.  Absolute and relative
         |               | argument numbers cannot be mixed in a
         |               | sprintf string.
---------+---------------+-----------------------------------------
 #       | bBoxX         | Use an alternative format.
         | aAeEfgG       | For the conversions `o', increase the precision
         |               | until the first digit will be `0' if
         |               | it is not formatted as complements.
         |               | For the conversions `x', `X', `b' and `B'
         |               | on non-zero, prefix the result with ``0x'',
         |               | ``0X'', ``0b'' and ``0B'', respectively.
         |               | For `a', `A', `e', `E', `f', `g', and 'G',
         |               | force a decimal point to be added,
         |               | even if no digits follow.
         |               | For `g' and 'G', do not remove trailing zeros.
---------+---------------+-----------------------------------------
+        | bBdiouxX      | Add a leading plus sign to non-negative
         | aAeEfgG       | numbers.
         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
         |               | a minus sign with absolute value for
         |               | negative values.
---------+---------------+-----------------------------------------
-        | all           | Left-justify the result of this conversion.
---------+---------------+-----------------------------------------
0 (zero) | bBdiouxX      | Pad with zeros, not spaces.
         | aAeEfgG       | For `o', `x', `X', `b' and `B', radix-1
         | (numeric fmt) | is used for negative numbers formatted as
         |               | complements.
---------+---------------+-----------------------------------------
*        | all           | Use the next argument as the field width.
         |               | If negative, left-justify the result. If the
         |               | asterisk is followed by a number and a dollar
         |               | sign, use the indicated argument as the width.

Examples of flags:

# `+' and space flag specifies the sign of non-negative numbers.
sprintf("%d", 123)  #=> "123"
sprintf("%+d", 123) #=> "+123"
sprintf("% d", 123) #=> " 123"

# `#' flag for `o' increases number of digits to show `0'.
# `+' and space flag changes format of negative numbers.
sprintf("%o", 123)   #=> "173"
sprintf("%#o", 123)  #=> "0173"
sprintf("%+o", -123) #=> "-173"
sprintf("%o", -123)  #=> "..7605"
sprintf("%#o", -123) #=> "..7605"

# `#' flag for `x' add a prefix `0x' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%x", 123)   #=> "7b"
sprintf("%#x", 123)  #=> "0x7b"
sprintf("%+x", -123) #=> "-7b"
sprintf("%x", -123)  #=> "..f85"
sprintf("%#x", -123) #=> "0x..f85"
sprintf("%#x", 0)    #=> "0"

# `#' for `X' uses the prefix `0X'.
sprintf("%X", 123)  #=> "7B"
sprintf("%#X", 123) #=> "0X7B"

# `#' flag for `b' add a prefix `0b' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%b", 123)   #=> "1111011"
sprintf("%#b", 123)  #=> "0b1111011"
sprintf("%+b", -123) #=> "-1111011"
sprintf("%b", -123)  #=> "..10000101"
sprintf("%#b", -123) #=> "0b..10000101"
sprintf("%#b", 0)    #=> "0"

# `#' for `B' uses the prefix `0B'.
sprintf("%B", 123)  #=> "1111011"
sprintf("%#B", 123) #=> "0B1111011"

# `#' for `e' forces to show the decimal point.
sprintf("%.0e", 1)  #=> "1e+00"
sprintf("%#.0e", 1) #=> "1.e+00"

# `#' for `f' forces to show the decimal point.
sprintf("%.0f", 1234)  #=> "1234"
sprintf("%#.0f", 1234) #=> "1234."

# `#' for `g' forces to show the decimal point.
# It also disables stripping lowest zeros.
sprintf("%g", 123.4)   #=> "123.4"
sprintf("%#g", 123.4)  #=> "123.400"
sprintf("%g", 123456)  #=> "123456"
sprintf("%#g", 123456) #=> "123456."

The field width is an optional integer, followed optionally by a period and a precision. The width specifies the minimum number of characters that will be written to the result for this field.

Examples of width:

# padding is done by spaces,       width=20
# 0 or radix-1.             <------------------>
sprintf("%20d", 123)   #=> "                 123"
sprintf("%+20d", 123)  #=> "                +123"
sprintf("%020d", 123)  #=> "00000000000000000123"
sprintf("%+020d", 123) #=> "+0000000000000000123"
sprintf("% 020d", 123) #=> " 0000000000000000123"
sprintf("%-20d", 123)  #=> "123                 "
sprintf("%-+20d", 123) #=> "+123                "
sprintf("%- 20d", 123) #=> " 123                "
sprintf("%020x", -123) #=> "..ffffffffffffffff85"

For numeric fields, the precision controls the number of decimal places displayed. For string fields, the precision determines the maximum number of characters to be copied from the string. (Thus, the format sequence %10.10s will always contribute exactly ten characters to the result.)

Examples of precisions:

# precision for `d', 'o', 'x' and 'b' is
# minimum number of digits               <------>
sprintf("%20.8d", 123)  #=> "            00000123"
sprintf("%20.8o", 123)  #=> "            00000173"
sprintf("%20.8x", 123)  #=> "            0000007b"
sprintf("%20.8b", 123)  #=> "            01111011"
sprintf("%20.8d", -123) #=> "           -00000123"
sprintf("%20.8o", -123) #=> "            ..777605"
sprintf("%20.8x", -123) #=> "            ..ffff85"
sprintf("%20.8b", -11)  #=> "            ..110101"

# "0x" and "0b" for `#x' and `#b' is not counted for
# precision but "0" for `#o' is counted.  <------>
sprintf("%#20.8d", 123)  #=> "            00000123"
sprintf("%#20.8o", 123)  #=> "            00000173"
sprintf("%#20.8x", 123)  #=> "          0x0000007b"
sprintf("%#20.8b", 123)  #=> "          0b01111011"
sprintf("%#20.8d", -123) #=> "           -00000123"
sprintf("%#20.8o", -123) #=> "            ..777605"
sprintf("%#20.8x", -123) #=> "          0x..ffff85"
sprintf("%#20.8b", -11)  #=> "          0b..110101"

# precision for `e' is number of
# digits after the decimal point           <------>
sprintf("%20.8e", 1234.56789) #=> "      1.23456789e+03"

# precision for `f' is number of
# digits after the decimal point               <------>
sprintf("%20.8f", 1234.56789) #=> "       1234.56789000"

# precision for `g' is number of
# significant digits                          <------->
sprintf("%20.8g", 1234.56789) #=> "           1234.5679"

#                                         <------->
sprintf("%20.8g", 123456789)  #=> "       1.2345679e+08"

# precision for `s' is
# maximum number of characters                    <------>
sprintf("%20.8s", "string test") #=> "            string t"

Examples:

sprintf("%d %04x", 123, 123)               #=> "123 007b"
sprintf("%08b '%4s'", 123, 123)            #=> "01111011 ' 123'"
sprintf("%1$*2$s %2$d %1$s", "hello", 8)   #=> "   hello 8 hello"
sprintf("%1$*2$s %2$d", "hello", -8)       #=> "hello    -8"
sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23)   #=> "+1.23: 1.23:1.23"
sprintf("%u", -123)                        #=> "-123"

For more complex formatting, Ruby supports a reference by name. %<name>s style uses format style, but %{name} style doesn't.

Examples:

sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
  #=> 1 : 2.000000
sprintf("%{foo}f", { :foo => 1 })
  # => "1f"

VALUE
rb_f_sprintf(int argc, const VALUE *argv)
{
    return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
}
gets(sep=$/) → string or nil click to toggle source
gets(limit) → string or nil
gets(sep,limit) → string or nil

Returns (and assigns to $_) the next line from the list of files in ARGV (or $*), or from standard input if no files are present on the command line. Returns nil at end of file. The optional argument specifies the record separator. The separator is included with the contents of each record. A separator of nil reads the entire contents, and a zero-length separator reads the input one paragraph at a time, where paragraphs are divided by two consecutive newlines. If the first argument is an integer, or optional second argument is given, the returning string would not be longer than the given value in bytes. If multiple filenames are present in ARGV, +gets(nil)+ will read the contents one file at a time.

ARGV << "testfile"
print while gets

produces:

This is line one
This is line two
This is line three
And so on...

The style of programming using $_ as an implicit parameter is gradually losing favor in the Ruby community.

static VALUE
rb_f_gets(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_gets(argc, argv, argf);
    }
    return rb_funcall2(argf, idGets, argc, argv);
}
global_variables → array click to toggle source

Returns an array of the names of global variables.

global_variables.grep /std/   #=> [:$stdin, :$stdout, :$stderr]

VALUE
rb_f_global_variables(void)
{
    VALUE ary = rb_ary_new();
    char buf[2];
    int i;

    st_foreach_safe(rb_global_tbl, gvar_i, ary);
    buf[0] = '$';
    for (i = 1; i <= 9; ++i) {
    buf[1] = (char)(i + '0');
    rb_ary_push(ary, ID2SYM(rb_intern2(buf, 2)));
    }
    return ary;
}
gsub(pattern, replacement) → string click to toggle source
gsub(pattern) {|...| block } → string

Equivalent to $_.gsub..., except that $_ receives the modified result. Available only when -p/-n command line option specified.

static VALUE
rb_f_gsub(int argc, VALUE *argv)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
    rb_lastline_set(str);
    return str;
}
block_given? → true or false click to toggle source
iterator? → true or false

Returns true if yield would execute a block in the current context. The iterator? form is mildly deprecated.

def try
  if block_given?
    yield
  else
    "no block"
  end
end
try                  #=> "no block"
try { "hello" }      #=> "hello"
try do "hello" end   #=> "hello"

VALUE
rb_f_block_given_p(void)
{
    rb_thread_t *th = GET_THREAD();
    rb_control_frame_t *cfp = th->cfp;
    cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));

    if (cfp != 0 && VM_CF_BLOCK_PTR(cfp)) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}
lambda { |...| block } → a_proc click to toggle source

Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.

VALUE
rb_block_lambda(void)
{
    return proc_new(rb_cProc, TRUE);
}
load(filename, wrap=false) → true click to toggle source

Loads and executes the Ruby program in the file filename. If the filename does not resolve to an absolute path, the file is searched for in the library directories listed in $:. If the optional wrap parameter is true, the loaded script will be executed under an anonymous module, protecting the calling program's global namespace. In no circumstance will any local variables in the loaded file be propagated to the loading environment.

static VALUE
rb_f_load(int argc, VALUE *argv)
{
    VALUE fname, wrap, path;

    rb_scan_args(argc, argv, "11", &fname, &wrap);

    if (RUBY_DTRACE_LOAD_ENTRY_ENABLED()) {
        RUBY_DTRACE_LOAD_ENTRY(StringValuePtr(fname),
                               rb_sourcefile(),
                               rb_sourceline());
    }

    path = rb_find_file(FilePathValue(fname));
    if (!path) {
        if (!rb_file_load_ok(RSTRING_PTR(fname)))
            load_failed(fname);
        path = fname;
    }
    rb_load_internal(path, RTEST(wrap));

    if (RUBY_DTRACE_LOAD_RETURN_ENABLED()) {
        RUBY_DTRACE_LOAD_RETURN(StringValuePtr(fname),
                               rb_sourcefile(),
                               rb_sourceline());
    }

    return Qtrue;
}
local_variables → array click to toggle source

Returns the names of the current local variables.

fred = 1
for i in 1..10
   # ...
end
local_variables   #=> [:fred, :i]

static VALUE
rb_f_local_variables(void)
{
    VALUE ary = rb_ary_new();
    rb_thread_t *th = GET_THREAD();
    rb_control_frame_t *cfp =
        vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
    int i;

    while (cfp) {
        if (cfp->iseq) {
            for (i = 0; i < cfp->iseq->local_table_size; i++) {
                ID lid = cfp->iseq->local_table[i];
                if (lid) {
                    const char *vname = rb_id2name(lid);
                    /* should skip temporary variable */
                    if (vname) {
                        rb_ary_push(ary, ID2SYM(lid));
                    }
                }
            }
        }
        if (!VM_EP_LEP_P(cfp->ep)) {
            /* block */
            VALUE *ep = VM_CF_PREV_EP(cfp);

            if (vm_collect_local_variables_in_heap(th, ep, ary)) {
                break;
            }
            else {
                while (cfp->ep != ep) {
                    cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
                }
            }
        }
        else {
            break;
        }
    }
    return ary;
}
loop { block } click to toggle source
loop → an_enumerator

Repeatedly executes the block.

If no block is given, an enumerator is returned instead.

loop do
  print "Input: "
  line = gets
  break if !line or line =~ /^qQ/
  # ...
end

StopIteration raised in the block breaks the loop.

static VALUE
rb_f_loop(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
    rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
    return Qnil;                /* dummy */
}
open(path [, mode [, perm]] [, opt]) → io or nil click to toggle source
open(path [, mode [, perm]] [, opt]) {|io| block } → obj

Creates an IO object connected to the given stream, file, or subprocess.

If path does not start with a pipe character (|), treat it as the name of a file to open using the specified mode (defaulting to “r”).

The mode is either a string or an integer. If it is an integer, it must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If it is a string, it is either “fmode”, “fmode:ext_enc”, or “fmode:ext_enc:int_enc”.

See the documentation of IO.new for full documentation of the mode string directives.

If a file is being created, its initial permissions may be set using the perm parameter. See File.new and the open(2) and chmod(2) man pages for a description of permissions.

If a block is specified, it will be invoked with the IO object as a parameter, and the IO will be automatically closed when the block terminates. The call returns the value of the block.

If path starts with a pipe character ("|"), a subprocess is created, connected to the caller by a pair of pipes. The returned IO object may be used to write to the standard input and read from the standard output of this subprocess.

If the command following the pipe is a single minus sign ("|-"), Ruby forks, and this subprocess is connected to the parent. If the command is not "-", the subprocess runs the command.

When the subprocess is ruby (opened via "|-"), the open call returns nil. If a block is associated with the open call, that block will run twice — once in the parent and once in the child.

The block parameter will be an IO object in the parent and nil in the child. The parent's IO object will be connected to the child's $stdin and $stdout. The subprocess will be terminated at the end of the block.

Examples

Reading from “testfile”:

open("testfile") do |f|
  print f.gets
end

Produces:

This is line one

Open a subprocess and read its output:

cmd = open("|date")
print cmd.gets
cmd.close

Produces:

Wed Apr  9 08:56:31 CDT 2003

Open a subprocess running the same Ruby program:

f = open("|-", "w+")
if f == nil
  puts "in Child"
  exit
else
  puts "Got: #{f.gets}"
end

Produces:

Got: in Child

Open a subprocess using a block to receive the IO object:

open "|-" do |f|
  if f then
    # parent process
    puts "Got: #{f.gets}"
  else
    # child process
    puts "in Child"
  end
end

Produces:

Got: in Child
static VALUE
rb_f_open(int argc, VALUE *argv)
{
    ID to_open = 0;
    int redirect = FALSE;

    if (argc >= 1) {
        CONST_ID(to_open, "to_open");
        if (rb_respond_to(argv[0], to_open)) {
            redirect = TRUE;
        }
        else {
            VALUE tmp = argv[0];
            FilePathValue(tmp);
            if (NIL_P(tmp)) {
                redirect = TRUE;
            }
            else {
                VALUE cmd = check_pipe_command(tmp);
                if (!NIL_P(cmd)) {
                    argv[0] = cmd;
                    return rb_io_s_popen(argc, argv, rb_cIO);
                }
            }
        }
    }
    if (redirect) {
        VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);

        if (rb_block_given_p()) {
            return rb_ensure(rb_yield, io, io_close, io);
        }
        return io;
    }
    return rb_io_s_open(argc, argv, rb_cFile);
}
p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil

For each object, directly writes obj.inspect followed by a newline to the program's standard output.

S = Struct.new(:name, :state)
s = S['dave', 'TX']
p s

produces:

#<S name="dave", state="TX">
static VALUE
rb_f_p(int argc, VALUE *argv, VALUE self)
{
    struct rb_f_p_arg arg;
    arg.argc = argc;
    arg.argv = argv;

    return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
}
print(obj, ...) → nil click to toggle source

Prints each object in turn to $stdout. If the output field separator ($,) is not nil, its contents will appear between each field. If the output record separator ($\</code>) is not nil, it will be appended to the output. If no arguments are given, prints <code>$_. Objects that aren't strings will be converted by calling their to_s method.

print "cat", [1,2,3], 99, "\n"
$, = ", "
$\ = "\n"
print "cat", [1,2,3], 99

produces:

cat12399
cat, 1, 2, 3, 99
static VALUE
rb_f_print(int argc, VALUE *argv)
{
    rb_io_print(argc, argv, rb_stdout);
    return Qnil;
}
printf(io, string [, obj ... ]) → nil click to toggle source
printf(string [, obj ... ]) → nil

Equivalent to:

io.write(sprintf(string, obj, ...)

or

$stdout.write(sprintf(string, obj, ...)
static VALUE
rb_f_printf(int argc, VALUE *argv)
{
    VALUE out;

    if (argc == 0) return Qnil;
    if (RB_TYPE_P(argv[0], T_STRING)) {
        out = rb_stdout;
    }
    else {
        out = argv[0];
        argv++;
        argc--;
    }
    rb_io_write(out, rb_f_sprintf(argc, argv));

    return Qnil;
}
proc { |...| block } → a_proc click to toggle source

Equivalent to Proc.new.

VALUE
rb_block_proc(void)
{
    return proc_new(rb_cProc, FALSE);
}
putc(int) → int click to toggle source
Equivalent to:

  $stdout.putc(int)

Refer to the documentation for IO#putc for important information regarding multi-byte characters.

static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
    if (recv == rb_stdout) {
        return rb_io_putc(recv, ch);
    }
    return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
}
puts(obj, ...) → nil click to toggle source

Equivalent to

$stdout.puts(obj, ...)
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
    if (recv == rb_stdout) {
        return rb_io_puts(argc, argv, recv);
    }
    return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
}
raise click to toggle source
raise(string)
raise(exception [, string [, array]])
fail
fail(string)
fail(exception [, string [, array]])

With no arguments, raises the exception in $! or raises a RuntimeError if $! is nil. With a single String argument, raises a RuntimeError with the string as a message. Otherwise, the first parameter should be the name of an Exception class (or an object that returns an Exception object when sent an exception message). The optional second parameter sets the message associated with the exception, and the third parameter is an array of callback information. Exceptions are caught by the rescue clause of begin...end blocks.

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
static VALUE
rb_f_raise(int argc, VALUE *argv)
{
    VALUE err;
    if (argc == 0) {
        err = get_errinfo();
        if (!NIL_P(err)) {
            argc = 1;
            argv = &err;
        }
    }
    rb_raise_jump(rb_make_exception(argc, argv));

    UNREACHABLE;
}
rand(max=0) → number click to toggle source

If called without an argument, or if max.to_i.abs == 0, rand returns a pseudo-random floating point number between 0.0 and 1.0, including 0.0 and excluding 1.0.

rand        #=> 0.2725926052826416

When max.abs is greater than or equal to 1, rand returns a pseudo-random integer greater than or equal to 0 and less than max.to_i.abs.

rand(100)   #=> 12

When max is a Range, rand returns a random number where range.member?(number) == true.

Negative or floating point values for max are allowed, but may give surprising results.

rand(-100) # => 87
rand(-0.5) # => 0.8130921818028143
rand(1.9)  # equivalent to rand(1), which is always 0

#srand may be used to ensure that sequences of random numbers are reproducible between different runs of a program.

See also Random#rand.

static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
    VALUE v, vmax, r;
    struct MT *mt = default_mt();

    if (argc == 0) goto zero_arg;
    rb_scan_args(argc, argv, "01", &vmax);
    if (NIL_P(vmax)) goto zero_arg;
    if ((v = rand_range(mt, vmax)) != Qfalse) {
        return v;
    }
    vmax = rb_to_int(vmax);
    if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
      zero_arg:
        return DBL2NUM(genrand_real(mt));
    }
    return r;
}
readline(sep=$/) → string click to toggle source
readline(limit) → string
readline(sep, limit) → string

Equivalent to Kernel::gets, except readline raises EOFError at end of file.

static VALUE
rb_f_readline(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_readline(argc, argv, argf);
    }
    return rb_funcall2(argf, rb_intern("readline"), argc, argv);
}
readlines(sep=$/) → array click to toggle source
readlines(limit) → array
readlines(sep,limit) → array

Returns an array containing the lines returned by calling Kernel.gets(sep) until the end of file.

static VALUE
rb_f_readlines(int argc, VALUE *argv, VALUE recv)
{
    if (recv == argf) {
        return argf_readlines(argc, argv, argf);
    }
    return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
}
require(name) → true or false click to toggle source

Loads the given name, returning true if successful and false if the feature is already loaded.

If the filename does not resolve to an absolute path, it will be searched for in the directories listed in $LOAD_PATH ($:).

If the filename has the extension “.rb”, it is loaded as a source file; if the extension is “.so”, “.o”, or “.dll”, or the default shared library extension on the current platform, Ruby loads the shared library as a Ruby extension. Otherwise, Ruby tries adding “.rb”, “.so”, and so on to the name until found. If the file named cannot be found, a LoadError will be raised.

For Ruby extensions the filename given may use any shared library extension. For example, on Linux the socket extension is “socket.so” and require 'socket.dll' will load the socket extension.

The absolute path of the loaded file is added to $LOADED_FEATURES ($"). A file will not be loaded again if its path already appears in $". For example, require 'a'; require './a' will not load a.rb again.

require "my-library.rb"
require "db-driver"

Any constants or globals within the loaded source file will be available in the calling program's global namespace. However, local variables will not be propagated to the loading environment.

VALUE
rb_f_require(VALUE obj, VALUE fname)
{
    return rb_require_safe(fname, rb_safe_level());
}
require_relative(string) → true or false click to toggle source

Ruby tries to load the library named string relative to the requiring file's path. If the file's path cannot be determined a LoadError is raised. If a file is loaded true is returned and false otherwise.

VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}
select(read_array click to toggle source
[, write_array
[, error_array
[, timeout]]]) → array or nil

Calls select(2) system call. It monitors given arrays of IO objects, waits one or more of IO objects ready for reading, are ready for writing, and have pending exceptions respectably, and returns an array that contains arrays of those IO objects. It will return nil if optional timeout value is given and no IO object is ready in timeout seconds.

Parameters

read_array

an array of IO objects that wait until ready for read

write_array

an array of IO objects that wait until ready for write

error_array

an array of IO objects that wait for exceptions

timeout

a numeric value in second

Example

rp, wp = IO.pipe
mesg = "ping "
100.times {
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

produces:

ping pong
ping pong
ping pong
(snipped)
ping
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
    VALUE timeout;
    struct select_args args;
    struct timeval timerec;
    int i;

    rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
    if (NIL_P(timeout)) {
        args.timeout = 0;
    }
    else {
        timerec = rb_time_interval(timeout);
        args.timeout = &timerec;
    }

    for (i = 0; i < numberof(args.fdsets); ++i)
        rb_fd_init(&args.fdsets[i]);

    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}
set_trace_func(proc) → proc click to toggle source
set_trace_func(nil) → nil

Establishes proc as the handler for tracing, or disables tracing if the parameter is nil.

proc takes up to six parameters:

  • an event name

  • a filename

  • a line number

  • an object id

  • a binding

  • the name of a class

proc is invoked whenever an event occurs.

Events are:

c-call

call a C-language routine

c-return

return from a C-language routine

call

call a Ruby method

class

start a class or module definition),

end

finish a class or module definition),

line

execute code on a new line

raise

raise an exception

return

return from a Ruby method

Tracing is disabled within the context of proc.

  class Test
  def test
    a = 1
    b = 2
  end
  end

  set_trace_func proc { |event, file, line, id, binding, classname|
     printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
  }
  t = Test.new
  t.test

    line prog.rb:11               false
  c-call prog.rb:11        new    Class
  c-call prog.rb:11 initialize   Object
c-return prog.rb:11 initialize   Object
c-return prog.rb:11        new    Class
    line prog.rb:12               false
    call prog.rb:2        test     Test
    line prog.rb:3        test     Test
    line prog.rb:4        test     Test
  return prog.rb:4        test     Test

static VALUE
set_trace_func(VALUE obj, VALUE trace)
{
    rb_secure(4);

    rb_remove_event_hook(call_trace_func);

    if (NIL_P(trace)) {
        return Qnil;
    }

    if (!rb_obj_is_proc(trace)) {
        rb_raise(rb_eTypeError, "trace_func needs to be Proc");
    }

    rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
    return trace;
}
sleep([duration]) → fixnum click to toggle source

Suspends the current thread for duration seconds (which may be any number, including a Float with fractional seconds). Returns the actual number of seconds slept (rounded), which may be less than that asked for if another thread calls Thread#run. Called without an argument, sleep() will sleep forever.

Time.new    #=> 2008-03-08 19:56:19 +0900
sleep 1.2   #=> 1
Time.new    #=> 2008-03-08 19:56:20 +0900
sleep 1.9   #=> 2
Time.new    #=> 2008-03-08 19:56:22 +0900

static VALUE
rb_f_sleep(int argc, VALUE *argv)
{
    time_t beg, end;

    beg = time(0);
    if (argc == 0) {
        rb_thread_sleep_forever();
    }
    else {
        rb_check_arity(argc, 0, 1);
        rb_thread_wait_for(rb_time_interval(argv[0]));
    }

    end = time(0) - beg;

    return INT2FIX(end);
}
spawn([env,] command... [,options]) → pid click to toggle source
spawn([env,] command... [,options]) → pid

spawn executes specified command and return its pid.

This method doesn't wait for end of the command. The parent process should use Process.wait to collect the termination status of its child or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

spawn has bunch of options to specify process attributes:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : don't clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : don't change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : don't create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => true  : don't inherit
  current directory:
    :chdir => str

If a hash is given as env, the environment is updated by env before exec(2) in the child process. If a pair in env has nil as the value, the variable is deleted.

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

If a hash is given as options, it specifies process group, create new process group, resource limit, current directory, umask and redirects for the child process. Also, it can be specified to clear environment variables.

The :unsetenv_others key in options specifies to clear environment variables, other than specified by env.

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

The :pgroup key in options specifies a process group. The corresponding value should be true, zero or positive integer. true and zero means the process should be a process leader of a new process group. Other values specifies a process group to be belongs.

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

The :new_pgroup key in options specifies to pass CREATE_NEW_PROCESS_GROUP flag to CreateProcessW() that is Windows API. This option is only for Windows. true means the new process is the root process of the new process group. The new process has CTRL+C disabled. This flag is necessary for Process.kill(:SIGINT, pid) on the subprocess. :new_pgroup is false by default.

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

The :rlimit_foo key specifies a resource limit. foo should be one of resource types such as core. The corresponding value should be an integer or an array which have one or two integers: same as cur_limit and max_limit arguments for Process.setrlimit.

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

The :umask key in options specifies the umask.

pid = spawn(command, :umask=>077)

The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection. The redirection maps a file descriptor in the child process.

For example, stderr can be merged into stdout as follows:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

The hash keys specifies a file descriptor in the child process started by spawn. :err, 2 and STDERR specifies the standard error stream (stderr).

The hash values specifies a file descriptor in the parent process which invokes spawn. :out, 1 and STDOUT specifies the standard output stream (stdout).

In the above example, the standard output in the child process is not specified. So it is inherited from the parent process.

The standard input stream (stdin) can be specified by :in, 0 and STDIN.

A filename can be specified as a hash value.

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

For stdout and stderr, it is opened in write mode. Otherwise read mode is used.

For specifying flags and permission of file creation explicitly, an array is used instead.

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

The array specifies a filename, flags and permission. The flags can be a string or an integer. If the flags is omitted or nil, File::RDONLY is assumed. The permission should be an integer. If the permission is omitted or nil, 0644 is assumed.

If an array of IOs and integers are specified as a hash key, all the elements are redirected.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

Another way to merge multiple file descriptors is [:child, fd]. [:child, fd] means the file descriptor in the child process. This is different from fd. For example, :err=>:out means redirecting child stderr to parent stdout. But :err=>[:child, :out] means redirecting child stderr to child stdout. They differ if stdout is redirected in the child process as follows.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

[:child, :out] can be used to merge stderr into stdout in IO.popen. In this case, IO.popen redirects stdout to a pipe in the child process and [:child, :out] refers the redirected stdout.

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

The :chdir key in options specifies the current directory.

pid = spawn(command, :chdir=>"/var/tmp")

spawn closes all non-standard unspecified descriptors by default. The “standard” descriptors are 0, 1 and 2. This behavior is specified by :close_others option. :close_others doesn't affect the standard descriptors which are closed only if :close is specified explicitly.

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

:close_others is true by default for spawn and IO.popen.

Note that fds which close-on-exec flag is already set are closed regardless of :close_others option.

So IO.pipe and spawn can be used as IO.popen.

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

:close is specified as a hash value to close a fd individually.

f = open(foo)
system(command, f=>:close)        # don't inherit f.

If a file descriptor need to be inherited, io=>io can be used.

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

It is also possible to exchange file descriptors.

pid = spawn(command, :out=>:err, :err=>:out)

The hash keys specify file descriptors in the child process. The hash values specifies file descriptors in the parent process. So the above specifies exchanging stdout and stderr. Internally, spawn uses an extra file descriptor to resolve such cyclic file descriptor mapping.

See Kernel.exec for the standard shell.

static VALUE
rb_f_spawn(int argc, VALUE *argv)
{
    rb_pid_t pid;
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

    pid = rb_spawn_process(eargp, errmsg, sizeof(errmsg));
    RB_GC_GUARD(execarg_obj);

    if (pid == -1) {
        const char *prog = errmsg;
        if (!prog[0]) {
            rb_sys_fail_str(fail_str);
        }
        rb_sys_fail(prog);
    }
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
    return PIDT2NUM(pid);
#else
    return Qnil;
#endif
}
format(format_string [, arguments...] ) → string click to toggle source
sprintf(format_string [, arguments...] ) → string

Returns the string resulting from applying format_string to any additional arguments. Within the format string, any characters other than format sequences are copied to the result.

The syntax of a format sequence is follows.

%[flags][width][.precision]type

A format sequence consists of a percent sign, followed by optional flags, width, and precision indicators, then terminated with a field type character. The field type controls how the corresponding sprintf argument is to be interpreted, while the flags modify that interpretation.

The field type characters are:

Field |  Integer Format
------+--------------------------------------------------------------
  b   | Convert argument as a binary number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..1'.
  B   | Equivalent to `b', but uses an uppercase 0B for prefix
      | in the alternative format by #.
  d   | Convert argument as a decimal number.
  i   | Identical to `d'.
  o   | Convert argument as an octal number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..7'.
  u   | Identical to `d'.
  x   | Convert argument as a hexadecimal number.
      | Negative numbers will be displayed as a two's complement
      | prefixed with `..f' (representing an infinite string of
      | leading 'ff's).
  X   | Equivalent to `x', but uses uppercase letters.

Field |  Float Format
------+--------------------------------------------------------------
  e   | Convert floating point argument into exponential notation
      | with one digit before the decimal point as [-]d.dddddde[+-]dd.
      | The precision specifies the number of digits after the decimal
      | point (defaulting to six).
  E   | Equivalent to `e', but uses an uppercase E to indicate
      | the exponent.
  f   | Convert floating point argument as [-]ddd.dddddd,
      | where the precision specifies the number of digits after
      | the decimal point.
  g   | Convert a floating point number using exponential form
      | if the exponent is less than -4 or greater than or
      | equal to the precision, or in dd.dddd form otherwise.
      | The precision specifies the number of significant digits.
  G   | Equivalent to `g', but use an uppercase `E' in exponent form.
  a   | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
      | which is consisted from optional sign, "0x", fraction part
      | as hexadecimal, "p", and exponential part as decimal.
  A   | Equivalent to `a', but use uppercase `X' and `P'.

Field |  Other Format
------+--------------------------------------------------------------
  c   | Argument is the numeric code for a single character or
      | a single character string itself.
  p   | The valuing of argument.inspect.
  s   | Argument is a string to be substituted.  If the format
      | sequence contains a precision, at most that many characters
      | will be copied.
  %   | A percent sign itself will be displayed.  No argument taken.

The flags modifies the behavior of the formats. The flag characters are:

Flag     | Applies to    | Meaning
---------+---------------+-----------------------------------------
space    | bBdiouxX      | Leave a space at the start of
         | aAeEfgG       | non-negative numbers.
         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
         |               | a minus sign with absolute value for
         |               | negative values.
---------+---------------+-----------------------------------------
(digit)$ | all           | Specifies the absolute argument number
         |               | for this field.  Absolute and relative
         |               | argument numbers cannot be mixed in a
         |               | sprintf string.
---------+---------------+-----------------------------------------
 #       | bBoxX         | Use an alternative format.
         | aAeEfgG       | For the conversions `o', increase the precision
         |               | until the first digit will be `0' if
         |               | it is not formatted as complements.
         |               | For the conversions `x', `X', `b' and `B'
         |               | on non-zero, prefix the result with ``0x'',
         |               | ``0X'', ``0b'' and ``0B'', respectively.
         |               | For `a', `A', `e', `E', `f', `g', and 'G',
         |               | force a decimal point to be added,
         |               | even if no digits follow.
         |               | For `g' and 'G', do not remove trailing zeros.
---------+---------------+-----------------------------------------
+        | bBdiouxX      | Add a leading plus sign to non-negative
         | aAeEfgG       | numbers.
         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
         |               | a minus sign with absolute value for
         |               | negative values.
---------+---------------+-----------------------------------------
-        | all           | Left-justify the result of this conversion.
---------+---------------+-----------------------------------------
0 (zero) | bBdiouxX      | Pad with zeros, not spaces.
         | aAeEfgG       | For `o', `x', `X', `b' and `B', radix-1
         | (numeric fmt) | is used for negative numbers formatted as
         |               | complements.
---------+---------------+-----------------------------------------
*        | all           | Use the next argument as the field width.
         |               | If negative, left-justify the result. If the
         |               | asterisk is followed by a number and a dollar
         |               | sign, use the indicated argument as the width.

Examples of flags:

# `+' and space flag specifies the sign of non-negative numbers.
sprintf("%d", 123)  #=> "123"
sprintf("%+d", 123) #=> "+123"
sprintf("% d", 123) #=> " 123"

# `#' flag for `o' increases number of digits to show `0'.
# `+' and space flag changes format of negative numbers.
sprintf("%o", 123)   #=> "173"
sprintf("%#o", 123)  #=> "0173"
sprintf("%+o", -123) #=> "-173"
sprintf("%o", -123)  #=> "..7605"
sprintf("%#o", -123) #=> "..7605"

# `#' flag for `x' add a prefix `0x' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%x", 123)   #=> "7b"
sprintf("%#x", 123)  #=> "0x7b"
sprintf("%+x", -123) #=> "-7b"
sprintf("%x", -123)  #=> "..f85"
sprintf("%#x", -123) #=> "0x..f85"
sprintf("%#x", 0)    #=> "0"

# `#' for `X' uses the prefix `0X'.
sprintf("%X", 123)  #=> "7B"
sprintf("%#X", 123) #=> "0X7B"

# `#' flag for `b' add a prefix `0b' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%b", 123)   #=> "1111011"
sprintf("%#b", 123)  #=> "0b1111011"
sprintf("%+b", -123) #=> "-1111011"
sprintf("%b", -123)  #=> "..10000101"
sprintf("%#b", -123) #=> "0b..10000101"
sprintf("%#b", 0)    #=> "0"

# `#' for `B' uses the prefix `0B'.
sprintf("%B", 123)  #=> "1111011"
sprintf("%#B", 123) #=> "0B1111011"

# `#' for `e' forces to show the decimal point.
sprintf("%.0e", 1)  #=> "1e+00"
sprintf("%#.0e", 1) #=> "1.e+00"

# `#' for `f' forces to show the decimal point.
sprintf("%.0f", 1234)  #=> "1234"
sprintf("%#.0f", 1234) #=> "1234."

# `#' for `g' forces to show the decimal point.
# It also disables stripping lowest zeros.
sprintf("%g", 123.4)   #=> "123.4"
sprintf("%#g", 123.4)  #=> "123.400"
sprintf("%g", 123456)  #=> "123456"
sprintf("%#g", 123456) #=> "123456."

The field width is an optional integer, followed optionally by a period and a precision. The width specifies the minimum number of characters that will be written to the result for this field.

Examples of width:

# padding is done by spaces,       width=20
# 0 or radix-1.             <------------------>
sprintf("%20d", 123)   #=> "                 123"
sprintf("%+20d", 123)  #=> "                +123"
sprintf("%020d", 123)  #=> "00000000000000000123"
sprintf("%+020d", 123) #=> "+0000000000000000123"
sprintf("% 020d", 123) #=> " 0000000000000000123"
sprintf("%-20d", 123)  #=> "123                 "
sprintf("%-+20d", 123) #=> "+123                "
sprintf("%- 20d", 123) #=> " 123                "
sprintf("%020x", -123) #=> "..ffffffffffffffff85"

For numeric fields, the precision controls the number of decimal places displayed. For string fields, the precision determines the maximum number of characters to be copied from the string. (Thus, the format sequence %10.10s will always contribute exactly ten characters to the result.)

Examples of precisions:

# precision for `d', 'o', 'x' and 'b' is
# minimum number of digits               <------>
sprintf("%20.8d", 123)  #=> "            00000123"
sprintf("%20.8o", 123)  #=> "            00000173"
sprintf("%20.8x", 123)  #=> "            0000007b"
sprintf("%20.8b", 123)  #=> "            01111011"
sprintf("%20.8d", -123) #=> "           -00000123"
sprintf("%20.8o", -123) #=> "            ..777605"
sprintf("%20.8x", -123) #=> "            ..ffff85"
sprintf("%20.8b", -11)  #=> "            ..110101"

# "0x" and "0b" for `#x' and `#b' is not counted for
# precision but "0" for `#o' is counted.  <------>
sprintf("%#20.8d", 123)  #=> "            00000123"
sprintf("%#20.8o", 123)  #=> "            00000173"
sprintf("%#20.8x", 123)  #=> "          0x0000007b"
sprintf("%#20.8b", 123)  #=> "          0b01111011"
sprintf("%#20.8d", -123) #=> "           -00000123"
sprintf("%#20.8o", -123) #=> "            ..777605"
sprintf("%#20.8x", -123) #=> "          0x..ffff85"
sprintf("%#20.8b", -11)  #=> "          0b..110101"

# precision for `e' is number of
# digits after the decimal point           <------>
sprintf("%20.8e", 1234.56789) #=> "      1.23456789e+03"

# precision for `f' is number of
# digits after the decimal point               <------>
sprintf("%20.8f", 1234.56789) #=> "       1234.56789000"

# precision for `g' is number of
# significant digits                          <------->
sprintf("%20.8g", 1234.56789) #=> "           1234.5679"

#                                         <------->
sprintf("%20.8g", 123456789)  #=> "       1.2345679e+08"

# precision for `s' is
# maximum number of characters                    <------>
sprintf("%20.8s", "string test") #=> "            string t"

Examples:

sprintf("%d %04x", 123, 123)               #=> "123 007b"
sprintf("%08b '%4s'", 123, 123)            #=> "01111011 ' 123'"
sprintf("%1$*2$s %2$d %1$s", "hello", 8)   #=> "   hello 8 hello"
sprintf("%1$*2$s %2$d", "hello", -8)       #=> "hello    -8"
sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23)   #=> "+1.23: 1.23:1.23"
sprintf("%u", -123)                        #=> "-123"

For more complex formatting, Ruby supports a reference by name. %<name>s style uses format style, but %{name} style doesn't.

Examples:

sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
  #=> 1 : 2.000000
sprintf("%{foo}f", { :foo => 1 })
  # => "1f"

VALUE
rb_f_sprintf(int argc, const VALUE *argv)
{
    return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
}
srand(number = Random.new_seed) → old_seed click to toggle source

Seeds the system pseudo-random number generator, Random::DEFAULT, with number. The previous seed value is returned.

If number is omitted, seeds the generator using a source of entropy provided by the operating system, if available (/dev/urandom on Unix systems or the RSA cryptographic provider on Windows), which is then combined with the time, the process id, and a sequence number.

srand may be used to ensure repeatable sequences of pseudo-random numbers between different runs of the program. By setting the seed to a known value, programs can be made deterministic during testing.

srand 1234               # => 268519324636777531569100071560086917274
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]
[ rand(10), rand(1000) ] # => [4, 664]
srand 1234               # => 1234
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]

static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
    VALUE seed, old;
    rb_random_t *r = &default_rand;

    rb_secure(4);
    if (argc == 0) {
        seed = random_seed();
    }
    else {
        rb_scan_args(argc, argv, "01", &seed);
    }
    old = r->seed;
    r->seed = rand_init(&r->mt, seed);

    return old;
}
sub(pattern, replacement) → $_ click to toggle source
sub(pattern) { block } → $_

Equivalent to $_.sub(args), except that $_ will be updated if substitution occurs. Available only when -p/-n command line option specified.

static VALUE
rb_f_sub(int argc, VALUE *argv)
{
    VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
    rb_lastline_set(str);
    return str;
}
syscall(num [, args...]) → integer click to toggle source
Calls the operating system function identified by _num_ and
returns the result of the function or raises SystemCallError if
it failed.

Arguments for the function can follow _num_. They must be either
+String+ objects or +Integer+ objects. A +String+ object is passed
as a pointer to the byte sequence. An +Integer+ object is passed
as an integer whose bit size is same as a pointer.
Up to nine parameters may be passed (14 on the Atari-ST).

The function identified by _num_ is system
dependent. On some Unix systems, the numbers may be obtained from a
header file called <code>syscall.h</code>.

   syscall 4, 1, "hello\n", 6   # '4' is write(2) on our box

<em>produces:</em>

   hello

Calling +syscall+ on a platform which does not have any way to
an arbitrary system function just fails with NotImplementedError.
Note

syscall is essentially unsafe and unportable. Feel free to shoot your foot. DL (Fiddle) library is preferred for safer and a bit more portable programming.

static VALUE
rb_f_syscall(int argc, VALUE *argv)
{
#ifdef atarist
    VALUE arg[13]; /* yes, we really need that many ! */
#else
    VALUE arg[8];
#endif
#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
# define SYSCALL __syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
# if SIZEOF_LONG == 8
    long num, retval = -1;
# elif SIZEOF_LONG_LONG == 8
    long long num, retval = -1;
# else
#  error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
# endif
#elif defined(__linux__)
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
    /*
     * Linux man page says, syscall(2) function prototype is below.
     *
     *     int syscall(int number, ...);
     *
     * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
     */
    long num, retval = -1;
#else
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2INT(x)
# define RETVAL2NUM(x) INT2NUM(x)
    int num, retval = -1;
#endif
    int i;

    if (RTEST(ruby_verbose)) {
        rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
    }

    rb_secure(2);
    if (argc == 0)
        rb_raise(rb_eArgError, "too few arguments for syscall");
    if (argc > numberof(arg))
        rb_raise(rb_eArgError, "too many arguments for syscall");
    num = NUM2SYSCALLID(argv[0]); ++argv;
    for (i = argc - 1; i--; ) {
        VALUE v = rb_check_string_type(argv[i]);

        if (!NIL_P(v)) {
            SafeStringValue(v);
            rb_str_modify(v);
            arg[i] = (VALUE)StringValueCStr(v);
        }
        else {
            arg[i] = (VALUE)NUM2LONG(argv[i]);
        }
    }

    switch (argc) {
      case 1:
        retval = SYSCALL(num);
        break;
      case 2:
        retval = SYSCALL(num, arg[0]);
        break;
      case 3:
        retval = SYSCALL(num, arg[0],arg[1]);
        break;
      case 4:
        retval = SYSCALL(num, arg[0],arg[1],arg[2]);
        break;
      case 5:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
        break;
      case 6:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
        break;
      case 7:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
        break;
      case 8:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
        break;
#ifdef atarist
      case 9:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7]);
        break;
      case 10:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7], arg[8]);
        break;
      case 11:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7], arg[8], arg[9]);
        break;
      case 12:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7], arg[8], arg[9], arg[10]);
        break;
      case 13:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7], arg[8], arg[9], arg[10], arg[11]);
        break;
      case 14:
        retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
        break;
#endif
    }

    if (retval == -1)
        rb_sys_fail(0);
    return RETVAL2NUM(retval);
#undef SYSCALL
#undef NUM2SYSCALLID
#undef RETVAL2NUM
}
system([env,] command... [,options]) → true, false or nil click to toggle source

Executes command… in a subshell. command… is one of following forms.

commandline                 : command line string which is passed to the standard shell
cmdname, arg1, ...          : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)

system returns true if the command gives zero exit status, false for non zero exit status. Returns nil if command execution fails. An error status is available in $?. The arguments are processed in the same way as for Kernel.spawn.

The hash arguments, env and options, are same as exec and spawn. See Kernel.spawn for details.

system("echo *")
system("echo", "*")

produces:

config.h main.rb
*

See Kernel.exec for the standard shell.

static VALUE
rb_f_system(int argc, VALUE *argv)
{
    rb_pid_t pid;
    int status;

#if defined(SIGCLD) && !defined(SIGCHLD)
# define SIGCHLD SIGCLD
#endif

#ifdef SIGCHLD
    RETSIGTYPE (*chfunc)(int);

    rb_last_status_clear();
    chfunc = signal(SIGCHLD, SIG_DFL);
#endif
    pid = rb_spawn_internal(argc, argv, NULL, 0);
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
    if (pid > 0) {
        int ret, status;
        ret = rb_waitpid(pid, &status, 0);
        if (ret == (rb_pid_t)-1)
            rb_sys_fail("Another thread waited the process started by system().");
    }
#endif
#ifdef SIGCHLD
    signal(SIGCHLD, chfunc);
#endif
    if (pid < 0) {
        return Qnil;
    }
    status = PST2INT(rb_last_status_get());
    if (status == EXIT_SUCCESS) return Qtrue;
    return Qfalse;
}
test(cmd, file1 [, file2] ) → obj click to toggle source

Uses the integer cmd to perform various tests on file1 (first table below) or on file1 and file2 (second table).

File tests on a single file:

Cmd    Returns   Meaning
"A"  | Time    | Last access time for file1
"b"  | boolean | True if file1 is a block device
"c"  | boolean | True if file1 is a character device
"C"  | Time    | Last change time for file1
"d"  | boolean | True if file1 exists and is a directory
"e"  | boolean | True if file1 exists
"f"  | boolean | True if file1 exists and is a regular file
"g"  | boolean | True if file1 has the \CF{setgid} bit
     |         | set (false under NT)
"G"  | boolean | True if file1 exists and has a group
     |         | ownership equal to the caller's group
"k"  | boolean | True if file1 exists and has the sticky bit set
"l"  | boolean | True if file1 exists and is a symbolic link
"M"  | Time    | Last modification time for file1
"o"  | boolean | True if file1 exists and is owned by
     |         | the caller's effective uid
"O"  | boolean | True if file1 exists and is owned by
     |         | the caller's real uid
"p"  | boolean | True if file1 exists and is a fifo
"r"  | boolean | True if file1 is readable by the effective
     |         | uid/gid of the caller
"R"  | boolean | True if file is readable by the real
     |         | uid/gid of the caller
"s"  | int/nil | If file1 has nonzero size, return the size,
     |         | otherwise return nil
"S"  | boolean | True if file1 exists and is a socket
"u"  | boolean | True if file1 has the setuid bit set
"w"  | boolean | True if file1 exists and is writable by
     |         | the effective uid/gid
"W"  | boolean | True if file1 exists and is writable by
     |         | the real uid/gid
"x"  | boolean | True if file1 exists and is executable by
     |         | the effective uid/gid
"X"  | boolean | True if file1 exists and is executable by
     |         | the real uid/gid
"z"  | boolean | True if file1 exists and has a zero length

Tests that take two files:

"-"  | boolean | True if file1 and file2 are identical
"="  | boolean | True if the modification times of file1
     |         | and file2 are equal
"<"  | boolean | True if the modification time of file1
     |         | is prior to that of file2
">"  | boolean | True if the modification time of file1
     |         | is after that of file2
static VALUE
rb_f_test(int argc, VALUE *argv)
{
    int cmd;

    if (argc == 0) rb_check_arity(argc, 2, 3);
    cmd = NUM2CHR(argv[0]);
    if (cmd == 0) {
      unknown:
        /* unknown command */
        if (ISPRINT(cmd)) {
            rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
        }
        else {
            rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
        }
    }
    if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
        CHECK(1);
        switch (cmd) {
          case 'b':
            return rb_file_blockdev_p(0, argv[1]);

          case 'c':
            return rb_file_chardev_p(0, argv[1]);

          case 'd':
            return rb_file_directory_p(0, argv[1]);

          case 'a':
          case 'e':
            return rb_file_exist_p(0, argv[1]);

          case 'f':
            return rb_file_file_p(0, argv[1]);

          case 'g':
            return rb_file_sgid_p(0, argv[1]);

          case 'G':
            return rb_file_grpowned_p(0, argv[1]);

          case 'k':
            return rb_file_sticky_p(0, argv[1]);

          case 'l':
            return rb_file_symlink_p(0, argv[1]);

          case 'o':
            return rb_file_owned_p(0, argv[1]);

          case 'O':
            return rb_file_rowned_p(0, argv[1]);

          case 'p':
            return rb_file_pipe_p(0, argv[1]);

          case 'r':
            return rb_file_readable_p(0, argv[1]);

          case 'R':
            return rb_file_readable_real_p(0, argv[1]);

          case 's':
            return rb_file_size_p(0, argv[1]);

          case 'S':
            return rb_file_socket_p(0, argv[1]);

          case 'u':
            return rb_file_suid_p(0, argv[1]);

          case 'w':
            return rb_file_writable_p(0, argv[1]);

          case 'W':
            return rb_file_writable_real_p(0, argv[1]);

          case 'x':
            return rb_file_executable_p(0, argv[1]);

          case 'X':
            return rb_file_executable_real_p(0, argv[1]);

          case 'z':
            return rb_file_zero_p(0, argv[1]);
        }
    }

    if (strchr("MAC", cmd)) {
        struct stat st;
        VALUE fname = argv[1];

        CHECK(1);
        if (rb_stat(fname, &st) == -1) {
            FilePathValue(fname);
            rb_sys_fail_path(fname);
        }

        switch (cmd) {
          case 'A':
            return stat_atime(&st);
          case 'M':
            return stat_mtime(&st);
          case 'C':
            return stat_ctime(&st);
        }
    }

    if (cmd == '-') {
        CHECK(2);
        return rb_file_identical_p(0, argv[1], argv[2]);
    }

    if (strchr("=<>", cmd)) {
        struct stat st1, st2;

        CHECK(2);
        if (rb_stat(argv[1], &st1) < 0) return Qfalse;
        if (rb_stat(argv[2], &st2) < 0) return Qfalse;

        switch (cmd) {
          case '=':
            if (st1.st_mtime == st2.st_mtime) return Qtrue;
            return Qfalse;

          case '>':
            if (st1.st_mtime > st2.st_mtime) return Qtrue;
            return Qfalse;

          case '<':
            if (st1.st_mtime < st2.st_mtime) return Qtrue;
            return Qfalse;
        }
    }
    goto unknown;
}
throw(tag [, obj]) click to toggle source

Transfers control to the end of the active catch block waiting for tag. Raises ArgumentError if there is no catch block for the tag. The optional second parameter supplies a return value for the catch block, which otherwise defaults to nil. For examples, see Kernel::catch.

static VALUE
rb_f_throw(int argc, VALUE *argv)
{
    VALUE tag, value;

    rb_scan_args(argc, argv, "11", &tag, &value);
    rb_throw_obj(tag, value);
    UNREACHABLE;
}
trace_var(symbol, cmd ) → nil click to toggle source
trace_var(symbol) {|val| block } → nil

Controls tracing of assignments to global variables. The parameter +symbol_ identifies the variable (as either a string name or a symbol identifier). cmd (which may be a string or a Proc object) or block is executed whenever the variable is assigned. The block or Proc object receives the variable's new value as a parameter. Also see Kernel::untrace_var.

trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
$_ = "hello"
$_ = ' there'

produces:

$_ is now 'hello'
$_ is now ' there'
VALUE
rb_f_trace_var(int argc, VALUE *argv)
{
    VALUE var, cmd;
    struct global_entry *entry;
    struct trace_var *trace;

    rb_secure(4);
    if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
    cmd = rb_block_proc();
    }
    if (NIL_P(cmd)) {
    return rb_f_untrace_var(argc, argv);
    }
    entry = rb_global_entry(rb_to_id(var));
    if (OBJ_TAINTED(cmd)) {
    rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
    }
    trace = ALLOC(struct trace_var);
    trace->next = entry->var->trace;
    trace->func = rb_trace_eval;
    trace->data = cmd;
    trace->removed = 0;
    entry->var->trace = trace;

    return Qnil;
}
trap( signal, command ) → obj click to toggle source
trap( signal ) {| | block } → obj

Specifies the handling of signals. The first parameter is a signal name (a string such as “SIGALRM'', “SIGUSR1'', and so on) or a signal number. The characters “SIG'' may be omitted from the signal name. The command or block specifies code to be run when the signal is raised. If the command is the string “IGNORE'' or “SIG_IGN'', the signal will be ignored. If the command is “DEFAULT'' or “SIG_DFL'', the Ruby's default handler will be invoked. If the command is “EXIT'', the script will be terminated by the signal. If the command is “SYSTEM_DEFAULT'', the operating system's default handler will be invoked. Otherwise, the given command or block will be run. The special signal name “EXIT'' or signal number zero will be invoked just prior to program termination. trap returns the previous handler for the given signal.

Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD")  { puts "Child died" }
fork && Process.wait

produces:

Terminating: 27461
Child died
Terminating: 27460
static VALUE
sig_trap(int argc, VALUE *argv)
{
    int sig;
    sighandler_t func;
    VALUE cmd;

    rb_secure(2);
    rb_check_arity(argc, 1, 2);

    sig = trap_signm(argv[0]);
    if (reserved_signal_p(sig)) {
        const char *name = signo2signm(sig);
        if (name)
            rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
        else
            rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
    }

    if (argc == 1) {
        cmd = rb_block_proc();
        func = sighandler;
    }
    else {
        cmd = argv[1];
        func = trap_handler(&cmd, sig);
    }

    if (OBJ_TAINTED(cmd)) {
        rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
    }

    return trap(sig, func, cmd);
}
untrace_var(symbol [, cmd] ) → array or nil click to toggle source

Removes tracing for the specified command on the given global variable and returns nil. If no command is specified, removes all tracing for that variable and returns an array containing the commands actually removed.

VALUE
rb_f_untrace_var(int argc, VALUE *argv)
{
    VALUE var, cmd;
    ID id;
    struct global_entry *entry;
    struct trace_var *trace;
    st_data_t data;

    rb_secure(4);
    rb_scan_args(argc, argv, "11", &var, &cmd);
    id = rb_check_id(&var);
    if (!id) {
    rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
    }
    if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
    rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
    }

    trace = (entry = (struct global_entry *)data)->var->trace;
    if (NIL_P(cmd)) {
    VALUE ary = rb_ary_new();

    while (trace) {
        struct trace_var *next = trace->next;
        rb_ary_push(ary, (VALUE)trace->data);
        trace->removed = 1;
        trace = next;
    }

    if (!entry->var->block_trace) remove_trace(entry->var);
    return ary;
    }
    else {
    while (trace) {
        if (trace->data == cmd) {
        trace->removed = 1;
        if (!entry->var->block_trace) remove_trace(entry->var);
        return rb_ary_new3(1, cmd);
        }
        trace = trace->next;
    }
    }
    return Qnil;
}
warn(msg, ...) → nil click to toggle source

Displays each of the given messages followed by a record separator on STDERR unless warnings have been disabled (for example with the -W0 flag).

  warn("warning 1", "warning 2")

<em>produces:</em>

  warning 1
  warning 2
static VALUE
rb_warn_m(int argc, VALUE *argv, VALUE exc)
{
    if (!NIL_P(ruby_verbose) && argc > 0) {
        rb_io_puts(argc, argv, rb_stderr);
    }
    return Qnil;
}


class KeyError - Ruby 2.0.0-p576 Core API Reference API Reference

class KeyError

Raised when the specified key is not found. It is a subclass of IndexError.

h = {"foo" => :bar}
h.fetch("foo") #=> :bar
h.fetch("baz") #=> KeyError: key not found: "baz"

In Files

  • error.c

Parent

IndexError


class LoadError - Ruby 2.0.0-p576 Core API Reference API Reference

class LoadError

Raised when a file required (a Ruby script, extension library, …) fails to load.

require 'this/file/does/not/exist'

raises the exception:

LoadError: no such file to load -- this/file/does/not/exist

In Files

  • error.c

Parent

ScriptError

Attributes

path[R]


class LocalJumpError - Ruby 2.0.0-p576 Core API Reference API Reference

class LocalJumpError

Raised when Ruby can't yield as requested.

A typical scenario is attempting to yield when no block is given:

def call_block
  yield 42
end
call_block

raises the exception:

LocalJumpError: no block given (yield)

A more subtle example:

def get_me_a_return
  Proc.new { return 42 }
end
get_me_a_return.call

raises the exception:

LocalJumpError: unexpected return

In Files

  • proc.c

Parent

StandardError

Public Instance Methods

exit_value() click to toggle source

call_seq:

local_jump_error.exit_value  -> obj

Returns the exit value associated with this LocalJumpError.

static VALUE
localjump_xvalue(VALUE exc)
{
    return rb_iv_get(exc, "@exit_value");
}
reason → symbol click to toggle source

The reason this block was terminated: :break, :redo, :retry, :next, :return, or :noreason.

static VALUE
localjump_reason(VALUE exc)
{
    return rb_iv_get(exc, "@reason");
}


module Marshal - Ruby 2.0.0-p576 Core API Reference API Reference

module Marshal

The marshaling library converts collections of Ruby objects into a byte stream, allowing them to be stored outside the currently active script. This data may subsequently be read and the original objects reconstituted.

Marshaled data has major and minor version numbers stored along with the object information. In normal use, marshaling can only load data written with the same major version number and an equal or lower minor version number. If Ruby's “verbose'' flag is set (normally using -d, -v, -w, or –verbose) the major and minor numbers must match exactly. Marshal versioning is independent of Ruby's version numbers. You can extract the version by reading the first two bytes of marshaled data.

str = Marshal.dump("thing")
RUBY_VERSION   #=> "1.9.0"
str[0].ord     #=> 4
str[1].ord     #=> 8

Some objects cannot be dumped: if the objects to be dumped include bindings, procedure or method objects, instances of class IO, or singleton objects, a TypeError will be raised.

If your class has special serialization needs (for example, if you want to serialize in some specific format), or if it contains objects that would otherwise not be serializable, you can implement your own serialization strategy.

There are two methods of doing this, your object can define either marshal_dump and marshal_load or _dump and _load. marshal_dump will take precedence over _dump if both are defined. marshal_dump may result in smaller Marshal strings.

Security considerations

By design, ::load can deserialize almost any class loaded into the Ruby process. In many cases this can lead to remote code execution if the Marshal data is loaded from an untrusted source.

As a result, ::load is not suitable as a general purpose serialization format and you should never unmarshal user supplied input or other untrusted data.

If you need to deserialize untrusted data, use JSON or another serialization format that is only able to load simple, 'primitive' types such as String, Array, Hash, etc. Never allow user input to specify arbitrary types to deserialize into.

marshal_dump and marshal_load

When dumping an object the method marshal_dump will be called. marshal_dump must return a result containing the information necessary for marshal_load to reconstitute the object. The result can be any object.

When loading an object dumped using marshal_dump the object is first allocated then marshal_load is called with the result from marshal_dump. marshal_load must recreate the object from the information in the result.

Example:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def marshal_dump
    [@name, @version]
  end

  def marshal_load array
    @name, @version = array
  end
end

_dump and _load

Use _dump and _load when you need to allocate the object you're restoring yourself.

When dumping an object the instance method _dump is called with an Integer which indicates the maximum depth of objects to dump (a value of -1 implies that you should disable depth checking). _dump must return a String containing the information necessary to reconstitute the object.

The class method _load should take a String and use it to return an object of the same class.

Example:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def _dump level
    [@name, @version].join ':'
  end

  def self._load args
    new(*args.split(':'))
  end
end

Since Marhsal.dump outputs a string you can have _dump return a Marshal string which is Marshal.loaded in _load for complex objects.

In Files

  • marshal.c

Constants

MAJOR_VERSION
MINOR_VERSION

Public Class Methods

dump( obj [, anIO] , limit=-1 ) → anIO click to toggle source

Serializes obj and all descendant objects. If anIO is specified, the serialized data will be written to it, otherwise the data will be returned as a String. If limit is specified, the traversal of subobjects will be limited to that depth. If limit is negative, no checking of depth will be performed.

class Klass
  def initialize(str)
    @str = str
  end
  def say_hello
    @str
  end
end

(produces no output)

o = Klass.new("hello\n")
data = Marshal.dump(o)
obj = Marshal.load(data)
obj.say_hello  #=> "hello\n"

Marshal can't dump following objects:

  • anonymous Class/Module.

  • objects which related to its system (ex: Dir, File::Stat, IO, File, Socket and so on)

  • an instance of MatchData, Data, Method, UnboundMethod, Proc, Thread, ThreadGroup, Continuation

  • objects which defines singleton methods

static VALUE
marshal_dump(int argc, VALUE *argv)
{
    VALUE obj, port, a1, a2;
    int limit = -1;
    struct dump_arg *arg;
    volatile VALUE wrapper;

    port = Qnil;
    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
    if (argc == 3) {
        if (!NIL_P(a2)) limit = NUM2INT(a2);
        if (NIL_P(a1)) io_needed();
        port = a1;
    }
    else if (argc == 2) {
        if (FIXNUM_P(a1)) limit = FIX2INT(a1);
        else if (NIL_P(a1)) io_needed();
        else port = a1;
    }
    RB_GC_GUARD(wrapper) = TypedData_Make_Struct(rb_cData, struct dump_arg, &dump_arg_data, arg);
    arg->dest = 0;
    arg->symbols = st_init_numtable();
    arg->data    = st_init_numtable();
    arg->infection = 0;
    arg->compat_tbl = st_init_numtable();
    arg->encodings = 0;
    arg->str = rb_str_buf_new(0);
    if (!NIL_P(port)) {
        if (!rb_respond_to(port, s_write)) {
            io_needed();
        }
        arg->dest = port;
        if (rb_check_funcall(port, s_binmode, 0, 0) != Qundef) {
            check_dump_arg(arg, s_binmode);
        }
    }
    else {
        port = arg->str;
    }

    w_byte(MARSHAL_MAJOR, arg);
    w_byte(MARSHAL_MINOR, arg);

    w_object(obj, arg, limit);
    if (arg->dest) {
        rb_io_write(arg->dest, arg->str);
        rb_str_resize(arg->str, 0);
    }
    clear_dump_arg(arg);
    RB_GC_GUARD(wrapper);

    return port;
}
load( source [, proc] ) → obj click to toggle source
restore( source [, proc] ) → obj

Returns the result of converting the serialized data in source into a Ruby object (possibly with associated subordinate objects). source may be either an instance of IO or an object that responds to to_str. If proc is specified, it will be passed each object as it is deserialized.

Never pass untrusted data (including user supplied input) to this method. Please see the overview for further details.

static VALUE
marshal_load(int argc, VALUE *argv)
{
    VALUE port, proc;
    int major, minor, infection = 0;
    VALUE v;
    volatile VALUE wrapper;
    struct load_arg *arg;

    rb_scan_args(argc, argv, "11", &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
        infection = (int)FL_TEST(port, MARSHAL_INFECTION); /* original taintedness */
        port = v;
    }
    else if (rb_respond_to(port, s_getbyte) && rb_respond_to(port, s_read)) {
        rb_check_funcall(port, s_binmode, 0, 0);
        infection = (int)(FL_TAINT | FL_TEST(port, FL_UNTRUSTED));
    }
    else {
        io_needed();
    }
    RB_GC_GUARD(wrapper) = TypedData_Make_Struct(rb_cData, struct load_arg, &load_arg_data, arg);
    arg->infection = infection;
    arg->src = port;
    arg->offset = 0;
    arg->symbols = st_init_numtable();
    arg->data    = st_init_numtable();
    arg->compat_tbl = st_init_numtable();
    arg->proc = 0;
    arg->readable = 0;

    if (NIL_P(v))
        arg->buf = xmalloc(BUFSIZ);
    else
        arg->buf = 0;

    major = r_byte(arg);
    minor = r_byte(arg);
    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
        clear_load_arg(arg);
        rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
                 MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }
    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
        rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
                MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }

    if (!NIL_P(proc)) arg->proc = proc;
    v = r_object(arg);
    clear_load_arg(arg);
    RB_GC_GUARD(wrapper);

    return v;
}
load( source [, proc] ) → obj click to toggle source
restore( source [, proc] ) → obj

Returns the result of converting the serialized data in source into a Ruby object (possibly with associated subordinate objects). source may be either an instance of IO or an object that responds to to_str. If proc is specified, it will be passed each object as it is deserialized.

Never pass untrusted data (including user supplied input) to this method. Please see the overview for further details.

static VALUE
marshal_load(int argc, VALUE *argv)
{
    VALUE port, proc;
    int major, minor, infection = 0;
    VALUE v;
    volatile VALUE wrapper;
    struct load_arg *arg;

    rb_scan_args(argc, argv, "11", &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
        infection = (int)FL_TEST(port, MARSHAL_INFECTION); /* original taintedness */
        port = v;
    }
    else if (rb_respond_to(port, s_getbyte) && rb_respond_to(port, s_read)) {
        rb_check_funcall(port, s_binmode, 0, 0);
        infection = (int)(FL_TAINT | FL_TEST(port, FL_UNTRUSTED));
    }
    else {
        io_needed();
    }
    RB_GC_GUARD(wrapper) = TypedData_Make_Struct(rb_cData, struct load_arg, &load_arg_data, arg);
    arg->infection = infection;
    arg->src = port;
    arg->offset = 0;
    arg->symbols = st_init_numtable();
    arg->data    = st_init_numtable();
    arg->compat_tbl = st_init_numtable();
    arg->proc = 0;
    arg->readable = 0;

    if (NIL_P(v))
        arg->buf = xmalloc(BUFSIZ);
    else
        arg->buf = 0;

    major = r_byte(arg);
    minor = r_byte(arg);
    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
        clear_load_arg(arg);
        rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
                 MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }
    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
        rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
                MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }

    if (!NIL_P(proc)) arg->proc = proc;
    v = r_object(arg);
    clear_load_arg(arg);
    RB_GC_GUARD(wrapper);

    return v;
}


class MatchData - Ruby 2.0.0-p576 Core API Reference API Reference

class MatchData

MatchData is the type of the special variable $~, and is the type of the object returned by Regexp#match and Regexp.last_match. It encapsulates all the results of a pattern match, results normally accessed through the special variables $&, $', $`, $1, $2, and so on.

In Files

  • re.c

Parent

Object

Public Instance Methods

mtch == mtch2 → true or false click to toggle source

Equality—Two matchdata are equal if their target strings, patterns, and matched positions are identical.

static VALUE
match_equal(VALUE match1, VALUE match2)
{
    const struct re_registers *regs1, *regs2;
    if (match1 == match2) return Qtrue;
    if (!RB_TYPE_P(match2, T_MATCH)) return Qfalse;
    if (!rb_str_equal(RMATCH(match1)->str, RMATCH(match2)->str)) return Qfalse;
    if (!rb_reg_equal(RMATCH(match1)->regexp, RMATCH(match2)->regexp)) return Qfalse;
    regs1 = RMATCH_REGS(match1);
    regs2 = RMATCH_REGS(match2);
    if (regs1->num_regs != regs2->num_regs) return Qfalse;
    if (memcmp(regs1->beg, regs2->beg, regs1->num_regs * sizeof(*regs1->beg))) return Qfalse;
    if (memcmp(regs1->end, regs2->end, regs1->num_regs * sizeof(*regs1->end))) return Qfalse;
    return Qtrue;
}
mtch[i] → str or nil click to toggle source
mtch[start, length] → array
mtch[range] → array
mtch[name] → str or nil

Match Reference – MatchData acts as an array, and may be accessed using the normal array indexing techniques. mtch[0] is equivalent to the special variable $&, and returns the entire matched string. mtch[1], mtch[2], and so on return the values of the matched backreferences (portions of the pattern between parentheses).

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m          #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
m[0]       #=> "HX1138"
m[1, 2]    #=> ["H", "X"]
m[1..3]    #=> ["H", "X", "113"]
m[-3, 2]   #=> ["X", "113"]

m = /(?<foo>a+)b/.match("ccaaab")
m          #=> #<MatchData "aaab" foo:"aaa">
m["foo"]   #=> "aaa"
m[:foo]    #=> "aaa"

static VALUE
match_aref(int argc, VALUE *argv, VALUE match)
{
    VALUE idx, rest;

    match_check(match);
    rb_scan_args(argc, argv, "11", &idx, &rest);

    if (NIL_P(rest)) {
        if (FIXNUM_P(idx)) {
            if (FIX2INT(idx) >= 0) {
                return rb_reg_nth_match(FIX2INT(idx), match);
            }
        }
        else {
            const char *p;
            int num;

            switch (TYPE(idx)) {
              case T_SYMBOL:
                idx = rb_id2str(SYM2ID(idx));
                /* fall through */
              case T_STRING:
                p = StringValuePtr(idx);
                if (!rb_enc_compatible(RREGEXP(RMATCH(match)->regexp)->src, idx) ||
                    (num = name_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp,
                                                  p, p + RSTRING_LEN(idx))) < 1) {
                    name_to_backref_error(idx);
                }
                return rb_reg_nth_match(num, match);

              default:
                break;
            }
        }
    }

    return rb_ary_aref(argc, argv, match_to_a(match));
}
begin(n) → integer click to toggle source

Returns the offset of the start of the nth element of the match array in the string. n can be a string or symbol to reference a named capture.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.begin(0)       #=> 1
m.begin(2)       #=> 2

m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.begin(:foo)  #=> 0
p m.begin(:bar)  #=> 2

static VALUE
match_begin(VALUE match, VALUE n)
{
    int i = match_backref_number(match, n);
    struct re_registers *regs = RMATCH_REGS(match);

    match_check(match);
    if (i < 0 || regs->num_regs <= i)
        rb_raise(rb_eIndexError, "index %d out of matches", i);

    if (BEG(i) < 0)
        return Qnil;

    update_char_offset(match);
    return INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg);
}
captures → array click to toggle source

Returns the array of captures; equivalent to mtch.to_a[1..-1].

f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
f1    #=> "H"
f2    #=> "X"
f3    #=> "113"
f4    #=> "8"

static VALUE
match_captures(VALUE match)
{
    return match_array(match, 1);
}
end(n) → integer click to toggle source

Returns the offset of the character immediately following the end of the nth element of the match array in the string. n can be a string or symbol to reference a named capture.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.end(0)         #=> 7
m.end(2)         #=> 3

m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.end(:foo)    #=> 1
p m.end(:bar)    #=> 3

static VALUE
match_end(VALUE match, VALUE n)
{
    int i = match_backref_number(match, n);
    struct re_registers *regs = RMATCH_REGS(match);

    match_check(match);
    if (i < 0 || regs->num_regs <= i)
        rb_raise(rb_eIndexError, "index %d out of matches", i);

    if (BEG(i) < 0)
        return Qnil;

    update_char_offset(match);
    return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end);
}
mtch == mtch2 → true or false click to toggle source

Equality—Two matchdata are equal if their target strings, patterns, and matched positions are identical.

static VALUE
match_equal(VALUE match1, VALUE match2)
{
    const struct re_registers *regs1, *regs2;
    if (match1 == match2) return Qtrue;
    if (!RB_TYPE_P(match2, T_MATCH)) return Qfalse;
    if (!rb_str_equal(RMATCH(match1)->str, RMATCH(match2)->str)) return Qfalse;
    if (!rb_reg_equal(RMATCH(match1)->regexp, RMATCH(match2)->regexp)) return Qfalse;
    regs1 = RMATCH_REGS(match1);
    regs2 = RMATCH_REGS(match2);
    if (regs1->num_regs != regs2->num_regs) return Qfalse;
    if (memcmp(regs1->beg, regs2->beg, regs1->num_regs * sizeof(*regs1->beg))) return Qfalse;
    if (memcmp(regs1->end, regs2->end, regs1->num_regs * sizeof(*regs1->end))) return Qfalse;
    return Qtrue;
}
hash → integer click to toggle source

Produce a hash based on the target string, regexp and matched positions of this matchdata.

static VALUE
match_hash(VALUE match)
{
    const struct re_registers *regs;
    st_index_t hashval = rb_hash_start(rb_str_hash(RMATCH(match)->str));

    rb_hash_uint(hashval, reg_hash(RMATCH(match)->regexp));
    regs = RMATCH_REGS(match);
    hashval = rb_hash_uint(hashval, regs->num_regs);
    hashval = rb_hash_uint(hashval, rb_memhash(regs->beg, regs->num_regs * sizeof(*regs->beg)));
    hashval = rb_hash_uint(hashval, rb_memhash(regs->end, regs->num_regs * sizeof(*regs->end)));
    hashval = rb_hash_end(hashval);
    return LONG2FIX(hashval);
}
inspect → str click to toggle source

Returns a printable version of mtch.

puts /.$/.match("foo").inspect
#=> #<MatchData "o">

puts /(.)(.)(.)/.match("foo").inspect
#=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">

puts /(.)(.)?(.)/.match("fo").inspect
#=> #<MatchData "fo" 1:"f" 2:nil 3:"o">

puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
#=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">

static VALUE
match_inspect(VALUE match)
{
    const char *cname = rb_obj_classname(match);
    VALUE str;
    int i;
    struct re_registers *regs = RMATCH_REGS(match);
    int num_regs = regs->num_regs;
    struct backref_name_tag *names;
    VALUE regexp = RMATCH(match)->regexp;

    if (regexp == 0) {
        return rb_sprintf("#<%s:%p>", cname, (void*)match);
    }

    names = ALLOCA_N(struct backref_name_tag, num_regs);
    MEMZERO(names, struct backref_name_tag, num_regs);

    onig_foreach_name(RREGEXP(regexp)->ptr,
            match_inspect_name_iter, names);

    str = rb_str_buf_new2("#<");
    rb_str_buf_cat2(str, cname);

    for (i = 0; i < num_regs; i++) {
        VALUE v;
        rb_str_buf_cat2(str, " ");
        if (0 < i) {
            if (names[i].name)
                rb_str_buf_cat(str, (const char *)names[i].name, names[i].len);
            else {
                rb_str_catf(str, "%d", i);
            }
            rb_str_buf_cat2(str, ":");
        }
        v = rb_reg_nth_match(i, match);
        if (v == Qnil)
            rb_str_buf_cat2(str, "nil");
        else
            rb_str_buf_append(str, rb_str_inspect(v));
    }
    rb_str_buf_cat2(str, ">");

    return str;
}
length → integer click to toggle source
size → integer

Returns the number of elements in the match array.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length   #=> 5
m.size     #=> 5

static VALUE
match_size(VALUE match)
{
    match_check(match);
    return INT2FIX(RMATCH_REGS(match)->num_regs);
}
names → [name1, name2, ...] click to toggle source

Returns a list of names of captures as an array of strings. It is same as mtch.regexp.names.

/(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
#=> ["foo", "bar", "baz"]

m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
m.names                          #=> ["x", "y"]

static VALUE
match_names(VALUE match)
{
    match_check(match);
    return rb_reg_names(RMATCH(match)->regexp);
}
offset(n) → array click to toggle source

Returns a two-element array containing the beginning and ending offsets of the nth match. n can be a string or symbol to reference a named capture.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.offset(0)      #=> [1, 7]
m.offset(4)      #=> [6, 7]

m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.offset(:foo) #=> [0, 1]
p m.offset(:bar) #=> [2, 3]

static VALUE
match_offset(VALUE match, VALUE n)
{
    int i = match_backref_number(match, n);
    struct re_registers *regs = RMATCH_REGS(match);

    match_check(match);
    if (i < 0 || regs->num_regs <= i)
        rb_raise(rb_eIndexError, "index %d out of matches", i);

    if (BEG(i) < 0)
        return rb_assoc_new(Qnil, Qnil);

    update_char_offset(match);
    return rb_assoc_new(INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg),
                        INT2FIX(RMATCH(match)->rmatch->char_offset[i].end));
}
post_match → str click to toggle source

Returns the portion of the original string after the current match. Equivalent to the special variable $'.

m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.post_match   #=> ": The Movie"

VALUE
rb_reg_match_post(VALUE match)
{
    VALUE str;
    long pos;
    struct re_registers *regs;

    if (NIL_P(match)) return Qnil;
    match_check(match);
    regs = RMATCH_REGS(match);
    if (BEG(0) == -1) return Qnil;
    str = RMATCH(match)->str;
    pos = END(0);
    str = rb_str_subseq(str, pos, RSTRING_LEN(str) - pos);
    if (OBJ_TAINTED(match)) OBJ_TAINT(str);
    return str;
}
pre_match → str click to toggle source

Returns the portion of the original string before the current match. Equivalent to the special variable $`.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.pre_match   #=> "T"

VALUE
rb_reg_match_pre(VALUE match)
{
    VALUE str;
    struct re_registers *regs;

    if (NIL_P(match)) return Qnil;
    match_check(match);
    regs = RMATCH_REGS(match);
    if (BEG(0) == -1) return Qnil;
    str = rb_str_subseq(RMATCH(match)->str, 0, BEG(0));
    if (OBJ_TAINTED(match)) OBJ_TAINT(str);
    return str;
}
regexp → regexp click to toggle source

Returns the regexp.

m = /a.*b/.match("abc")
m.regexp #=> /a.*b/

static VALUE
match_regexp(VALUE match)
{
    match_check(match);
    return RMATCH(match)->regexp;
}
length → integer click to toggle source
size → integer

Returns the number of elements in the match array.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length   #=> 5
m.size     #=> 5

static VALUE
match_size(VALUE match)
{
    match_check(match);
    return INT2FIX(RMATCH_REGS(match)->num_regs);
}
string → str click to toggle source

Returns a frozen copy of the string passed in to match.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.string   #=> "THX1138."

static VALUE
match_string(VALUE match)
{
    match_check(match);
    return RMATCH(match)->str;  /* str is frozen */
}
to_a → anArray click to toggle source

Returns the array of matches.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.to_a   #=> ["HX1138", "H", "X", "113", "8"]

Because to_a is called when expanding *variable, there's a useful assignment shortcut for extracting matched fields. This is slightly slower than accessing the fields directly (as an intermediate array is generated).

all,f1,f2,f3 = *(/(.)(.)(\d+)(\d)/.match("THX1138."))
all   #=> "HX1138"
f1    #=> "H"
f2    #=> "X"
f3    #=> "113"

static VALUE
match_to_a(VALUE match)
{
    return match_array(match, 0);
}
to_s → str click to toggle source

Returns the entire matched string.

m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.to_s   #=> "HX1138"

static VALUE
match_to_s(VALUE match)
{
    VALUE str = rb_reg_last_match(match);

    match_check(match);
    if (NIL_P(str)) str = rb_str_new(0,0);
    if (OBJ_TAINTED(match)) OBJ_TAINT(str);
    if (OBJ_TAINTED(RMATCH(match)->str)) OBJ_TAINT(str);
    return str;
}
values_at([index]*) → array click to toggle source

Uses each index to access the matching values, returning an array of the corresponding matches.

m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.to_a               #=> ["HX1138", "H", "X", "113", "8"]
m.values_at(0, 2, -2)   #=> ["HX1138", "X", "113"]

static VALUE
match_values_at(int argc, VALUE *argv, VALUE match)
{
    struct re_registers *regs;

    match_check(match);
    regs = RMATCH_REGS(match);
    return rb_get_values_at(match, regs->num_regs, argc, argv, match_entry);
}


module Math - Ruby 2.0.0-p576 Core API Reference API Reference

module Math

The Math module contains module functions for basic trigonometric and transcendental functions. See class Float for a list of constants that define Ruby's floating point accuracy.

In Files

  • math.c

Constants

E
PI

Public Class Methods

acos(x) → float click to toggle source

Computes the arc cosine of x. Returns 0..PI.

static VALUE
math_acos(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < -1.0 || 1.0 < d0) domain_error("acos");
    d = acos(d0);
    return DBL2NUM(d);
}
acosh(x) → float click to toggle source

Computes the inverse hyperbolic cosine of x.

static VALUE
math_acosh(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < 1.0) domain_error("acosh");
    d = acosh(d0);
    return DBL2NUM(d);
}
asin(x) → float click to toggle source

Computes the arc sine of x. Returns -{PI/2} .. {PI/2}.

static VALUE
math_asin(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < -1.0 || 1.0 < d0) domain_error("asin");
    d = asin(d0);
    return DBL2NUM(d);
}
asinh(x) → float click to toggle source

Computes the inverse hyperbolic sine of x.

static VALUE
math_asinh(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(asinh(RFLOAT_VALUE(x)));
}
atan(x) → float click to toggle source

Computes the arc tangent of x. Returns -{PI/2} .. {PI/2}.

static VALUE
math_atan(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(atan(RFLOAT_VALUE(x)));
}
atan2(y, x) → float click to toggle source

Computes the arc tangent given y and x. Returns -PI..PI.

Math.atan2(-0.0, -1.0) #=> -3.141592653589793
Math.atan2(-1.0, -1.0) #=> -2.356194490192345
Math.atan2(-1.0, 0.0)  #=> -1.5707963267948966
Math.atan2(-1.0, 1.0)  #=> -0.7853981633974483
Math.atan2(-0.0, 1.0)  #=> -0.0
Math.atan2(0.0, 1.0)   #=> 0.0
Math.atan2(1.0, 1.0)   #=> 0.7853981633974483
Math.atan2(1.0, 0.0)   #=> 1.5707963267948966
Math.atan2(1.0, -1.0)  #=> 2.356194490192345
Math.atan2(0.0, -1.0)  #=> 3.141592653589793

static VALUE
math_atan2(VALUE obj, VALUE y, VALUE x)
{
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
    double dx, dy;
    Need_Float2(y, x);
    dx = RFLOAT_VALUE(x);
    dy = RFLOAT_VALUE(y);
    if (dx == 0.0 && dy == 0.0) {
        if (!signbit(dx))
            return DBL2NUM(dy);
        if (!signbit(dy))
            return DBL2NUM(M_PI);
        return DBL2NUM(-M_PI);
    }
    if (isinf(dx) && isinf(dy)) domain_error("atan2");
    return DBL2NUM(atan2(dy, dx));
}
atanh(x) → float click to toggle source

Computes the inverse hyperbolic tangent of x.

static VALUE
math_atanh(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 <  -1.0 || +1.0 <  d0) domain_error("atanh");
    /* check for pole error */
    if (d0 == -1.0) return DBL2NUM(-INFINITY);
    if (d0 == +1.0) return DBL2NUM(+INFINITY);
    d = atanh(d0);
    return DBL2NUM(d);
}
cbrt(numeric) → float click to toggle source

Returns the cube root of numeric.

-9.upto(9) {|x|
  p [x, Math.cbrt(x), Math.cbrt(x)**3]
}
#=>
[-9, -2.0800838230519, -9.0]
[-8, -2.0, -8.0]
[-7, -1.91293118277239, -7.0]
[-6, -1.81712059283214, -6.0]
[-5, -1.7099759466767, -5.0]
[-4, -1.5874010519682, -4.0]
[-3, -1.44224957030741, -3.0]
[-2, -1.25992104989487, -2.0]
[-1, -1.0, -1.0]
[0, 0.0, 0.0]
[1, 1.0, 1.0]
[2, 1.25992104989487, 2.0]
[3, 1.44224957030741, 3.0]
[4, 1.5874010519682, 4.0]
[5, 1.7099759466767, 5.0]
[6, 1.81712059283214, 6.0]
[7, 1.91293118277239, 7.0]
[8, 2.0, 8.0]
[9, 2.0800838230519, 9.0]

static VALUE
math_cbrt(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(cbrt(RFLOAT_VALUE(x)));
}
cos(x) → float click to toggle source

Computes the cosine of x (expressed in radians). Returns -1..1.

static VALUE
math_cos(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(cos(RFLOAT_VALUE(x)));
}
cosh(x) → float click to toggle source

Computes the hyperbolic cosine of x (expressed in radians).

static VALUE
math_cosh(VALUE obj, VALUE x)
{
    Need_Float(x);

    return DBL2NUM(cosh(RFLOAT_VALUE(x)));
}
erf(x) → float click to toggle source

Calculates the error function of x.

static VALUE
math_erf(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(erf(RFLOAT_VALUE(x)));
}
erfc(x) → float click to toggle source

Calculates the complementary error function of x.

static VALUE
math_erfc(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(erfc(RFLOAT_VALUE(x)));
}
exp(x) → float click to toggle source

Returns e**x.

Math.exp(0)       #=> 1.0
Math.exp(1)       #=> 2.718281828459045
Math.exp(1.5)     #=> 4.4816890703380645

static VALUE
math_exp(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(exp(RFLOAT_VALUE(x)));
}
frexp(numeric) → [ fraction, exponent ] click to toggle source

Returns a two-element array containing the normalized fraction (a Float) and exponent (a Fixnum) of numeric.

fraction, exponent = Math.frexp(1234)   #=> [0.6025390625, 11]
fraction * 2**exponent                  #=> 1234.0

static VALUE
math_frexp(VALUE obj, VALUE x)
{
    double d;
    int exp;

    Need_Float(x);

    d = frexp(RFLOAT_VALUE(x), &exp);
    return rb_assoc_new(DBL2NUM(d), INT2NUM(exp));
}
gamma(x) → float click to toggle source

Calculates the gamma function of x.

Note that gamma(n) is same as fact(n-1) for integer n > 0. However gamma(n) returns float and can be an approximation.

def fact(n) (1..n).inject(1) {|r,i| r*i } end
1.upto(26) {|i| p [i, Math.gamma(i), fact(i-1)] }
#=> [1, 1.0, 1]
#   [2, 1.0, 1]
#   [3, 2.0, 2]
#   [4, 6.0, 6]
#   [5, 24.0, 24]
#   [6, 120.0, 120]
#   [7, 720.0, 720]
#   [8, 5040.0, 5040]
#   [9, 40320.0, 40320]
#   [10, 362880.0, 362880]
#   [11, 3628800.0, 3628800]
#   [12, 39916800.0, 39916800]
#   [13, 479001600.0, 479001600]
#   [14, 6227020800.0, 6227020800]
#   [15, 87178291200.0, 87178291200]
#   [16, 1307674368000.0, 1307674368000]
#   [17, 20922789888000.0, 20922789888000]
#   [18, 355687428096000.0, 355687428096000]
#   [19, 6.402373705728e+15, 6402373705728000]
#   [20, 1.21645100408832e+17, 121645100408832000]
#   [21, 2.43290200817664e+18, 2432902008176640000]
#   [22, 5.109094217170944e+19, 51090942171709440000]
#   [23, 1.1240007277776077e+21, 1124000727777607680000]
#   [24, 2.5852016738885062e+22, 25852016738884976640000]
#   [25, 6.204484017332391e+23, 620448401733239439360000]
#   [26, 1.5511210043330954e+25, 15511210043330985984000000]

static VALUE
math_gamma(VALUE obj, VALUE x)
{
    static const double fact_table[] = {
        /* fact(0) */ 1.0,
        /* fact(1) */ 1.0,
        /* fact(2) */ 2.0,
        /* fact(3) */ 6.0,
        /* fact(4) */ 24.0,
        /* fact(5) */ 120.0,
        /* fact(6) */ 720.0,
        /* fact(7) */ 5040.0,
        /* fact(8) */ 40320.0,
        /* fact(9) */ 362880.0,
        /* fact(10) */ 3628800.0,
        /* fact(11) */ 39916800.0,
        /* fact(12) */ 479001600.0,
        /* fact(13) */ 6227020800.0,
        /* fact(14) */ 87178291200.0,
        /* fact(15) */ 1307674368000.0,
        /* fact(16) */ 20922789888000.0,
        /* fact(17) */ 355687428096000.0,
        /* fact(18) */ 6402373705728000.0,
        /* fact(19) */ 121645100408832000.0,
        /* fact(20) */ 2432902008176640000.0,
        /* fact(21) */ 51090942171709440000.0,
        /* fact(22) */ 1124000727777607680000.0,
        /* fact(23)=25852016738884976640000 needs 56bit mantissa which is
         * impossible to represent exactly in IEEE 754 double which have
         * 53bit mantissa. */
    };
    double d0, d;
    double intpart, fracpart;
    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (isinf(d0) && signbit(d0)) domain_error("gamma");
    fracpart = modf(d0, &intpart);
    if (fracpart == 0.0) {
        if (intpart < 0) domain_error("gamma");
        if (0 < intpart &&
            intpart - 1 < (double)numberof(fact_table)) {
            return DBL2NUM(fact_table[(int)intpart - 1]);
        }
    }
    d = tgamma(d0);
    return DBL2NUM(d);
}
hypot(x, y) → float click to toggle source

Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle with sides x and y.

Math.hypot(3, 4)   #=> 5.0

static VALUE
math_hypot(VALUE obj, VALUE x, VALUE y)
{
    Need_Float2(x, y);
    return DBL2NUM(hypot(RFLOAT_VALUE(x), RFLOAT_VALUE(y)));
}
ldexp(flt, int) → float click to toggle source

Returns the value of flt*(2**int).

fraction, exponent = Math.frexp(1234)
Math.ldexp(fraction, exponent)   #=> 1234.0

static VALUE
math_ldexp(VALUE obj, VALUE x, VALUE n)
{
    Need_Float(x);
    return DBL2NUM(ldexp(RFLOAT_VALUE(x), NUM2INT(n)));
}
lgamma(x) → [float, -1 or 1] click to toggle source

Calculates the logarithmic gamma of x and the sign of gamma of x.

::lgamma is same as

[Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]

but avoid overflow by ::gamma for large x.

static VALUE
math_lgamma(VALUE obj, VALUE x)
{
    double d0, d;
    int sign=1;
    VALUE v;
    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (isinf(d0)) {
        if (signbit(d0)) domain_error("lgamma");
        return rb_assoc_new(DBL2NUM(INFINITY), INT2FIX(1));
    }
    d = lgamma_r(d0, &sign);
    v = DBL2NUM(d);
    return rb_assoc_new(v, INT2FIX(sign));
}
log(numeric) → float click to toggle source
log(num,base) → float

Returns the natural logarithm of numeric. If additional second argument is given, it will be the base of logarithm.

Math.log(1)          #=> 0.0
Math.log(Math::E)    #=> 1.0
Math.log(Math::E**3) #=> 3.0
Math.log(12,3)       #=> 2.2618595071429146

static VALUE
math_log(int argc, VALUE *argv)
{
    VALUE x, base;
    double d0, d;

    rb_scan_args(argc, argv, "11", &x, &base);
    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < 0.0) domain_error("log");
    /* check for pole error */
    if (d0 == 0.0) return DBL2NUM(-INFINITY);
    d = log(d0);
    if (argc == 2) {
        Need_Float(base);
        d /= log(RFLOAT_VALUE(base));
    }
    return DBL2NUM(d);
}
log10(numeric) → float click to toggle source

Returns the base 10 logarithm of numeric.

Math.log10(1)       #=> 0.0
Math.log10(10)      #=> 1.0
Math.log10(10**100) #=> 100.0

static VALUE
math_log10(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < 0.0) domain_error("log10");
    /* check for pole error */
    if (d0 == 0.0) return DBL2NUM(-INFINITY);
    d = log10(d0);
    return DBL2NUM(d);
}
log2(numeric) → float click to toggle source

Returns the base 2 logarithm of numeric.

Math.log2(1)      #=> 0.0
Math.log2(2)      #=> 1.0
Math.log2(32768)  #=> 15.0
Math.log2(65536)  #=> 16.0

static VALUE
math_log2(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < 0.0) domain_error("log2");
    /* check for pole error */
    if (d0 == 0.0) return DBL2NUM(-INFINITY);
    d = log2(d0);
    return DBL2NUM(d);
}
sin(x) → float click to toggle source

Computes the sine of x (expressed in radians). Returns -1..1.

static VALUE
math_sin(VALUE obj, VALUE x)
{
    Need_Float(x);

    return DBL2NUM(sin(RFLOAT_VALUE(x)));
}
sinh(x) → float click to toggle source

Computes the hyperbolic sine of x (expressed in radians).

static VALUE
math_sinh(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(sinh(RFLOAT_VALUE(x)));
}
sqrt(numeric) → float click to toggle source

Returns the non-negative square root of numeric.

0.upto(10) {|x|
  p [x, Math.sqrt(x), Math.sqrt(x)**2]
}
#=>
[0, 0.0, 0.0]
[1, 1.0, 1.0]
[2, 1.4142135623731, 2.0]
[3, 1.73205080756888, 3.0]
[4, 2.0, 4.0]
[5, 2.23606797749979, 5.0]
[6, 2.44948974278318, 6.0]
[7, 2.64575131106459, 7.0]
[8, 2.82842712474619, 8.0]
[9, 3.0, 9.0]
[10, 3.16227766016838, 10.0]

static VALUE
math_sqrt(VALUE obj, VALUE x)
{
    double d0, d;

    Need_Float(x);
    d0 = RFLOAT_VALUE(x);
    /* check for domain error */
    if (d0 < 0.0) domain_error("sqrt");
    if (d0 == 0.0) return DBL2NUM(0.0);
    d = sqrt(d0);
    return DBL2NUM(d);
}
tan(x) → float click to toggle source

Returns the tangent of x (expressed in radians).

static VALUE
math_tan(VALUE obj, VALUE x)
{
    Need_Float(x);

    return DBL2NUM(tan(RFLOAT_VALUE(x)));
}
tanh() → float click to toggle source

Computes the hyperbolic tangent of x (expressed in radians).

static VALUE
math_tanh(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(tanh(RFLOAT_VALUE(x)));
}


class Math::DomainError - Ruby 2.0.0-p576 Core API Reference API Reference

class Math::DomainError

Raised when a mathematical function is evaluated outside of its domain of definition.

For example, since cos returns values in the range -1..1, its inverse function acos is only defined on that interval:

Math.acos(42)

produces:

Math::DomainError: Numerical argument is out of domain - "acos"

In Files

  • math.c

Parent

StandardError


class Method - Ruby 2.0.0-p576 Core API Reference API Reference

class Method

Proc

In Files

  • proc.c

Parent

Object

Public Instance Methods

meth == other_meth → true or false click to toggle source

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
        return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
        return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
        m1->rclass != m2->rclass ||
        m1->recv != m2->recv) {
        return Qfalse;
    }

    return Qtrue;
}
call(args, ...) → obj click to toggle source
meth[args, ...] → obj

Invokes the meth with the specified arguments, returning the method's return value.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32

VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE proc = rb_block_given_p() ? rb_block_proc() : Qnil;
    return rb_method_call_with_block(argc, argv, method, proc);
}
arity → fixnum click to toggle source

Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. For methods written in C, returns -1 if the call takes a variable number of arguments.

class C
  def one;    end
  def two(a); end
  def three(*a);  end
  def four(a, b); end
  def five(a, b, *c);    end
  def six(a, b, *c, &d); end
end
c = C.new
c.method(:one).arity     #=> 0
c.method(:two).arity     #=> 1
c.method(:three).arity   #=> -1
c.method(:four).arity    #=> 2
c.method(:five).arity    #=> -3
c.method(:six).arity     #=> -3

"cat".method(:size).arity      #=> 0
"cat".method(:replace).arity   #=> 1
"cat".method(:squeeze).arity   #=> -1
"cat".method(:count).arity     #=> -1

static VALUE
method_arity_m(VALUE method)
{
    int n = method_arity(method);
    return INT2FIX(n);
}
call(args, ...) → obj click to toggle source
meth[args, ...] → obj

Invokes the meth with the specified arguments, returning the method's return value.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32

VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE proc = rb_block_given_p() ? rb_block_proc() : Qnil;
    return rb_method_call_with_block(argc, argv, method, proc);
}
clone → new_method click to toggle source

Returns a clone of this method.

class A
  def foo
    return "bar"
  end
end

m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"

static VALUE
method_clone(VALUE self)
{
    VALUE clone;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(self, struct METHOD, &method_data_type, orig);
    clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
    CLONESETUP(clone, self);
    *data = *orig;
    data->me = ALLOC(rb_method_entry_t);
    *data->me = *orig->me;
    if (data->me->def) data->me->def->alias_count++;
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);

    return clone;
}
meth == other_meth → true or false click to toggle source

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
        return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
        return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
        m1->rclass != m2->rclass ||
        m1->recv != m2->recv) {
        return Qfalse;
    }

    return Qtrue;
}
hash → integer click to toggle source

Returns a hash value corresponding to the method object.

static VALUE
method_hash(VALUE method)
{
    struct METHOD *m;
    st_index_t hash;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
    hash = rb_hash_start((st_index_t)m->rclass);
    hash = rb_hash_uint(hash, (st_index_t)m->recv);
    hash = rb_hash_method_entry(hash, m->me);
    hash = rb_hash_end(hash);

    return INT2FIX(hash);
}
to_s → string click to toggle source
inspect → string

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
        VALUE v = rb_ivar_get(data->me->klass, attached);

        if (data->recv == Qundef) {
            rb_str_buf_append(str, rb_inspect(data->me->klass));
        }
        else if (data->recv == v) {
            rb_str_buf_append(str, rb_inspect(v));
            sharp = ".";
        }
        else {
            rb_str_buf_append(str, rb_inspect(data->recv));
            rb_str_buf_cat2(str, "(");
            rb_str_buf_append(str, rb_inspect(v));
            rb_str_buf_cat2(str, ")");
            sharp = ".";
        }
    }
    else {
        rb_str_buf_cat2(str, rb_class2name(data->rclass));
        if (data->rclass != data->me->klass) {
            rb_str_buf_cat2(str, "(");
            rb_str_buf_cat2(str, rb_class2name(data->me->klass));
            rb_str_buf_cat2(str, ")");
        }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}
name → symbol click to toggle source

Returns the name of the method.

static VALUE
method_name(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return ID2SYM(data->id);
}
owner → class_or_module click to toggle source

Returns the class or module that defines the method.

static VALUE
method_owner(VALUE obj)
{
    struct METHOD *data;
    VALUE defined_class;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    defined_class = data->defined_class;

    if (RB_TYPE_P(defined_class, T_ICLASS)) {
        defined_class = RBASIC(defined_class)->klass;
    }

    return defined_class;
}
parameters → array click to toggle source

Returns the parameter information of this method.

static VALUE
rb_method_parameters(VALUE method)
{
    rb_iseq_t *iseq = rb_method_get_iseq(method);
    if (!iseq) {
        return unnamed_parameters(method_arity(method));
    }
    return rb_iseq_parameters(iseq, 0);
}
receiver → object click to toggle source

Returns the bound receiver of the method object.

static VALUE
method_receiver(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return data->recv;
}
source_location → [String, Fixnum] click to toggle source

Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)

VALUE
rb_method_location(VALUE method)
{
    rb_method_definition_t *def = method_get_def(method);
    return method_def_location(def);
}
to_proc → prc click to toggle source

Returns a Proc object corresponding to this method.

static VALUE
method_proc(VALUE method)
{
    VALUE procval;
    rb_proc_t *proc;
    /*
     * class Method
     *   def to_proc
     *     proc{|*args|
     *       self.call(*args)
     *     }
     *   end
     * end
     */
    procval = rb_iterate(mlambda, 0, bmcall, method);
    GetProcPtr(procval, proc);
    proc->is_from_method = 1;
    return procval;
}
to_s → string click to toggle source
inspect → string

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
        VALUE v = rb_ivar_get(data->me->klass, attached);

        if (data->recv == Qundef) {
            rb_str_buf_append(str, rb_inspect(data->me->klass));
        }
        else if (data->recv == v) {
            rb_str_buf_append(str, rb_inspect(v));
            sharp = ".";
        }
        else {
            rb_str_buf_append(str, rb_inspect(data->recv));
            rb_str_buf_cat2(str, "(");
            rb_str_buf_append(str, rb_inspect(v));
            rb_str_buf_cat2(str, ")");
            sharp = ".";
        }
    }
    else {
        rb_str_buf_cat2(str, rb_class2name(data->rclass));
        if (data->rclass != data->me->klass) {
            rb_str_buf_cat2(str, "(");
            rb_str_buf_cat2(str, rb_class2name(data->me->klass));
            rb_str_buf_cat2(str, ")");
        }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}
unbind → unbound_method click to toggle source

Dissociates meth from its current receiver. The resulting UnboundMethod can subsequently be bound to a new object of the same class (see UnboundMethod).

static VALUE
method_unbind(VALUE obj)
{
    VALUE method;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, orig);
    method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
                                   &method_data_type, data);
    data->recv = Qundef;
    data->id = orig->id;
    data->me = ALLOC(rb_method_entry_t);
    *data->me = *orig->me;
    if (orig->me->def) orig->me->def->alias_count++;
    data->rclass = orig->rclass;
    data->defined_class = orig->defined_class;
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);
    OBJ_INFECT(method, obj);

    return method;
}


class Module - Ruby 2.0.0-p576 Core API Reference API Reference

class Module

A Module is a collection of methods and constants. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not. Conversely, module methods may be called without creating an encapsulating object, while instance methods may not. (See Module#module_function)

In the descriptions that follow, the parameter sym refers to a symbol, which is either a quoted string or a Symbol (such as :name).

module Mod
  include Math
  CONST = 1
  def meth
    #  ...
  end
end
Mod.class              #=> Module
Mod.constants          #=> [:CONST, :PI, :E]
Mod.instance_methods   #=> [:meth]

In Files

  • class.c
  • eval.c
  • load.c
  • object.c
  • proc.c
  • vm_eval.c
  • vm_method.c

Parent

Object

Public Class Methods

constants → array click to toggle source
constants(inherited) → array

In the first form, returns an array of the names of all constants accessible from the point of call. This list includes the names of all modules and classes defined in the global scope.

Module.constants.first(4)
   # => [:ARGF, :ARGV, :ArgumentError, :Array]

Module.constants.include?(:SEEK_SET)   # => false

class IO
  Module.constants.include?(:SEEK_SET) # => true
end

The second form calls the instance method constants.

static VALUE
rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
{
    const NODE *cref = rb_vm_cref();
    VALUE klass;
    VALUE cbase = 0;
    void *data = 0;

    if (argc > 0 || mod != rb_cModule) {
        return rb_mod_constants(argc, argv, mod);
    }

    while (cref) {
        klass = cref->nd_clss;
        if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
            !NIL_P(klass)) {
            data = rb_mod_const_at(cref->nd_clss, data);
            if (!cbase) {
                cbase = klass;
            }
        }
        cref = cref->nd_next;
    }

    if (cbase) {
        data = rb_mod_const_of(cbase, data);
    }
    return rb_const_list(data);
}
nesting → array click to toggle source

Returns the list of Modules nested at the point of call.

module M1
  module M2
    $a = Module.nesting
  end
end
$a           #=> [M1::M2, M1]
$a[0].name   #=> "M1::M2"

static VALUE
rb_mod_nesting(void)
{
    VALUE ary = rb_ary_new();
    const NODE *cref = rb_vm_cref();

    while (cref && cref->nd_next) {
        VALUE klass = cref->nd_clss;
        if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
            !NIL_P(klass)) {
            rb_ary_push(ary, klass);
        }
        cref = cref->nd_next;
    }
    return ary;
}
new → mod click to toggle source
new {|mod| block } → mod

Creates a new anonymous module. If a block is given, it is passed the module object, and the block is evaluated in the context of this module using module_eval.

fred = Module.new do
  def meth1
    "hello"
  end
  def meth2
    "bye"
  end
end
a = "my string"
a.extend(fred)   #=> "my string"
a.meth1          #=> "hello"
a.meth2          #=> "bye"

Assign the module to a constant (name starting uppercase) if you want to treat it like a regular module.

static VALUE
rb_mod_initialize(VALUE module)
{
    if (rb_block_given_p()) {
        rb_mod_module_exec(1, &module, module);
    }
    return Qnil;
}

Public Instance Methods

mod < other → true, false, or nil click to toggle source

Returns true if mod is a subclass of other. Returns nil if there's no relationship between the two. (Think of the relationship in terms of the class definition: “class A<B” implies “A<B”).

static VALUE
rb_mod_lt(VALUE mod, VALUE arg)
{
    if (mod == arg) return Qfalse;
    return rb_class_inherited_p(mod, arg);
}
mod <= other → true, false, or nil click to toggle source

Returns true if mod is a subclass of other or is the same as other. Returns nil if there's no relationship between the two. (Think of the relationship in terms of the class definition: “class A<B” implies “A<B”).

VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
    VALUE start = mod;

    if (mod == arg) return Qtrue;
    if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
        rb_raise(rb_eTypeError, "compared with non class/module");
    }
    arg = RCLASS_ORIGIN(arg);
    if (class_search_ancestor(mod, arg)) {
        return Qtrue;
    }
    /* not mod < arg; check if mod > arg */
    if (class_search_ancestor(arg, start)) {
        return Qfalse;
    }
    return Qnil;
}
module <=> other_module → -1, 0, +1, or nil click to toggle source

Comparison—Returns -1, 0, +1 or nil depending on whether module includes other_module, they are the same, or if module is included by other_module. This is the basis for the tests in Comparable.

Returns nil if module has no relationship with other_module, if other_module is not a module, or if the two values are incomparable.

static VALUE
rb_mod_cmp(VALUE mod, VALUE arg)
{
    VALUE cmp;

    if (mod == arg) return INT2FIX(0);
    if (!CLASS_OR_MODULE_P(arg)) {
        return Qnil;
    }

    cmp = rb_class_inherited_p(mod, arg);
    if (NIL_P(cmp)) return Qnil;
    if (cmp) {
        return INT2FIX(-1);
    }
    return INT2FIX(1);
}
obj == other → true or false click to toggle source
equal?(other) → true or false
eql?(other) → true or false

Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

Unlike ==, the equal? method should never be overridden by subclasses as it is used to determine object identity (that is, a.equal?(b) if and only if a is the same object as b):

obj = "a"
other = obj.dup

a == other      #=> true
a.equal? other  #=> false
a.equal? a      #=> true

The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}
mod === obj → true or false click to toggle source

Case Equality—Returns true if anObject is an instance of mod or one of mod's descendants. Of limited use for modules, but can be used in case statements to classify objects by class.

static VALUE
rb_mod_eqq(VALUE mod, VALUE arg)
{
    return rb_obj_is_kind_of(arg, mod);
}
mod > other → true, false, or nil click to toggle source

Returns true if mod is an ancestor of other. Returns nil if there's no relationship between the two. (Think of the relationship in terms of the class definition: “class A<B” implies “B>A”).

static VALUE
rb_mod_gt(VALUE mod, VALUE arg)
{
    if (mod == arg) return Qfalse;
    return rb_mod_ge(mod, arg);
}
mod >= other → true, false, or nil click to toggle source

Returns true if mod is an ancestor of other, or the two modules are the same. Returns nil if there's no relationship between the two. (Think of the relationship in terms of the class definition: “class A<B” implies “B>A”).

static VALUE
rb_mod_ge(VALUE mod, VALUE arg)
{
    if (!CLASS_OR_MODULE_P(arg)) {
        rb_raise(rb_eTypeError, "compared with non class/module");
    }

    return rb_class_inherited_p(arg, mod);
}
ancestors → array click to toggle source

Returns a list of modules included in mod (including mod itself).

module Mod
  include Math
  include Comparable
end

Mod.ancestors    #=> [Mod, Comparable, Math]
Math.ancestors   #=> [Math]

VALUE
rb_mod_ancestors(VALUE mod)
{
    VALUE p, ary = rb_ary_new();

    for (p = mod; p; p = RCLASS_SUPER(p)) {
    if (FL_TEST(p, FL_SINGLETON))
        continue;
    if (BUILTIN_TYPE(p) == T_ICLASS) {
        rb_ary_push(ary, RBASIC(p)->klass);
    }
    else if (p == RCLASS_ORIGIN(p)) {
        rb_ary_push(ary, p);
    }
    }
    return ary;
}
autoload(module, filename) → nil click to toggle source

Registers filename to be loaded (using Kernel::require) the first time that module (which may be a String or a symbol) is accessed in the namespace of mod.

module A
end
A.autoload(:B, "b")
A::B.doit            # autoloads "b"

static VALUE
rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
{
    ID id = rb_to_id(sym);

    FilePathValue(file);
    rb_autoload(mod, id, RSTRING_PTR(file));
    return Qnil;
}
autoload?(name) → String or nil click to toggle source

Returns filename to be loaded if name is registered as autoload in the namespace of mod.

module A
end
A.autoload(:B, "b")
A.autoload?(:B)            #=> "b"

static VALUE
rb_mod_autoload_p(VALUE mod, VALUE sym)
{
    ID id = rb_check_id(&sym);
    if (!id) {
        return Qnil;
    }
    return rb_autoload_p(mod, id);
}
class_eval(string [, filename [, lineno]]) → obj click to toggle source
module_eval {|| block } → obj

Evaluates the string or block in the context of mod, except that when a block is given, constant/class variable lookup is not affected. This can be used to add methods to a class. module_eval returns the result of evaluating its argument. The optional filename and lineno parameters set the text for error messages.

class Thing
end
a = %q{def hello() "Hello there!" end}
Thing.module_eval(a)
puts Thing.new.hello()
Thing.module_eval("invalid code", "dummy", 123)

produces:

Hello there!
dummy:123:in `module_eval': undefined local variable
    or method `code' for Thing:Class
VALUE
rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
{
    return specific_eval(argc, argv, mod, mod);
}
module_exec(arg...) {|var...| block } → obj click to toggle source
class_exec(arg...) {|var...| block } → obj

Evaluates the given block in the context of the class/module. The method defined in the block will belong to the receiver.

class Thing
end
Thing.class_exec{
  def hello() "Hello there!" end
}
puts Thing.new.hello()

produces:

Hello there!
VALUE
rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
{
    return yield_under(mod, mod, rb_ary_new4(argc, argv));
}
class_variable_defined?(symbol) → true or false click to toggle source

Returns true if the given class variable is defined in obj.

class Fred
  @@foo = 99
end
Fred.class_variable_defined?(:@@foo)    #=> true
Fred.class_variable_defined?(:@@bar)    #=> false

static VALUE
rb_mod_cvar_defined(VALUE obj, VALUE iv)
{
    ID id = rb_check_id(&iv);

    if (!id) {
        if (rb_is_class_name(iv)) {
            return Qfalse;
        }
        else {
            rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name",
                              QUOTE(iv));
        }
    }
    if (!rb_is_class_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
                      QUOTE_ID(id));
    }
    return rb_cvar_defined(obj, id);
}
class_variable_get(symbol) → obj click to toggle source

Returns the value of the given class variable (or throws a NameError exception). The @@ part of the variable name should be included for regular class variables

class Fred
  @@foo = 99
end
Fred.class_variable_get(:@@foo)     #=> 99

static VALUE
rb_mod_cvar_get(VALUE obj, VALUE iv)
{
    ID id = rb_check_id(&iv);

    if (!id) {
        if (rb_is_class_name(iv)) {
            rb_name_error_str(iv, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"",
                              iv, rb_class_name(obj));
        }
        else {
            rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name",
                              QUOTE(iv));
        }
    }
    if (!rb_is_class_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
                      QUOTE_ID(id));
    }
    return rb_cvar_get(obj, id);
}
class_variable_set(symbol, obj) → obj click to toggle source

Sets the class variable names by symbol to object.

class Fred
  @@foo = 99
  def foo
    @@foo
  end
end
Fred.class_variable_set(:@@foo, 101)     #=> 101
Fred.new.foo                             #=> 101

static VALUE
rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val)
{
    ID id = rb_to_id(iv);

    if (!rb_is_class_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
                      QUOTE_ID(id));
    }
    rb_cvar_set(obj, id, val);
    return val;
}
class_variables(inherit=true) → array click to toggle source

Returns an array of the names of class variables in mod. This includes the names of class variables in any included modules, unless the inherit parameter is set to false.

class One
  @@var1 = 1
end
class Two < One
  @@var2 = 2
end
One.class_variables          #=> [:@@var1]
Two.class_variables          #=> [:@@var2, :@@var1]
Two.class_variables(false)   #=> [:@@var2]

VALUE
rb_mod_class_variables(int argc, VALUE *argv, VALUE mod)
{
    VALUE inherit;
    st_table *tbl;

    if (argc == 0) {
    inherit = Qtrue;
    }
    else {
    rb_scan_args(argc, argv, "01", &inherit);
    }
    if (RTEST(inherit)) {
    tbl = mod_cvar_of(mod, 0);
    }
    else {
    tbl = mod_cvar_at(mod, 0);
    }
    return cvar_list(tbl);
}
const_defined?(sym, inherit=true) → true or false click to toggle source

Checks for a constant with the given name in mod If inherit is set, the lookup will also search the ancestors (and Object if mod is a Module.)

Returns whether or not a definition is found:

Math.const_defined? "PI"   #=> true
IO.const_defined? :SYNC   #=> true
IO.const_defined? :SYNC, false   #=> false

static VALUE
rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
{
    VALUE name, recur;
    ID id;

    if (argc == 1) {
        name = argv[0];
        recur = Qtrue;
    }
    else {
        rb_scan_args(argc, argv, "11", &name, &recur);
    }
    if (!(id = rb_check_id(&name))) {
        if (rb_is_const_name(name)) {
            return Qfalse;
        }
        else {
            rb_name_error_str(name, "wrong constant name %"PRIsVALUE,
                              QUOTE(name));
        }
    }
    if (!rb_is_const_id(id)) {
        rb_name_error(id, "wrong constant name %"PRIsVALUE,
                      QUOTE_ID(id));
    }
    return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
}
const_get(sym, inherit=true) → obj click to toggle source
const_get(str, inherit=true) → obj

Checks for a constant with the given name in mod If inherit is set, the lookup will also search the ancestors (and Object if mod is a Module.)

The value of the constant is returned if a definition is found, otherwise a NameError is raised.

Math.const_get(:PI)   #=> 3.14159265358979

This method will recursively look up constant names if a namespaced class name is provided. For example:

module Foo; class Bar; end end
Object.const_get 'Foo::Bar'

The inherit flag is respected on each lookup. For example:

module Foo
  class Bar
    VAL = 10
  end

  class Baz < Bar; end
end

Object.const_get 'Foo::Baz::VAL'         # => 10
Object.const_get 'Foo::Baz::VAL', false  # => NameError

static VALUE
rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
{
    VALUE name, recur;
    rb_encoding *enc;
    const char *pbeg, *p, *path, *pend;
    ID id;
    int nestable = 1;

    if (argc == 1) {
        name = argv[0];
        recur = Qtrue;
    }
    else {
        rb_scan_args(argc, argv, "11", &name, &recur);
    }

    if (SYMBOL_P(name)) {
        name = rb_sym_to_s(name);
        nestable = 0;
    }

    name = rb_check_string_type(name);
    Check_Type(name, T_STRING);

    enc = rb_enc_get(name);
    path = RSTRING_PTR(name);

    if (!rb_enc_asciicompat(enc)) {
        rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
    }

    pbeg = p = path;
    pend = path + RSTRING_LEN(name);

    if (p >= pend || !*p) {
      wrong_name:
        rb_raise(rb_eNameError, "wrong constant name %"PRIsVALUE,
                 QUOTE(name));
    }

    if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
        if (!nestable) goto wrong_name;
        mod = rb_cObject;
        p += 2;
        pbeg = p;
    }

    while (p < pend) {
        VALUE part;
        long len, beglen;

        while (p < pend && *p != ':') p++;

        if (pbeg == p) goto wrong_name;

        id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
        beglen = pbeg-path;

        if (p < pend && p[0] == ':') {
            if (!nestable) goto wrong_name;
            if (p + 2 >= pend || p[1] != ':') goto wrong_name;
            p += 2;
            pbeg = p;
        }

        if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
            rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
                     QUOTE(name));
        }

        if (!id) {
            if (!ISUPPER(*pbeg) || !rb_enc_symname2_p(pbeg, len, enc)) {
                part = rb_str_subseq(name, beglen, len);
                rb_name_error_str(part, "wrong constant name %"PRIsVALUE,
                                  QUOTE(part));
            }
            else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
                id = rb_intern3(pbeg, len, enc);
            }
            else {
                part = rb_str_subseq(name, beglen, len);
                rb_name_error_str(part, "uninitialized constant %"PRIsVALUE"%"PRIsVALUE,
                                  rb_str_subseq(name, 0, beglen),
                                  QUOTE(part));
            }
        }
        if (!rb_is_const_id(id)) {
            rb_name_error(id, "wrong constant name %"PRIsVALUE,
                          QUOTE_ID(id));
        }
        mod = RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
    }

    return mod;
}
const_missing(sym) → obj click to toggle source

Invoked when a reference is made to an undefined constant in mod. It is passed a symbol for the undefined constant, and returns a value to be used for that constant. The following code is an example of the same:

def Foo.const_missing(name)
  name # return the constant name as Symbol
end

Foo::UNDEFINED_CONST    #=> :UNDEFINED_CONST: symbol returned

In the next example when a reference is made to an undefined constant, it attempts to load a file whose name is the lowercase version of the constant (thus class Fred is assumed to be in file fred.rb). If found, it returns the loaded class. It therefore implements an autoload feature similar to Kernel#autoload and #autoload.

def Object.const_missing(name)
  @looked_for ||= {}
  str_name = name.to_s
  raise "Class not found: #{name}" if @looked_for[str_name]
  @looked_for[str_name] = 1
  file = str_name.downcase
  require file
  klass = const_get(name)
  return klass if klass
  raise "Class not found: #{name}"
end

VALUE
rb_mod_const_missing(VALUE klass, VALUE name)
{
    rb_vm_pop_cfunc_frame();
    uninitialized_constant(klass, rb_to_id(name));

    UNREACHABLE;
}
const_set(sym, obj) → obj click to toggle source

Sets the named constant to the given object, returning that object. Creates a new constant if no constant with the given name previously existed.

Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0)   #=> 3.14285714285714
Math::HIGH_SCHOOL_PI - Math::PI              #=> 0.00126448926734968

static VALUE
rb_mod_const_set(VALUE mod, VALUE name, VALUE value)
{
    ID id = rb_to_id(name);

    if (!rb_is_const_id(id)) {
        rb_name_error(id, "wrong constant name %"PRIsVALUE,
                      QUOTE_ID(id));
    }
    rb_const_set(mod, id, value);
    return value;
}
constants(inherit=true) → array click to toggle source

Returns an array of the names of the constants accessible in mod. This includes the names of constants in any included modules (example at start of section), unless the inherit parameter is set to false.

IO.constants.include?(:SYNC)        #=> true
IO.constants(false).include?(:SYNC) #=> false

Also see Module::const_defined?.

VALUE
rb_mod_constants(int argc, VALUE *argv, VALUE mod)
{
    VALUE inherit;
    st_table *tbl;

    if (argc == 0) {
    inherit = Qtrue;
    }
    else {
    rb_scan_args(argc, argv, "01", &inherit);
    }
    if (RTEST(inherit)) {
    tbl = rb_mod_const_of(mod, 0);
    }
    else {
    tbl = rb_mod_const_at(mod, 0);
    }
    return rb_const_list(tbl);
}
freeze → mod click to toggle source

Prevents further modifications to mod.

This method returns self.

static VALUE
rb_mod_freeze(VALUE mod)
{
    rb_class_name(mod);
    return rb_obj_freeze(mod);
}
include?(module) → true or false click to toggle source

Returns true if module is included in mod or one of mod's ancestors.

module A
end
class B
  include A
end
class C < B
end
B.include?(A)   #=> true
C.include?(A)   #=> true
A.include?(A)   #=> false

VALUE
rb_mod_include_p(VALUE mod, VALUE mod2)
{
    VALUE p;

    Check_Type(mod2, T_MODULE);
    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
    if (BUILTIN_TYPE(p) == T_ICLASS) {
        if (RBASIC(p)->klass == mod2) return Qtrue;
    }
    }
    return Qfalse;
}
included_modules → array click to toggle source

Returns the list of modules included in mod.

module Mixin
end

module Outer
  include Mixin
end

Mixin.included_modules   #=> []
Outer.included_modules   #=> [Mixin]

VALUE
rb_mod_included_modules(VALUE mod)
{
    VALUE ary = rb_ary_new();
    VALUE p;
    VALUE origin = RCLASS_ORIGIN(mod);

    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
    if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
        VALUE m = RBASIC(p)->klass;
        if (RB_TYPE_P(m, T_MODULE))
        rb_ary_push(ary, m);
    }
    }
    return ary;
}
inspect() click to toggle source
Alias for: to_s
instance_method(symbol) → unbound_method click to toggle source

Returns an UnboundMethod representing the given instance method in mod.

class Interpreter
  def do_a() print "there, "; end
  def do_d() print "Hello ";  end
  def do_e() print "!\n";     end
  def do_v() print "Dave";    end
  Dispatcher = {
    "a" => instance_method(:do_a),
    "d" => instance_method(:do_d),
    "e" => instance_method(:do_e),
    "v" => instance_method(:do_v)
  }
  def interpret(string)
    string.each_char {|b| Dispatcher[b].bind(self).call }
  end
end

interpreter = Interpreter.new
interpreter.interpret('dave')

produces:

Hello there, Dave!
static VALUE
rb_mod_instance_method(VALUE mod, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(mod, vid);
    }
    return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE);
}
instance_methods(include_super=true) → array click to toggle source

Returns an array containing the names of the public and protected instance methods in the receiver. For a module, these are the public and protected methods; for a class, they are the instance (not singleton) methods. With no argument, or with an argument that is false, the instance methods in mod are returned, otherwise the methods in mod and mod's superclasses are returned.

module A
  def method1()  end
end
class B
  def method2()  end
end
class C < B
  def method3()  end
end

A.instance_methods                #=> [:method1]
B.instance_methods(false)         #=> [:method2]
C.instance_methods(false)         #=> [:method3]
C.instance_methods(true).length   #=> 43

VALUE
rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
}
method_defined?(symbol) → true or false click to toggle source

Returns true if the named method is defined by mod (or its included modules and, if mod is a class, its ancestors). Public and protected methods are matched.

module A
  def method1()  end
end
class B
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1    #=> true
C.method_defined? "method1"   #=> true
C.method_defined? "method2"   #=> true
C.method_defined? "method3"   #=> true
C.method_defined? "method4"   #=> false

static VALUE
rb_mod_method_defined(VALUE mod, VALUE mid)
{
    ID id = rb_check_id(&mid);
    if (!id || !rb_method_boundp(mod, id, 1)) {
        return Qfalse;
    }
    return Qtrue;

}
class_eval(string [, filename [, lineno]]) → obj click to toggle source
module_eval {|| block } → obj

Evaluates the string or block in the context of mod, except that when a block is given, constant/class variable lookup is not affected. This can be used to add methods to a class. module_eval returns the result of evaluating its argument. The optional filename and lineno parameters set the text for error messages.

class Thing
end
a = %q{def hello() "Hello there!" end}
Thing.module_eval(a)
puts Thing.new.hello()
Thing.module_eval("invalid code", "dummy", 123)

produces:

Hello there!
dummy:123:in `module_eval': undefined local variable
    or method `code' for Thing:Class
VALUE
rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
{
    return specific_eval(argc, argv, mod, mod);
}
module_exec(arg...) {|var...| block } → obj click to toggle source
class_exec(arg...) {|var...| block } → obj

Evaluates the given block in the context of the class/module. The method defined in the block will belong to the receiver.

class Thing
end
Thing.class_exec{
  def hello() "Hello there!" end
}
puts Thing.new.hello()

produces:

Hello there!
VALUE
rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
{
    return yield_under(mod, mod, rb_ary_new4(argc, argv));
}
name → string click to toggle source

Returns the name of the module mod. Returns nil for anonymous modules.

VALUE
rb_mod_name(VALUE mod)
{
    int permanent;
    VALUE path = classname(mod, &permanent);

    if (!NIL_P(path)) return rb_str_dup(path);
    return path;
}
private_class_method(symbol, ...) → mod click to toggle source

Makes existing class methods private. Often used to hide the default constructor new.

class SimpleSingleton  # Not thread safe
  private_class_method :new
  def SimpleSingleton.create(*args, &block)
    @me = new(*args, &block) if ! @me
    @me
  end
end

static VALUE
rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
{
    set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
    return obj;
}
private_constant(symbol, ...) → mod click to toggle source

Makes a list of existing constants private.

VALUE
rb_mod_private_constant(int argc, VALUE *argv, VALUE obj)
{
    set_const_visibility(obj, argc, argv, CONST_PRIVATE);
    return obj;
}
private_instance_methods(include_super=true) → array click to toggle source

Returns a list of the private instance methods defined in mod. If the optional parameter is not false, the methods of any ancestors are included.

module Mod
  def method1()  end
  private :method1
  def method2()  end
end
Mod.instance_methods           #=> [:method2]
Mod.private_instance_methods   #=> [:method1]

VALUE
rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
}
private_method_defined?(symbol) → true or false click to toggle source

Returns true if the named private method is defined by _ mod_ (or its included modules and, if mod is a class, its ancestors).

module A
  def method1()  end
end
class B
  private
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1            #=> true
C.private_method_defined? "method1"   #=> false
C.private_method_defined? "method2"   #=> true
C.method_defined? "method2"           #=> false

static VALUE
rb_mod_private_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, NOEX_PRIVATE);
}
protected_instance_methods(include_super=true) → array click to toggle source

Returns a list of the protected instance methods defined in mod. If the optional parameter is not false, the methods of any ancestors are included.

VALUE
rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
}
protected_method_defined?(symbol) → true or false click to toggle source

Returns true if the named protected method is defined by mod (or its included modules and, if mod is a class, its ancestors).

module A
  def method1()  end
end
class B
  protected
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1              #=> true
C.protected_method_defined? "method1"   #=> false
C.protected_method_defined? "method2"   #=> true
C.method_defined? "method2"             #=> true

static VALUE
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, NOEX_PROTECTED);
}
public_class_method(symbol, ...) → mod click to toggle source

Makes a list of existing class methods public.

static VALUE
rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
{
    set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
    return obj;
}
public_constant(symbol, ...) → mod click to toggle source

Makes a list of existing constants public.

VALUE
rb_mod_public_constant(int argc, VALUE *argv, VALUE obj)
{
    set_const_visibility(obj, argc, argv, CONST_PUBLIC);
    return obj;
}
public_instance_method(symbol) → unbound_method click to toggle source

Similar to #instance_method, searches public method only.

static VALUE
rb_mod_public_instance_method(VALUE mod, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(mod, vid);
    }
    return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE);
}
public_instance_methods(include_super=true) → array click to toggle source

Returns a list of the public instance methods defined in mod. If the optional parameter is not false, the methods of any ancestors are included.

VALUE
rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
}
public_method_defined?(symbol) → true or false click to toggle source

Returns true if the named public method is defined by mod (or its included modules and, if mod is a class, its ancestors).

module A
  def method1()  end
end
class B
  protected
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1           #=> true
C.public_method_defined? "method1"   #=> true
C.public_method_defined? "method2"   #=> false
C.method_defined? "method2"          #=> true

static VALUE
rb_mod_public_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, NOEX_PUBLIC);
}
remove_class_variable(sym) → obj click to toggle source

Removes the definition of the sym, returning that constant's value.

class Dummy
  @@var = 99
  puts @@var
  remove_class_variable(:@@var)
  p(defined? @@var)
end

produces:

99
nil
VALUE
rb_mod_remove_cvar(VALUE mod, VALUE name)
{
    const ID id = rb_check_id(&name);
    st_data_t val, n = id;

    if (!id) {
    if (rb_is_class_name(name)) {
        rb_name_error_str(name, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"",
                  name, rb_class_name(mod));
    }
    else {
        rb_name_error_str(name, "wrong class variable name %"PRIsVALUE"", QUOTE(name));
    }
    }
    if (!rb_is_class_id(id)) {
    rb_name_error(id, "wrong class variable name %"PRIsVALUE"", QUOTE_ID(id));
    }
    if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
    rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
    rb_check_frozen(mod);
    if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
    return (VALUE)val;
    }
    if (rb_cvar_defined(mod, id)) {
    rb_name_error(id, "cannot remove %"PRIsVALUE" for %"PRIsVALUE"",
         QUOTE_ID(id), rb_class_name(mod));
    }
    rb_name_error(id, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"",
          QUOTE_ID(id), rb_class_name(mod));

    UNREACHABLE;
}
to_s → string click to toggle source

Return a string representing this module or class. For basic classes and modules, this is the name. For singletons, we show information on the thing we're attached to as well.

static VALUE
rb_mod_to_s(VALUE klass)
{
    ID id_defined_at;
    VALUE refined_class, defined_at;

    if (FL_TEST(klass, FL_SINGLETON)) {
        VALUE s = rb_usascii_str_new2("#<Class:");
        VALUE v = rb_iv_get(klass, "__attached__");

        if (CLASS_OR_MODULE_P(v)) {
            rb_str_append(s, rb_inspect(v));
        }
        else {
            rb_str_append(s, rb_any_to_s(v));
        }
        rb_str_cat2(s, ">");

        return s;
    }
    refined_class = rb_refinement_module_get_refined_class(klass);
    if (!NIL_P(refined_class)) {
        VALUE s = rb_usascii_str_new2("#<refinement:");

        rb_str_concat(s, rb_inspect(refined_class));
        rb_str_cat2(s, "@");
        CONST_ID(id_defined_at, "__defined_at__");
        defined_at = rb_attr_get(klass, id_defined_at);
        rb_str_concat(s, rb_inspect(defined_at));
        rb_str_cat2(s, ">");
        return s;
    }
    return rb_str_dup(rb_class_name(klass));
}
Also aliased as: inspect


class Mutex - Ruby 2.0.0-p576 Core API Reference API Reference

class Mutex

Mutex implements a simple semaphore that can be used to coordinate access to shared data from multiple concurrent threads.

Example:

require 'thread'
semaphore = Mutex.new

a = Thread.new {
  semaphore.synchronize {
    # access shared resource
  }
}

b = Thread.new {
  semaphore.synchronize {
    # access shared resource
  }
}

In Files

  • thread.c

Parent

Object

Public Class Methods

new → mutex click to toggle source

Creates a new Mutex

static VALUE
mutex_initialize(VALUE self)
{
    return self;
}

Public Instance Methods

lock → self click to toggle source

Attempts to grab the lock and waits if it isn't available. Raises ThreadError if mutex was locked by the current thread.

VALUE
rb_mutex_lock(VALUE self)
{
    rb_thread_t *th = GET_THREAD();
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);

    /* When running trap handler */
    if (!mutex->allow_trap && th->interrupt_mask & TRAP_INTERRUPT_MASK) {
        rb_raise(rb_eThreadError, "can't be called from trap context");
    }

    if (rb_mutex_trylock(self) == Qfalse) {
        if (mutex->th == GET_THREAD()) {
            rb_raise(rb_eThreadError, "deadlock; recursive locking");
        }

        while (mutex->th != th) {
            int interrupted;
            enum rb_thread_status prev_status = th->status;
            volatile int timeout_ms = 0;
            struct rb_unblock_callback oldubf;

            set_unblock_function(th, lock_interrupt, mutex, &oldubf, FALSE);
            th->status = THREAD_STOPPED_FOREVER;
            th->locking_mutex = self;

            native_mutex_lock(&mutex->lock);
            th->vm->sleeper++;
            /*
             * Carefully! while some contended threads are in lock_func(),
             * vm->sleepr is unstable value. we have to avoid both deadlock
             * and busy loop.
             */
            if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
                !patrol_thread) {
                timeout_ms = 100;
                patrol_thread = th;
            }

            GVL_UNLOCK_BEGIN();
            interrupted = lock_func(th, mutex, (int)timeout_ms);
            native_mutex_unlock(&mutex->lock);
            GVL_UNLOCK_END();

            if (patrol_thread == th)
                patrol_thread = NULL;

            reset_unblock_function(th, &oldubf);

            th->locking_mutex = Qfalse;
            if (mutex->th && interrupted == 2) {
                rb_check_deadlock(th->vm);
            }
            if (th->status == THREAD_STOPPED_FOREVER) {
                th->status = prev_status;
            }
            th->vm->sleeper--;

            if (mutex->th == th) mutex_locked(th, self);

            if (interrupted) {
                RUBY_VM_CHECK_INTS_BLOCKING(th);
            }
        }
    }
    return self;
}
locked? → true or false click to toggle source

Returns true if this lock is currently held by some thread.

VALUE
rb_mutex_locked_p(VALUE self)
{
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);
    return mutex->th ? Qtrue : Qfalse;
}
owned? → true or false click to toggle source

Returns true if this lock is currently held by current thread. This API is experimental, and subject to change.

VALUE
rb_mutex_owned_p(VALUE self)
{
    VALUE owned = Qfalse;
    rb_thread_t *th = GET_THREAD();
    rb_mutex_t *mutex;

    GetMutexPtr(self, mutex);

    if (mutex->th == th)
        owned = Qtrue;

    return owned;
}
sleep(timeout = nil) → number click to toggle source

Releases the lock and sleeps timeout seconds if it is given and non-nil or forever. Raises ThreadError if mutex wasn't locked by the current thread.

Note that this method can wakeup without explicit Thread#wakeup call. For example, receiving signal and so on.

static VALUE
mutex_sleep(int argc, VALUE *argv, VALUE self)
{
    VALUE timeout;

    rb_scan_args(argc, argv, "01", &timeout);
    return rb_mutex_sleep(self, timeout);
}
synchronize { ... } → result of the block click to toggle source

Obtains a lock, runs the block, and releases the lock when the block completes. See the example under Mutex.

static VALUE
rb_mutex_synchronize_m(VALUE self, VALUE args)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eThreadError, "must be called with a block");
    }

    return rb_mutex_synchronize(self, rb_yield, Qundef);
}
try_lock → true or false click to toggle source

Attempts to obtain the lock and returns immediately. Returns true if the lock was granted.

VALUE
rb_mutex_trylock(VALUE self)
{
    rb_mutex_t *mutex;
    VALUE locked = Qfalse;
    GetMutexPtr(self, mutex);

    native_mutex_lock(&mutex->lock);
    if (mutex->th == 0) {
        mutex->th = GET_THREAD();
        locked = Qtrue;

        mutex_locked(GET_THREAD(), self);
    }
    native_mutex_unlock(&mutex->lock);

    return locked;
}
unlock → self click to toggle source

Releases the lock. Raises ThreadError if mutex wasn't locked by the current thread.

VALUE
rb_mutex_unlock(VALUE self)
{
    const char *err;
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);

    err = rb_mutex_unlock_th(mutex, GET_THREAD());
    if (err) rb_raise(rb_eThreadError, "%s", err);

    return self;
}


class NameError - Ruby 2.0.0-p576 Core API Reference API Reference

class NameError

Raised when a given name is invalid or undefined.

puts foo

raises the exception:

NameError: undefined local variable or method `foo' for main:Object

Since constant names must start with a capital:

Fixnum.const_set :answer, 42

raises the exception:

NameError: wrong constant name answer

In Files

  • error.c

Parent

StandardError

Public Class Methods

new(msg [, name]) → name_error click to toggle source

Construct a new NameError exception. If given the name parameter may subsequently be examined using the NameError.name method.

static VALUE
name_err_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE name;

    name = (argc > 1) ? argv[--argc] : Qnil;
    rb_call_super(argc, argv);
    rb_iv_set(self, "name", name);
    return self;
}

Public Instance Methods

name → string or nil click to toggle source

Return the name associated with this NameError exception.

static VALUE
name_err_name(VALUE self)
{
    return rb_attr_get(self, rb_intern("name"));
}
to_s → string click to toggle source

Produce a nicely-formatted string representing the NameError.

static VALUE
name_err_to_s(VALUE exc)
{
    VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
    VALUE str = mesg;

    if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
    StringValue(str);
    return str;
}


class NilClass - Ruby 2.0.0-p576 Core API Reference API Reference

class NilClass

The class of the singleton object nil.

In Files

  • complex.c
  • object.c
  • rational.c

Parent

Object

Public Instance Methods

false & obj → false click to toggle source
nil & obj → false

And—Returns false. obj is always evaluated as it is the argument to a method call—there is no short-circuit evaluation in this case.

static VALUE
false_and(VALUE obj, VALUE obj2)
{
    return Qfalse;
}
false ^ obj → true or false click to toggle source
nil ^ obj → true or false

Exclusive Or—If obj is nil or false, returns false; otherwise, returns true.

static VALUE
false_xor(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qtrue:Qfalse;
}
inspect → "nil" click to toggle source

Always returns the string “nil”.

static VALUE
nil_inspect(VALUE obj)
{
    return rb_usascii_str_new2("nil");
}
nil?() click to toggle source

call_seq:

nil.nil?               -> true

Only the object nil responds true to nil?.

static VALUE
rb_true(VALUE obj)
{
    return Qtrue;
}
rationalize([eps]) → (0/1) click to toggle source

Returns zero as a rational. The optional argument eps is always ignored.

static VALUE
nilclass_rationalize(int argc, VALUE *argv, VALUE self)
{
    rb_scan_args(argc, argv, "01", NULL);
    return nilclass_to_r(self);
}
to_a → [] click to toggle source

Always returns an empty array.

nil.to_a   #=> []

static VALUE
nil_to_a(VALUE obj)
{
    return rb_ary_new2(0);
}
to_c → (0+0i) click to toggle source

Returns zero as a complex.

static VALUE
nilclass_to_c(VALUE self)
{
    return rb_complex_new1(INT2FIX(0));
}
to_f → 0.0 click to toggle source

Always returns zero.

nil.to_f   #=> 0.0

static VALUE
nil_to_f(VALUE obj)
{
    return DBL2NUM(0.0);
}
to_h → {} click to toggle source

Always returns an empty hash.

nil.to_h   #=> {}

static VALUE
nil_to_h(VALUE obj)
{
    return rb_hash_new();
}
to_i → 0 click to toggle source

Always returns zero.

nil.to_i   #=> 0

static VALUE
nil_to_i(VALUE obj)
{
    return INT2FIX(0);
}
to_r → (0/1) click to toggle source

Returns zero as a rational.

static VALUE
nilclass_to_r(VALUE self)
{
    return rb_rational_new1(INT2FIX(0));
}
to_s → "" click to toggle source

Always returns the empty string.

static VALUE
nil_to_s(VALUE obj)
{
    return rb_usascii_str_new(0, 0);
}
false | obj → true or false click to toggle source
nil | obj → true or false

Or—Returns false if obj is nil or false; true otherwise.

static VALUE
false_or(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qtrue:Qfalse;
}


class NoMemoryError - Ruby 2.0.0-p576 Core API Reference API Reference

class NoMemoryError

Raised when memory allocation fails.

In Files

  • error.c

Parent

Exception


class NoMethodError - Ruby 2.0.0-p576 Core API Reference API Reference

class NoMethodError

Raised when a method is called on a receiver which doesn't have it defined and also fails to respond with method_missing.

"hello".to_ary

raises the exception:

NoMethodError: undefined method `to_ary' for "hello":String

In Files

  • error.c

Parent

NameError

Public Class Methods

new(msg, name [, args]) → no_method_error click to toggle source

Construct a NoMethodError exception for a method of the given name called with the given arguments. The name may be accessed using the #name method on the resulting object, and the arguments using the #args method.

static VALUE
nometh_err_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE args = (argc > 2) ? argv[--argc] : Qnil;
    name_err_initialize(argc, argv, self);
    rb_iv_set(self, "args", args);
    return self;
}

Public Instance Methods

args → obj click to toggle source

Return the arguments passed in as the third parameter to the constructor.

static VALUE
nometh_err_args(VALUE self)
{
    return rb_attr_get(self, rb_intern("args"));
}


class NotImplementedError - Ruby 2.0.0-p576 Core API Reference API Reference

class NotImplementedError

Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception if the underlying operating system or Ruby runtime does not support them.

Note that if fork raises a NotImplementedError, then respond_to?(:fork) returns false.

In Files

  • error.c

Parent

ScriptError


class Numeric - Ruby 2.0.0-p576 Core API Reference API Reference

class Numeric

Document-class: FloatDomainError

Raised when attempting to convert special float values (in particular infinite or NaN) to numerical classes which don't support them.

Float::INFINITY.to_r

raises the exception:

FloatDomainError: Infinity

In Files

  • complex.c
  • numeric.c
  • rational.c

Parent

Object

Included Modules

  • Comparable

Public Instance Methods

modulo(numeric) → real click to toggle source
x.modulo(y) means x-y*(x/y).floor

Equivalent to num.divmod(aNumeric).

See Numeric#divmod.

static VALUE
num_modulo(VALUE x, VALUE y)
{
    return rb_funcall(x, '-', 1,
                      rb_funcall(y, '*', 1,
                                 rb_funcall(x, rb_intern("div"), 1, y)));
}
+num → num click to toggle source

Unary Plus—Returns the receiver's value.

static VALUE
num_uplus(VALUE num)
{
    return num;
}
-num → numeric click to toggle source

Unary Minus—Returns the receiver's value, negated.

static VALUE
num_uminus(VALUE num)
{
    VALUE zero;

    zero = INT2FIX(0);
    do_coerce(&zero, &num, TRUE);

    return rb_funcall(zero, '-', 1, num);
}
number <=> other → 0 or nil click to toggle source

Returns zero if number equals other, otherwise nil is returned if the two values are incomparable.

static VALUE
num_cmp(VALUE x, VALUE y)
{
    if (x == y) return INT2FIX(0);
    return Qnil;
}
abs → numeric click to toggle source
magnitude → numeric

Returns the absolute value of num.

12.abs         #=> 12
(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56

static VALUE
num_abs(VALUE num)
{
    if (negative_int_p(num)) {
        return rb_funcall(num, rb_intern("-@"), 0);
    }
    return num;
}
abs2 → real click to toggle source

Returns square of self.

static VALUE
numeric_abs2(VALUE self)
{
    return f_mul(self, self);
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
numeric_arg(VALUE self)
{
    if (f_positive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
numeric_arg(VALUE self)
{
    if (f_positive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
ceil → integer click to toggle source

Returns the smallest Integer greater than or equal to num. Class Numeric achieves this by converting itself to a Float then invoking Float#ceil.

1.ceil        #=> 1
1.2.ceil      #=> 2
(-1.2).ceil   #=> -1
(-1.0).ceil   #=> -1

static VALUE
num_ceil(VALUE num)
{
    return flo_ceil(rb_Float(num));
}
coerce(numeric) → array click to toggle source

If aNumeric is the same type as num, returns an array containing aNumeric and num. Otherwise, returns an array with both aNumeric and num represented as Float objects. This coercion mechanism is used by Ruby to handle mixed-type numeric operations: it is intended to find a compatible common type between the two operands of the operator.

1.coerce(2.5)   #=> [2.5, 1.0]
1.2.coerce(3)   #=> [3.0, 1.2]
1.coerce(2)     #=> [2, 1]

static VALUE
num_coerce(VALUE x, VALUE y)
{
    if (CLASS_OF(x) == CLASS_OF(y))
        return rb_assoc_new(y, x);
    x = rb_Float(x);
    y = rb_Float(y);
    return rb_assoc_new(y, x);
}
conj → self click to toggle source
conjugate → self

Returns self.

static VALUE
numeric_conj(VALUE self)
{
    return self;
}
conj → self click to toggle source
conjugate → self

Returns self.

static VALUE
numeric_conj(VALUE self)
{
    return self;
}
denominator → integer click to toggle source

Returns the denominator (always positive).

static VALUE
numeric_denominator(VALUE self)
{
    return f_denominator(f_to_r(self));
}
div(numeric) → integer click to toggle source

Uses / to perform division, then converts the result to an integer. numeric does not define the / operator; this is left to subclasses.

Equivalent to num.divmod(aNumeric).

See Numeric#divmod.

static VALUE
num_div(VALUE x, VALUE y)
{
    if (rb_equal(INT2FIX(0), y)) rb_num_zerodiv();
    return rb_funcall(rb_funcall(x, '/', 1, y), rb_intern("floor"), 0);
}
divmod(numeric) → array click to toggle source

Returns an array containing the quotient and modulus obtained by dividing num by numeric. If q, r = x.divmod(y), then

q = floor(x/y)
x = q*y+r

The quotient is rounded toward -infinity, as shown in the following table:

 a    |  b  |  a.divmod(b)  |   a/b   | a.modulo(b) | a.remainder(b)
------+-----+---------------+---------+-------------+---------------
 13   |  4  |   3,    1     |   3     |    1        |     1
------+-----+---------------+---------+-------------+---------------
 13   | -4  |  -4,   -3     |  -4     |   -3        |     1
------+-----+---------------+---------+-------------+---------------
-13   |  4  |  -4,    3     |  -4     |    3        |    -1
------+-----+---------------+---------+-------------+---------------
-13   | -4  |   3,   -1     |   3     |   -1        |    -1
------+-----+---------------+---------+-------------+---------------
 11.5 |  4  |   2,    3.5   |   2.875 |    3.5      |     3.5
------+-----+---------------+---------+-------------+---------------
 11.5 | -4  |  -3,   -0.5   |  -2.875 |   -0.5      |     3.5
------+-----+---------------+---------+-------------+---------------
-11.5 |  4  |  -3,    0.5   |  -2.875 |    0.5      |    -3.5
------+-----+---------------+---------+-------------+---------------
-11.5 | -4  |   2,   -3.5   |   2.875 |   -3.5      |    -3.5

Examples

11.divmod(3)         #=> [3, 2]
11.divmod(-3)        #=> [-4, -1]
11.divmod(3.5)       #=> [3, 0.5]
(-11).divmod(3.5)    #=> [-4, 3.0]
(11.5).divmod(3.5)   #=> [3, 1.0]

static VALUE
num_divmod(VALUE x, VALUE y)
{
    return rb_assoc_new(num_div(x, y), num_modulo(x, y));
}
eql?(numeric) → true or false click to toggle source

Returns true if num and numeric are the same type and have equal values.

1 == 1.0          #=> true
1.eql?(1.0)       #=> false
(1.0).eql?(1.0)   #=> true

static VALUE
num_eql(VALUE x, VALUE y)
{
    if (TYPE(x) != TYPE(y)) return Qfalse;

    return rb_equal(x, y);
}
fdiv(numeric) → float click to toggle source

Returns float division.

static VALUE
num_fdiv(VALUE x, VALUE y)
{
    return rb_funcall(rb_Float(x), '/', 1, y);
}
floor → integer click to toggle source

Returns the largest integer less than or equal to num. Numeric implements this by converting anInteger to a Float and invoking Float#floor.

1.floor      #=> 1
(-1).floor   #=> -1

static VALUE
num_floor(VALUE num)
{
    return flo_floor(rb_Float(num));
}
i → Complex(0,num) click to toggle source

Returns the corresponding imaginary number. Not available for complex numbers.

static VALUE
num_imaginary(VALUE num)
{
    return rb_complex_new(INT2FIX(0), num);
}
imag → 0 click to toggle source
imaginary → 0

Returns zero.

static VALUE
numeric_imag(VALUE self)
{
    return INT2FIX(0);
}
imag → 0 click to toggle source
imaginary → 0

Returns zero.

static VALUE
numeric_imag(VALUE self)
{
    return INT2FIX(0);
}
integer? → true or false click to toggle source

Returns true if num is an Integer (including Fixnum and Bignum).

(1.0).integer? #=> false
(1).integer?   #=> true

static VALUE
num_int_p(VALUE num)
{
    return Qfalse;
}
abs → numeric click to toggle source
magnitude → numeric

Returns the absolute value of num.

12.abs         #=> 12
(-34.56).abs   #=> 34.56
-34.56.abs     #=> 34.56

static VALUE
num_abs(VALUE num)
{
    if (negative_int_p(num)) {
        return rb_funcall(num, rb_intern("-@"), 0);
    }
    return num;
}
modulo(numeric) → real click to toggle source
x.modulo(y) means x-y*(x/y).floor

Equivalent to num.divmod(aNumeric).

See Numeric#divmod.

static VALUE
num_modulo(VALUE x, VALUE y)
{
    return rb_funcall(x, '-', 1,
                      rb_funcall(y, '*', 1,
                                 rb_funcall(x, rb_intern("div"), 1, y)));
}
nonzero? → self or nil click to toggle source

Returns self if num is not zero, nil otherwise. This behavior is useful when chaining comparisons:

a = %w( z Bb bB bb BB a aA Aa AA A )
b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
b   #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]

static VALUE
num_nonzero_p(VALUE num)
{
    if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
        return Qnil;
    }
    return num;
}
numerator → integer click to toggle source

Returns the numerator.

static VALUE
numeric_numerator(VALUE self)
{
    return f_numerator(f_to_r(self));
}
arg → 0 or float click to toggle source
angle → 0 or float
phase → 0 or float

Returns 0 if the value is positive, pi otherwise.

static VALUE
numeric_arg(VALUE self)
{
    if (f_positive_p(self))
        return INT2FIX(0);
    return rb_const_get(rb_mMath, id_PI);
}
polar → array click to toggle source

Returns an array; [num.abs, num.arg].

static VALUE
numeric_polar(VALUE self)
{
    return rb_assoc_new(f_abs(self), f_arg(self));
}
quo(numeric) → real click to toggle source

Returns most exact division (rational for integers, float for floats).

static VALUE
num_quo(VALUE x, VALUE y)
{
    return rb_funcall(rb_rational_raw1(x), '/', 1, y);
}
real → self click to toggle source

Returns self.

static VALUE
numeric_real(VALUE self)
{
    return self;
}
real? → true or false click to toggle source

Returns true if num is a Real (i.e. non Complex).

static VALUE
num_real_p(VALUE num)
{
    return Qtrue;
}
rect → array click to toggle source

Returns an array; [num, 0].

static VALUE
numeric_rect(VALUE self)
{
    return rb_assoc_new(self, INT2FIX(0));
}
rect → array click to toggle source

Returns an array; [num, 0].

static VALUE
numeric_rect(VALUE self)
{
    return rb_assoc_new(self, INT2FIX(0));
}
remainder(numeric) → real click to toggle source
x.remainder(y) means x-y*(x/y).truncate

See Numeric#divmod.

static VALUE
num_remainder(VALUE x, VALUE y)
{
    VALUE z = rb_funcall(x, '%', 1, y);

    if ((!rb_equal(z, INT2FIX(0))) &&
        ((negative_int_p(x) &&
          positive_int_p(y)) ||
         (positive_int_p(x) &&
          negative_int_p(y)))) {
        return rb_funcall(z, '-', 1, y);
    }
    return z;
}
round([ndigits]) → integer or float click to toggle source

Rounds num to a given precision in decimal digits (default 0 digits). Precision may be negative. Returns a floating point number when ndigits is more than zero. Numeric implements this by converting itself to a Float and invoking Float#round.

static VALUE
num_round(int argc, VALUE* argv, VALUE num)
{
    return flo_round(argc, argv, rb_Float(num));
}
singleton_method_added(p1) click to toggle source

Trap attempts to add methods to Numeric objects. Always raises a TypeError

static VALUE
num_sadded(VALUE x, VALUE name)
{
    ID mid = rb_to_id(name);
    /* ruby_frame = ruby_frame->prev; */ /* pop frame for "singleton_method_added" */
    /* Numerics should be values; singleton_methods should not be added to them */
    rb_remove_method_id(rb_singleton_class(x), mid);
    rb_raise(rb_eTypeError,
             "can't define singleton method \"%"PRIsVALUE"\" for %"PRIsVALUE,
             rb_id2str(mid),
             rb_obj_class(x));

    UNREACHABLE;
}
step(limit[, step]) {|i| block } → self click to toggle source
step(limit[, step]) → an_enumerator

Invokes block with the sequence of numbers starting at num, incremented by step (default 1) on each call. The loop finishes when the value to be passed to the block is greater than limit (if step is positive) or less than limit (if step is negative). If all the arguments are integers, the loop operates using an integer counter. If any of the arguments are floating point numbers, all are converted to floats, and the loop is executed floor(n + n*epsilon)+ 1 times, where n = (limit - num)/step. Otherwise, the loop starts at num, uses either the < or > operator to compare the counter against limit, and increments itself using the + operator.

If no block is given, an enumerator is returned instead.

1.step(10, 2) { |i| print i, " " }
Math::E.step(Math::PI, 0.2) { |f| print f, " " }

produces:

1 3 5 7 9
2.71828182845905 2.91828182845905 3.11828182845905
static VALUE
num_step(int argc, VALUE *argv, VALUE from)
{
    VALUE to, step;

    RETURN_SIZED_ENUMERATOR(from, argc, argv, num_step_size);
    if (argc == 1) {
        to = argv[0];
        step = INT2FIX(1);
    }
    else {
        rb_check_arity(argc, 1, 2);
        to = argv[0];
        step = argv[1];
        if (rb_equal(step, INT2FIX(0))) {
            rb_raise(rb_eArgError, "step can't be 0");
        }
    }

    if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
        long i, end, diff;

        i = FIX2LONG(from);
        end = FIX2LONG(to);
        diff = FIX2LONG(step);

        if (diff > 0) {
            while (i <= end) {
                rb_yield(LONG2FIX(i));
                i += diff;
            }
        }
        else {
            while (i >= end) {
                rb_yield(LONG2FIX(i));
                i += diff;
            }
        }
    }
    else if (!ruby_float_step(from, to, step, FALSE)) {
        VALUE i = from;
        ID cmp;

        if (positive_int_p(step)) {
            cmp = '>';
        }
        else {
            cmp = '<';
        }
        for (;;) {
            if (RTEST(rb_funcall(i, cmp, 1, to))) break;
            rb_yield(i);
            i = rb_funcall(i, '+', 1, step);
        }
    }
    return from;
}
to_c → complex click to toggle source

Returns the value as a complex.

static VALUE
numeric_to_c(VALUE self)
{
    return rb_complex_new1(self);
}
to_int → integer click to toggle source

Invokes the child class's to_i method to convert num to an integer.

1.0.class => Float
1.0.to_int.class => Fixnum
1.0.to_i.class => Fixnum

static VALUE
num_to_int(VALUE num)
{
    return rb_funcall(num, id_to_i, 0, 0);
}
truncate → integer click to toggle source

Returns num truncated to an integer. Numeric implements this by converting its value to a float and invoking Float#truncate.

static VALUE
num_truncate(VALUE num)
{
    return flo_truncate(rb_Float(num));
}
zero? → true or false click to toggle source

Returns true if num has a zero value.

static VALUE
num_zero_p(VALUE num)
{
    if (rb_equal(num, INT2FIX(0))) {
        return Qtrue;
    }
    return Qfalse;
}


class Object - Ruby 2.0.0-p576 Core API Reference API Reference

class Object

Object is the default root of all Ruby objects. Object inherits from BasicObject which allows creating alternate object hierarchies. Methods on object are available to all classes unless explicitly overridden.

Object mixes in the Kernel module, making the built-in kernel functions globally accessible. Although the instance methods of Object are defined by the Kernel module, we have chosen to document them here for clarity.

When referencing constants in classes inheriting from Object you do not need to use the full namespace. For example, referencing File inside YourClass will find the top-level File class.

In the descriptions of Object's methods, the parameter symbol refers to a symbol, which is either a quoted string or a Symbol (such as :name).

In Files

  • class.c
  • enumerator.c
  • eval.c
  • gc.c
  • hash.c
  • io.c
  • object.c
  • parse.c
  • proc.c
  • ruby.c
  • version.c
  • vm.c
  • vm_eval.c
  • vm_method.c

Parent

BasicObject

Included Modules

  • Kernel

Constants

ARGF

ARGF is a stream designed for use in scripts that process files given as command-line arguments or passed in via STDIN.

See ARGF (the class) for more details.

ARGV

ARGV contains the command line arguments used to run ruby with the first value containing the name of the executable.

A library like OptionParser can be used to process command-line arguments.

DATA

DATA is a File that contains the data section of the executed file. To create a data section use __END__:

$ cat t.rb
puts DATA.gets
__END__
hello world!

$ ruby t.rb
hello world!
ENV

ENV is a Hash-like accessor for environment variables.

See ENV (the class) for more details.

FALSE

An alias of false

NIL

An alias of nil

RUBY_COPYRIGHT

The copyright string for ruby

RUBY_DESCRIPTION

The full ruby version string, like ruby -v prints'

RUBY_ENGINE

The engine or interpreter this ruby uses.

RUBY_PATCHLEVEL

The patchlevel for this ruby. If this is a development build of ruby the patchlevel will be -1

RUBY_PLATFORM

The platform for this ruby

RUBY_RELEASE_DATE

The date this ruby was released

RUBY_REVISION

The SVN revision for this ruby.

RUBY_VERSION

The running version of ruby

SCRIPT_LINES__

When a Hash is assigned to SCRIPT_LINES__ the contents of files loaded after the assignment will be added as an Array of lines with the file name as the key.

STDERR

Holds the original stderr

STDIN

Holds the original stdin

STDOUT

Holds the original stdout

TOPLEVEL_BINDING

The Binding of the top level scope

TRUE

An alias of true

Public Instance Methods

obj !~ other → true or false click to toggle source

Returns true if two objects do not match (using the =~ method), otherwise false.

static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
    VALUE result = rb_funcall(obj1, id_match, 1, obj2);
    return RTEST(result) ? Qfalse : Qtrue;
}
obj <=> other → 0 or nil click to toggle source

Returns 0 if obj and other are the same object or obj == other, otherwise nil.

The <=> is used by various methods to compare objects, for example Enumerable#sort, Enumerable#max etc.

Your implementation of <=> should return one of the following values: -1, 0, 1 or nil. -1 means self is smaller than other. 0 means self is equal to other. 1 means self is bigger than other. Nil means the two values could not be compared.

When you define <=>, you can include Comparable to gain the methods <=, <,

, >=, > and between?.

static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2 || rb_equal(obj1, obj2))
        return INT2FIX(0);
    return Qnil;
}
obj === other → true or false click to toggle source

Case Equality – For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.

VALUE
rb_equal(VALUE obj1, VALUE obj2)
{
    VALUE result;

    if (obj1 == obj2) return Qtrue;
    result = rb_funcall(obj1, id_eq, 1, obj2);
    if (RTEST(result)) return Qtrue;
    return Qfalse;
}
obj =~ other → nil click to toggle source

Pattern Match—Overridden by descendants (notably Regexp and String) to provide meaningful pattern-match semantics.

static VALUE
rb_obj_match(VALUE obj1, VALUE obj2)
{
    return Qnil;
}
class → class click to toggle source

Returns the class of obj. This method must always be called with an explicit receiver, as class is also a reserved word in Ruby.

1.class      #=> Fixnum
self.class   #=> Object

VALUE
rb_obj_class(VALUE obj)
{
    return rb_class_real(CLASS_OF(obj));
}
clone → an_object click to toggle source

Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. Copies the frozen and tainted state of obj. See also the discussion under Object#dup.

class Klass
   attr_accessor :str
end
s1 = Klass.new      #=> #<Klass:0x401b3a38>
s1.str = "Hello"    #=> "Hello"
s2 = s1.clone       #=> #<Klass:0x401b3998 @str="Hello">
s2.str[1,4] = "i"   #=> "i"
s1.inspect          #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
s2.inspect          #=> "#<Klass:0x401b3998 @str=\"Hi\">"

This method may have class-specific behavior. If so, that behavior will be documented under the #initialize_copy method of the class.

VALUE
rb_obj_clone(VALUE obj)
{
    VALUE clone;
    VALUE singleton;

    if (rb_special_const_p(obj)) {
        rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
    }
    clone = rb_obj_alloc(rb_obj_class(obj));
    singleton = rb_singleton_class_clone_and_attach(obj, clone);
    RBASIC(clone)->klass = singleton;
    if (FL_TEST(singleton, FL_SINGLETON)) {
        rb_singleton_class_attached(singleton, clone);
    }
    RBASIC(clone)->flags &= (FL_TAINT|FL_UNTRUSTED);
    RBASIC(clone)->flags |= RBASIC(obj)->flags & ~(FL_FREEZE|FL_FINALIZE);
    init_copy(clone, obj);
    rb_funcall(clone, id_init_clone, 1, obj);
    RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;

    return clone;
}
define_singleton_method(symbol, method) → new_method click to toggle source
define_singleton_method(symbol) { block } → proc

Defines a singleton method in the receiver. The method parameter can be a Proc, a Method or an UnboundMethod object. If a block is specified, it is used as the method body.

class A
  class << self
    def class_name
      to_s
    end
  end
end
A.define_singleton_method(:who_am_i) do
  "I am: #{class_name}"
end
A.who_am_i   # ==> "I am: A"

guy = "Bob"
guy.define_singleton_method(:hello) { "#{self}: Hello there!" }
guy.hello    #=>  "Bob: Hello there!"

static VALUE
rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
{
    VALUE klass = rb_singleton_class(obj);

    return rb_mod_define_method(argc, argv, klass);
}
display(port=$>) → nil click to toggle source

Prints obj on the given port (default $>). Equivalent to:

def display(port=$>)
  port.write self
end

For example:

1.display
"cat".display
[ 4, 5, 6 ].display
puts

produces:

1cat456
static VALUE
rb_obj_display(int argc, VALUE *argv, VALUE self)
{
    VALUE out;

    if (argc == 0) {
        out = rb_stdout;
    }
    else {
        rb_scan_args(argc, argv, "01", &out);
    }
    rb_io_write(out, self);

    return Qnil;
}
dup → an_object click to toggle source

Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. dup copies the tainted state of obj. See also the discussion under Object#clone. In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance.

This method may have class-specific behavior. If so, that behavior will be documented under the #initialize_copy method of the class.

VALUE
rb_obj_dup(VALUE obj)
{
    VALUE dup;

    if (rb_special_const_p(obj)) {
        rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
    }
    dup = rb_obj_alloc(rb_obj_class(obj));
    init_copy(dup, obj);
    rb_funcall(dup, id_init_dup, 1, obj);

    return dup;
}
to_enum(method = :each, *args) → enum click to toggle source
enum_for(method = :each, *args) → enum
to_enum(method = :each, *args) {|*args| block} → enum
enum_for(method = :each, *args){|*args| block} → enum

Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.

If a block is given, it will be used to calculate the size of the enumerator without the need to iterate it (see Enumerator#size).

Examples

str = "xyz"

enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122

# protect an array from being modified by some_method
a = [1, 2, 3]
some_method(a.to_enum)

It is typical to call #to_enum when defining methods for a generic Enumerable, in case no block is passed.

Here is such an example, with parameter passing and a sizing block:

module Enumerable
  # a generic method to repeat the values of any enumerable
  def repeat(n)
    raise ArgumentError, "#{n} is negative!" if n < 0
    unless block_given?
      return to_enum(__method__, n) do # __method__ is :repeat here
        sz = size     # Call size and multiply by n...
        sz * n if sz  # but return nil if size itself is nil
      end
    end
    each do |*val|
      n.times { yield *val }
    end
  end
end

%[hello world].repeat(2) { |w| puts w }
  # => Prints 'hello', 'hello', 'world', 'world'
enum = (1..14).repeat(3)
  # => returns an Enumerator when called without a block
enum.first(4) # => [1, 1, 1, 2]
enum.size # => 42

static VALUE
obj_to_enum(int argc, VALUE *argv, VALUE obj)
{
    VALUE enumerator, meth = sym_each;

    if (argc > 0) {
        --argc;
        meth = *argv++;
    }
    enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
    if (rb_block_given_p()) {
        enumerator_ptr(enumerator)->size = rb_block_proc();
    }
    return enumerator;
}
obj == other → true or false click to toggle source
equal?(other) → true or false
eql?(other) → true or false

Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

Unlike ==, the equal? method should never be overridden by subclasses as it is used to determine object identity (that is, a.equal?(b) if and only if a is the same object as b):

obj = "a"
other = obj.dup

a == other      #=> true
a.equal? other  #=> false
a.equal? a      #=> true

The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}
extend(module, ...) → obj click to toggle source

Adds to obj the instance methods from each module given as a parameter.

module Mod
  def hello
    "Hello from Mod.\n"
  end
end

class Klass
  def hello
    "Hello from Klass.\n"
  end
end

k = Klass.new
k.hello         #=> "Hello from Klass.\n"
k.extend(Mod)   #=> #<Klass:0x401b3bc8>
k.hello         #=> "Hello from Mod.\n"

static VALUE
rb_obj_extend(int argc, VALUE *argv, VALUE obj)
{
    int i;
    ID id_extend_object, id_extended;

    CONST_ID(id_extend_object, "extend_object");
    CONST_ID(id_extended, "extended");

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    for (i = 0; i < argc; i++)
        Check_Type(argv[i], T_MODULE);
    while (argc--) {
        rb_funcall(argv[argc], id_extend_object, 1, obj);
        rb_funcall(argv[argc], id_extended, 1, obj);
    }
    return obj;
}
freeze → obj click to toggle source

Prevents further modifications to obj. A RuntimeError will be raised if modification is attempted. There is no way to unfreeze a frozen object. See also Object#frozen?.

This method returns self.

a = [ "a", "b", "c" ]
a.freeze
a << "z"

produces:

prog.rb:3:in `<<': can't modify frozen array (RuntimeError)
 from prog.rb:3
VALUE
rb_obj_freeze(VALUE obj)
{
    if (!OBJ_FROZEN(obj)) {
        if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(obj)) {
            rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
        }
        OBJ_FREEZE(obj);
        if (SPECIAL_CONST_P(obj)) {
            if (!immediate_frozen_tbl) {
                immediate_frozen_tbl = st_init_numtable();
            }
            st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
        }
    }
    return obj;
}
frozen? → true or false click to toggle source

Returns the freeze status of obj.

a = [ "a", "b", "c" ]
a.freeze    #=> ["a", "b", "c"]
a.frozen?   #=> true

VALUE
rb_obj_frozen_p(VALUE obj)
{
    if (OBJ_FROZEN(obj)) return Qtrue;
    if (SPECIAL_CONST_P(obj)) {
        if (!immediate_frozen_tbl) return Qfalse;
        if (st_lookup(immediate_frozen_tbl, obj, 0)) return Qtrue;
    }
    return Qfalse;
}
hash() click to toggle source

Generates a Fixnum hash value for this object. This function must have the property that a.eql?(b) implies a.hash == b.hash.

The hash value is used along with eql? by the Hash class to determine if two objects reference the same hash key. Any hash value that exceeds the capacity of a Fixnum will be truncated before being used.

The hash value for an object may not be identical across invocations or implementations of ruby. If you need a stable identifier across ruby invocations and implementations you will need to generate one with a custom method.

VALUE
rb_obj_hash(VALUE obj)
{
    VALUE oid = rb_obj_id(obj);
#if SIZEOF_LONG == SIZEOF_VOIDP
    st_index_t index = NUM2LONG(oid);
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
    st_index_t index = NUM2LL(oid);
#else
# error not supported
#endif
    st_index_t h = rb_hash_end(rb_hash_start(index));
    return LONG2FIX(h);
}
inspect → string click to toggle source

Returns a string containing a human-readable representation of obj. By default, show the class name and the list of the instance variables and their values (by calling inspect on each of them). User defined classes should override this method to make better representation of obj. When overriding this method, it should return a string whose encoding is compatible with the default external encoding.

[ 1, 2, 3..4, 'five' ].inspect   #=> "[1, 2, 3..4, \"five\"]"
Time.new.inspect                 #=> "2008-03-08 19:43:39 +0900"

class Foo
end
Foo.new.inspect                  #=> "#<Foo:0x0300c868>"

class Bar
  def initialize
    @bar = 1
  end
end
Bar.new.inspect                  #=> "#<Bar:0x0300c868 @bar=1>"

class Baz
  def to_s
    "baz"
  end
end
Baz.new.inspect                  #=> "#<Baz:0x0300c868>"

static VALUE
rb_obj_inspect(VALUE obj)
{
    if (rb_ivar_count(obj) > 0) {
        VALUE str;
        VALUE c = rb_class_name(CLASS_OF(obj));

        str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
        return rb_exec_recursive(inspect_obj, obj, str);
    }
    else {
        return rb_any_to_s(obj);
    }
}
instance_of?(class) → true or false click to toggle source

Returns true if obj is an instance of the given class. See also Object#kind_of?.

class A;     end
class B < A; end
class C < B; end

b = B.new
b.instance_of? A   #=> false
b.instance_of? B   #=> true
b.instance_of? C   #=> false

VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
    c = class_or_module_required(c);
    if (rb_obj_class(obj) == c) return Qtrue;
    return Qfalse;
}
instance_variable_defined?(symbol) → true or false click to toggle source

Returns true if the given instance variable is defined in obj.

class Fred
  def initialize(p1, p2)
    @a, @b = p1, p2
  end
end
fred = Fred.new('cat', 99)
fred.instance_variable_defined?(:@a)    #=> true
fred.instance_variable_defined?("@b")   #=> true
fred.instance_variable_defined?("@c")   #=> false

static VALUE
rb_obj_ivar_defined(VALUE obj, VALUE iv)
{
    ID id = rb_check_id(&iv);

    if (!id) {
        if (rb_is_instance_name(iv)) {
            return Qfalse;
        }
        else {
            rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                              QUOTE(iv));
        }
    }
    if (!rb_is_instance_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                      QUOTE_ID(id));
    }
    return rb_ivar_defined(obj, id);
}
instance_variable_get(symbol) → obj click to toggle source

Returns the value of the given instance variable, or nil if the instance variable is not set. The @ part of the variable name should be included for regular instance variables. Throws a NameError exception if the supplied symbol is not valid as an instance variable name.

class Fred
  def initialize(p1, p2)
    @a, @b = p1, p2
  end
end
fred = Fred.new('cat', 99)
fred.instance_variable_get(:@a)    #=> "cat"
fred.instance_variable_get("@b")   #=> 99

static VALUE
rb_obj_ivar_get(VALUE obj, VALUE iv)
{
    ID id = rb_check_id(&iv);

    if (!id) {
        if (rb_is_instance_name(iv)) {
            return Qnil;
        }
        else {
            rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                              QUOTE(iv));
        }
    }
    if (!rb_is_instance_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                      QUOTE_ID(id));
    }
    return rb_ivar_get(obj, id);
}
instance_variable_set(symbol, obj) → obj click to toggle source

Sets the instance variable names by symbol to object, thereby frustrating the efforts of the class's author to attempt to provide proper encapsulation. The variable did not have to exist prior to this call.

class Fred
  def initialize(p1, p2)
    @a, @b = p1, p2
  end
end
fred = Fred.new('cat', 99)
fred.instance_variable_set(:@a, 'dog')   #=> "dog"
fred.instance_variable_set(:@c, 'cat')   #=> "cat"
fred.inspect                             #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"

static VALUE
rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val)
{
    ID id = rb_to_id(iv);

    if (!rb_is_instance_id(id)) {
        rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                      QUOTE_ID(id));
    }
    return rb_ivar_set(obj, id, val);
}
instance_variables → array click to toggle source

Returns an array of instance variable names for the receiver. Note that simply defining an accessor does not create the corresponding instance variable.

class Fred
  attr_accessor :a1
  def initialize
    @iv = 3
  end
end
Fred.new.instance_variables   #=> [:@iv]

VALUE
rb_obj_instance_variables(VALUE obj)
{
    VALUE ary;

    ary = rb_ary_new();
    rb_ivar_foreach(obj, ivar_i, ary);
    return ary;
}
is_a?(class) → true or false click to toggle source
kind_of?(class) → true or false

Returns true if class is the class of obj, or if class is one of the superclasses of obj or modules included in obj.

module M;    end
class A
  include M
end
class B < A; end
class C < B; end

b = B.new
b.is_a? A          #=> true
b.is_a? B          #=> true
b.is_a? C          #=> false
b.is_a? M          #=> true

b.kind_of? A       #=> true
b.kind_of? B       #=> true
b.kind_of? C       #=> false
b.kind_of? M       #=> true

VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
    VALUE cl = CLASS_OF(obj);

    c = class_or_module_required(c);
    return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
}
is_a?(class) → true or false click to toggle source
kind_of?(class) → true or false

Returns true if class is the class of obj, or if class is one of the superclasses of obj or modules included in obj.

module M;    end
class A
  include M
end
class B < A; end
class C < B; end

b = B.new
b.is_a? A          #=> true
b.is_a? B          #=> true
b.is_a? C          #=> false
b.is_a? M          #=> true

b.kind_of? A       #=> true
b.kind_of? B       #=> true
b.kind_of? C       #=> false
b.kind_of? M       #=> true

VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
    VALUE cl = CLASS_OF(obj);

    c = class_or_module_required(c);
    return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
}
method(sym) → method click to toggle source

Looks up the named method as a receiver in obj, returning a Method object (or raising NameError). The Method object acts as a closure in obj's object instance, so instance variables and the value of self remain available.

class Demo
  def initialize(n)
    @iv = n
  end
  def hello()
    "Hello, @iv = #{@iv}"
  end
end

k = Demo.new(99)
m = k.method(:hello)
m.call   #=> "Hello, @iv = 99"

l = Demo.new('Fred')
m = l.method("hello")
m.call   #=> "Hello, @iv = Fred"

VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(CLASS_OF(obj), vid);
    }
    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, FALSE);
}
methods(all=true) → array click to toggle source

Returns a list of the names of public and protected methods of obj. This will include all the methods accessible in obj's ancestors. If the all parameter is set to false, only those methods in the receiver will be listed.

class Klass
  def klass_method()
  end
end
k = Klass.new
k.methods[0..9]    #=> [:klass_method, :nil?, :===,
                   #    :==~, :!, :eql?
                   #    :hash, :<=>, :class, :singleton_class]
k.methods.length   #=> 57

VALUE
rb_obj_methods(int argc, VALUE *argv, VALUE obj)
{
  retry:
    if (argc == 0) {
    return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
    }
    else {
    VALUE recur;

    rb_scan_args(argc, argv, "1", &recur);
    if (RTEST(recur)) {
        argc = 0;
        goto retry;
    }
    return rb_obj_singleton_methods(argc, argv, obj);
    }
}
nil?() click to toggle source

call_seq:

nil.nil?               -> true
<anything_else>.nil?   -> false

Only the object nil responds true to nil?.

static VALUE
rb_false(VALUE obj)
{
    return Qfalse;
}
__id__ → integer click to toggle source
object_id → integer

Returns an integer identifier for obj.

The same number will be returned on all calls to id for a given object, and no two active objects will share an id.

#object_id is a different concept from the :name notation, which returns the symbol id of name.

Replaces the deprecated Object#id.

VALUE
rb_obj_id(VALUE obj)
{
    /*
     *                32-bit VALUE space
     *          MSB ------------------------ LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol  ssssssssssssssssssssssss00001110
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
     *  fixnum  fffffffffffffffffffffffffffffff1
     *
     *                    object_id space
     *                                       LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
     *
     *  where A = sizeof(RVALUE)/4
     *
     *  sizeof(RVALUE) is
     *  20 if 32-bit, double is 4-byte aligned
     *  24 if 32-bit, double is 8-byte aligned
     *  40 if 64-bit
     */
    if (SYMBOL_P(obj)) {
        return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
    }
    else if (FLONUM_P(obj)) {
#if SIZEOF_LONG == SIZEOF_VOIDP
        return LONG2NUM((SIGNED_VALUE)obj);
#else
        return LL2NUM((SIGNED_VALUE)obj);
#endif
    }
    else if (SPECIAL_CONST_P(obj)) {
        return LONG2NUM((SIGNED_VALUE)obj);
    }
    return nonspecial_obj_id(obj);
}
private_methods(all=true) → array click to toggle source

Returns the list of private methods accessible to obj. If the all parameter is set to false, only those methods in the receiver will be listed.

VALUE
rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
{
    return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
}
protected_methods(all=true) → array click to toggle source

Returns the list of protected methods accessible to obj. If the all parameter is set to false, only those methods in the receiver will be listed.

VALUE
rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
{
    return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
}
public_method(sym) → method click to toggle source

Similar to method, searches public method only.

VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(CLASS_OF(obj), vid);
    }
    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, TRUE);
}
public_methods(all=true) → array click to toggle source

Returns the list of public methods accessible to obj. If the all parameter is set to false, only those methods in the receiver will be listed.

VALUE
rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
{
    return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
}
public_send(symbol [, args...]) → obj click to toggle source

Invokes the method identified by symbol, passing it any arguments specified. Unlike send, #public_send calls public methods only.

1.public_send(:puts, "hello")  # causes NoMethodError
VALUE
rb_f_public_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal(argc, argv, recv, CALL_PUBLIC);
}
remove_instance_variable(symbol) → obj click to toggle source

Removes the named instance variable from obj, returning that variable's value.

class Dummy
  attr_reader :var
  def initialize
    @var = 99
  end
  def remove
    remove_instance_variable(:@var)
  end
end
d = Dummy.new
d.var      #=> 99
d.remove   #=> 99
d.var      #=> nil

VALUE
rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
    VALUE val = Qnil;
    const ID id = rb_check_id(&name);
    st_data_t n, v;
    struct st_table *iv_index_tbl;
    st_data_t index;

    if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
    rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
    rb_check_frozen(obj);
    if (!id) {
    if (rb_is_instance_name(name)) {
        rb_name_error_str(name, "instance variable %"PRIsVALUE" not defined",
                  name);
    }
    else {
        rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as an instance variable name",
                  QUOTE(name));
    }
    }
    if (!rb_is_instance_id(id)) {
    rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
              QUOTE_ID(id));
    }

    if (SPECIAL_CONST_P(obj)) goto generic;
    switch (BUILTIN_TYPE(obj)) {
      case T_OBJECT:
        iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
        if (!iv_index_tbl) break;
        if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
        if (ROBJECT_NUMIV(obj) <= (long)index) break;
        val = ROBJECT_IVPTR(obj)[index];
        if (val != Qundef) {
            ROBJECT_IVPTR(obj)[index] = Qundef;
            return val;
        }
    break;
      case T_CLASS:
      case T_MODULE:
    n = id;
    if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
        return (VALUE)v;
    }
    break;
      default:
      generic:
    if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
        v = val;
        if (generic_ivar_remove(obj, (st_data_t)id, &v)) {
        return (VALUE)v;
        }
    }
    break;
    }
    rb_name_error(id, "instance variable %"PRIsVALUE" not defined", QUOTE_ID(id));

    UNREACHABLE;
}
respond_to?(symbol, include_all=false) → true or false click to toggle source

Returns true if obj responds to the given method. Private and protected methods are included in the search only if the optional second parameter evaluates to true.

If the method is not implemented, as Process.fork on Windows, File.lchmod on GNU/Linux, etc., false is returned.

If the method is not defined, respond_to_missing? method is called and the result is returned.

static VALUE
obj_respond_to(int argc, VALUE *argv, VALUE obj)
{
    VALUE mid, priv;
    ID id;

    rb_scan_args(argc, argv, "11", &mid, &priv);
    if (!(id = rb_check_id(&mid))) {
        if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
            VALUE args[2];
            args[0] = ID2SYM(rb_to_id(mid));
            args[1] = priv;
            return rb_funcall2(obj, idRespond_to_missing, 2, args);
        }
        return Qfalse;
    }
    if (basic_obj_respond_to(obj, id, !RTEST(priv)))
        return Qtrue;
    return Qfalse;
}
respond_to_missing?(symbol, include_all) → true or false click to toggle source

DO NOT USE THIS DIRECTLY.

Hook method to return whether the obj can respond to id method or not.

See respond_to?.

static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
    return Qfalse;
}
send(symbol [, args...]) → obj click to toggle source
__send__(symbol [, args...]) → obj

Invokes the method identified by symbol, passing it any arguments specified. You can use __send__ if the name send clashes with an existing method in obj.

class Klass
  def hello(*args)
    "Hello " + args.join(' ')
  end
end
k = Klass.new
k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"

VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal(argc, argv, recv, CALL_FCALL);
}
singleton_class → class click to toggle source

Returns the singleton class of obj. This method creates a new singleton class if obj does not have it.

If obj is nil, true, or false, it returns NilClass, TrueClass, or FalseClass, respectively. If obj is a Fixnum or a Symbol, it raises a TypeError.

Object.new.singleton_class  #=> #<Class:#<Object:0xb7ce1e24>>
String.singleton_class      #=> #<Class:String>
nil.singleton_class         #=> NilClass

static VALUE
rb_obj_singleton_class(VALUE obj)
{
    return rb_singleton_class(obj);
}
singleton_methods(all=true) → array click to toggle source

Returns an array of the names of singleton methods for obj. If the optional all parameter is true, the list will include methods in modules included in obj. Only public and protected singleton methods are returned.

module Other
  def three() end
end

class Single
  def Single.four() end
end

a = Single.new

def a.one()
end

class << a
  include Other
  def two()
  end
end

Single.singleton_methods    #=> [:four]
a.singleton_methods(false)  #=> [:two, :one]
a.singleton_methods         #=> [:two, :one, :three]

VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{
    VALUE recur, ary, klass;
    st_table *list;

    if (argc == 0) {
    recur = Qtrue;
    }
    else {
    rb_scan_args(argc, argv, "01", &recur);
    }
    klass = CLASS_OF(obj);
    list = st_init_numtable();
    if (klass && FL_TEST(klass, FL_SINGLETON)) {
    if (RCLASS_M_TBL(klass))
        st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
    klass = RCLASS_SUPER(klass);
    }
    if (RTEST(recur)) {
    while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
        if (RCLASS_M_TBL(klass))
        st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
        klass = RCLASS_SUPER(klass);
    }
    }
    ary = rb_ary_new();
    st_foreach(list, ins_methods_i, ary);
    st_free_table(list);

    return ary;
}
taint → obj click to toggle source

Marks obj as tainted—if the $SAFE level is set appropriately, many method calls which might alter the running programs environment will refuse to accept tainted strings.

VALUE
rb_obj_taint(VALUE obj)
{
    rb_secure(4);
    if (!OBJ_TAINTED(obj)) {
        rb_check_frozen(obj);
        OBJ_TAINT(obj);
    }
    return obj;
}
tainted? → true or false click to toggle source

Returns true if the object is tainted.

VALUE
rb_obj_tainted(VALUE obj)
{
    if (OBJ_TAINTED(obj))
        return Qtrue;
    return Qfalse;
}
tap{|x|...} → obj click to toggle source

Yields x to the block, and then returns x. The primary purpose of this method is to “tap into” a method chain, in order to perform operations on intermediate results within the chain.

(1..10)                .tap {|x| puts "original: #{x.inspect}"}
  .to_a                .tap {|x| puts "array: #{x.inspect}"}
  .select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
  .map { |x| x*x }     .tap {|x| puts "squares: #{x.inspect}"}

VALUE
rb_obj_tap(VALUE obj)
{
    rb_yield(obj);
    return obj;
}
to_enum(method = :each, *args) → enum click to toggle source
enum_for(method = :each, *args) → enum
to_enum(method = :each, *args) {|*args| block} → enum
enum_for(method = :each, *args){|*args| block} → enum

Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.

If a block is given, it will be used to calculate the size of the enumerator without the need to iterate it (see Enumerator#size).

Examples

str = "xyz"

enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122

# protect an array from being modified by some_method
a = [1, 2, 3]
some_method(a.to_enum)

It is typical to call #to_enum when defining methods for a generic Enumerable, in case no block is passed.

Here is such an example, with parameter passing and a sizing block:

module Enumerable
  # a generic method to repeat the values of any enumerable
  def repeat(n)
    raise ArgumentError, "#{n} is negative!" if n < 0
    unless block_given?
      return to_enum(__method__, n) do # __method__ is :repeat here
        sz = size     # Call size and multiply by n...
        sz * n if sz  # but return nil if size itself is nil
      end
    end
    each do |*val|
      n.times { yield *val }
    end
  end
end

%[hello world].repeat(2) { |w| puts w }
  # => Prints 'hello', 'hello', 'world', 'world'
enum = (1..14).repeat(3)
  # => returns an Enumerator when called without a block
enum.first(4) # => [1, 1, 1, 2]
enum.size # => 42

static VALUE
obj_to_enum(int argc, VALUE *argv, VALUE obj)
{
    VALUE enumerator, meth = sym_each;

    if (argc > 0) {
        --argc;
        meth = *argv++;
    }
    enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
    if (rb_block_given_p()) {
        enumerator_ptr(enumerator)->size = rb_block_proc();
    }
    return enumerator;
}
to_s → string click to toggle source

Returns a string representing obj. The default to_s prints the object's class and an encoding of the object id. As a special case, the top-level object that is the initial execution context of Ruby programs returns “main.''

VALUE
rb_any_to_s(VALUE obj)
{
    VALUE str;
    VALUE cname = rb_class_name(CLASS_OF(obj));

    str = rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)obj);
    OBJ_INFECT(str, obj);

    return str;
}
trust → obj click to toggle source

Removes the untrusted mark from obj.

VALUE
rb_obj_trust(VALUE obj)
{
    rb_secure(3);
    if (OBJ_UNTRUSTED(obj)) {
        rb_check_frozen(obj);
        FL_UNSET(obj, FL_UNTRUSTED);
    }
    return obj;
}
untaint → obj click to toggle source

Removes the taint from obj.

VALUE
rb_obj_untaint(VALUE obj)
{
    rb_secure(3);
    if (OBJ_TAINTED(obj)) {
        rb_check_frozen(obj);
        FL_UNSET(obj, FL_TAINT);
    }
    return obj;
}
untrust → obj click to toggle source

Marks obj as untrusted.

VALUE
rb_obj_untrust(VALUE obj)
{
    rb_secure(4);
    if (!OBJ_UNTRUSTED(obj)) {
        rb_check_frozen(obj);
        OBJ_UNTRUST(obj);
    }
    return obj;
}
untrusted? → true or false click to toggle source

Returns true if the object is untrusted.

VALUE
rb_obj_untrusted(VALUE obj)
{
    if (OBJ_UNTRUSTED(obj))
        return Qtrue;
    return Qfalse;
}


module ObjectSpace - Ruby 2.0.0-p576 Core API Reference API Reference

module ObjectSpace

The ObjectSpace module contains a number of routines that interact with the garbage collection facility and allow you to traverse all living objects with an iterator.

ObjectSpace also provides support for object finalizers, procs that will be called when a specific object is about to be destroyed by garbage collection.

include ObjectSpace

a = "A"
b = "B"
c = "C"

define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
define_finalizer(a, proc {|id| puts "Finalizer two on #{id}" })
define_finalizer(b, proc {|id| puts "Finalizer three on #{id}" })

produces:

Finalizer three on 537763470
Finalizer one on 537763480
Finalizer two on 537763480

In Files

  • gc.c

Public Class Methods

_id2ref(object_id) → an_object click to toggle source

Converts an object id to a reference to the object. May not be called on an object id passed as a parameter to a finalizer.

s = "I am a string"                    #=> "I am a string"
r = ObjectSpace._id2ref(s.object_id)   #=> "I am a string"
r == s                                 #=> true

static VALUE
id2ref(VALUE obj, VALUE objid)
{
#if SIZEOF_LONG == SIZEOF_VOIDP
#define NUM2PTR(x) NUM2ULONG(x)
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
#define NUM2PTR(x) NUM2ULL(x)
#endif
    rb_objspace_t *objspace = &rb_objspace;
    VALUE ptr;
    void *p0;

    rb_secure(4);
    ptr = NUM2PTR(objid);
    p0 = (void *)ptr;

    if (ptr == Qtrue) return Qtrue;
    if (ptr == Qfalse) return Qfalse;
    if (ptr == Qnil) return Qnil;
    if (FIXNUM_P(ptr)) return (VALUE)ptr;
    if (FLONUM_P(ptr)) return (VALUE)ptr;
    ptr = obj_id_to_ref(objid);

    if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
        ID symid = ptr / sizeof(RVALUE);
        if (rb_id2name(symid) == 0)
            rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
        return ID2SYM(symid);
    }

    if (!is_id_value(objspace, ptr)) {
        rb_raise(rb_eRangeError, "%p is not id value", p0);
    }
    if (!is_live_object(objspace, ptr)) {
        rb_raise(rb_eRangeError, "%p is recycled object", p0);
    }
    return (VALUE)ptr;
}
count_objects([result_hash]) → hash click to toggle source

Counts objects for each type.

It returns a hash, such as:

{
  :TOTAL=>10000,
  :FREE=>3011,
  :T_OBJECT=>6,
  :T_CLASS=>404,
  # ...
}

The contents of the returned hash are implementation specific. It may be changed in future.

If the optional argument result_hash is given, it is overwritten and returned. This is intended to avoid probe effect.

This method is only expected to work on C Ruby.

static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
    rb_objspace_t *objspace = &rb_objspace;
    size_t counts[T_MASK+1];
    size_t freed = 0;
    size_t total = 0;
    size_t i;
    VALUE hash;

    if (rb_scan_args(argc, argv, "01", &hash) == 1) {
        if (!RB_TYPE_P(hash, T_HASH))
            rb_raise(rb_eTypeError, "non-hash given");
    }

    for (i = 0; i <= T_MASK; i++) {
        counts[i] = 0;
    }

    for (i = 0; i < heaps_used; i++) {
        RVALUE *p, *pend;

        p = objspace->heap.sorted[i]->start; pend = p + objspace->heap.sorted[i]->limit;
        for (;p < pend; p++) {
            if (p->as.basic.flags) {
                counts[BUILTIN_TYPE(p)]++;
            }
            else {
                freed++;
            }
        }
        total += objspace->heap.sorted[i]->limit;
    }

    if (hash == Qnil) {
        hash = rb_hash_new();
    }
    else if (!RHASH_EMPTY_P(hash)) {
        st_foreach(RHASH_TBL(hash), set_zero, hash);
    }
    rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
    rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));

    for (i = 0; i <= T_MASK; i++) {
        VALUE type;
        switch (i) {
#define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t)); break;
            COUNT_TYPE(T_NONE);
            COUNT_TYPE(T_OBJECT);
            COUNT_TYPE(T_CLASS);
            COUNT_TYPE(T_MODULE);
            COUNT_TYPE(T_FLOAT);
            COUNT_TYPE(T_STRING);
            COUNT_TYPE(T_REGEXP);
            COUNT_TYPE(T_ARRAY);
            COUNT_TYPE(T_HASH);
            COUNT_TYPE(T_STRUCT);
            COUNT_TYPE(T_BIGNUM);
            COUNT_TYPE(T_FILE);
            COUNT_TYPE(T_DATA);
            COUNT_TYPE(T_MATCH);
            COUNT_TYPE(T_COMPLEX);
            COUNT_TYPE(T_RATIONAL);
            COUNT_TYPE(T_NIL);
            COUNT_TYPE(T_TRUE);
            COUNT_TYPE(T_FALSE);
            COUNT_TYPE(T_SYMBOL);
            COUNT_TYPE(T_FIXNUM);
            COUNT_TYPE(T_UNDEF);
            COUNT_TYPE(T_NODE);
            COUNT_TYPE(T_ICLASS);
            COUNT_TYPE(T_ZOMBIE);
#undef COUNT_TYPE
          default:              type = INT2NUM(i); break;
        }
        if (counts[i])
            rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
    }

    return hash;
}
define_finalizer(obj, aProc=proc()) click to toggle source

Adds aProc as a finalizer, to be called after obj was destroyed.

static VALUE
define_final(int argc, VALUE *argv, VALUE os)
{
    VALUE obj, block;

    rb_scan_args(argc, argv, "11", &obj, &block);
    rb_check_frozen(obj);
    if (argc == 1) {
        block = rb_block_proc();
    }
    else if (!rb_respond_to(block, rb_intern("call"))) {
        rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
                 rb_obj_classname(block));
    }

    return define_final0(obj, block);
}
each_object([module]) {|obj| ... } → fixnum click to toggle source
each_object([module]) → an_enumerator

Calls the block once for each living, nonimmediate object in this Ruby process. If module is specified, calls the block for only those classes or modules that match (or are a subclass of) module. Returns the number of objects found. Immediate objects (Fixnums, Symbols true, false, and nil) are never returned. In the example below, each_object returns both the numbers we defined and several constants defined in the Math module.

If no block is given, an enumerator is returned instead.

a = 102.7
b = 95       # Won't be returned
c = 12345678987654321
count = ObjectSpace.each_object(Numeric) {|x| p x }
puts "Total count: #{count}"

produces:

12345678987654321
102.7
2.71828182845905
3.14159265358979
2.22044604925031e-16
1.7976931348623157e+308
2.2250738585072e-308
Total count: 7
static VALUE
os_each_obj(int argc, VALUE *argv, VALUE os)
{
    VALUE of;

    rb_secure(4);
    if (argc == 0) {
        of = 0;
    }
    else {
        rb_scan_args(argc, argv, "01", &of);
    }
    RETURN_ENUMERATOR(os, 1, &of);
    return os_obj_of(of);
}
start → nil click to toggle source
garbage_collect → nil
garbage_collect → nil

Initiates garbage collection, unless manually disabled.

VALUE
rb_gc_start(void)
{
    rb_gc();
    return Qnil;
}
undefine_finalizer(obj) click to toggle source

Removes all finalizers for obj.

static VALUE
undefine_final(VALUE os, VALUE obj)
{
    return rb_undefine_final(obj);
}


class ObjectSpace::WeakMap - Ruby 2.0.0-p576 Core API Reference API Reference

class ObjectSpace::WeakMap

An ObjectSpace::WeakMap object holds references to any objects, but those objects can get garbage collected.

This class is mostly used internally by WeakRef, please use lib/weakref.rb for the public interface.

In Files

  • gc.c

Parent

Object

Public Instance Methods

[](p1) click to toggle source

Retrieves a weakly referenced object with the given key

static VALUE
wmap_aref(VALUE self, VALUE wmap)
{
    st_data_t data;
    VALUE obj;
    struct weakmap *w;
    rb_objspace_t *objspace = &rb_objspace;

    TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
    if (!st_lookup(w->wmap2obj, (st_data_t)wmap, &data)) return Qnil;
    obj = (VALUE)data;
    if (!is_id_value(objspace, obj)) return Qnil;
    if (!is_live_object(objspace, obj)) return Qnil;
    return obj;
}
[]=(p1, p2) click to toggle source

Creates a weak reference from the given key to the given value

static VALUE
wmap_aset(VALUE self, VALUE wmap, VALUE orig)
{
    st_data_t data;
    VALUE rids;
    struct weakmap *w;

    TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
    rb_define_final(orig, w->final);
    rb_define_final(wmap, w->final);
    if (st_lookup(w->obj2wmap, (st_data_t)orig, &data)) {
        rids = (VALUE)data;
    }
    else {
        rids = rb_ary_tmp_new(1);
        st_insert(w->obj2wmap, (st_data_t)orig, (st_data_t)rids);
    }
    rb_ary_push(rids, wmap);
    st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
    return nonspecial_obj_id(orig);
}


class Proc - Ruby 2.0.0-p576 Core API Reference API Reference

class Proc

Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.

def gen_times(factor)
  return Proc.new {|n| n*factor }
end

times3 = gen_times(3)
times5 = gen_times(5)

times3.call(12)               #=> 36
times5.call(5)                #=> 25
times3.call(times5.call(4))   #=> 60

In Files

  • proc.c

Parent

Object

Public Class Methods

new {|...| block } → a_proc click to toggle source
new → a_proc

Creates a new Proc object, bound to the current context. Proc::new may be called without a block only within a method with an attached block, in which case that block is converted to the Proc object.

def proc_from
  Proc.new
end
proc = proc_from { "hello" }
proc.call   #=> "hello"

static VALUE
rb_proc_s_new(int argc, VALUE *argv, VALUE klass)
{
    VALUE block = proc_new(klass, FALSE);

    rb_obj_call_init(block, argc, argv);
    return block;
}

Public Instance Methods

proc === obj → result_of_proc click to toggle source

Invokes the block with obj as the proc's parameter like #call. It is to allow a proc object to be a target of when clause in a case statement.

static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    rb_proc_t *proc;
    rb_block_t *blockptr = 0;
    rb_iseq_t *iseq;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            RB_GC_GUARD(passed_procval) = rb_block_proc();
            GetProcPtr(passed_procval, passed_proc);
            blockptr = &passed_proc->block;
        }
    }

    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
    RB_GC_GUARD(procval);
    return vret;
}
call(params,...) → obj click to toggle source
prc[params,...] → obj
(params,...) → obj

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It's a syntax sugar to hide “call”.

For procs created using lambda or ->() an error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created using Proc.new or Kernel.proc, extra parameters are silently discarded.

Returns the value of the last expression evaluated in the block. See also Proc#yield.

a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
a_proc = lambda {|a,b| a}
a_proc.call(1,2,3)

produces:

prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError)
 from prog.rb:5:in `call'
 from prog.rb:5:in `<main>'
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    rb_proc_t *proc;
    rb_block_t *blockptr = 0;
    rb_iseq_t *iseq;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            RB_GC_GUARD(passed_procval) = rb_block_proc();
            GetProcPtr(passed_procval, passed_proc);
            blockptr = &passed_proc->block;
        }
    }

    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
    RB_GC_GUARD(procval);
    return vret;
}
arity → fixnum click to toggle source

Returns the number of arguments that would not be ignored. If the block is declared to take no arguments, returns 0. If the block is known to take exactly n arguments, returns n. If the block has optional arguments, return -n-1, where n is the number of mandatory arguments. A proc with no argument declarations is the same a block declaring || as its arguments.

proc {}.arity          #=>  0
proc {||}.arity        #=>  0
proc {|a|}.arity       #=>  1
proc {|a,b|}.arity     #=>  2
proc {|a,b,c|}.arity   #=>  3
proc {|*a|}.arity      #=> -1
proc {|a,*b|}.arity    #=> -2
proc {|a,*b, c|}.arity #=> -3

proc   { |x = 0| }.arity       #=> 0
lambda { |a = 0| }.arity       #=> -1
proc   { |x=0, y| }.arity      #=> 0
lambda { |x=0, y| }.arity      #=> -2
proc   { |x=0, y=0| }.arity    #=> 0
lambda { |x=0, y=0| }.arity    #=> -1
proc   { |x, y=0| }.arity      #=> 1
lambda { |x, y=0| }.arity      #=> -2
proc   { |(x, y), z=0| }.arity #=> 1
lambda { |(x, y), z=0| }.arity #=> -2

static VALUE
proc_arity(VALUE self)
{
    int arity = rb_proc_arity(self);
    return INT2FIX(arity);
}
binding → binding click to toggle source

Returns the binding associated with prc. Note that Kernel#eval accepts either a Proc or a Binding object as its second parameter.

def fred(param)
  proc {}
end

b = fred(99)
eval("param", b.binding)   #=> 99

static VALUE
proc_binding(VALUE self)
{
    rb_proc_t *proc;
    VALUE bindval;
    rb_binding_t *bind;

    GetProcPtr(self, proc);
    if (RB_TYPE_P((VALUE)proc->block.iseq, T_NODE)) {
        if (!IS_METHOD_PROC_NODE((NODE *)proc->block.iseq)) {
            rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
        }
    }

    bindval = binding_alloc(rb_cBinding);
    GetBindingPtr(bindval, bind);
    bind->env = proc->envval;
    if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) {
        bind->path = proc->block.iseq->location.path;
        bind->first_lineno = rb_iseq_first_lineno(proc->block.iseq);
    }
    else {
        bind->path = Qnil;
        bind->first_lineno = 0;
    }
    return bindval;
}
call(params,...) → obj click to toggle source
prc[params,...] → obj
(params,...) → obj

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It's a syntax sugar to hide “call”.

For procs created using lambda or ->() an error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created using Proc.new or Kernel.proc, extra parameters are silently discarded.

Returns the value of the last expression evaluated in the block. See also Proc#yield.

a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
a_proc = lambda {|a,b| a}
a_proc.call(1,2,3)

produces:

prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError)
 from prog.rb:5:in `call'
 from prog.rb:5:in `<main>'
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    rb_proc_t *proc;
    rb_block_t *blockptr = 0;
    rb_iseq_t *iseq;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            RB_GC_GUARD(passed_procval) = rb_block_proc();
            GetProcPtr(passed_procval, passed_proc);
            blockptr = &passed_proc->block;
        }
    }

    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
    RB_GC_GUARD(procval);
    return vret;
}
curry → a_proc click to toggle source
curry(arity) → a_proc

Returns a curried proc. If the optional arity argument is given, it determines the number of arguments. A curried proc receives some arguments. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.

b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> 6
p b.curry(5)[1][2][3][4][5]  #=> 6
p b.curry(5)[1, 2][3, 4][5]  #=> 6
p b.curry(1)[1]              #=> 1

b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> 10
p b.curry(5)[1][2][3][4][5]  #=> 15
p b.curry(5)[1, 2][3, 4][5]  #=> 15
p b.curry(1)[1]              #=> 1

b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> wrong number of arguments (4 for 3)
p b.curry(5)                 #=> wrong number of arguments (5 for 3)
p b.curry(1)                 #=> wrong number of arguments (1 for 3)

b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
p b.curry[1][2][3]           #=> 6
p b.curry[1, 2][3, 4]        #=> 10
p b.curry(5)[1][2][3][4][5]  #=> 15
p b.curry(5)[1, 2][3, 4][5]  #=> 15
p b.curry(1)                 #=> wrong number of arguments (1 for 3)

b = proc { :foo }
p b.curry[]                  #=> :foo

static VALUE
proc_curry(int argc, VALUE *argv, VALUE self)
{
    int sarity, max_arity, min_arity = rb_proc_min_max_arity(self, &max_arity);
    VALUE arity;

    rb_scan_args(argc, argv, "01", &arity);
    if (NIL_P(arity)) {
        arity = INT2FIX(min_arity);
    }
    else {
        sarity = FIX2INT(arity);
        if (rb_proc_lambda_p(self)) {
            rb_check_arity(sarity, min_arity, max_arity);
        }
    }

    return make_curry_proc(self, rb_ary_new(), arity);
}
hash → integer click to toggle source

Returns a hash value corresponding to proc body.

static VALUE
proc_hash(VALUE self)
{
    st_index_t hash;
    hash = rb_hash_start(0);
    hash = rb_hash_proc(hash, self);
    hash = rb_hash_end(hash);
    return LONG2FIX(hash);
}
inspect() click to toggle source
Alias for: to_s
lambda? → true or false click to toggle source

Returns true for a Proc object for which argument handling is rigid. Such procs are typically generated by lambda.

A Proc object generated by proc ignores extra arguments.

proc {|a,b| [a,b] }.call(1,2,3)    #=> [1,2]

It provides nil for missing arguments.

proc {|a,b| [a,b] }.call(1)        #=> [1,nil]

It expands a single array argument.

proc {|a,b| [a,b] }.call([1,2])    #=> [1,2]

A Proc object generated by lambda doesn't have such tricks.

lambda {|a,b| [a,b] }.call(1,2,3)  #=> ArgumentError
lambda {|a,b| [a,b] }.call(1)      #=> ArgumentError
lambda {|a,b| [a,b] }.call([1,2])  #=> ArgumentError

#lambda? is a predicate for the tricks. It returns true if no tricks apply.

lambda {}.lambda?            #=> true
proc {}.lambda?              #=> false

::new is the same as proc.

Proc.new {}.lambda?          #=> false

lambda, proc and ::new preserve the tricks of a Proc object given by & argument.

lambda(&lambda {}).lambda?   #=> true
proc(&lambda {}).lambda?     #=> true
Proc.new(&lambda {}).lambda? #=> true

lambda(&proc {}).lambda?     #=> false
proc(&proc {}).lambda?       #=> false
Proc.new(&proc {}).lambda?   #=> false

A Proc object generated by & argument has the tricks

def n(&b) b.lambda? end
n {}                         #=> false

The & argument preserves the tricks if a Proc object is given by & argument.

n(&lambda {})                #=> true
n(&proc {})                  #=> false
n(&Proc.new {})              #=> false

A Proc object converted from a method has no tricks.

def m() end
method(:m).to_proc.lambda?   #=> true

n(&method(:m))               #=> true
n(&method(:m).to_proc)       #=> true

define_method is treated the same as method definition. The defined method has no tricks.

class C
  define_method(:d) {}
end
C.new.d(1,2)       #=> ArgumentError
C.new.method(:d).to_proc.lambda?   #=> true

define_method always defines a method without the tricks, even if a non-lambda Proc object is given. This is the only exception for which the tricks are not preserved.

class C
  define_method(:e, &proc {})
end
C.new.e(1,2)       #=> ArgumentError
C.new.method(:e).to_proc.lambda?   #=> true

This exception insures that methods never have tricks and makes it easy to have wrappers to define methods that behave as usual.

class C
  def self.def2(name, &body)
    define_method(name, &body)
  end

  def2(:f) {}
end
C.new.f(1,2)       #=> ArgumentError

The wrapper def2 defines a method which has no tricks.

VALUE
rb_proc_lambda_p(VALUE procval)
{
    rb_proc_t *proc;
    GetProcPtr(procval, proc);

    return proc->is_lambda ? Qtrue : Qfalse;
}
parameters → array click to toggle source

Returns the parameter information of this proc.

prc = lambda{|x, y=42, *other|}
prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]

static VALUE
rb_proc_parameters(VALUE self)
{
    int is_proc;
    rb_iseq_t *iseq = get_proc_iseq(self, &is_proc);
    if (!iseq) {
        return unnamed_parameters(rb_proc_arity(self));
    }
    return rb_iseq_parameters(iseq, is_proc);
}
source_location → [String, Fixnum] click to toggle source

Returns the Ruby source filename and line number containing this proc or nil if this proc was not defined in Ruby (i.e. native)

VALUE
rb_proc_location(VALUE self)
{
    return iseq_location(get_proc_iseq(self, 0));
}
to_proc → prc click to toggle source

Part of the protocol for converting objects to Proc objects. Instances of class Proc simply return themselves.

static VALUE
proc_to_proc(VALUE self)
{
    return self;
}
to_s → string click to toggle source

Returns the unique identifier for this proc, along with an indication of where the proc was defined.

static VALUE
proc_to_s(VALUE self)
{
    VALUE str = 0;
    rb_proc_t *proc;
    const char *cname = rb_obj_classname(self);
    rb_iseq_t *iseq;
    const char *is_lambda;

    GetProcPtr(self, proc);
    iseq = proc->block.iseq;
    is_lambda = proc->is_lambda ? " (lambda)" : "";

    if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
        int first_lineno = 0;

        if (iseq->line_info_table) {
            first_lineno = rb_iseq_first_lineno(iseq);
        }
        str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self,
                         RSTRING_PTR(iseq->location.path),
                         first_lineno, is_lambda);
    }
    else {
        str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq,
                         is_lambda);
    }

    if (OBJ_TAINTED(self)) {
        OBJ_TAINT(str);
    }
    return str;
}
Also aliased as: inspect
call(params,...) → obj click to toggle source
prc[params,...] → obj
(params,...) → obj

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It's a syntax sugar to hide “call”.

For procs created using lambda or ->() an error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created using Proc.new or Kernel.proc, extra parameters are silently discarded.

Returns the value of the last expression evaluated in the block. See also Proc#yield.

a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
a_proc = lambda {|a,b| a}
a_proc.call(1,2,3)

produces:

prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError)
 from prog.rb:5:in `call'
 from prog.rb:5:in `<main>'
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    rb_proc_t *proc;
    rb_block_t *blockptr = 0;
    rb_iseq_t *iseq;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            RB_GC_GUARD(passed_procval) = rb_block_proc();
            GetProcPtr(passed_procval, passed_proc);
            blockptr = &passed_proc->block;
        }
    }

    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
    RB_GC_GUARD(procval);
    return vret;
}


module Process - Ruby 2.0.0-p576 Core API Reference API Reference

module Process

The Process module is a collection of methods used to manipulate processes.

In Files

  • process.c

Constants

PRIO_PGRP

see ::setpriority

PRIO_PROCESS

see ::setpriority

PRIO_USER

see ::setpriority

RLIMIT_AS

Maximum size of the process's virtual memory (address space) in bytes.

see the system getrlimit(2) manual for details.

RLIMIT_CORE

Maximum size of the core file.

see the system getrlimit(2) manual for details.

RLIMIT_CPU

CPU time limit in seconds.

see the system getrlimit(2) manual for details.

RLIMIT_DATA

Maximum size of the process's data segment.

see the system getrlimit(2) manual for details.

RLIMIT_FSIZE

Maximum size of files that the process may create.

see the system getrlimit(2) manual for details.

RLIMIT_MEMLOCK

Maximum number of bytes of memory that may be locked into RAM.

see the system getrlimit(2) manual for details.

RLIMIT_MSGQUEUE

Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

RLIMIT_NICE

Specifies a ceiling to which the process's nice value can be raised.

see the system getrlimit(2) manual for details.

RLIMIT_NOFILE

Specifies a value one greater than the maximum file descriptor number that can be opened by this process.

see the system getrlimit(2) manual for details.

RLIMIT_NPROC

The maximum number of processes that can be created for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

RLIMIT_RSS

Specifies the limit (in pages) of the process's resident set.

see the system getrlimit(2) manual for details.

RLIMIT_RTPRIO

Specifies a ceiling on the real-time priority that may be set for this process.

see the system getrlimit(2) manual for details.

RLIMIT_RTTIME

Specifies limit on CPU time this process scheduled under a real-time scheduling policy can consume.

see the system getrlimit(2) manual for details.

RLIMIT_SBSIZE

Maximum size of the socket buffer.

RLIMIT_SIGPENDING

Specifies a limit on the number of signals that may be queued for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

RLIMIT_STACK

Maximum size of the stack, in bytes.

see the system getrlimit(2) manual for details.

RLIM_INFINITY

see ::setrlimit

RLIM_SAVED_CUR

see ::setrlimit

RLIM_SAVED_MAX

see ::setrlimit

WNOHANG

see ::wait

WUNTRACED

see ::wait

Public Class Methods

abort click to toggle source
Kernel::abort([msg])
Process::abort([msg])

Terminate execution immediately, effectively by calling Kernel.exit(false). If msg is given, it is written to STDERR prior to terminating.

VALUE
rb_f_abort(int argc, VALUE *argv)
{
    rb_secure(4);
    if (argc == 0) {
        if (!NIL_P(GET_THREAD()->errinfo)) {
            ruby_error_print();
        }
        rb_exit(EXIT_FAILURE);
    }
    else {
        VALUE args[2];

        rb_scan_args(argc, argv, "1", &args[1]);
        StringValue(argv[0]);
        rb_io_puts(argc, argv, rb_stderr);
        args[0] = INT2NUM(EXIT_FAILURE);
        rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
    }

    UNREACHABLE;
}
daemon() → 0 click to toggle source
daemon(nochdir=nil,noclose=nil) → 0

Detach the process from controlling terminal and run in the background as system daemon. Unless the argument nochdir is true (i.e. non false), it changes the current working directory to the root (“/”). Unless the argument noclose is true, daemon() will redirect standard input, standard output and standard error to /dev/null. Return zero on success, or raise one of Errno::*.

static VALUE
proc_daemon(int argc, VALUE *argv)
{
    VALUE nochdir, noclose;
    int n;

    rb_secure(2);
    rb_scan_args(argc, argv, "02", &nochdir, &noclose);

    prefork();
    n = rb_daemon(RTEST(nochdir), RTEST(noclose));
    if (n < 0) rb_sys_fail("daemon");
    return INT2FIX(n);
}
detach(pid) → thread click to toggle source

Some operating systems retain the status of terminated child processes until the parent collects that status (normally using some variant of wait(). If the parent never collects this status, the child stays around as a zombie process. Process::detach prevents this by setting up a separate Ruby thread whose sole job is to reap the status of the process pid when it terminates. Use detach only when you do not intent to explicitly wait for the child to terminate.

The waiting thread returns the exit status of the detached process when it terminates, so you can use Thread#join to know the result. If specified pid is not a valid child process ID, the thread returns nil immediately.

The waiting thread has pid method which returns the pid.

In this first example, we don't reap the first child process, so it appears as a zombie in the process status display.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

produces:

27389 Z

In the next example, Process::detach is used to reap the child automatically.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.detach(p1)
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

(produces no output)

static VALUE
proc_detach(VALUE obj, VALUE pid)
{
    rb_secure(2);
    return rb_detach_process(NUM2PIDT(pid));
}
egid → fixnum click to toggle source
Process::GID.eid → fixnum
Process::Sys.geteid → fixnum

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}
egid = fixnum → fixnum click to toggle source

Sets the effective group ID for this process. Not available on all platforms.

static VALUE
proc_setegid(VALUE obj, VALUE egid)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
    rb_gid_t gid;
#endif

    check_gid_switch();

#if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
    gid = OBJ2GID(egid);
#endif

#if defined(HAVE_SETRESGID)
    if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(-1, gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETEGID
    if (setegid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    if (gid == getgid()) {
        if (setgid(gid) < 0) rb_sys_fail(0);
    }
    else {
        rb_notimplement();
    }
#else
    rb_notimplement();
#endif
    return egid;
}
euid → fixnum click to toggle source
Process::UID.eid → fixnum
Process::Sys.geteuid → fixnum

Returns the effective user ID for this process.

Process.euid   #=> 501

static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}
euid= user click to toggle source

Sets the effective user ID for this process. Not available on all platforms.

static VALUE
proc_seteuid_m(VALUE mod, VALUE euid)
{
    check_uid_switch();
    proc_seteuid(OBJ2UID(euid));
    return euid;
}
exec([env,] command... [,options]) click to toggle source

Replaces the current process by running the given external command. command… is one of following forms.

commandline                 : command line string which is passed to the standard shell
cmdname, arg1, ...          : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)

If single string is given as the command, it is taken as a command line that is subject to shell expansion before being executed.

The standard shell means always "/bin/sh" on Unix-like systems, ENV["RUBYSHELL"] or ENV["COMSPEC"] on Windows NT series, and similar.

If two or more string given, the first is taken as a command name and the rest are passed as parameters to command with no shell expansion.

If a two-element array at the beginning of the command, the first element is the command to be executed, and the second argument is used as the argv[0] value, which may show up in process listings.

In order to execute the command, one of the exec(2) system calls is used, so the running command may inherit some of the environment of the original program (including open file descriptors). This behavior is modified by env and options. See spawn for details.

Raises SystemCallError if the command couldn't execute (typically Errno::ENOENT when it was not found).

This method modifies process attributes according to options (details described in spawn) before exec(2) system call. The modified attributes may be retained when exec(2) system call fails. For example, hard resource limits is not restorable. If it is not acceptable, consider to create a child process using spawn or system.

exec "echo *"       # echoes list of files in current directory
# never get here

exec "echo", "*"    # echoes an asterisk
# never get here
VALUE
rb_f_exec(int argc, VALUE *argv)
{
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;
#define CHILD_ERRMSG_BUFLEN 80
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

#if defined(__APPLE__) || defined(__HAIKU__)
    rb_exec_without_timer_thread(eargp, errmsg, sizeof(errmsg));
#else
    rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
#endif
    RB_GC_GUARD(execarg_obj);
    if (errmsg[0])
        rb_sys_fail(errmsg);
    rb_sys_fail_str(fail_str);
    return Qnil;                /* dummy */
}
exit(status=true) click to toggle source
Kernel::exit(status=true)
Process::exit(status=true)

Initiates the termination of the Ruby script by raising the SystemExit exception. This exception may be caught. The optional parameter is used to return a status code to the invoking environment. true and FALSE of status means success and failure respectively. The interpretation of other integer values are system dependent.

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end
puts "after begin block"

produces:

rescued a SystemExit exception
after begin block

Just prior to termination, Ruby executes any at_exit functions (see Kernel::at_exit) and runs any object finalizers (see ObjectSpace.define_finalizer).

at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
exit

produces:

at_exit function
in finalizer
VALUE
rb_f_exit(int argc, VALUE *argv)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
        istatus = exit_status_code(status);
    }
    else {
        istatus = EXIT_SUCCESS;
    }
    rb_exit(istatus);

    UNREACHABLE;
}
exit!(status=false) click to toggle source

Exits the process immediately. No exit handlers are run. status is returned to the underlying system as the exit status.

Process.exit!(true)
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
        istatus = exit_status_code(status);
    }
    else {
        istatus = EXIT_FAILURE;
    }
    _exit(istatus);

    UNREACHABLE;
}
fork [{ block }] → fixnum or nil click to toggle source
fork [{ block }] → fixnum or nil

Creates a subprocess. If a block is specified, that block is run in the subprocess, and the subprocess terminates with a status of zero. Otherwise, the fork call returns twice, once in the parent, returning the process ID of the child, and once in the child, returning nil. The child process can exit using Kernel.exit! to avoid running any at_exit functions. The parent process should use Process.wait to collect the termination statuses of its children or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

The thread calling fork is the only thread in the created child process. fork doesn't copy other threads.

If fork is not usable, Process.respond_to?(:fork) returns false.

static VALUE
rb_f_fork(VALUE obj)
{
    rb_pid_t pid;

    rb_secure(2);

    switch (pid = rb_fork_ruby(NULL)) {
      case 0:
        rb_thread_atfork();
        if (rb_block_given_p()) {
            int status;

            rb_protect(rb_yield, Qundef, &status);
            ruby_stop(status);
        }
        return Qnil;

      case -1:
        rb_sys_fail("fork(2)");
        return Qnil;

      default:
        return PIDT2NUM(pid);
    }
}
getpgid(pid) → integer click to toggle source

Returns the process group ID for the given process id. Not available on all platforms.

Process.getpgid(Process.ppid())   #=> 25527

static VALUE
proc_getpgid(VALUE obj, VALUE pid)
{
    rb_pid_t i;

    rb_secure(2);
    i = getpgid(NUM2PIDT(pid));
    if (i < 0) rb_sys_fail(0);
    return PIDT2NUM(i);
}
getpgrp → integer click to toggle source

Returns the process group ID for this process. Not available on all platforms.

Process.getpgid(0)   #=> 25527
Process.getpgrp      #=> 25527

static VALUE
proc_getpgrp(void)
{
    rb_pid_t pgrp;

    rb_secure(2);
#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
    pgrp = getpgrp();
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#else /* defined(HAVE_GETPGID) */
    pgrp = getpgid(0);
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#endif
}
getpriority(kind, integer) → fixnum click to toggle source

Gets the scheduling priority for specified process, process group, or user. kind indicates the kind of entity to find: one of Process::PRIO_PGRP, Process::PRIO_USER, or Process::PRIO_PROCESS. integer is an id indicating the particular process, process group, or user (an id of 0 means current). Lower priorities are more favorable for scheduling. Not available on all platforms.

Process.getpriority(Process::PRIO_USER, 0)      #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19

static VALUE
proc_getpriority(VALUE obj, VALUE which, VALUE who)
{
    int prio, iwhich, iwho;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);

    errno = 0;
    prio = getpriority(iwhich, iwho);
    if (errno) rb_sys_fail(0);
    return INT2FIX(prio);
}
getrlimit(resource) → [cur_limit, max_limit] click to toggle source

Gets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

resource indicates the kind of resource to limit. It is specified as a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. See ::setrlimit for details.

cur_limit and max_limit may be Process::RLIM_INFINITY, Process::RLIM_SAVED_MAX or Process::RLIM_SAVED_CUR. See ::setrlimit and the system getrlimit(2) manual for details.

static VALUE
proc_getrlimit(VALUE obj, VALUE resource)
{
    struct rlimit rlim;

    rb_secure(2);

    if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
        rb_sys_fail("getrlimit");
    }
    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
}
getsid() → integer click to toggle source
getsid(pid) → integer

Returns the session ID for for the given process id. If not give, return current process sid. Not available on all platforms.

Process.getsid()                #=> 27422
Process.getsid(0)               #=> 27422
Process.getsid(Process.pid())   #=> 27422

static VALUE
proc_getsid(int argc, VALUE *argv)
{
    rb_pid_t sid;
    VALUE pid;

    rb_secure(2);
    rb_scan_args(argc, argv, "01", &pid);

    if (NIL_P(pid))
        pid = INT2NUM(0);

    sid = getsid(NUM2PIDT(pid));
    if (sid < 0) rb_sys_fail(0);
    return PIDT2NUM(sid);
}
gid → fixnum click to toggle source
Process::GID.rid → fixnum
Process::Sys.getgid → fixnum

Returns the (real) group ID for this process.

Process.gid   #=> 500

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}
gid= fixnum → fixnum click to toggle source

Sets the group ID for this process.

static VALUE
proc_setgid(VALUE obj, VALUE id)
{
    rb_gid_t gid;

    check_gid_switch();

    gid = OBJ2GID(id);
#if defined(HAVE_SETRESGID)
    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRGID
    if (setrgid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    {
        if (getegid() == gid) {
            if (setgid(gid) < 0) rb_sys_fail(0);
        }
        else {
            rb_notimplement();
        }
    }
#endif
    return GIDT2NUM(gid);
}
groups → array click to toggle source

Get an Array of the gids of groups in the supplemental group access list for this process.

Process.groups   #=> [27, 6, 10, 11]

static VALUE
proc_getgroups(VALUE obj)
{
    VALUE ary, tmp;
    int i, ngroups;
    rb_gid_t *groups;

    ngroups = getgroups(0, NULL);
    if (ngroups == -1)
        rb_sys_fail(0);

    groups = ALLOCV_N(rb_gid_t, tmp, ngroups);

    ngroups = getgroups(ngroups, groups);
    if (ngroups == -1)
        rb_sys_fail(0);

    ary = rb_ary_new();
    for (i = 0; i < ngroups; i++)
        rb_ary_push(ary, GIDT2NUM(groups[i]));

    ALLOCV_END(tmp);

    return ary;
}
groups= array → array click to toggle source

Set the supplemental group access list to the given Array of group IDs.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.groups = [27, 6, 10, 11]   #=> [27, 6, 10, 11]
Process.groups   #=> [27, 6, 10, 11]

static VALUE
proc_setgroups(VALUE obj, VALUE ary)
{
    int ngroups, i;
    rb_gid_t *groups;
    VALUE tmp;
    PREPARE_GETGRNAM;

    Check_Type(ary, T_ARRAY);

    ngroups = RARRAY_LENINT(ary);
    if (ngroups > maxgroups())
        rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());

    groups = ALLOCV_N(rb_gid_t, tmp, ngroups);

    for (i = 0; i < ngroups; i++) {
        VALUE g = RARRAY_PTR(ary)[i];

        groups[i] = OBJ2GID1(g);
    }
    FINISH_GETGRNAM;

    if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
        rb_sys_fail(0);

    ALLOCV_END(tmp);

    return proc_getgroups(obj);
}
initgroups(username, gid) → array click to toggle source

Initializes the supplemental group access list by reading the system group database and using all groups of which the given user is a member. The group with the specified gid is also added to the list. Returns the resulting Array of the gids of all the groups in the supplementary group access list. Not available on all platforms.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.initgroups( "mgranger", 30 )   #=> [30, 6, 10, 11]
Process.groups   #=> [30, 6, 10, 11]

static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
    if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
        rb_sys_fail(0);
    }
    return proc_getgroups(obj);
}
kill(signal, pid, ...) → fixnum click to toggle source

Sends the given signal to the specified process id(s) if pid is positive. If pid is zero signal is sent to all processes whose group ID is equal to the group ID of the process. signal may be an integer signal number or a POSIX signal name (either with or without a SIG prefix). If signal is negative (or starts with a minus sign), kills process groups instead of processes. Not all signals are available on all platforms.

pid = fork do
   Signal.trap("HUP") { puts "Ouch!"; exit }
   # ... do some work ...
end
# ...
Process.kill("HUP", pid)
Process.wait

produces:

Ouch!

If signal is an integer but wrong for signal, Errno::EINVAL or RangeError will be raised. Otherwise unless signal is a String or a Symbol, and a known signal name, ArgumentError will be raised.

Also, Errno::ESRCH or RangeError for invalid pid, Errno::EPERM when failed because of no privilege, will be raised. In these cases, signals may have been sent to preceding processes.

VALUE
rb_f_kill(int argc, VALUE *argv)
{
#ifndef HAVE_KILLPG
#define killpg(pg, sig) kill(-(pg), (sig))
#endif
    int negative = 0;
    int sig;
    int i;
    volatile VALUE str;
    const char *s;

    rb_secure(2);
    rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);

    switch (TYPE(argv[0])) {
      case T_FIXNUM:
    sig = FIX2INT(argv[0]);
    break;

      case T_SYMBOL:
    s = rb_id2name(SYM2ID(argv[0]));
    if (!s) rb_raise(rb_eArgError, "bad signal");
    goto str_signal;

      case T_STRING:
    s = RSTRING_PTR(argv[0]);
      str_signal:
    if (s[0] == '-') {
        negative++;
        s++;
    }
    if (strncmp("SIG", s, 3) == 0)
        s += 3;
    if ((sig = signm2signo(s)) == 0)
        rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);

    if (negative)
        sig = -sig;
    break;

      default:
    str = rb_check_string_type(argv[0]);
    if (!NIL_P(str)) {
        s = RSTRING_PTR(str);
        goto str_signal;
    }
    rb_raise(rb_eArgError, "bad signal type %s",
         rb_obj_classname(argv[0]));
    break;
    }

    if (sig < 0) {
    sig = -sig;
    for (i=1; i<argc; i++) {
        if (killpg(NUM2PIDT(argv[i]), sig) < 0)
        rb_sys_fail(0);
    }
    }
    else {
    for (i=1; i<argc; i++) {
        if (kill(NUM2PIDT(argv[i]), sig) < 0)
        rb_sys_fail(0);
    }
    }
    return INT2FIX(i-1);
}
maxgroups → fixnum click to toggle source

Returns the maximum number of gids allowed in the supplemental group access list.

Process.maxgroups   #=> 32

static VALUE
proc_getmaxgroups(VALUE obj)
{
    return INT2FIX(maxgroups());
}
maxgroups= fixnum → fixnum click to toggle source

Sets the maximum number of gids allowed in the supplemental group access list.

static VALUE
proc_setmaxgroups(VALUE obj, VALUE val)
{
    int ngroups = FIX2INT(val);
    int ngroups_max = get_sc_ngroups_max();

    if (ngroups <= 0)
        rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);

    if (ngroups > RB_MAX_GROUPS)
        ngroups = RB_MAX_GROUPS;

    if (ngroups_max > 0 && ngroups > ngroups_max)
        ngroups = ngroups_max;

    _maxgroups = ngroups;

    return INT2FIX(_maxgroups);
}
pid → fixnum click to toggle source

Returns the process id of this process. Not available on all platforms.

Process.pid   #=> 27415

static VALUE
get_pid(void)
{
    rb_secure(2);
    return PIDT2NUM(getpid());
}
ppid → fixnum click to toggle source

Returns the process id of the parent of this process. Returns untrustworthy value on Win32/64. Not available on all platforms.

puts "I am #{Process.pid}"
Process.fork { puts "Dad is #{Process.ppid}" }

produces:

I am 27417
Dad is 27417
static VALUE
get_ppid(void)
{
    rb_secure(2);
    return PIDT2NUM(getppid());
}
setpgid(pid, integer) → 0 click to toggle source

Sets the process group ID of pid (0 indicates this process) to integer. Not available on all platforms.

static VALUE
proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
{
    rb_pid_t ipid, ipgrp;

    rb_secure(2);
    ipid = NUM2PIDT(pid);
    ipgrp = NUM2PIDT(pgrp);

    if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
    return INT2FIX(0);
}
setpgrp → 0 click to toggle source

Equivalent to setpgid(0,0). Not available on all platforms.

static VALUE
proc_setpgrp(void)
{
    rb_secure(2);
  /* check for posix setpgid() first; this matches the posix */
  /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
  /* this confusion. */
#ifdef HAVE_SETPGID
    if (setpgid(0,0) < 0) rb_sys_fail(0);
#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
    if (setpgrp() < 0) rb_sys_fail(0);
#endif
    return INT2FIX(0);
}
setpriority(kind, integer, priority) → 0 click to toggle source

See Process#getpriority.

Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
Process.getpriority(Process::PRIO_USER, 0)          #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19

static VALUE
proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
{
    int iwhich, iwho, iprio;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);
    iprio  = NUM2INT(prio);

    if (setpriority(iwhich, iwho, iprio) < 0)
        rb_sys_fail(0);
    return INT2FIX(0);
}
setrlimit(resource, cur_limit, max_limit) → nil click to toggle source
setrlimit(resource, cur_limit) → nil

Sets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

If max_limit is not given, cur_limit is used.

resource indicates the kind of resource to limit. It should be a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. The available resources are OS dependent. Ruby may support following resources.

AS

total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)

CORE

core size (bytes) (SUSv3)

CPU

CPU time (seconds) (SUSv3)

DATA

data segment (bytes) (SUSv3)

FSIZE

file size (bytes) (SUSv3)

MEMLOCK

total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)

MSGQUEUE

allocation for POSIX message queues (bytes) (GNU/Linux)

NICE

ceiling on process's nice(2) value (number) (GNU/Linux)

NOFILE

file descriptors (number) (SUSv3)

NPROC

number of processes for the user (number) (4.4BSD, GNU/Linux)

RSS

resident memory size (bytes) (4.2BSD, GNU/Linux)

RTPRIO

ceiling on the process's real-time priority (number) (GNU/Linux)

RTTIME

CPU time for real-time process (us) (GNU/Linux)

SBSIZE

all socket buffers (bytes) (NetBSD, FreeBSD)

SIGPENDING

number of queued signals allowed (signals) (GNU/Linux)

STACK

stack size (bytes) (SUSv3)

cur_limit and max_limit may be :INFINITY, "INFINITY" or Process::RLIM_INFINITY, which means that the resource is not limited. They may be Process::RLIM_SAVED_MAX, Process::RLIM_SAVED_CUR and corresponding symbols and strings too. See system setrlimit(2) manual for details.

The following example raises the soft limit of core size to the hard limit to try to make core dump possible.

Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
static VALUE
proc_setrlimit(int argc, VALUE *argv, VALUE obj)
{
    VALUE resource, rlim_cur, rlim_max;
    struct rlimit rlim;

    rb_secure(2);

    rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
    if (rlim_max == Qnil)
        rlim_max = rlim_cur;

    rlim.rlim_cur = rlimit_resource_value(rlim_cur);
    rlim.rlim_max = rlimit_resource_value(rlim_max);

    if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
        rb_sys_fail("setrlimit");
    }
    return Qnil;
}
setsid → fixnum click to toggle source

Establishes this process as a new session and process group leader, with no controlling tty. Returns the session id. Not available on all platforms.

Process.setsid   #=> 27422

static VALUE
proc_setsid(void)
{
    rb_pid_t pid;

    rb_secure(2);
    pid = setsid();
    if (pid < 0) rb_sys_fail(0);
    return PIDT2NUM(pid);
}
spawn([env,] command... [,options]) → pid click to toggle source
spawn([env,] command... [,options]) → pid

spawn executes specified command and return its pid.

This method doesn't wait for end of the command. The parent process should use Process.wait to collect the termination status of its child or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

spawn has bunch of options to specify process attributes:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : don't clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : don't change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : don't create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => true  : don't inherit
  current directory:
    :chdir => str

If a hash is given as env, the environment is updated by env before exec(2) in the child process. If a pair in env has nil as the value, the variable is deleted.

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

If a hash is given as options, it specifies process group, create new process group, resource limit, current directory, umask and redirects for the child process. Also, it can be specified to clear environment variables.

The :unsetenv_others key in options specifies to clear environment variables, other than specified by env.

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

The :pgroup key in options specifies a process group. The corresponding value should be true, zero or positive integer. true and zero means the process should be a process leader of a new process group. Other values specifies a process group to be belongs.

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

The :new_pgroup key in options specifies to pass CREATE_NEW_PROCESS_GROUP flag to CreateProcessW() that is Windows API. This option is only for Windows. true means the new process is the root process of the new process group. The new process has CTRL+C disabled. This flag is necessary for Process.kill(:SIGINT, pid) on the subprocess. :new_pgroup is false by default.

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

The :rlimit_foo key specifies a resource limit. foo should be one of resource types such as core. The corresponding value should be an integer or an array which have one or two integers: same as cur_limit and max_limit arguments for ::setrlimit.

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

The :umask key in options specifies the umask.

pid = spawn(command, :umask=>077)

The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection. The redirection maps a file descriptor in the child process.

For example, stderr can be merged into stdout as follows:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

The hash keys specifies a file descriptor in the child process started by spawn. :err, 2 and STDERR specifies the standard error stream (stderr).

The hash values specifies a file descriptor in the parent process which invokes spawn. :out, 1 and STDOUT specifies the standard output stream (stdout).

In the above example, the standard output in the child process is not specified. So it is inherited from the parent process.

The standard input stream (stdin) can be specified by :in, 0 and STDIN.

A filename can be specified as a hash value.

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

For stdout and stderr, it is opened in write mode. Otherwise read mode is used.

For specifying flags and permission of file creation explicitly, an array is used instead.

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

The array specifies a filename, flags and permission. The flags can be a string or an integer. If the flags is omitted or nil, File::RDONLY is assumed. The permission should be an integer. If the permission is omitted or nil, 0644 is assumed.

If an array of IOs and integers are specified as a hash key, all the elements are redirected.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

Another way to merge multiple file descriptors is [:child, fd]. [:child, fd] means the file descriptor in the child process. This is different from fd. For example, :err=>:out means redirecting child stderr to parent stdout. But :err=>[:child, :out] means redirecting child stderr to child stdout. They differ if stdout is redirected in the child process as follows.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

[:child, :out] can be used to merge stderr into stdout in IO.popen. In this case, IO.popen redirects stdout to a pipe in the child process and [:child, :out] refers the redirected stdout.

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

The :chdir key in options specifies the current directory.

pid = spawn(command, :chdir=>"/var/tmp")

spawn closes all non-standard unspecified descriptors by default. The “standard” descriptors are 0, 1 and 2. This behavior is specified by :close_others option. :close_others doesn't affect the standard descriptors which are closed only if :close is specified explicitly.

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

:close_others is true by default for spawn and IO.popen.

Note that fds which close-on-exec flag is already set are closed regardless of :close_others option.

So IO.pipe and spawn can be used as IO.popen.

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

:close is specified as a hash value to close a fd individually.

f = open(foo)
system(command, f=>:close)        # don't inherit f.

If a file descriptor need to be inherited, io=>io can be used.

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

It is also possible to exchange file descriptors.

pid = spawn(command, :out=>:err, :err=>:out)

The hash keys specify file descriptors in the child process. The hash values specifies file descriptors in the parent process. So the above specifies exchanging stdout and stderr. Internally, spawn uses an extra file descriptor to resolve such cyclic file descriptor mapping.

See Kernel.exec for the standard shell.

static VALUE
rb_f_spawn(int argc, VALUE *argv)
{
    rb_pid_t pid;
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

    pid = rb_spawn_process(eargp, errmsg, sizeof(errmsg));
    RB_GC_GUARD(execarg_obj);

    if (pid == -1) {
        const char *prog = errmsg;
        if (!prog[0]) {
            rb_sys_fail_str(fail_str);
        }
        rb_sys_fail(prog);
    }
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
    return PIDT2NUM(pid);
#else
    return Qnil;
#endif
}
times → aStructTms click to toggle source

Returns a Tms structure (see Struct::Tms) that contains user and system CPU times for this process, and also for children processes.

t = Process.times
[ t.utime, t.stime, t.cutime, t.cstime ]   #=> [0.0, 0.02, 0.00, 0.00]

VALUE
rb_proc_times(VALUE obj)
{
    const double hertz =
#ifdef HAVE__SC_CLK_TCK
        (double)sysconf(_SC_CLK_TCK);
#else
#ifndef HZ
# ifdef CLK_TCK
#   define HZ CLK_TCK
# else
#   define HZ 60
# endif
#endif /* HZ */
        HZ;
#endif
    struct tms buf;
    volatile VALUE utime, stime, cutime, sctime;

    times(&buf);
    return rb_struct_new(rb_cProcessTms,
                         utime = DBL2NUM(buf.tms_utime / hertz),
                         stime = DBL2NUM(buf.tms_stime / hertz),
                         cutime = DBL2NUM(buf.tms_cutime / hertz),
                         sctime = DBL2NUM(buf.tms_cstime / hertz));
}
uid → fixnum click to toggle source
Process::UID.rid → fixnum
Process::Sys.getuid → fixnum

Returns the (real) user ID of this process.

Process.uid   #=> 501

static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}
uid= user → numeric click to toggle source

Sets the (user) user ID for this process. Not available on all platforms.

static VALUE
proc_setuid(VALUE obj, VALUE id)
{
    rb_uid_t uid;

    check_uid_switch();

    uid = OBJ2UID(id);
#if defined(HAVE_SETRESUID)
    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREUID
    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRUID
    if (setruid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
    {
        if (geteuid() == uid) {
            if (setuid(uid) < 0) rb_sys_fail(0);
        }
        else {
            rb_notimplement();
        }
    }
#endif
    return id;
}
wait() → fixnum click to toggle source
wait(pid=-1, flags=0) → fixnum
waitpid(pid=-1, flags=0) → fixnum

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
        pid = -1;
    }
    else {
        rb_scan_args(argc, argv, "02", &vpid, &vflags);
        pid = NUM2PIDT(vpid);
        if (argc == 2 && !NIL_P(vflags)) {
            flags = NUM2UINT(vflags);
        }
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
        rb_sys_fail(0);
    if (pid == 0) {
        rb_last_status_clear();
        return Qnil;
    }
    return PIDT2NUM(pid);
}
wait2(pid=-1, flags=0) → [pid, status] click to toggle source
waitpid2(pid=-1, flags=0) → [pid, status]

Waits for a child process to exit (see ::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}
waitall → [ [pid1,status1], ...] click to toggle source

Waits for all children, returning an array of pid/status pairs (where status is a Process::Status object).

fork { sleep 0.2; exit 2 }   #=> 27432
fork { sleep 0.1; exit 1 }   #=> 27433
fork {            exit 0 }   #=> 27434
p Process.waitall

produces:

[[30982, #<Process::Status: pid 30982 exit 0>],
 [30979, #<Process::Status: pid 30979 exit 1>],
 [30976, #<Process::Status: pid 30976 exit 2>]]
static VALUE
proc_waitall(void)
{
    VALUE result;
    rb_pid_t pid;
    int status;

    rb_secure(2);
    result = rb_ary_new();
#ifdef NO_WAITPID
    if (pid_tbl) {
        st_foreach(pid_tbl, waitall_each, result);
    }
#else
    rb_last_status_clear();
#endif

    for (pid = -1;;) {
#ifdef NO_WAITPID
        pid = wait(&status);
#else
        pid = rb_waitpid(-1, &status, 0);
#endif
        if (pid == -1) {
            if (errno == ECHILD)
                break;
#ifdef NO_WAITPID
            if (errno == EINTR) {
                rb_thread_schedule();
                continue;
            }
#endif
            rb_sys_fail(0);
        }
#ifdef NO_WAITPID
        rb_last_status_set(status, pid);
#endif
        rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
    }
    return result;
}
wait() → fixnum click to toggle source
wait(pid=-1, flags=0) → fixnum
waitpid(pid=-1, flags=0) → fixnum

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
        pid = -1;
    }
    else {
        rb_scan_args(argc, argv, "02", &vpid, &vflags);
        pid = NUM2PIDT(vpid);
        if (argc == 2 && !NIL_P(vflags)) {
            flags = NUM2UINT(vflags);
        }
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
        rb_sys_fail(0);
    if (pid == 0) {
        rb_last_status_clear();
        return Qnil;
    }
    return PIDT2NUM(pid);
}
wait2(pid=-1, flags=0) → [pid, status] click to toggle source
waitpid2(pid=-1, flags=0) → [pid, status]

Waits for a child process to exit (see ::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}


module Process::GID - Ruby 2.0.0-p576 Core API Reference API Reference

module Process::GID

The Process::GID module contains a collection of module functions which can be used to portably get, set, and switch the current process's real, effective, and saved group IDs.

In Files

  • process.c

Public Class Methods

Process::GID.change_privilege(group) → fixnum click to toggle source

Change the current process's real and effective group ID to that specified by group. Returns the new group ID. Not available on all platforms.

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.change_privilege(33)    #=> 33
[Process.gid, Process.egid]          #=> [33, 33]

static VALUE
p_gid_change_privilege(VALUE obj, VALUE id)
{
    rb_gid_t gid;

    check_gid_switch();

    gid = OBJ2GID(id);

    if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
        if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
        if (setgid(gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
        if (getgid() == gid) {
            if (SAVED_GROUP_ID == gid) {
                if (setregid(-1, gid) < 0) rb_sys_fail(0);
            }
            else {
                if (gid == 0) { /* (r,e,s) == (root, y, x) */
                    if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
                    if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
                    if (setregid(gid, gid) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = gid;
                }
                else { /* (r,e,s) == (z, y, x) */
                    if (setregid(0, 0) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = 0;
                    if (setregid(gid, gid) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = gid;
                }
            }
        }
        else {
            if (setregid(gid, gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
        if (getgid() == gid) {
            if (SAVED_GROUP_ID == gid) {
                if (setegid(gid) < 0) rb_sys_fail(0);
            }
            else {
                if (gid == 0) {
                    if (setegid(gid) < 0) rb_sys_fail(0);
                    if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = 0;
                    if (setrgid(0) < 0) rb_sys_fail(0);
                }
                else {
                    if (setrgid(0) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = 0;
                    if (setegid(gid) < 0) rb_sys_fail(0);
                    if (setrgid(gid) < 0) rb_sys_fail(0);
                    SAVED_GROUP_ID = gid;
                }
            }
        }
        else {
            if (setegid(gid) < 0) rb_sys_fail(0);
            if (setrgid(gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
#else
        rb_notimplement();
#endif
    }
    else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
        if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
                      (getegid() == gid)? (rb_gid_t)-1: gid,
                      (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
        if (SAVED_GROUP_ID == gid) {
            if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
                         (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
                rb_sys_fail(0);
        }
        else if (getgid() != gid) {
            if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
                rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
        else if (/* getgid() == gid && */ getegid() != gid) {
            if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
            if (setregid(gid, -1) < 0) rb_sys_fail(0);
        }
        else { /* getgid() == gid && getegid() == gid */
            if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
            if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
            if (setregid(gid, -1) < 0) rb_sys_fail(0);
        }
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
        if (SAVED_GROUP_ID == gid) {
            if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
            if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
        }
        else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
            if (getgid() != gid) {
                if (setrgid(gid) < 0) rb_sys_fail(0);
                SAVED_GROUP_ID = gid;
            }
            else {
                if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
                SAVED_GROUP_ID = gid;
                if (setrgid(gid) < 0) rb_sys_fail(0);
            }
        }
        else if (/* getegid() != gid && */ getgid() == gid) {
            if (setegid(gid) < 0) rb_sys_fail(0);
            if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
            if (setrgid(gid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_44BSD_SETGID
        if (getgid() == gid) {
            /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
            if (setgid(gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETEGID
        if (getgid() == gid && SAVED_GROUP_ID == gid) {
            if (setegid(gid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETGID
        if (getgid() == gid && SAVED_GROUP_ID == gid) {
            if (setgid(gid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#else
        (void)gid;
        rb_notimplement();
#endif
    }
    return id;
}
egid → fixnum click to toggle source
Process::GID.eid → fixnum
Process::Sys.geteid → fixnum

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}
from_name(p1) click to toggle source
static VALUE
p_gid_from_name(VALUE self, VALUE id)
{
    return GIDT2NUM(OBJ2GID(id));
}
Process::GID.grant_privilege(group) → fixnum click to toggle source
Process::GID.eid = group → fixnum

Set the effective group ID, and if possible, the saved group ID of the process to the given group. Returns the new effective group ID. Not available on all platforms.

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.grant_privilege(31)     #=> 33
[Process.gid, Process.egid]          #=> [0, 33]

static VALUE
p_gid_grant_privilege(VALUE obj, VALUE id)
{
    rb_setegid_core(OBJ2GID(id));
    return id;
}
Process::GID.re_exchange → fixnum click to toggle source

Exchange real and effective group IDs and return the new effective group ID. Not available on all platforms.

[Process.gid, Process.egid]   #=> [0, 33]
Process::GID.re_exchange      #=> 0
[Process.gid, Process.egid]   #=> [33, 0]

static VALUE
p_gid_exchange(VALUE obj)
{
    rb_gid_t gid;
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
    rb_gid_t egid;
#endif

    check_gid_switch();

    gid = getgid();
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
    egid = getegid();
#endif

#if defined(HAVE_SETRESGID)
    if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    if (setregid(egid,gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#else
    rb_notimplement();
#endif
    return GIDT2NUM(gid);
}
Process::GID.re_exchangeable? → true or false click to toggle source

Returns true if the real and effective group IDs of a process may be exchanged on the current platform.

static VALUE
p_gid_exchangeable(void)
{
#if defined(HAVE_SETRESGID)
    return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    return Qtrue;
#else
    return Qfalse;
#endif
}
gid → fixnum click to toggle source
Process::GID.rid → fixnum
Process::Sys.getgid → fixnum

Returns the (real) group ID for this process.

Process.gid   #=> 500

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}
Process::GID.sid_available? → true or false click to toggle source

Returns true if the current platform has saved group ID functionality.

static VALUE
p_gid_have_saved_id(void)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
    return Qtrue;
#else
    return Qfalse;
#endif
}
Process::GID.switch → fixnum click to toggle source
Process::GID.switch {|| block} → object

Switch the effective and real group IDs of the current process. If a block is given, the group IDs will be switched back after the block is executed. Returns the new effective group ID if called without a block, and the return value of the block if one is given.

static VALUE
p_gid_switch(VALUE obj)
{
    rb_gid_t gid, egid;

    check_gid_switch();

    gid = getgid();
    egid = getegid();

    if (gid != egid) {
        proc_setegid(obj, GIDT2NUM(gid));
        if (rb_block_given_p()) {
            under_gid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
        }
        else {
            return GIDT2NUM(egid);
        }
    }
    else if (egid != SAVED_GROUP_ID) {
        proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
        if (rb_block_given_p()) {
            under_gid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
        }
        else {
            return GIDT2NUM(gid);
        }
    }
    else {
        errno = EPERM;
        rb_sys_fail(0);
    }

    UNREACHABLE;
}


class Process::Status - Ruby 2.0.0-p576 Core API Reference API Reference

class Process::Status

Process::Status encapsulates the information on the status of a running or terminated system process. The built-in variable $? is either nil or a Process::Status object.

fork { exit 99 }   #=> 26557
Process.wait       #=> 26557
$?.class           #=> Process::Status
$?.to_i            #=> 25344
$? >> 8            #=> 99
$?.stopped?        #=> false
$?.exited?         #=> true
$?.exitstatus      #=> 99

Posix systems record information on processes using a 16-bit integer. The lower bits record the process status (stopped, exited, signaled) and the upper bits possibly contain additional information (for example the program's return code in the case of exited processes). Pre Ruby 1.8, these bits were exposed directly to the Ruby program. Ruby now encapsulates these in a Process::Status object. To maximize compatibility, however, these objects retain a bit-oriented interface. In the descriptions that follow, when we talk about the integer value of stat, we're referring to this 16 bit value.

In Files

  • process.c

Parent

Object

Public Instance Methods

stat & num → fixnum click to toggle source

Logical AND of the bits in stat with num.

fork { exit 0x37 }
Process.wait
sprintf('%04x', $?.to_i)       #=> "3700"
sprintf('%04x', $? & 0x1e00)   #=> "1600"

static VALUE
pst_bitand(VALUE st1, VALUE st2)
{
    int status = PST2INT(st1) & NUM2INT(st2);

    return INT2NUM(status);
}
stat == other → true or false click to toggle source

Returns true if the integer value of stat equals other.

static VALUE
pst_equal(VALUE st1, VALUE st2)
{
    if (st1 == st2) return Qtrue;
    return rb_equal(pst_to_i(st1), st2);
}
stat >> num → fixnum click to toggle source

Shift the bits in stat right num places.

fork { exit 99 }   #=> 26563
Process.wait       #=> 26563
$?.to_i            #=> 25344
$? >> 8            #=> 99

static VALUE
pst_rshift(VALUE st1, VALUE st2)
{
    int status = PST2INT(st1) >> NUM2INT(st2);

    return INT2NUM(status);
}
coredump? → true or false click to toggle source

Returns true if stat generated a coredump when it terminated. Not available on all platforms.

static VALUE
pst_wcoredump(VALUE st)
{
#ifdef WCOREDUMP
    int status = PST2INT(st);

    if (WCOREDUMP(status))
        return Qtrue;
    else
        return Qfalse;
#else
    return Qfalse;
#endif
}
exited? → true or false click to toggle source

Returns true if stat exited normally (for example using an exit() call or finishing the program).

static VALUE
pst_wifexited(VALUE st)
{
    int status = PST2INT(st);

    if (WIFEXITED(status))
        return Qtrue;
    else
        return Qfalse;
}
exitstatus → fixnum or nil click to toggle source

Returns the least significant eight bits of the return code of stat. Only available if exited? is true.

fork { }           #=> 26572
Process.wait       #=> 26572
$?.exited?         #=> true
$?.exitstatus      #=> 0

fork { exit 99 }   #=> 26573
Process.wait       #=> 26573
$?.exited?         #=> true
$?.exitstatus      #=> 99

static VALUE
pst_wexitstatus(VALUE st)
{
    int status = PST2INT(st);

    if (WIFEXITED(status))
        return INT2NUM(WEXITSTATUS(status));
    return Qnil;
}
inspect → string click to toggle source

Override the inspection method.

system("false")
p $?.inspect #=> "#<Process::Status: pid 12861 exit 1>"

static VALUE
pst_inspect(VALUE st)
{
    rb_pid_t pid;
    int status;
    VALUE vpid, str;

    vpid = pst_pid(st);
    if (NIL_P(vpid)) {
        return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
    }
    pid = NUM2PIDT(vpid);
    status = PST2INT(st);

    str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
    pst_message(str, pid, status);
    rb_str_cat2(str, ">");
    return str;
}
pid → fixnum click to toggle source

Returns the process ID that this status object represents.

fork { exit }   #=> 26569
Process.wait    #=> 26569
$?.pid          #=> 26569

static VALUE
pst_pid(VALUE st)
{
    return rb_attr_get(st, rb_intern("pid"));
}
signaled? → true or false click to toggle source

Returns true if stat terminated because of an uncaught signal.

static VALUE
pst_wifsignaled(VALUE st)
{
    int status = PST2INT(st);

    if (WIFSIGNALED(status))
        return Qtrue;
    else
        return Qfalse;
}
stopped? → true or false click to toggle source

Returns true if this process is stopped. This is only returned if the corresponding wait call had the WUNTRACED flag set.

static VALUE
pst_wifstopped(VALUE st)
{
    int status = PST2INT(st);

    if (WIFSTOPPED(status))
        return Qtrue;
    else
        return Qfalse;
}
stopsig → fixnum or nil click to toggle source

Returns the number of the signal that caused stat to stop (or nil if self is not stopped).

static VALUE
pst_wstopsig(VALUE st)
{
    int status = PST2INT(st);

    if (WIFSTOPPED(status))
        return INT2NUM(WSTOPSIG(status));
    return Qnil;
}
success? → true, false or nil click to toggle source

Returns true if stat is successful, false if not. Returns nil if exited? is not true.

static VALUE
pst_success_p(VALUE st)
{
    int status = PST2INT(st);

    if (!WIFEXITED(status))
        return Qnil;
    return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
}
termsig → fixnum or nil click to toggle source

Returns the number of the signal that caused stat to terminate (or nil if self was not terminated by an uncaught signal).

static VALUE
pst_wtermsig(VALUE st)
{
    int status = PST2INT(st);

    if (WIFSIGNALED(status))
        return INT2NUM(WTERMSIG(status));
    return Qnil;
}
to_i → fixnum click to toggle source
to_int → fixnum

Returns the bits in stat as a Fixnum. Poking around in these bits is platform dependent.

fork { exit 0xab }         #=> 26566
Process.wait               #=> 26566
sprintf('%04x', $?.to_i)   #=> "ab00"

static VALUE
pst_to_i(VALUE st)
{
    return rb_iv_get(st, "status");
}
to_s → string click to toggle source

Show pid and exit status as a string.

system("false")
p $?.to_s         #=> "pid 12766 exit 1"

static VALUE
pst_to_s(VALUE st)
{
    rb_pid_t pid;
    int status;
    VALUE str;

    pid = NUM2PIDT(pst_pid(st));
    status = PST2INT(st);

    str = rb_str_buf_new(0);
    pst_message(str, pid, status);
    return str;
}


module Process::Sys - Ruby 2.0.0-p576 Core API Reference API Reference

module Process::Sys

The Process::Sys module contains UID and GID functions which provide direct bindings to the system calls of the same names instead of the more-portable versions of the same functionality found in the Process, Process::UID, and Process::GID modules.

In Files

  • process.c

Public Class Methods

egid → fixnum click to toggle source
Process::GID.eid → fixnum
Process::Sys.geteid → fixnum

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}
euid → fixnum click to toggle source
Process::UID.eid → fixnum
Process::Sys.geteuid → fixnum

Returns the effective user ID for this process.

Process.euid   #=> 501

static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}
gid → fixnum click to toggle source
Process::GID.rid → fixnum
Process::Sys.getgid → fixnum

Returns the (real) group ID for this process.

Process.gid   #=> 500

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}
uid → fixnum click to toggle source
Process::UID.rid → fixnum
Process::Sys.getuid → fixnum

Returns the (real) user ID of this process.

Process.uid   #=> 501

static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}
Process::Sys.issetugid → true or false click to toggle source

Returns true if the process was created as a result of an execve(2) system call which had either of the setuid or setgid bits set (and extra privileges were given as a result) or if it has changed any of its real, effective or saved user or group IDs since it began execution.

static VALUE
p_sys_issetugid(VALUE obj)
{
    rb_secure(2);
    if (issetugid()) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}
Process::Sys.setegid(group) → nil click to toggle source

Set the effective group ID of the calling process to group. Not available on all platforms.

static VALUE
p_sys_setegid(VALUE obj, VALUE id)
{
    check_gid_switch();
    if (setegid(OBJ2GID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.seteuid(user) → nil click to toggle source

Set the effective user ID of the calling process to user. Not available on all platforms.

static VALUE
p_sys_seteuid(VALUE obj, VALUE id)
{
    check_uid_switch();
    if (seteuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setgid(group) → nil click to toggle source

Set the group ID of the current process to group. Not available on all platforms.

static VALUE
p_sys_setgid(VALUE obj, VALUE id)
{
    check_gid_switch();
    if (setgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setregid(rid, eid) → nil click to toggle source

Sets the (group) real and/or effective group IDs of the current process to rid and eid, respectively. A value of -1 for either means to leave that ID unchanged. Not available on all platforms.

static VALUE
p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
{
    rb_gid_t rgid, egid;
    PREPARE_GETGRNAM;
    check_gid_switch();
    rgid = OBJ2GID(rid);
    egid = OBJ2GID(eid);
    FINISH_GETGRNAM;
    if (setregid(rgid, egid) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setresgid(rid, eid, sid) → nil click to toggle source

Sets the (group) real, effective, and saved user IDs of the current process to rid, eid, and sid respectively. A value of -1 for any value means to leave that ID unchanged. Not available on all platforms.

static VALUE
p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
{
    rb_gid_t rgid, egid, sgid;
    PREPARE_GETGRNAM;
    check_gid_switch();
    rgid = OBJ2GID(rid);
    egid = OBJ2GID(eid);
    sgid = OBJ2GID(sid);
    FINISH_GETGRNAM;
    if (setresgid(rgid, egid, sgid) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setresuid(rid, eid, sid) → nil click to toggle source

Sets the (user) real, effective, and saved user IDs of the current process to rid, eid, and sid respectively. A value of -1 for any value means to leave that ID unchanged. Not available on all platforms.

static VALUE
p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
{
    rb_uid_t ruid, euid, suid;
    PREPARE_GETPWNAM;
    check_uid_switch();
    ruid = OBJ2UID1(rid);
    euid = OBJ2UID1(eid);
    suid = OBJ2UID1(sid);
    FINISH_GETPWNAM;
    if (setresuid(ruid, euid, suid) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setreuid(rid, eid) → nil click to toggle source

Sets the (user) real and/or effective user IDs of the current process to rid and eid, respectively. A value of -1 for either means to leave that ID unchanged. Not available on all platforms.

static VALUE
p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
{
    rb_uid_t ruid, euid;
    PREPARE_GETPWNAM;
    check_uid_switch();
    ruid = OBJ2UID1(rid);
    euid = OBJ2UID1(eid);
    FINISH_GETPWNAM;
    if (setreuid(ruid, euid) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setrgid(group) → nil click to toggle source

Set the real group ID of the calling process to group. Not available on all platforms.

static VALUE
p_sys_setrgid(VALUE obj, VALUE id)
{
    check_gid_switch();
    if (setrgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setruid(user) → nil click to toggle source

Set the real user ID of the calling process to user. Not available on all platforms.

static VALUE
p_sys_setruid(VALUE obj, VALUE id)
{
    check_uid_switch();
    if (setruid(OBJ2UID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}
Process::Sys.setuid(user) → nil click to toggle source

Set the user ID of the current process to user. Not available on all platforms.

static VALUE
p_sys_setuid(VALUE obj, VALUE id)
{
    check_uid_switch();
    if (setuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
    return Qnil;
}


module Process::UID - Ruby 2.0.0-p576 Core API Reference API Reference

module Process::UID

The Process::UID module contains a collection of module functions which can be used to portably get, set, and switch the current process's real, effective, and saved user IDs.

In Files

  • process.c

Public Class Methods

Process::UID.change_privilege(user) → fixnum click to toggle source

Change the current process's real and effective user ID to that specified by user. Returns the new user ID. Not available on all platforms.

[Process.uid, Process.euid]          #=> [0, 0]
Process::UID.change_privilege(31)    #=> 31
[Process.uid, Process.euid]          #=> [31, 31]

static VALUE
p_uid_change_privilege(VALUE obj, VALUE id)
{
    rb_uid_t uid;

    check_uid_switch();

    uid = OBJ2UID(id);

    if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESUID)
        if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETUID)
        if (setuid(uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        if (getuid() == uid) {
            if (SAVED_USER_ID == uid) {
                if (setreuid(-1, uid) < 0) rb_sys_fail(0);
            }
            else {
                if (uid == 0) { /* (r,e,s) == (root, root, x) */
                    if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
                    if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
                    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
                else {
                    if (setreuid(0, -1) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
            }
        }
        else {
            if (setreuid(uid, uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
        if (getuid() == uid) {
            if (SAVED_USER_ID == uid) {
                if (seteuid(uid) < 0) rb_sys_fail(0);
            }
            else {
                if (uid == 0) {
                    if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (setruid(0) < 0) rb_sys_fail(0);
                }
                else {
                    if (setruid(0) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (seteuid(uid) < 0) rb_sys_fail(0);
                    if (setruid(uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
            }
        }
        else {
            if (seteuid(uid) < 0) rb_sys_fail(0);
            if (setruid(uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
#else
        (void)uid;
        rb_notimplement();
#endif
    }
    else { /* unprivileged user */
#if defined(HAVE_SETRESUID)
        if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
                      (geteuid() == uid)? (rb_uid_t)-1: uid,
                      (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        if (SAVED_USER_ID == uid) {
            if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
                         (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
                rb_sys_fail(0);
        }
        else if (getuid() != uid) {
            if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
                rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
        else if (/* getuid() == uid && */ geteuid() != uid) {
            if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setreuid(uid, -1) < 0) rb_sys_fail(0);
        }
        else { /* getuid() == uid && geteuid() == uid */
            if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
            if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setreuid(uid, -1) < 0) rb_sys_fail(0);
        }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
        if (SAVED_USER_ID == uid) {
            if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
            if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
        }
        else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
            if (getuid() != uid) {
                if (setruid(uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
            }
            else {
                if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
                if (setruid(uid) < 0) rb_sys_fail(0);
            }
        }
        else if (/* geteuid() != uid && */ getuid() == uid) {
            if (seteuid(uid) < 0) rb_sys_fail(0);
            if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setruid(uid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_44BSD_SETUID
        if (getuid() == uid) {
            /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
            if (setuid(uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETEUID
        if (getuid() == uid && SAVED_USER_ID == uid) {
            if (seteuid(uid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETUID
        if (getuid() == uid && SAVED_USER_ID == uid) {
            if (setuid(uid) < 0) rb_sys_fail(0);
        }
        else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#else
        rb_notimplement();
#endif
    }
    return id;
}
euid → fixnum click to toggle source
Process::UID.eid → fixnum
Process::Sys.geteuid → fixnum

Returns the effective user ID for this process.

Process.euid   #=> 501

static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}
from_name(p1) click to toggle source
static VALUE
p_uid_from_name(VALUE self, VALUE id)
{
    return UIDT2NUM(OBJ2UID(id));
}
Process::UID.grant_privilege(user) → fixnum click to toggle source
Process::UID.eid= user → fixnum

Set the effective user ID, and if possible, the saved user ID of the process to the given user. Returns the new effective user ID. Not available on all platforms.

[Process.uid, Process.euid]          #=> [0, 0]
Process::UID.grant_privilege(31)     #=> 31
[Process.uid, Process.euid]          #=> [0, 31]

static VALUE
p_uid_grant_privilege(VALUE obj, VALUE id)
{
    rb_seteuid_core(OBJ2UID(id));
    return id;
}
Process::UID.re_exchange → fixnum click to toggle source

Exchange real and effective user IDs and return the new effective user ID. Not available on all platforms.

[Process.uid, Process.euid]   #=> [0, 31]
Process::UID.re_exchange      #=> 0
[Process.uid, Process.euid]   #=> [31, 0]

static VALUE
p_uid_exchange(VALUE obj)
{
    rb_uid_t uid;
#if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
    rb_uid_t euid;
#endif

    check_uid_switch();

    uid = getuid();
#if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
    euid = geteuid();
#endif

#if defined(HAVE_SETRESUID)
    if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
    SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
    if (setreuid(euid,uid) < 0) rb_sys_fail(0);
    SAVED_USER_ID = uid;
#else
    rb_notimplement();
#endif
    return UIDT2NUM(uid);
}
Process::UID.re_exchangeable? → true or false click to toggle source

Returns true if the real and effective user IDs of a process may be exchanged on the current platform.

static VALUE
p_uid_exchangeable(void)
{
#if defined(HAVE_SETRESUID)
    return Qtrue;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
    return Qtrue;
#else
    return Qfalse;
#endif
}
uid → fixnum click to toggle source
Process::UID.rid → fixnum
Process::Sys.getuid → fixnum

Returns the (real) user ID of this process.

Process.uid   #=> 501

static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}
Process::UID.sid_available? → true or false click to toggle source

Returns true if the current platform has saved user ID functionality.

static VALUE
p_uid_have_saved_id(void)
{
#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
    return Qtrue;
#else
    return Qfalse;
#endif
}
Process::UID.switch → fixnum click to toggle source
Process::UID.switch {|| block} → object

Switch the effective and real user IDs of the current process. If a block is given, the user IDs will be switched back after the block is executed. Returns the new effective user ID if called without a block, and the return value of the block if one is given.

static VALUE
p_uid_switch(VALUE obj)
{
    rb_uid_t uid, euid;

    check_uid_switch();

    uid = getuid();
    euid = geteuid();

    if (uid != euid) {
        proc_seteuid(uid);
        if (rb_block_given_p()) {
            under_uid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
        }
        else {
            return UIDT2NUM(euid);
        }
    }
    else if (euid != SAVED_USER_ID) {
        proc_seteuid(SAVED_USER_ID);
        if (rb_block_given_p()) {
            under_uid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
        }
        else {
            return UIDT2NUM(uid);
        }
    }
    else {
        errno = EPERM;
        rb_sys_fail(0);
    }

    UNREACHABLE;
}


class Random - Ruby 2.0.0-p576 Core API Reference API Reference

class Random

Random provides an interface to Ruby's pseudo-random number generator, or PRNG. The PRNG produces a deterministic sequence of bits which approximate true randomness. The sequence may be represented by integers, floats, or binary strings.

The generator may be initialized with either a system-generated or user-supplied seed value by using ::srand.

The class method #rand provides the base functionality of Kernel#rand along with better handling of floating point values. These are both interfaces to Random::DEFAULT, the Ruby system PRNG.

::new will create a new PRNG with a state independent of Random::DEFAULT, allowing multiple generators with different seed values or sequence positions to exist simultaneously. Random objects can be marshaled, allowing sequences to be saved and resumed.

PRNGs are currently implemented as a modified Mersenne Twister with a period of 2**19937-1.

In Files

  • random.c

Parent

Object

Constants

DEFAULT

Public Class Methods

new(seed = Random.new_seed) → prng click to toggle source

Creates a new PRNG using seed to set the initial state. If seed is omitted, the generator is initialized with ::new_seed.

See ::srand for more information on the use of seed values.

static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
    VALUE vseed;
    rb_random_t *rnd = get_rnd(obj);

    if (argc == 0) {
        rb_check_frozen(obj);
        vseed = random_seed();
    }
    else {
        rb_scan_args(argc, argv, "01", &vseed);
        rb_check_copyable(obj, vseed);
    }
    rnd->seed = rand_init(&rnd->mt, vseed);
    return obj;
}
new_seed → integer click to toggle source

Returns an arbitrary seed value. This is used by ::new when no seed value is specified as an argument.

Random.new_seed  #=> 115032730400174366788466674494640623225

static VALUE
random_seed(void)
{
    unsigned int buf[DEFAULT_SEED_CNT];
    fill_random_seed(buf);
    return make_seed_value(buf);
}
rand → float click to toggle source
rand(max) → number

Alias of Random::DEFAULT.rand.

static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
    return rand_random(argc, argv, rand_start(&default_rand));
}
srand(number = Random.new_seed) → old_seed click to toggle source

Seeds the system pseudo-random number generator, Random::DEFAULT, with number. The previous seed value is returned.

If number is omitted, seeds the generator using a source of entropy provided by the operating system, if available (/dev/urandom on Unix systems or the RSA cryptographic provider on Windows), which is then combined with the time, the process id, and a sequence number.

srand may be used to ensure repeatable sequences of pseudo-random numbers between different runs of the program. By setting the seed to a known value, programs can be made deterministic during testing.

srand 1234               # => 268519324636777531569100071560086917274
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]
[ rand(10), rand(1000) ] # => [4, 664]
srand 1234               # => 1234
[ rand, rand ]           # => [0.1915194503788923, 0.6221087710398319]

static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
    VALUE seed, old;
    rb_random_t *r = &default_rand;

    rb_secure(4);
    if (argc == 0) {
        seed = random_seed();
    }
    else {
        rb_scan_args(argc, argv, "01", &seed);
    }
    old = r->seed;
    r->seed = rand_init(&r->mt, seed);

    return old;
}

Public Instance Methods

prng1 == prng2 → true or false click to toggle source

Returns true if the two generators have the same internal state, otherwise false. Equivalent generators will return the same sequence of pseudo-random numbers. Two generators will generally have the same state only if they were initialized with the same seed

Random.new == Random.new             # => false
Random.new(1234) == Random.new(1234) # => true

and have the same invocation history.

prng1 = Random.new(1234)
prng2 = Random.new(1234)
prng1 == prng2 # => true

prng1.rand     # => 0.1915194503788923
prng1 == prng2 # => false

prng2.rand     # => 0.1915194503788923
prng1 == prng2 # => true

static VALUE
random_equal(VALUE self, VALUE other)
{
    rb_random_t *r1, *r2;
    if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
    r1 = get_rnd(self);
    r2 = get_rnd(other);
    if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse;
    if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
    if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
    if (r1->mt.left != r2->mt.left) return Qfalse;
    return Qtrue;
}
bytes(size) → a_string click to toggle source

Returns a random binary string containing size bytes.

random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO"
random_string.size                   # => 10

static VALUE
random_bytes(VALUE obj, VALUE len)
{
    return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
}
rand → float click to toggle source
rand(max) → number

When max is an Integer, rand returns a random integer greater than or equal to zero and less than max. Unlike Kernel#rand, when max is a negative integer or zero, rand raises an ArgumentError.

prng = Random.new
prng.rand(100)       # => 42

When max is a Float, rand returns a random floating point number between 0.0 and max, including 0.0 and excluding max.

prng.rand(1.5)       # => 1.4600282860034115

When max is a Range, rand returns a random number where range.member?(number) == true.

prng.rand(5..9)      # => one of [5, 6, 7, 8, 9]
prng.rand(5...9)     # => one of [5, 6, 7, 8]
prng.rand(5.0..9.0)  # => between 5.0 and 9.0, including 9.0
prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0

Both the beginning and ending values of the range must respond to subtract (-) and add (+)methods, or rand will raise an ArgumentError.

static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
    return rand_random(argc, argv, get_rnd(obj));
}
seed → integer click to toggle source

Returns the seed value used to initialize the generator. This may be used to initialize another generator with the same state at a later time, causing it to produce the same sequence of numbers.

prng1 = Random.new(1234)
prng1.seed       #=> 1234
prng1.rand(100)  #=> 47

prng2 = Random.new(prng1.seed)
prng2.rand(100)  #=> 47

static VALUE
random_get_seed(VALUE obj)
{
    return get_rnd(obj)->seed;
}


class Range - Ruby 2.0.0-p576 Core API Reference API Reference

class Range

A Range represents an interval—a set of values with a beginning and an end. Ranges may be constructed using the s..e and s...e literals, or with ::new. Ranges constructed using .. run from the beginning to the end inclusively. Those created using ... exclude the end value. When used as an iterator, ranges return each value in the sequence.

(-1..-5).to_a      #=> []
(-5..-1).to_a      #=> [-5, -4, -3, -2, -1]
('a'..'e').to_a    #=> ["a", "b", "c", "d", "e"]
('a'...'e').to_a   #=> ["a", "b", "c", "d"]

Custom Objects in Ranges

Ranges can be constructed using any objects that can be compared using the <=> operator. Methods that treat the range as a sequence (each and methods inherited from Enumerable) expect the begin object to implement a succ method to return the next object in sequence. The step and include? methods require the begin object to implement succ or to be numeric.

In the Xs class below both <=> and succ are implemented so Xs can be used to construct ranges. Note that the Comparable module is included so the == method is defined in terms of <=>.

class Xs                # represent a string of 'x's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'x' * @length
  end
end

An example of using Xs to construct a range:

r = Xs.new(3)..Xs.new(6)   #=> xxx..xxxxxx
r.to_a                     #=> [xxx, xxxx, xxxxx, xxxxxx]
r.member?(Xs.new(5))       #=> true

In Files

  • range.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

new(begin, end, exclude_end=false) → rng click to toggle source

Constructs a range using the given begin and end. If the exclude_end parameter is omitted or is false, the rng will include the end object; otherwise, it will be excluded.

static VALUE
range_initialize(int argc, VALUE *argv, VALUE range)
{
    VALUE beg, end, flags;

    rb_scan_args(argc, argv, "21", &beg, &end, &flags);
    /* Ranges are immutable, so that they should be initialized only once. */
    if (RANGE_EXCL(range) != Qnil) {
        rb_name_error(idInitialize, "`initialize' called twice");
    }
    range_init(range, beg, end, RTEST(flags));
    return Qnil;
}

Public Instance Methods

rng == obj → true or false click to toggle source

Returns true only if obj is a Range, has equivalent begin and end items (by comparing them with ==), and has the same exclude_end? setting as the range.

(0..2) == (0..2)            #=> true
(0..2) == Range.new(0,2)    #=> true
(0..2) == (0...2)           #=> false

static VALUE
range_eq(VALUE range, VALUE obj)
{
    if (range == obj)
        return Qtrue;
    if (!rb_obj_is_kind_of(obj, rb_cRange))
        return Qfalse;

    return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
}
rng === obj → true or false click to toggle source

Returns true if obj is an element of the range, false otherwise. Conveniently, === is the comparison operator used by case statements.

case 79
when 1..50   then   print "low\n"
when 51..75  then   print "medium\n"
when 76..100 then   print "high\n"
end

produces:

high
static VALUE
range_eqq(VALUE range, VALUE val)
{
    return rb_funcall(range, rb_intern("include?"), 1, val);
}
begin → obj click to toggle source

Returns the object that defines the beginning of the range.

(1..10).begin   #=> 1

static VALUE
range_begin(VALUE range)
{
    return RANGE_BEG(range);
}
bsearch {|obj| block } → value click to toggle source

By using binary search, finds a value in range which meets the given condition in O(log n) where n is the size of the range.

You can use this method in two use cases: a find-minimum mode and a find-any mode. In either case, the elements of the range must be monotone (or sorted) with respect to the block.

In find-minimum mode (this is a good choice for typical use case), the block must return true or false, and there must be a value x so that:

  • the block returns false for any value which is less than x, and

  • the block returns true for any value which is greater than or equal to i.

If x is within the range, this method returns the value x. Otherwise, it returns nil.

ary = [0, 4, 7, 10, 12]
(0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
(0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
(0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
(0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil

(0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0

In find-any mode (this behaves like libc's bsearch(3)), the block must return a number, and there must be two values x and y (x <= y) so that:

  • the block returns a positive number for v if v < x,

  • the block returns zero for v if x <= v < y, and

  • the block returns a negative number for v if y <= v.

This method returns any value which is within the intersection of the given range and x…y (if any). If there is no value that satisfies the condition, it returns nil.

ary = [0, 100, 100, 100, 200]
(0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
(0..4).bsearch {|i| 300 - ary[i] } #=> nil
(0..4).bsearch {|i|  50 - ary[i] } #=> nil

You must not mix the two modes at a time; the block must always return either true/false, or always return a number. It is undefined which value is actually picked up at each iteration.

static VALUE
range_bsearch(VALUE range)
{
    VALUE beg, end;
    int smaller, satisfied = 0;

    /* Implementation notes:
     * Floats are handled by mapping them to 64 bits integers.
     * Apart from sign issues, floats and their 64 bits integer have the
     * same order, assuming they are represented as exponent followed
     * by the mantissa. This is true with or without implicit bit.
     *
     * Finding the average of two ints needs to be careful about
     * potential overflow (since float to long can use 64 bits)
     * as well as the fact that -1/2 can be 0 or -1 in C89.
     *
     * Note that -0.0 is mapped to the same int as 0.0 as we don't want
     * (-1...0.0).bsearch to yield -0.0.
     */

#define BSEARCH_CHECK(val) \
    do { \
        VALUE v = rb_yield(val); \
        if (FIXNUM_P(v)) { \
            if (FIX2INT(v) == 0) return val; \
            smaller = FIX2INT(v) < 0; \
        } \
        else if (v == Qtrue) { \
            satisfied = 1; \
            smaller = 1; \
        } \
        else if (v == Qfalse || v == Qnil) { \
            smaller = 0; \
        } \
        else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
            int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
            if (!cmp) return val; \
            smaller = cmp < 0; \
        } \
        else { \
            rb_raise(rb_eTypeError, "wrong argument type %s" \
                " (must be numeric, true, false or nil)", \
                rb_obj_classname(v)); \
        } \
    } while (0)

#define BSEARCH(conv) \
    do { \
        RETURN_ENUMERATOR(range, 0, 0); \
        if (EXCL(range)) high--; \
        org_high = high; \
        while (low < high) { \
            mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
                : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
            BSEARCH_CHECK(conv(mid)); \
            if (smaller) { \
                high = mid; \
            } \
            else { \
                low = mid + 1; \
            } \
        } \
        if (low == org_high) { \
            BSEARCH_CHECK(conv(low)); \
            if (!smaller) return Qnil; \
        } \
        if (!satisfied) return Qnil; \
        return conv(low); \
    } while (0)

    beg = RANGE_BEG(range);
    end = RANGE_END(range);

    if (FIXNUM_P(beg) && FIXNUM_P(end)) {
        long low = FIX2LONG(beg);
        long high = FIX2LONG(end);
        long mid, org_high;
        BSEARCH(INT2FIX);
    }
#if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
    else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
        int64_t low  = double_as_int64(RFLOAT_VALUE(rb_Float(beg)));
        int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end)));
        int64_t mid, org_high;
        BSEARCH(int64_as_double_to_num);
    }
#endif
    else if (is_integer_p(beg) && is_integer_p(end)) {
        VALUE low = rb_to_int(beg);
        VALUE high = rb_to_int(end);
        VALUE mid, org_high;
        RETURN_ENUMERATOR(range, 0, 0);
        if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1));
        org_high = high;

        while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
            mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
            BSEARCH_CHECK(mid);
            if (smaller) {
                high = mid;
            }
            else {
                low = rb_funcall(mid, '+', 1, INT2FIX(1));
            }
        }
        if (rb_equal(low, org_high)) {
            BSEARCH_CHECK(low);
            if (!smaller) return Qnil;
        }
        if (!satisfied) return Qnil;
        return low;
    }
    else {
        rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
    }
    return range;
}
cover?(obj) → true or false click to toggle source

Returns true if obj is between the begin and end of the range.

This tests begin <= obj <= end when exclude_end? is false and begin <= obj < end when exclude_end? is true.

("a".."z").cover?("c")    #=> true
("a".."z").cover?("5")    #=> false
("a".."z").cover?("cc")   #=> true

static VALUE
range_cover(VALUE range, VALUE val)
{
    VALUE beg, end;

    beg = RANGE_BEG(range);
    end = RANGE_END(range);
    if (r_le(beg, val)) {
        if (EXCL(range)) {
            if (r_lt(val, end))
                return Qtrue;
        }
        else {
            if (r_le(val, end))
                return Qtrue;
        }
    }
    return Qfalse;
}
each {| i | block } → rng click to toggle source
each → an_enumerator

Iterates over the elements of range, passing each in turn to the block.

The each method can only be used if the begin object of the range supports the succ method. A TypeError is raised if the object does not have succ method defined (like Float).

If no block is given, an enumerator is returned instead.

(10..15).each {|n| print n, ' ' }
# prints: 10 11 12 13 14 15

(2.5..5).each {|n| print n, ' ' }
# raises: TypeError: can't iterate from Float

static VALUE
range_each(VALUE range)
{
    VALUE beg, end;

    RETURN_SIZED_ENUMERATOR(range, 0, 0, range_size);

    beg = RANGE_BEG(range);
    end = RANGE_END(range);

    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
        long lim = FIX2LONG(end);
        long i;

        if (!EXCL(range))
            lim += 1;
        for (i = FIX2LONG(beg); i < lim; i++) {
            rb_yield(LONG2FIX(i));
        }
    }
    else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
        VALUE args[2];

        args[0] = rb_sym_to_s(end);
        args[1] = EXCL(range) ? Qtrue : Qfalse;
        rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
    }
    else {
        VALUE tmp = rb_check_string_type(beg);

        if (!NIL_P(tmp)) {
            VALUE args[2];

            args[0] = end;
            args[1] = EXCL(range) ? Qtrue : Qfalse;
            rb_block_call(tmp, rb_intern("upto"), 2, args, rb_yield, 0);
        }
        else {
            if (!discrete_object_p(beg)) {
                rb_raise(rb_eTypeError, "can't iterate from %s",
                         rb_obj_classname(beg));
            }
            range_each_func(range, each_i, NULL);
        }
    }
    return range;
}
end → obj click to toggle source

Returns the object that defines the end of the range.

(1..10).end    #=> 10
(1...10).end   #=> 10

static VALUE
range_end(VALUE range)
{
    return RANGE_END(range);
}
eql?(obj) → true or false click to toggle source

Returns true only if obj is a Range, has equivalent begin and end items (by comparing them with eql?), and has the same exclude_end? setting as the range.

(0..2).eql?(0..2)            #=> true
(0..2).eql?(Range.new(0,2))  #=> true
(0..2).eql?(0...2)           #=> false

static VALUE
range_eql(VALUE range, VALUE obj)
{
    if (range == obj)
        return Qtrue;
    if (!rb_obj_is_kind_of(obj, rb_cRange))
        return Qfalse;
    return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
}
exclude_end? → true or false click to toggle source

Returns true if the range excludes its end value.

(1..5).exclude_end?     #=> false
(1...5).exclude_end?    #=> true

static VALUE
range_exclude_end_p(VALUE range)
{
    return EXCL(range) ? Qtrue : Qfalse;
}
first → obj click to toggle source
first(n) → an_array

Returns the first object in the range, or an array of the first n elements.

(10..20).first     #=> 10
(10..20).first(3)  #=> [10, 11, 12]

static VALUE
range_first(int argc, VALUE *argv, VALUE range)
{
    VALUE n, ary[2];

    if (argc == 0) return RANGE_BEG(range);

    rb_scan_args(argc, argv, "1", &n);
    ary[0] = n;
    ary[1] = rb_ary_new2(NUM2LONG(n));
    rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);

    return ary[1];
}
hash → fixnum click to toggle source

Compute a hash-code for this range. Two ranges with equal begin and end points (using eql?), and the same exclude_end? value will generate the same hash-code.

static VALUE
range_hash(VALUE range)
{
    return rb_exec_recursive_outer(recursive_hash, range, 0);
}
member?(obj) → true or false click to toggle source
include?(obj) → true or false

Returns true if obj is an element of the range, false otherwise. If begin and end are numeric, comparison is done according to the magnitude of the values.

("a".."z").include?("g")   #=> true
("a".."z").include?("A")   #=> false
("a".."z").include?("cc")  #=> false

static VALUE
range_include(VALUE range, VALUE val)
{
    VALUE beg = RANGE_BEG(range);
    VALUE end = RANGE_END(range);
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
             rb_obj_is_kind_of(beg, rb_cNumeric) ||
             rb_obj_is_kind_of(end, rb_cNumeric);

    if (nv ||
        !NIL_P(rb_check_to_integer(beg, "to_int")) ||
        !NIL_P(rb_check_to_integer(end, "to_int"))) {
        if (r_le(beg, val)) {
            if (EXCL(range)) {
                if (r_lt(val, end))
                    return Qtrue;
            }
            else {
                if (r_le(val, end))
                    return Qtrue;
            }
        }
        return Qfalse;
    }
    else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
             RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
        if (NIL_P(val)) return Qfalse;
        if (RB_TYPE_P(val, T_STRING)) {
            if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
                return Qfalse;
            else {
                char b = RSTRING_PTR(beg)[0];
                char e = RSTRING_PTR(end)[0];
                char v = RSTRING_PTR(val)[0];

                if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
                    if (b <= v && v < e) return Qtrue;
                    if (!EXCL(range) && v == e) return Qtrue;
                    return Qfalse;
                }
            }
        }
    }
    /* TODO: ruby_frame->this_func = rb_intern("include?"); */
    return rb_call_super(1, &val);
}
inspect → string click to toggle source

Convert this range object to a printable form (using inspect to convert the begin and end objects).

static VALUE
range_inspect(VALUE range)
{
    return rb_exec_recursive(inspect_range, range, 0);
}
last → obj click to toggle source
last(n) → an_array

Returns the last object in the range, or an array of the last n elements.

Note that with no arguments last will return the object that defines the end of the range even if exclude_end? is true.

(10..20).last      #=> 20
(10...20).last     #=> 20
(10..20).last(3)   #=> [18, 19, 20]
(10...20).last(3)  #=> [17, 18, 19]

static VALUE
range_last(int argc, VALUE *argv, VALUE range)
{
    if (argc == 0) return RANGE_END(range);
    return rb_ary_last(argc, argv, rb_Array(range));
}
max → obj click to toggle source
max {| a,b | block } → obj

Returns the maximum value in the range. Returns nil if the begin value of the range larger than the end value.

Can be given an optional block to override the default comparison method a <=> b.

(10..20).max    #=> 20

static VALUE
range_max(VALUE range)
{
    VALUE e = RANGE_END(range);
    int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);

    if (rb_block_given_p() || (EXCL(range) && !nm)) {
        return rb_call_super(0, 0);
    }
    else {
        VALUE b = RANGE_BEG(range);
        int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

        if (c > 0)
            return Qnil;
        if (EXCL(range)) {
            if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
                rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
            }
            if (c == 0) return Qnil;
            if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
                rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
            }
            if (FIXNUM_P(e)) {
                return LONG2NUM(FIX2LONG(e) - 1);
            }
            return rb_funcall(e, '-', 1, INT2FIX(1));
        }
        return e;
    }
}
member?(obj) → true or false click to toggle source
include?(obj) → true or false

Returns true if obj is an element of the range, false otherwise. If begin and end are numeric, comparison is done according to the magnitude of the values.

("a".."z").include?("g")   #=> true
("a".."z").include?("A")   #=> false
("a".."z").include?("cc")  #=> false

static VALUE
range_include(VALUE range, VALUE val)
{
    VALUE beg = RANGE_BEG(range);
    VALUE end = RANGE_END(range);
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
             rb_obj_is_kind_of(beg, rb_cNumeric) ||
             rb_obj_is_kind_of(end, rb_cNumeric);

    if (nv ||
        !NIL_P(rb_check_to_integer(beg, "to_int")) ||
        !NIL_P(rb_check_to_integer(end, "to_int"))) {
        if (r_le(beg, val)) {
            if (EXCL(range)) {
                if (r_lt(val, end))
                    return Qtrue;
            }
            else {
                if (r_le(val, end))
                    return Qtrue;
            }
        }
        return Qfalse;
    }
    else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
             RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
        if (NIL_P(val)) return Qfalse;
        if (RB_TYPE_P(val, T_STRING)) {
            if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
                return Qfalse;
            else {
                char b = RSTRING_PTR(beg)[0];
                char e = RSTRING_PTR(end)[0];
                char v = RSTRING_PTR(val)[0];

                if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
                    if (b <= v && v < e) return Qtrue;
                    if (!EXCL(range) && v == e) return Qtrue;
                    return Qfalse;
                }
            }
        }
    }
    /* TODO: ruby_frame->this_func = rb_intern("include?"); */
    return rb_call_super(1, &val);
}
min → obj click to toggle source
min {| a,b | block } → obj

Returns the minimum value in the range. Returns nil if the begin value of the range is larger than the end value.

Can be given an optional block to override the default comparison method a <=> b.

(10..20).min    #=> 10

static VALUE
range_min(VALUE range)
{
    if (rb_block_given_p()) {
        return rb_call_super(0, 0);
    }
    else {
        VALUE b = RANGE_BEG(range);
        VALUE e = RANGE_END(range);
        int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

        if (c > 0 || (c == 0 && EXCL(range)))
            return Qnil;
        return b;
    }
}
size → num click to toggle source

Returns the number of elements in the range. Both the begin and the end of the Range must be Numeric, otherwise nil is returned.

(10..20).size    #=> 11
('a'..'z').size  #=> nil
(-Float::INFINITY..Float::INFINITY).size #=> Infinity

static VALUE
range_size(VALUE range)
{
    VALUE b = RANGE_BEG(range), e = RANGE_END(range);
    if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
        return num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
    }
    return Qnil;
}
step(n=1) {| obj | block } → rng click to toggle source
step(n=1) → an_enumerator

Iterates over the range, passing each nth element to the block. If begin and end are numeric, n is added for each iteration. Otherwise step invokes succ to iterate through range elements.

If no block is given, an enumerator is returned instead.

range = Xs.new(1)..Xs.new(10)
range.step(2) {|x| puts x}
puts
range.step(3) {|x| puts x}

produces:

 1 x
 3 xxx
 5 xxxxx
 7 xxxxxxx
 9 xxxxxxxxx

 1 x
 4 xxxx
 7 xxxxxxx
10 xxxxxxxxxx

See Range for the definition of class Xs.

static VALUE
range_step(int argc, VALUE *argv, VALUE range)
{
    VALUE b, e, step, tmp;

    RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);

    b = RANGE_BEG(range);
    e = RANGE_END(range);
    if (argc == 0) {
        step = INT2FIX(1);
    }
    else {
        rb_scan_args(argc, argv, "01", &step);
        if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
            step = rb_to_int(step);
        }
        if (rb_funcall(step, '<', 1, INT2FIX(0))) {
            rb_raise(rb_eArgError, "step can't be negative");
        }
        else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
            rb_raise(rb_eArgError, "step can't be 0");
        }
    }

    if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
        long end = FIX2LONG(e);
        long i, unit = FIX2LONG(step);

        if (!EXCL(range))
            end += 1;
        i = FIX2LONG(b);
        while (i < end) {
            rb_yield(LONG2NUM(i));
            if (i + unit < i) break;
            i += unit;
        }

    }
    else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
        VALUE args[2], iter[2];

        args[0] = rb_sym_to_s(e);
        args[1] = EXCL(range) ? Qtrue : Qfalse;
        iter[0] = INT2FIX(1);
        iter[1] = step;
        rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
    }
    else if (ruby_float_step(b, e, step, EXCL(range))) {
        /* done */
    }
    else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
             !NIL_P(rb_check_to_integer(b, "to_int")) ||
             !NIL_P(rb_check_to_integer(e, "to_int"))) {
        ID op = EXCL(range) ? '<' : idLE;
        VALUE v = b;
        int i = 0;

        while (RTEST(rb_funcall(v, op, 1, e))) {
            rb_yield(v);
            i++;
            v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
        }
    }
    else {
        tmp = rb_check_string_type(b);

        if (!NIL_P(tmp)) {
            VALUE args[2], iter[2];

            b = tmp;
            args[0] = e;
            args[1] = EXCL(range) ? Qtrue : Qfalse;
            iter[0] = INT2FIX(1);
            iter[1] = step;
            rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
        }
        else {
            VALUE args[2];

            if (!discrete_object_p(b)) {
                rb_raise(rb_eTypeError, "can't iterate from %s",
                         rb_obj_classname(b));
            }
            args[0] = INT2FIX(1);
            args[1] = step;
            range_each_func(range, step_i, args);
        }
    }
    return range;
}
to_s → string click to toggle source

Convert this range object to a printable form (using to_s to convert the begin and end objects).

static VALUE
range_to_s(VALUE range)
{
    VALUE str, str2;

    str = rb_obj_as_string(RANGE_BEG(range));
    str2 = rb_obj_as_string(RANGE_END(range));
    str = rb_str_dup(str);
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
    rb_str_append(str, str2);
    OBJ_INFECT(str, str2);

    return str;
}


class RangeError - Ruby 2.0.0-p576 Core API Reference API Reference

class RangeError

Raised when a given numerical value is out of range.

[1, 2, 3].drop(1 << 100)

raises the exception:

RangeError: bignum too big to convert into `long'

In Files

  • error.c

Parent

StandardError


class Rational - Ruby 2.0.0-p576 Core API Reference API Reference

class Rational

A rational number can be represented as a paired integer number; a/b (b>0). Where a is numerator and b is denominator. Integer a equals rational a/1 mathematically.

In ruby, you can create rational object with Rational, #to_r or rationalize method. The return values will be irreducible.

Rational(1)      #=> (1/1)
Rational(2, 3)   #=> (2/3)
Rational(4, -6)  #=> (-2/3)
3.to_r           #=> (3/1)

You can also create rational object from floating-point numbers or strings.

Rational(0.3)    #=> (5404319552844595/18014398509481984)
Rational('0.3')  #=> (3/10)
Rational('2/3')  #=> (2/3)

0.3.to_r         #=> (5404319552844595/18014398509481984)
'0.3'.to_r       #=> (3/10)
'2/3'.to_r       #=> (2/3)
0.3.rationalize  #=> (3/10)

A rational object is an exact number, which helps you to write program without any rounding errors.

10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)

However, when an expression has inexact factor (numerical value or operation), will produce an inexact result.

Rational(10) / 3   #=> (10/3)
Rational(10) / 3.0 #=> 3.3333333333333335

Rational(-8) ** Rational(1, 3)
                   #=> (1.0000000000000002+1.7320508075688772i)

In Files

  • rational.c

Parent

Numeric

Public Instance Methods

rat * numeric → numeric click to toggle source

Performs multiplication.

Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
Rational(900)   * Rational(1)      #=> (900/1)
Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
Rational(9, 8)  * 4                #=> (9/2)
Rational(20, 9) * 9.8              #=> 21.77777777777778

static VALUE
nurat_mul(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        {
            get_dat1(self);

            return f_muldiv(self,
                            dat->num, dat->den,
                            other, ONE, '*');
        }
      case T_FLOAT:
        return f_mul(f_to_f(self), other);
      case T_RATIONAL:
        {
            get_dat2(self, other);

            return f_muldiv(self,
                            adat->num, adat->den,
                            bdat->num, bdat->den, '*');
        }
      default:
        return rb_num_coerce_bin(self, other, '*');
    }
}
rat ** numeric → numeric click to toggle source

Performs exponentiation.

Rational(2)    ** Rational(3)    #=> (8/1)
Rational(10)   ** -2             #=> (1/100)
Rational(10)   ** -2.0           #=> 0.01
Rational(-4)   ** Rational(1,2)  #=> (1.2246063538223773e-16+2.0i)
Rational(1, 2) ** 0              #=> (1/1)
Rational(1, 2) ** 0.0            #=> 1.0

static VALUE
nurat_expt(VALUE self, VALUE other)
{
    if (k_numeric_p(other) && k_exact_zero_p(other))
        return f_rational_new_bang1(CLASS_OF(self), ONE);

    if (k_rational_p(other)) {
        get_dat1(other);

        if (f_one_p(dat->den))
            other = dat->num; /* c14n */
    }

    /* Deal with special cases of 0**n and 1**n */
    if (k_numeric_p(other) && k_exact_p(other)) {
        get_dat1(self);
        if (f_one_p(dat->den))
            if (f_one_p(dat->num))
                return f_rational_new_bang1(CLASS_OF(self), ONE);
            else if (f_minus_one_p(dat->num) && k_integer_p(other))
                return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
            else if (f_zero_p(dat->num))
                if (FIX2INT(f_cmp(other, ZERO)) == -1)
                    rb_raise_zerodiv();
                else
                    return f_rational_new_bang1(CLASS_OF(self), ZERO);
    }

    /* General case */
    switch (TYPE(other)) {
      case T_FIXNUM:
        {
            VALUE num, den;

            get_dat1(self);

            switch (FIX2INT(f_cmp(other, ZERO))) {
              case 1:
                num = f_expt(dat->num, other);
                den = f_expt(dat->den, other);
                break;
              case -1:
                num = f_expt(dat->den, f_negate(other));
                den = f_expt(dat->num, f_negate(other));
                break;
              default:
                num = ONE;
                den = ONE;
                break;
            }
            return f_rational_new2(CLASS_OF(self), num, den);
        }
      case T_BIGNUM:
        rb_warn("in a**b, b may be too big");
        /* fall through */
      case T_FLOAT:
      case T_RATIONAL:
        return f_expt(f_to_f(self), other);
      default:
        return rb_num_coerce_bin(self, other, id_expt);
    }
}
rat + numeric → numeric click to toggle source

Performs addition.

Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
Rational(900)   + Rational(1)      #=> (900/1)
Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
Rational(9, 8)  + 4                #=> (41/8)
Rational(20, 9) + 9.8              #=> 12.022222222222222

static VALUE
nurat_add(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        {
            get_dat1(self);

            return f_addsub(self,
                            dat->num, dat->den,
                            other, ONE, '+');
        }
      case T_FLOAT:
        return f_add(f_to_f(self), other);
      case T_RATIONAL:
        {
            get_dat2(self, other);

            return f_addsub(self,
                            adat->num, adat->den,
                            bdat->num, bdat->den, '+');
        }
      default:
        return rb_num_coerce_bin(self, other, '+');
    }
}
rat - numeric → numeric click to toggle source

Performs subtraction.

Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
Rational(900)   - Rational(1)      #=> (899/1)
Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
Rational(9, 8)  - 4                #=> (23/8)
Rational(20, 9) - 9.8              #=> -7.577777777777778

static VALUE
nurat_sub(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        {
            get_dat1(self);

            return f_addsub(self,
                            dat->num, dat->den,
                            other, ONE, '-');
        }
      case T_FLOAT:
        return f_sub(f_to_f(self), other);
      case T_RATIONAL:
        {
            get_dat2(self, other);

            return f_addsub(self,
                            adat->num, adat->den,
                            bdat->num, bdat->den, '-');
        }
      default:
        return rb_num_coerce_bin(self, other, '-');
    }
}
rat / numeric → numeric click to toggle source
quo(numeric) → numeric

Performs division.

Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
Rational(900)   / Rational(1)      #=> (900/1)
Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
Rational(9, 8)  / 4                #=> (9/32)
Rational(20, 9) / 9.8              #=> 0.22675736961451246

static VALUE
nurat_div(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        if (f_zero_p(other))
            rb_raise_zerodiv();
        {
            get_dat1(self);

            return f_muldiv(self,
                            dat->num, dat->den,
                            other, ONE, '/');
        }
      case T_FLOAT:
        {
            double x = RFLOAT_VALUE(other), den;
            get_dat1(self);

            if (isnan(x)) return DBL2NUM(NAN);
            if (isinf(x)) return INT2FIX(0);
            if (x != 0.0 && modf(x, &den) == 0.0) {
                return rb_rational_raw2(dat->num, f_mul(rb_dbl2big(den), dat->den));
            }
        }
        return rb_funcall(f_to_f(self), '/', 1, other);
      case T_RATIONAL:
        if (f_zero_p(other))
            rb_raise_zerodiv();
        {
            get_dat2(self, other);

            if (f_one_p(self))
                return f_rational_new_no_reduce2(CLASS_OF(self),
                                                 bdat->den, bdat->num);

            return f_muldiv(self,
                            adat->num, adat->den,
                            bdat->num, bdat->den, '/');
        }
      default:
        return rb_num_coerce_bin(self, other, '/');
    }
}
rational <=> numeric → -1, 0, +1 or nil click to toggle source

Performs comparison and returns -1, 0, or +1.

nil is returned if the two values are incomparable.

Rational(2, 3)  <=> Rational(2, 3)  #=> 0
Rational(5)     <=> 5               #=> 0
Rational(2,3)   <=> Rational(1,3)   #=> 1
Rational(1,3)   <=> 1               #=> -1
Rational(1,3)   <=> 0.3             #=> 1

static VALUE
nurat_cmp(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        {
            get_dat1(self);

            if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
                return f_cmp(dat->num, other); /* c14n */
            return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
        }
      case T_FLOAT:
        return f_cmp(f_to_f(self), other);
      case T_RATIONAL:
        {
            VALUE num1, num2;

            get_dat2(self, other);

            if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
                FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
                num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
                num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
            }
            else {
                num1 = f_mul(adat->num, bdat->den);
                num2 = f_mul(bdat->num, adat->den);
            }
            return f_cmp(f_sub(num1, num2), ZERO);
        }
      default:
        return rb_num_coerce_cmp(self, other, id_cmp);
    }
}
rat == object → true or false click to toggle source

Returns true if rat equals object numerically.

Rational(2, 3)  == Rational(2, 3)   #=> true
Rational(5)     == 5                #=> true
Rational(0)     == 0.0              #=> true
Rational('1/3') == 0.33             #=> false
Rational('1/2') == '1/2'            #=> false

static VALUE
nurat_eqeq_p(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        {
            get_dat1(self);

            if (f_zero_p(dat->num) && f_zero_p(other))
                return Qtrue;

            if (!FIXNUM_P(dat->den))
                return Qfalse;
            if (FIX2LONG(dat->den) != 1)
                return Qfalse;
            if (f_eqeq_p(dat->num, other))
                return Qtrue;
            return Qfalse;
        }
      case T_FLOAT:
        return f_eqeq_p(f_to_f(self), other);
      case T_RATIONAL:
        {
            get_dat2(self, other);

            if (f_zero_p(adat->num) && f_zero_p(bdat->num))
                return Qtrue;

            return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
                              f_eqeq_p(adat->den, bdat->den));
        }
      default:
        return f_eqeq_p(other, self);
    }
}
ceil → integer click to toggle source
ceil(precision=0) → rational

Returns the truncated value (toward positive infinity).

Rational(3).ceil      #=> 3
Rational(2, 3).ceil   #=> 1
Rational(-3, 2).ceil  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
'%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"

static VALUE
nurat_ceil_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_ceil);
}
denominator → integer click to toggle source

Returns the denominator (always positive).

Rational(7).denominator             #=> 1
Rational(7, 1).denominator          #=> 1
Rational(9, -4).denominator         #=> 4
Rational(-2, -10).denominator       #=> 5
rat.numerator.gcd(rat.denominator)  #=> 1

static VALUE
nurat_denominator(VALUE self)
{
    get_dat1(self);
    return dat->den;
}
fdiv(numeric) → float click to toggle source

Performs division and returns the value as a float.

Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
Rational(2).fdiv(3)          #=> 0.6666666666666666

static VALUE
nurat_fdiv(VALUE self, VALUE other)
{
    if (f_zero_p(other))
        return f_div(self, f_to_f(other));
    return f_to_f(f_div(self, other));
}
floor → integer click to toggle source
floor(precision=0) → rational

Returns the truncated value (toward negative infinity).

Rational(3).floor      #=> 3
Rational(2, 3).floor   #=> 0
Rational(-3, 2).floor  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
'%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"

static VALUE
nurat_floor_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_floor);
}
inspect → string click to toggle source

Returns the value as a string for inspection.

Rational(2).inspect      #=> "(2/1)"
Rational(-8, 6).inspect  #=> "(-4/3)"
Rational('1/2').inspect  #=> "(1/2)"

static VALUE
nurat_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, f_format(self, f_inspect));
    rb_str_cat2(s, ")");

    return s;
}
numerator → integer click to toggle source

Returns the numerator.

Rational(7).numerator        #=> 7
Rational(7, 1).numerator     #=> 7
Rational(9, -4).numerator    #=> -9
Rational(-2, -10).numerator  #=> 1

static VALUE
nurat_numerator(VALUE self)
{
    get_dat1(self);
    return dat->num;
}
rat / numeric → numeric click to toggle source
quo(numeric) → numeric

Performs division.

Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
Rational(900)   / Rational(1)      #=> (900/1)
Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
Rational(9, 8)  / 4                #=> (9/32)
Rational(20, 9) / 9.8              #=> 0.22675736961451246

static VALUE
nurat_div(VALUE self, VALUE other)
{
    switch (TYPE(other)) {
      case T_FIXNUM:
      case T_BIGNUM:
        if (f_zero_p(other))
            rb_raise_zerodiv();
        {
            get_dat1(self);

            return f_muldiv(self,
                            dat->num, dat->den,
                            other, ONE, '/');
        }
      case T_FLOAT:
        {
            double x = RFLOAT_VALUE(other), den;
            get_dat1(self);

            if (isnan(x)) return DBL2NUM(NAN);
            if (isinf(x)) return INT2FIX(0);
            if (x != 0.0 && modf(x, &den) == 0.0) {
                return rb_rational_raw2(dat->num, f_mul(rb_dbl2big(den), dat->den));
            }
        }
        return rb_funcall(f_to_f(self), '/', 1, other);
      case T_RATIONAL:
        if (f_zero_p(other))
            rb_raise_zerodiv();
        {
            get_dat2(self, other);

            if (f_one_p(self))
                return f_rational_new_no_reduce2(CLASS_OF(self),
                                                 bdat->den, bdat->num);

            return f_muldiv(self,
                            adat->num, adat->den,
                            bdat->num, bdat->den, '/');
        }
      default:
        return rb_num_coerce_bin(self, other, '/');
    }
}
rationalize → self click to toggle source
rationalize(eps) → rational

Returns a simpler approximation of the value if the optional argument eps is given (rat-|eps| <= result <= rat+|eps|), self otherwise.

r = Rational(5033165, 16777216)
r.rationalize                    #=> (5033165/16777216)
r.rationalize(Rational('0.01'))  #=> (3/10)
r.rationalize(Rational('0.1'))   #=> (1/3)

static VALUE
nurat_rationalize(int argc, VALUE *argv, VALUE self)
{
    VALUE e, a, b, p, q;

    if (argc == 0)
        return self;

    if (f_negative_p(self))
        return f_negate(nurat_rationalize(argc, argv, f_abs(self)));

    rb_scan_args(argc, argv, "01", &e);
    e = f_abs(e);
    a = f_sub(self, e);
    b = f_add(self, e);

    if (f_eqeq_p(a, b))
        return self;

    nurat_rationalize_internal(a, b, &p, &q);
    return f_rational_new2(CLASS_OF(self), p, q);
}
round → integer click to toggle source
round(precision=0) → rational

Returns the truncated value (toward the nearest integer; 0.5 => 1; -0.5 => -1).

Rational(3).round      #=> 3
Rational(2, 3).round   #=> 1
Rational(-3, 2).round  #=> -2

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
'%f' % Rational('-123.456').round(-1)  #=> "-120.000000"

static VALUE
nurat_round_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_round);
}
to_f → float click to toggle source

Return the value as a float.

Rational(2).to_f      #=> 2.0
Rational(9, 4).to_f   #=> 2.25
Rational(-3, 4).to_f  #=> -0.75
Rational(20, 3).to_f  #=> 6.666666666666667

static VALUE
nurat_to_f(VALUE self)
{
    get_dat1(self);
    return f_fdiv(dat->num, dat->den);
}
to_i → integer click to toggle source

Returns the truncated value as an integer.

Equivalent to

rat.truncate.

Rational(2, 3).to_i   #=> 0
Rational(3).to_i      #=> 3
Rational(300.6).to_i  #=> 300
Rational(98,71).to_i  #=> 1
Rational(-30,2).to_i  #=> -15

static VALUE
nurat_truncate(VALUE self)
{
    get_dat1(self);
    if (f_negative_p(dat->num))
        return f_negate(f_idiv(f_negate(dat->num), dat->den));
    return f_idiv(dat->num, dat->den);
}
to_r → self click to toggle source

Returns self.

Rational(2).to_r      #=> (2/1)
Rational(-8, 6).to_r  #=> (-4/3)

static VALUE
nurat_to_r(VALUE self)
{
    return self;
}
to_s → string click to toggle source

Returns the value as a string.

Rational(2).to_s      #=> "2/1"
Rational(-8, 6).to_s  #=> "-4/3"
Rational('1/2').to_s  #=> "1/2"

static VALUE
nurat_to_s(VALUE self)
{
    return f_format(self, f_to_s);
}
truncate → integer click to toggle source
truncate(precision=0) → rational

Returns the truncated value (toward zero).

Rational(3).truncate      #=> 3
Rational(2, 3).truncate   #=> 0
Rational(-3, 2).truncate  #=> -1

       decimal      -  1  2  3 . 4  5  6
                      ^  ^  ^  ^   ^  ^
      precision      -3 -2 -1  0  +1 +2

'%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
'%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"

static VALUE
nurat_truncate_n(int argc, VALUE *argv, VALUE self)
{
    return f_round_common(argc, argv, self, nurat_truncate);
}


class Rational::compatible - Ruby 2.0.0-p576 Core API Reference API Reference

class Rational::compatible

In Files

  • rational.c

Parent

Object


class Regexp - Ruby 2.0.0-p576 Core API Reference API Reference

class Regexp

A Regexp holds a regular expression, used to match a pattern against strings. Regexps are created using the /.../ and %r{...} literals, and by the Regexp::new constructor.

Regular expressions (regexps) are patterns which describe the contents of a string. They're used for testing whether a string contains a given pattern, or extracting the portions that match. They are created with the /pat/ and %r{pat} literals or the Regexp.new constructor.

A regexp is usually delimited with forward slashes (/). For example:

/hay/ =~ 'haystack'   #=> 0
/y/.match('haystack') #=> #<MatchData "y">

If a string contains the pattern it is said to match. A literal string matches itself.

# 'haystack' does not contain the pattern 'needle', so doesn't match.
/needle/.match('haystack') #=> nil
# 'haystack' does contain the pattern 'hay', so it matches
/hay/.match('haystack')    #=> #<MatchData "hay">

Specifically, /st/ requires that the string contains the letter s followed by the letter t, so it matches haystack, also.

=~ and #match

Pattern matching may be achieved by using =~ operator or #match method.

=~ operator

=~ is Ruby's basic pattern-matching operator. When one operand is a regular expression and the other is a string then the regular expression is used as a pattern to match against the string. (This operator is equivalently defined by Regexp and String so the order of String and Regexp do not matter. Other classes may have different implementations of =~.) If a match is found, the operator returns index of first match in string, otherwise it returns nil.

/hay/ =~ 'haystack'   #=> 0
'haystack' =~ /hay/   #=> 0
/a/   =~ 'haystack'   #=> 1
/u/   =~ 'haystack'   #=> nil

Using =~ operator with a String and Regexp the $~ global variable is set after a successful match. $~ holds a MatchData object. ::last_match is equivalent to $~.

#match method

match method return a MatchData object :

/st/.match('haystack')   #=> #<MatchData "st">

Metacharacters and Escapes

The following are metacharacters (, ), [, ], {, }, ., ?, +, *. They have a specific meaning when appearing in a pattern. To match them literally they must be backslash-escaped. To match a backslash literally backslash-escape that: <tt>\\</tt>.

/1 \+ 2 = 3\?/.match('Does 1 + 2 = 3?') #=> #<MatchData "1 + 2 = 3?">

Patterns behave like double-quoted strings so can contain the same backslash escapes.

/\s\u{6771 4eac 90fd}/.match("Go to 東京都")
    #=> #<MatchData " 東京都">

Arbitrary Ruby expressions can be embedded into patterns with the #{...} construct.

place = "東京都"
/#{place}/.match("Go to 東京都")
    #=> #<MatchData "東京都">

Character Classes

A character class is delimited with square brackets ([, ]) and lists characters that may appear at that point in the match. /[ab]/ means a or b, as opposed to /ab/ which means a followed by b.

/W[aeiou]rd/.match("Word") #=> #<MatchData "Word">

Within a character class the hyphen (-) is a metacharacter denoting an inclusive range of characters. [abcd] is equivalent to [a-d]. A range can be followed by another range, so [abcdwxyz] is equivalent to [a-dw-z]. The order in which ranges or individual characters appear inside a character class is irrelevant.

/[0-9a-f]/.match('9f') #=> #<MatchData "9">
/[9f]/.match('9f')     #=> #<MatchData "9">

If the first character of a character class is a caret (^) the class is inverted: it matches any character except those named.

/[^a-eg-z]/.match('f') #=> #<MatchData "f">

A character class may contain another character class. By itself this isn't useful because [a-z[0-9]] describes the same set as [a-z0-9]. However, character classes also support the && operator which performs set intersection on its arguments. The two can be combined as follows:

/[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))
# This is equivalent to:
/[abh-w]/

The following metacharacters also behave like character classes:

  • /./ - Any character except a newline.

  • /./m - Any character (the m modifier enables multiline mode)

  • /\w/ - A word character ([a-zA-Z0-9_])

  • /\W/ - A non-word character ([^a-zA-Z0-9_])

  • /\d/ - A digit character ([0-9])

  • /\D/ - A non-digit character ([^0-9])

  • /\h/ - A hexdigit character ([0-9a-fA-F])

  • /\H/ - A non-hexdigit character ([^0-9a-fA-F])

  • /\s/ - A whitespace character: /[ \t\r\n\f]/

  • /\S/ - A non-whitespace character: /[^ \t\r\n\f]/

POSIX bracket expressions are also similar to character classes. They provide a portable alternative to the above, with the added benefit that they encompass non-ASCII characters. For instance, /\d/ matches only the ASCII decimal digits (0-9); whereas /[[:digit:]]/ matches any character in the Unicode Nd category.

  • /[[:alnum:]]/ - Alphabetic and numeric character

  • /[[:alpha:]]/ - Alphabetic character

  • /[[:blank:]]/ - Space or tab

  • /[[:cntrl:]]/ - Control character

  • /[[:digit:]]/ - Digit

  • /[[:graph:]]/ - Non-blank character (excludes spaces, control characters, and similar)

  • /[[:lower:]]/ - Lowercase alphabetical character

  • /[[:print:]]/ - Like [:graph:], but includes the space character

  • /[[:punct:]]/ - Punctuation character

  • /[[:space:]]/ - Whitespace character ([:blank:], newline, carriage return, etc.)

  • /[[:upper:]]/ - Uppercase alphabetical

  • /[[:xdigit:]]/ - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)

Ruby also supports the following non-POSIX character classes:

  • /[[:word:]]/ - A character in one of the following Unicode general categories Letter, Mark, Number, Connector_Punctuation

  • /[[:ascii:]]/ - A character in the ASCII character set

    # U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO"
/[[:digit:]]/.match("\u06F2")    #=> #<MatchData "\u{06F2}">
/[[:upper:]][[:lower:]]/.match("Hello") #=> #<MatchData "He">
/[[:xdigit:]][[:xdigit:]]/.match("A6")  #=> #<MatchData "A6">

Repetition

The constructs described so far match a single character. They can be followed by a repetition metacharacter to specify how many times they need to occur. Such metacharacters are called quantifiers.

  • * - Zero or more times

  • + - One or more times

  • ? - Zero or one times (optional)

  • {n} - Exactly n times

  • {n,} - n or more times

  • {,m} - m or less times

  • {n,m} - At least n and at most m times

    # At least one uppercase character ('H'), at least one lowercase
# character ('e'), two 'l' characters, then one 'o'
"Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> #<MatchData "Hello">

Repetition is greedy by default: as many occurrences as possible are matched while still allowing the overall match to succeed. By contrast, lazy matching makes the minimal amount of matches necessary for overall success. A greedy metacharacter can be made lazy by following it with ?.

# Both patterns below match the string. The first uses a greedy
# quantifier so '.+' matches '<a><b>'; the second uses a lazy
# quantifier so '.+?' matches '<a>'.
/<.+>/.match("<a><b>")  #=> #<MatchData "<a><b>">
/<.+?>/.match("<a><b>") #=> #<MatchData "<a>">

A quantifier followed by + matches possessively: once it has matched it does not backtrack. They behave like greedy quantifiers, but having matched they refuse to “give up” their match even if this jeopardises the overall match.

Capturing

Parentheses can be used for capturing. The text enclosed by the n<sup>th</sup> group of parentheses can be subsequently referred to with n. Within a pattern use the backreference \n; outside of the pattern use MatchData[n].

# 'at' is captured by the first group of parentheses, then referred to
# later with \1
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")
    #=> #<MatchData "cat sat in" 1:"at">
# Regexp#match returns a MatchData object which makes the captured
# text available with its #[] method.
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at'

Capture groups can be referred to by name when defined with the (?<name>) or (?'name') constructs.

/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")
    => #<MatchData "$3.67" dollars:"3" cents:"67">
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")[:dollars] #=> "3"

Named groups can be backreferenced with \k<name>, where name is the group name.

/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
    #=> #<MatchData "ototo" vowel:"o">

Note: A regexp can't use named backreferences and numbered backreferences simultaneously.

When named capture groups are used with a literal regexp on the left-hand side of an expression and the =~ operator, the captured text is also assigned to local variables with corresponding names.

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"

Grouping

Parentheses also group the terms they enclose, allowing them to be quantified as one atomic whole.

# The pattern below matches a vowel followed by 2 word characters:
# 'aen'
/[aeiou]\w{2}/.match("Caenorhabditis elegans") #=> #<MatchData "aen">
# Whereas the following pattern matches a vowel followed by a word
# character, twice, i.e. <tt>[aeiou]\w[aeiou]\w</tt>: 'enor'.
/([aeiou]\w){2}/.match("Caenorhabditis elegans")
    #=> #<MatchData "enor" 1:"or">

The (?:…) construct provides grouping without capturing. That is, it combines the terms it contains into an atomic whole without creating a backreference. This benefits performance at the slight expense of readability.

# The group of parentheses captures 'n' and the second 'ti'. The
# second group is referred to later with the backreference \2
/I(n)ves(ti)ga\2ons/.match("Investigations")
    #=> #<MatchData "Investigations" 1:"n" 2:"ti">
# The first group of parentheses is now made non-capturing with '?:',
# so it still matches 'n', but doesn't create the backreference. Thus,
# the backreference \1 now refers to 'ti'.
/I(?:n)ves(ti)ga\1ons/.match("Investigations")
    #=> #<MatchData "Investigations" 1:"ti">

Atomic Grouping

Grouping can be made atomic with (?>pat). This causes the subexpression pat to be matched independently of the rest of the expression such that what it matches becomes fixed for the remainder of the match, unless the entire subexpression must be abandoned and subsequently revisited. In this way pat is treated as a non-divisible whole. Atomic grouping is typically used to optimise patterns so as to prevent the regular expression engine from backtracking needlessly.

# The <tt>"</tt> in the pattern below matches the first character of
# the string, then <tt>.*</tt> matches <i>Quote"</i>. This causes the
# overall match to fail, so the text matched by <tt>.*</tt> is
# backtracked by one position, which leaves the final character of the
# string available to match <tt>"</tt>
      /".*"/.match('"Quote"')     #=> #<MatchData "\"Quote\"">
# If <tt>.*</tt> is grouped atomically, it refuses to backtrack
# <i>Quote"</i>, even though this means that the overall match fails
/"(?>.*)"/.match('"Quote"') #=> nil

Subexpression Calls

The \g<name> syntax matches the previous subexpression named name, which can be a group name or number, again. This differs from backreferences in that it re-executes the group rather than simply trying to re-match the same text.

# Matches a <i>(</i> character and assigns it to the <tt>paren</tt>
# group, tries to call that the <tt>paren</tt> sub-expression again
# but fails, then matches a literal <i>)</i>.
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '()'

/\A(?<paren>\(\g<paren>*\))*\z/ =~ '(())' #=> 0
# ^1
#      ^2
#           ^3
#                 ^4
#      ^5
#           ^6
#                      ^7
#                       ^8
#                       ^9
#                           ^10

  1. Matches at the beginning of the string, i.e. before the first character.

  2. Enters a named capture group called paren

  3. Matches a literal (, the first character in the string

  4. Calls the paren group again, i.e. recurses back to the second step

  5. Re-enters the paren group

  6. Matches a literal (, the second character in the string

  7. Try to call paren a third time, but fail because doing so would prevent an overall successful match

  8. Match a literal ), the third character in the string. Marks the end of the second recursive call

  9. Match a literal ), the fourth character in the string

  10. Match the end of the string

Alternation

The vertical bar metacharacter (|) combines two expressions into a single one that matches either of the expressions. Each expression is an alternative.

/\w(and|or)\w/.match("Feliformia") #=> #<MatchData "form" 1:"or">
/\w(and|or)\w/.match("furandi")    #=> #<MatchData "randi" 1:"and">
/\w(and|or)\w/.match("dissemblance") #=> nil

Character Properties

The \p{} construct matches characters with the named property, much like POSIX bracket classes.

  • /\p{Alnum}/ - Alphabetic and numeric character

  • /\p{Alpha}/ - Alphabetic character

  • /\p{Blank}/ - Space or tab

  • /\p{Cntrl}/ - Control character

  • /\p{Digit}/ - Digit

  • /\p{Graph}/ - Non-blank character (excludes spaces, control characters, and similar)

  • /\p{Lower}/ - Lowercase alphabetical character

  • /\p{Print}/ - Like \p{Graph}, but includes the space character

  • /\p{Punct}/ - Punctuation character

  • /\p{Space}/ - Whitespace character ([:blank:], newline, carriage return, etc.)

  • /\p{Upper}/ - Uppercase alphabetical

  • /\p{XDigit}/ - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)

  • /\p{Word}/ - A member of one of the following Unicode general category Letter, Mark, Number, Connector_Punctuation

  • /\p{ASCII}/ - A character in the ASCII character set

  • /\p{Any}/ - Any Unicode character (including unassigned characters)

  • /\p{Assigned}/ - An assigned character

A Unicode character's General Category value can also be matched with \p{Ab} where Ab is the category's abbreviation as described below:

  • /\p{L}/ - 'Letter'

  • /\p{Ll}/ - 'Letter: Lowercase'

  • /\p{Lm}/ - 'Letter: Mark'

  • /\p{Lo}/ - 'Letter: Other'

  • /\p{Lt}/ - 'Letter: Titlecase'

  • /\p{Lu}/ - 'Letter: Uppercase

  • /\p{Lo}/ - 'Letter: Other'

  • /\p{M}/ - 'Mark'

  • /\p{Mn}/ - 'Mark: Nonspacing'

  • /\p{Mc}/ - 'Mark: Spacing Combining'

  • /\p{Me}/ - 'Mark: Enclosing'

  • /\p{N}/ - 'Number'

  • /\p{Nd}/ - 'Number: Decimal Digit'

  • /\p{Nl}/ - 'Number: Letter'

  • /\p{No}/ - 'Number: Other'

  • /\p{P}/ - 'Punctuation'

  • /\p{Pc}/ - 'Punctuation: Connector'

  • /\p{Pd}/ - 'Punctuation: Dash'

  • /\p{Ps}/ - 'Punctuation: Open'

  • /\p{Pe}/ - 'Punctuation: Close'

  • /\p{Pi}/ - 'Punctuation: Initial Quote'

  • /\p{Pf}/ - 'Punctuation: Final Quote'

  • /\p{Po}/ - 'Punctuation: Other'

  • /\p{S}/ - 'Symbol'

  • /\p{Sm}/ - 'Symbol: Math'

  • /\p{Sc}/ - 'Symbol: Currency'

  • /\p{Sc}/ - 'Symbol: Currency'

  • /\p{Sk}/ - 'Symbol: Modifier'

  • /\p{So}/ - 'Symbol: Other'

  • /\p{Z}/ - 'Separator'

  • /\p{Zs}/ - 'Separator: Space'

  • /\p{Zl}/ - 'Separator: Line'

  • /\p{Zp}/ - 'Separator: Paragraph'

  • /\p{C}/ - 'Other'

  • /\p{Cc}/ - 'Other: Control'

  • /\p{Cf}/ - 'Other: Format'

  • /\p{Cn}/ - 'Other: Not Assigned'

  • /\p{Co}/ - 'Other: Private Use'

  • /\p{Cs}/ - 'Other: Surrogate'

Lastly, \p{} matches a character's Unicode script. The following scripts are supported: Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Inherited, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lycian, Lydian, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Saurashtra, Shavian, Sinhala, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai, and Yi.

# Unicode codepoint U+06E9 is named "ARABIC PLACE OF SAJDAH" and
# belongs to the Arabic script.
/\p{Arabic}/.match("\u06E9") #=> #<MatchData "\u06E9">

All character properties can be inverted by prefixing their name with a caret (^).

# Letter 'A' is not in the Unicode Ll (Letter; Lowercase) category, so
# this match succeeds
/\p{^Ll}/.match("A") #=> #<MatchData "A">

Anchors

Anchors are metacharacter that match the zero-width positions between characters, anchoring the match to a specific position.

  • ^ - Matches beginning of line

  • $ - Matches end of line

  • \A - Matches beginning of string.

  • \Z - Matches end of string. If string ends with a newline, it matches just before newline

  • \z - Matches end of string

  • \G - Matches point where last match finished

  • \b - Matches word boundaries when outside brackets; backspace (0x08) when inside brackets

  • \B - Matches non-word boundaries

  • (?=pat) - Positive lookahead assertion: ensures that the following characters match pat, but doesn't include those characters in the matched text

  • (?!pat) - Negative lookahead assertion: ensures that the following characters do not match pat, but doesn't include those characters in the matched text

  • (?<=pat) - Positive lookbehind assertion: ensures that the preceding characters match pat, but doesn't include those characters in the matched text

  • (?<!pat) - Negative lookbehind assertion: ensures that the preceding characters do not match pat, but doesn't include those characters in the matched text

    # If a pattern isn't anchored it can begin at any point in the string
/real/.match("surrealist") #=> #<MatchData "real">
# Anchoring the pattern to the beginning of the string forces the
# match to start there. 'real' doesn't occur at the beginning of the
# string, so now the match fails
/\Areal/.match("surrealist") #=> nil
# The match below fails because although 'Demand' contains 'and', the
pattern does not occur at a word boundary.
/\band/.match("Demand")
# Whereas in the following example 'and' has been anchored to a
# non-word boundary so instead of matching the first 'and' it matches
# from the fourth letter of 'demand' instead
/\Band.+/.match("Supply and demand curve") #=> #<MatchData "and curve">
# The pattern below uses positive lookahead and positive lookbehind to
# match text appearing in <b></b> tags without including the tags in the
# match
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>")
    #=> #<MatchData "bold">

Options

The end delimiter for a regexp can be followed by one or more single-letter options which control how the pattern can match.

  • /pat/i - Ignore case

  • /pat/m - Treat a newline as a character matched by .

  • /pat/x - Ignore whitespace and comments in the pattern

  • /pat/o - Perform #{} interpolation only once

i, m, and x can also be applied on the subexpression level with the (?on-off) construct, which enables options on, and disables options off for the expression enclosed by the parentheses.

/a(?i:b)c/.match('aBc') #=> #<MatchData "aBc">
/a(?i:b)c/.match('abc') #=> #<MatchData "abc">

Options may also be used with Regexp.new:

Regexp.new("abc", Regexp::IGNORECASE)                     #=> /abc/i
Regexp.new("abc", Regexp::MULTILINE)                      #=> /abc/m
Regexp.new("abc # Comment", Regexp::EXTENDED)             #=> /abc # Comment/x
Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi

Free-Spacing Mode and Comments

As mentioned above, the x option enables free-spacing mode. Literal white space inside the pattern is ignored, and the octothorpe (#) character introduces a comment until the end of the line. This allows the components of the pattern to be organised in a potentially more readable fashion.

# A contrived pattern to match a number with optional decimal places
float_pat = /\A
    [[:digit:]]+ # 1 or more digits before the decimal point
    (\.          # Decimal point
        [[:digit:]]+ # 1 or more digits after the decimal point
    )? # The decimal point and following digits are optional
\Z/
float_pat.match('3.14') #=> #<MatchData "3.14" 1:".14">

Note: To match whitespace in an x pattern use an escape such as \s or \p{Space}.

Comments can be included in a non-x pattern with the (?#comment) construct, where comment is arbitrary text ignored by the regexp engine.

Encoding

Regular expressions are assumed to use the source encoding. This can be overridden with one of the following modifiers.

  • /pat/u - UTF-8

  • /pat/e - EUC-JP

  • /pat/s - Windows-31J

  • /pat/n - ASCII-8BIT

A regexp can be matched against a string when they either share an encoding, or the regexp's encoding is US-ASCII and the string's encoding is ASCII-compatible.

If a match between incompatible encodings is attempted an Encoding::CompatibilityError exception is raised.

The Regexp#fixed_encoding? predicate indicates whether the regexp has a fixed encoding, that is one incompatible with ASCII. A regexp's encoding can be explicitly fixed by supplying Regexp::FIXEDENCODING as the second argument of Regexp.new:

r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING)
r =~"a\u3042"
   #=> Encoding::CompatibilityError: incompatible encoding regexp match
        (ISO-8859-1 regexp with UTF-8 string)

Special global variables

Pattern matching sets some global variables :

  • $~ is equivalent to ::last_match;

  • $& contains the complete matched text;

  • $` contains string before match;

  • $' contains string after match;

  • $1, $2 and so on contain text matching first, second, etc capture group;

  • $+ contains last capture group.

Example:

m = /s(\w{2}).*(c)/.match('haystack') #=> #<MatchData "stac" 1:"ta" 2:"c">
$~                                    #=> #<MatchData "stac" 1:"ta" 2:"c">
Regexp.latch_match                    #=> #<MatchData "stac" 1:"ta" 2:"c">

$&      #=> "stac"
        # same as m[0]
$`      #=> "hay"
        # same as m.pre_match
$'      #=> "k"
        # same as m.post_match
$1      #=> "ta"
        # same as m[1]
$2      #=> "c"
        # same as m[2]
$3      #=> nil
        # no third group in pattern
$+      #=> "c"
        # same as m[-1]

These global variables are thread-local and method-local variables.

Performance

Certain pathological combinations of constructs can lead to abysmally bad performance.

Consider a string of 25 as, a d, 4 as, and a c.

s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
#=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac"

The following patterns match instantly as you would expect:

/(b|a)/ =~ s #=> 0
/(b|a+)/ =~ s #=> 0
/(b|a+)*\/ =~ s #=> 0

However, the following pattern takes appreciably longer:

/(b|a+)*c/ =~ s #=> 26

This happens because an atom in the regexp is quantified by both an immediate + and an enclosing * with nothing to differentiate which is in control of any particular character. The nondeterminism that results produces super-linear performance. (Consult Mastering Regular Expressions (3rd ed.), pp 222, by Jeffery Friedl, for an in-depth analysis). This particular case can be fixed by use of atomic grouping, which prevents the unnecessary backtracking:

(start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start)
   #=> 24.702736882
(start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start)
   #=> 0.000166571

A similar case is typified by the following example, which takes approximately 60 seconds to execute for me:

# Match a string of 29 <i>a</i>s against a pattern of 29 optional
# <i>a</i>s followed by 29 mandatory <i>a</i>s.
Regexp.new('a?' * 29 + 'a' * 29) =~ 'a' * 29

The 29 optional as match the string, but this prevents the 29 mandatory as that follow from matching. Ruby must then backtrack repeatedly so as to satisfy as many of the optional matches as it can while still matching the mandatory 29. It is plain to us that none of the optional matches can succeed, but this fact unfortunately eludes Ruby.

The best way to improve performance is to significantly reduce the amount of backtracking needed. For this case, instead of individually matching 29 optional as, a range of optional as can be matched all at once with a{0,29}:

Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29

In Files

  • re.c

Parent

Object

Constants

EXTENDED

see #options and ::new

FIXEDENCODING

see #options and ::new

IGNORECASE

see #options and ::new

MULTILINE

see #options and ::new

NOENCODING

see #options and ::new

Public Class Methods

compile(*args) click to toggle source

Synonym for Regexp.new

escape(str) → string click to toggle source
quote(str) → string

Escapes any characters that would have special meaning in a regular expression. Returns a new escaped string, or self if no characters are escaped. For any string, Regexp.new(Regexp.escape(str))=~str will be true.

Regexp.escape('\*?{}.')   #=> \\\*\?\{\}\.

static VALUE
rb_reg_s_quote(VALUE c, VALUE str)
{
    return rb_reg_quote(reg_operand(str, TRUE));
}
last_match → matchdata click to toggle source
last_match(n) → str

The first form returns the MatchData object generated by the last successful pattern match. Equivalent to reading the special global variable $~ (see Special global variables in Regexp for details).

The second form returns the nth field in this MatchData object. n can be a string or symbol to reference a named capture.

Note that the ::last_match is local to the thread and method scope of the method that did the pattern match.

/c(.)t/ =~ 'cat'        #=> 0
Regexp.last_match       #=> #<MatchData "cat" 1:"a">
Regexp.last_match(0)    #=> "cat"
Regexp.last_match(1)    #=> "a"
Regexp.last_match(2)    #=> nil

/(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "var = val"
Regexp.last_match       #=> #<MatchData "var = val" lhs:"var" rhs:"val">
Regexp.last_match(:lhs) #=> "var"
Regexp.last_match(:rhs) #=> "val"

static VALUE
rb_reg_s_last_match(int argc, VALUE *argv)
{
    VALUE nth;

    if (argc > 0 && rb_scan_args(argc, argv, "01", &nth) == 1) {
        VALUE match = rb_backref_get();
        int n;
        if (NIL_P(match)) return Qnil;
        n = match_backref_number(match, nth);
        return rb_reg_nth_match(n, match);
    }
    return match_getter();
}
new(string, [options [, kcode]]) → regexp click to toggle source
new(regexp) → regexp
compile(string, [options [, kcode]]) → regexp
compile(regexp) → regexp

Constructs a new regular expression from pattern, which can be either a String or a Regexp (in which case that regexp's options are propagated), and new options may not be specified (a change as of Ruby 1.8).

If options is a Fixnum, it should be one or more of the constants Regexp::EXTENDED, Regexp::IGNORECASE, and Regexp::MULTILINE, or-ed together. Otherwise, if options is not nil or false, the regexp will be case insensitive.

When the kcode parameter is `n' or `N' sets the regexp no encoding. It means that the regexp is for binary strings.

r1 = Regexp.new('^a-z+:\s+\w+') #=> /^a-z+:\s+\w+/
r2 = Regexp.new('cat', true)     #=> /cat/i
r3 = Regexp.new(r2)              #=> /cat/i
r4 = Regexp.new('dog', Regexp::EXTENDED | Regexp::IGNORECASE) #=> /dog/ix

static VALUE
rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
{
    onig_errmsg_buffer err = "";
    int flags = 0;
    VALUE str;
    rb_encoding *enc;
    const char *ptr;
    long len;

    rb_check_arity(argc, 1, 3);
    if (RB_TYPE_P(argv[0], T_REGEXP)) {
        VALUE re = argv[0];

        if (argc > 1) {
            rb_warn("flags ignored");
        }
        rb_reg_check(re);
        flags = rb_reg_options(re);
        ptr = RREGEXP_SRC_PTR(re);
        len = RREGEXP_SRC_LEN(re);
        enc = rb_enc_get(re);
        if (rb_reg_initialize(self, ptr, len, enc, flags, err, NULL, 0)) {
            str = rb_enc_str_new(ptr, len, enc);
            rb_reg_raise_str(str, flags, err);
        }
    }
    else {
        if (argc >= 2) {
            if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
            else if (RTEST(argv[1])) flags = ONIG_OPTION_IGNORECASE;
        }
        enc = 0;
        if (argc == 3 && !NIL_P(argv[2])) {
            char *kcode = StringValuePtr(argv[2]);
            if (kcode[0] == 'n' || kcode[0] == 'N') {
                enc = rb_ascii8bit_encoding();
                flags |= ARG_ENCODING_NONE;
            }
            else {
                rb_warn("encoding option is ignored - %s", kcode);
            }
        }
        str = argv[0];
        ptr = StringValuePtr(str);
        if (enc
            ? rb_reg_initialize(self, ptr, RSTRING_LEN(str), enc, flags, err, NULL, 0)
            : rb_reg_initialize_str(self, str, flags, err, NULL, 0)) {
            rb_reg_raise_str(str, flags, err);
        }
    }
    return self;
}
escape(str) → string click to toggle source
quote(str) → string

Escapes any characters that would have special meaning in a regular expression. Returns a new escaped string, or self if no characters are escaped. For any string, Regexp.new(Regexp.escape(str))=~str will be true.

Regexp.escape('\*?{}.')   #=> \\\*\?\{\}\.

static VALUE
rb_reg_s_quote(VALUE c, VALUE str)
{
    return rb_reg_quote(reg_operand(str, TRUE));
}
try_convert(obj) → re or nil click to toggle source

Try to convert obj into a Regexp, using to_regexp method. Returns converted regexp or nil if obj cannot be converted for any reason.

Regexp.try_convert(/re/)         #=> /re/
Regexp.try_convert("re")         #=> nil

o = Object.new
Regexp.try_convert(o)            #=> nil
def o.to_regexp() /foo/ end
Regexp.try_convert(o)            #=> /foo/

static VALUE
rb_reg_s_try_convert(VALUE dummy, VALUE re)
{
    return rb_check_regexp_type(re);
}
union(pat1, pat2, ...) → new_regexp click to toggle source
union(pats_ary) → new_regexp

Return a Regexp object that is the union of the given patterns, i.e., will match any of its parts. The patterns can be Regexp objects, in which case their options will be preserved, or Strings. If no patterns are given, returns /(?!)/. The behavior is unspecified if any given pattern contains capture.

Regexp.union                         #=> /(?!)/
Regexp.union("penzance")             #=> /penzance/
Regexp.union("a+b*c")                #=> /a\+b\*c/
Regexp.union("skiing", "sledding")   #=> /skiing|sledding/
Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
Regexp.union(/dogs/, /cats/)        #=> /(?-mix:dogs)|(?i-mx:cats)/

static VALUE
rb_reg_s_union_m(VALUE self, VALUE args)
{
    VALUE v;
    if (RARRAY_LEN(args) == 1 &&
        !NIL_P(v = rb_check_array_type(rb_ary_entry(args, 0)))) {
        return rb_reg_s_union(self, v);
    }
    return rb_reg_s_union(self, args);
}

Public Instance Methods

rxp == other_rxp → true or false click to toggle source
eql?(other_rxp) → true or false

Equality—Two regexps are equal if their patterns are identical, they have the same character set code, and their casefold? values are the same.

/abc/  == /abc/   #=> false
/abc/  == /abc/   #=> false
/abc/  == /abc/   #=> false
/abc/ == /abc/   #=> false

static VALUE
rb_reg_equal(VALUE re1, VALUE re2)
{
    if (re1 == re2) return Qtrue;
    if (!RB_TYPE_P(re2, T_REGEXP)) return Qfalse;
    rb_reg_check(re1); rb_reg_check(re2);
    if (FL_TEST(re1, KCODE_FIXED) != FL_TEST(re2, KCODE_FIXED)) return Qfalse;
    if (RREGEXP(re1)->ptr->options != RREGEXP(re2)->ptr->options) return Qfalse;
    if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse;
    if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse;
    if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) {
        return Qtrue;
    }
    return Qfalse;
}
rxp === str → true or false click to toggle source

Case Equality—Used in case statements.

a = "HELLO"
case a
when /^[a-z]*$/; print "Lower case\n"
when /^[A-Z]*$/; print "Upper case\n"
else;            print "Mixed case\n"
end
#=> "Upper case"

Following a regular expression literal with the #=== operator allows you to compare against a String.

/^[a-z]*$/ === "HELLO" #=> false
/^[A-Z]*$/ === "HELLO" #=> true

VALUE
rb_reg_eqq(VALUE re, VALUE str)
{
    long start;

    str = reg_operand(str, FALSE);
    if (NIL_P(str)) {
        rb_backref_set(Qnil);
        return Qfalse;
    }
    start = rb_reg_search(re, str, 0, 0);
    if (start < 0) {
        return Qfalse;
    }
    return Qtrue;
}
rxp =~ str → integer or nil click to toggle source

Match—Matches rxp against str.

/at/ =~ "input data"   #=> 7
/ax/ =~ "input data"   #=> nil

If =~ is used with a regexp literal with named captures, captured strings (or nil) is assigned to local variables named by the capture names.

/(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = y  "
p lhs    #=> "x"
p rhs    #=> "y"

If it is not matched, nil is assigned for the variables.

/(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = "
p lhs    #=> nil
p rhs    #=> nil

This assignment is implemented in the Ruby parser. The parser detects 'regexp-literal =~ expression' for the assignment. The regexp must be a literal without interpolation and placed at left hand side.

The assignment does not occur if the regexp is not a literal.

re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
re =~ "  x = y  "
p lhs    # undefined local variable
p rhs    # undefined local variable

A regexp interpolation, #{}, also disables the assignment.

rhs_pat = /(?<rhs>\w+)/
/(?<lhs>\w+)\s*=\s*#{rhs_pat}/ =~ "x = y"
p lhs    # undefined local variable

The assignment does not occur if the regexp is placed at the right hand side.

"  x = y  " =~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
p lhs, rhs # undefined local variable
VALUE
rb_reg_match(VALUE re, VALUE str)
{
    long pos = reg_match_pos(re, &str, 0);
    if (pos < 0) return Qnil;
    pos = rb_str_sublen(str, pos);
    return LONG2FIX(pos);
}
casefold? → true or false click to toggle source

Returns the value of the case-insensitive flag.

/a/.casefold?           #=> false
/a/.casefold?          #=> true
/(?i:a)/.casefold?      #=> false

static VALUE
rb_reg_casefold_p(VALUE re)
{
    rb_reg_check(re);
    if (RREGEXP(re)->ptr->options & ONIG_OPTION_IGNORECASE) return Qtrue;
    return Qfalse;
}
encoding → encoding click to toggle source

Returns the Encoding object that represents the encoding of obj.

VALUE
rb_obj_encoding(VALUE obj)
{
    int idx = rb_enc_get_index(obj);
    if (idx < 0) {
    rb_raise(rb_eTypeError, "unknown encoding");
    }
    return rb_enc_from_encoding_index(idx);
}
rxp == other_rxp → true or false click to toggle source
eql?(other_rxp) → true or false

Equality—Two regexps are equal if their patterns are identical, they have the same character set code, and their casefold? values are the same.

/abc/  == /abc/   #=> false
/abc/  == /abc/   #=> false
/abc/  == /abc/   #=> false
/abc/ == /abc/   #=> false

static VALUE
rb_reg_equal(VALUE re1, VALUE re2)
{
    if (re1 == re2) return Qtrue;
    if (!RB_TYPE_P(re2, T_REGEXP)) return Qfalse;
    rb_reg_check(re1); rb_reg_check(re2);
    if (FL_TEST(re1, KCODE_FIXED) != FL_TEST(re2, KCODE_FIXED)) return Qfalse;
    if (RREGEXP(re1)->ptr->options != RREGEXP(re2)->ptr->options) return Qfalse;
    if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse;
    if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse;
    if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) {
        return Qtrue;
    }
    return Qfalse;
}
fixed_encoding? → true or false click to toggle source

Returns false if rxp is applicable to a string with any ASCII compatible encoding. Returns true otherwise.

r = /a/
r.fixed_encoding?                               #=> false
r =~ "\u{6666} a"                               #=> 2
r =~ "\xa1\xa2 a".force_encoding("euc-jp")      #=> 2
r =~ "abc".force_encoding("euc-jp")             #=> 0

r = /a/
r.fixed_encoding?                               #=> true
r.encoding                                      #=> #<Encoding:UTF-8>
r =~ "\u{6666} a"                               #=> 2
r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
r =~ "abc".force_encoding("euc-jp")             #=> 0

r = /\u{6666}/
r.fixed_encoding?                               #=> true
r.encoding                                      #=> #<Encoding:UTF-8>
r =~ "\u{6666} a"                               #=> 0
r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
r =~ "abc".force_encoding("euc-jp")             #=> nil

static VALUE
rb_reg_fixed_encoding_p(VALUE re)
{
    if (FL_TEST(re, KCODE_FIXED))
        return Qtrue;
    else
        return Qfalse;
}
hash → fixnum click to toggle source

Produce a hash based on the text and options of this regular expression.

static VALUE
rb_reg_hash(VALUE re)
{
    st_index_t hashval = reg_hash(re);
    return LONG2FIX(hashval);
}
inspect → string click to toggle source

Produce a nicely formatted string-version of rxp. Perhaps surprisingly, #inspect actually produces the more natural version of the string than #to_s.

/ab+c/x.inspect        #=> "/ab+c/ix"

static VALUE
rb_reg_inspect(VALUE re)
{
    if (!RREGEXP(re)->ptr || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
        return rb_any_to_s(re);
    }
    return rb_reg_desc(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), re);
}
match(str) → matchdata or nil click to toggle source
match(str,pos) → matchdata or nil

Returns a MatchData object describing the match, or nil if there was no match. This is equivalent to retrieving the value of the special variable $~ following a normal match. If the second parameter is present, it specifies the position in the string to begin the search.

/(.)(.)(.)/.match("abc")[2]   #=> "b"
/(.)(.)/.match("abc", 1)[2]   #=> "c"

If a block is given, invoke the block with MatchData if match succeed, so that you can write

pat.match(str) {|m| ...}

instead of

if m = pat.match(str)
  ...
end

The return value is a value from block execution in this case.

static VALUE
rb_reg_match_m(int argc, VALUE *argv, VALUE re)
{
    VALUE result, str, initpos;
    long pos;

    if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) {
        pos = NUM2LONG(initpos);
    }
    else {
        pos = 0;
    }

    pos = reg_match_pos(re, &str, pos);
    if (pos < 0) {
        rb_backref_set(Qnil);
        return Qnil;
    }
    result = rb_backref_get();
    rb_match_busy(result);
    if (!NIL_P(result) && rb_block_given_p()) {
        return rb_yield(result);
    }
    return result;
}
named_captures → hash click to toggle source

Returns a hash representing information about named captures of rxp.

A key of the hash is a name of the named captures. A value of the hash is an array which is list of indexes of corresponding named captures.

/(?<foo>.)(?<bar>.)/.named_captures
#=> {"foo"=>[1], "bar"=>[2]}

/(?<foo>.)(?<foo>.)/.named_captures
#=> {"foo"=>[1, 2]}

If there are no named captures, an empty hash is returned.

/(.)(.)/.named_captures
#=> {}

static VALUE
rb_reg_named_captures(VALUE re)
{
    VALUE hash = rb_hash_new();
    rb_reg_check(re);
    onig_foreach_name(RREGEXP(re)->ptr, reg_named_captures_iter, (void*)hash);
    return hash;
}
names → [name1, name2, ...] click to toggle source

Returns a list of names of captures as an array of strings.

/(?<foo>.)(?<bar>.)(?<baz>.)/.names
#=> ["foo", "bar", "baz"]

/(?<foo>.)(?<foo>.)/.names
#=> ["foo"]

/(.)(.)/.names
#=> []

static VALUE
rb_reg_names(VALUE re)
{
    VALUE ary = rb_ary_new();
    rb_reg_check(re);
    onig_foreach_name(RREGEXP(re)->ptr, reg_names_iter, (void*)ary);
    return ary;
}
options → fixnum click to toggle source

Returns the set of bits corresponding to the options used when creating this Regexp (see Regexp::new for details. Note that additional bits may be set in the returned options: these are used internally by the regular expression code. These extra bits are ignored if the options are passed to Regexp::new.

Regexp::IGNORECASE                  #=> 1
Regexp::EXTENDED                    #=> 2
Regexp::MULTILINE                   #=> 4

/cat/.options                       #=> 0
/cat/x.options                     #=> 3
Regexp.new('cat', true).options     #=> 1
/\xa1\xa2/.options                 #=> 16

r = /cat/x
Regexp.new(r.source, r.options)     #=> /cat/ix

static VALUE
rb_reg_options_m(VALUE re)
{
    int options = rb_reg_options(re);
    return INT2NUM(options);
}
source → str click to toggle source

Returns the original string of the pattern.

/ab+c/x.source #=> "ab+c"

Note that escape sequences are retained as is.

/\x20\+/.source  #=> "\\x20\\+"

static VALUE
rb_reg_source(VALUE re)
{
    VALUE str;

    rb_reg_check(re);
    str = rb_enc_str_new(RREGEXP_SRC_PTR(re),RREGEXP_SRC_LEN(re), rb_enc_get(re));
    if (OBJ_TAINTED(re)) OBJ_TAINT(str);
    return str;
}
to_s → str click to toggle source

Returns a string containing the regular expression and its options (using the (?opts:source) notation. This string can be fed back in to Regexp::new to a regular expression with the same semantics as the original. (However, Regexp#== may not return true when comparing the two, as the source of the regular expression itself may differ, as the example shows). Regexp#inspect produces a generally more readable version of rxp.

r1 = /ab+c/x           #=> /ab+c/ix
s1 = r1.to_s            #=> "(?ix-m:ab+c)"
r2 = Regexp.new(s1)     #=> /(?ix-m:ab+c)/
r1 == r2                #=> false
r1.source               #=> "ab+c"
r2.source               #=> "(?ix-m:ab+c)"

static VALUE
rb_reg_to_s(VALUE re)
{
    int options, opt;
    const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
    long len;
    const UChar* ptr;
    VALUE str = rb_str_buf_new2("(?");
    char optbuf[5];
    rb_encoding *enc = rb_enc_get(re);

    rb_reg_check(re);

    rb_enc_copy(str, re);
    options = RREGEXP(re)->ptr->options;
    ptr = (UChar*)RREGEXP_SRC_PTR(re);
    len = RREGEXP_SRC_LEN(re);
  again:
    if (len >= 4 && ptr[0] == '(' && ptr[1] == '?') {
        int err = 1;
        ptr += 2;
        if ((len -= 2) > 0) {
            do {
                opt = char_to_option((int )*ptr);
                if (opt != 0) {
                    options |= opt;
                }
                else {
                    break;
                }
                ++ptr;
            } while (--len > 0);
        }
        if (len > 1 && *ptr == '-') {
            ++ptr;
            --len;
            do {
                opt = char_to_option((int )*ptr);
                if (opt != 0) {
                    options &= ~opt;
                }
                else {
                    break;
                }
                ++ptr;
            } while (--len > 0);
        }
        if (*ptr == ')') {
            --len;
            ++ptr;
            goto again;
        }
        if (*ptr == ':' && ptr[len-1] == ')') {
            Regexp *rp;

            ++ptr;
            len -= 2;
            err = onig_new(&rp, ptr, ptr + len, ONIG_OPTION_DEFAULT,
                           enc, OnigDefaultSyntax, NULL);
            onig_free(rp);
        }
        if (err) {
            options = RREGEXP(re)->ptr->options;
            ptr = (UChar*)RREGEXP_SRC_PTR(re);
            len = RREGEXP_SRC_LEN(re);
        }
    }

    if (*option_to_str(optbuf, options)) rb_str_buf_cat2(str, optbuf);

    if ((options & embeddable) != embeddable) {
        optbuf[0] = '-';
        option_to_str(optbuf + 1, ~options);
        rb_str_buf_cat2(str, optbuf);
    }

    rb_str_buf_cat2(str, ":");
    rb_reg_expr_str(str, (char*)ptr, len, enc, NULL);
    rb_str_buf_cat2(str, ")");
    rb_enc_copy(str, re);

    OBJ_INFECT(str, re);
    return str;
}
~ rxp → integer or nil click to toggle source

Match—Matches rxp against the contents of $_. Equivalent to rxp =~ $_.

$_ = "input data"
~ /at/   #=> 7

VALUE
rb_reg_match2(VALUE re)
{
    long start;
    VALUE line = rb_lastline_get();

    if (!RB_TYPE_P(line, T_STRING)) {
        rb_backref_set(Qnil);
        return Qnil;
    }

    start = rb_reg_search(re, line, 0, 0);
    if (start < 0) {
        return Qnil;
    }
    start = rb_str_sublen(line, start);
    return LONG2FIX(start);
}


class RegexpError - Ruby 2.0.0-p576 Core API Reference API Reference

class RegexpError

Raised when given an invalid regexp expression.

Regexp.new("?")

raises the exception:

RegexpError: target of repeat operator is not specified: /?/

In Files

  • re.c

Parent

StandardError


class Ripper - Ruby 2.0.0-p576 Core API Reference API Reference

class Ripper

In Files

  • parse.c

Parent

Object

Constants

Version

Public Class Methods

new(src, filename="(ripper)", lineno=1) → ripper click to toggle source

Create a new Ripper object. src must be a String, an IO, or an Object which has gets method.

This method does not starts parsing. See also #parse and #parse.

static VALUE
ripper_initialize(int argc, VALUE *argv, VALUE self)
{
    struct parser_params *parser;
    VALUE src, fname, lineno;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
    if (RB_TYPE_P(src, T_FILE)) {
        parser->parser_lex_gets = ripper_lex_get_generic;
    }
    else {
        StringValue(src);
        parser->parser_lex_gets = lex_get_str;
    }
    parser->parser_lex_input = src;
    parser->eofp = Qfalse;
    if (NIL_P(fname)) {
        fname = STR_NEW2("(ripper)");
    }
    else {
        StringValue(fname);
    }
    parser_initialize(parser);

    parser->parser_ruby_sourcefile_string = fname;
    parser->parser_ruby_sourcefile = RSTRING_PTR(fname);
    parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;

    return Qnil;
}

Public Instance Methods

ripper#column → Integer click to toggle source

Return column number of current parsing line. This number starts from 0.

static VALUE
ripper_column(VALUE self)
{
    struct parser_params *parser;
    long col;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    if (!ripper_initialized_p(parser)) {
        rb_raise(rb_eArgError, "method called for uninitialized object");
    }
    if (NIL_P(parser->parsing_thread)) return Qnil;
    col = parser->tokp - parser->parser_lex_pbeg;
    return LONG2NUM(col);
}
ripper#encoding → encoding click to toggle source

Return encoding of the source.

VALUE
rb_parser_encoding(VALUE vparser)
{
    struct parser_params *parser;

    TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
    return rb_enc_from_encoding(current_enc);
}
ripper#end_seen? → Boolean click to toggle source

Return true if parsed source ended by +__END__+.

VALUE
rb_parser_end_seen_p(VALUE vparser)
{
    struct parser_params *parser;

    TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
    return ruby__end__seen ? Qtrue : Qfalse;
}
ripper#filename → String click to toggle source

Return current parsing filename.

static VALUE
ripper_filename(VALUE self)
{
    struct parser_params *parser;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    if (!ripper_initialized_p(parser)) {
        rb_raise(rb_eArgError, "method called for uninitialized object");
    }
    return parser->parser_ruby_sourcefile_string;
}
ripper#lineno → Integer click to toggle source

Return line number of current parsing line. This number starts from 1.

static VALUE
ripper_lineno(VALUE self)
{
    struct parser_params *parser;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    if (!ripper_initialized_p(parser)) {
        rb_raise(rb_eArgError, "method called for uninitialized object");
    }
    if (NIL_P(parser->parsing_thread)) return Qnil;
    return INT2NUM(parser->parser_ruby_sourceline);
}
ripper#parse click to toggle source

Start parsing and returns the value of the root action.

static VALUE
ripper_parse(VALUE self)
{
    struct parser_params *parser;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    if (!ripper_initialized_p(parser)) {
        rb_raise(rb_eArgError, "method called for uninitialized object");
    }
    if (!NIL_P(parser->parsing_thread)) {
        if (parser->parsing_thread == rb_thread_current())
            rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
        else
            rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
    }
    parser->parsing_thread = rb_thread_current();
    rb_ensure(ripper_parse0, self, ripper_ensure, self);

    return parser->result;
}
yydebug → true or false click to toggle source

Get yydebug.

VALUE
rb_parser_get_yydebug(VALUE self)
{
    struct parser_params *parser;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    return yydebug ? Qtrue : Qfalse;
}
yydebug = flag click to toggle source

Set yydebug.

VALUE
rb_parser_set_yydebug(VALUE self, VALUE flag)
{
    struct parser_params *parser;

    TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
    yydebug = RTEST(flag);
    return flag;
}


class RubyVM - Ruby 2.0.0-p576 Core API Reference API Reference

class RubyVM

::RubyVM

In Files

  • iseq.c
  • vm.c

Parent

Object

Constants

DEFAULT_PARAMS

DEFAULT_PARAMS This constant variable shows VM's default parameters. Note that changing these values does not affect VM exection. Specification is not stable and you should not depend on this value. Of course, this constant is MRI specific.

INSTRUCTION_NAMES

INSTRUCTION_NAMES

OPTS

OPTS, which shows vm build options

USAGE_ANALYSIS_INSN

USAGE_ANALYSIS_*

USAGE_ANALYSIS_INSN_BIGRAM
USAGE_ANALYSIS_REGS


class RubyVM::Env - Ruby 2.0.0-p576 Core API Reference API Reference

class RubyVM::Env

::RubyVM::Env

In Files

  • iseq.c

Parent

Object


class RubyVM::InstructionSequence - Ruby 2.0.0-p576 Core API Reference API Reference

class RubyVM::InstructionSequence

The InstructionSequence class represents a compiled sequence of instructions for the Ruby Virtual Machine.

With it, you can get a handle to the instructions that make up a method or a proc, compile strings of Ruby code down to VM instructions, and disassemble instruction sequences to strings for easy inspection. It is mostly useful if you want to learn how the Ruby VM works, but it also lets you control various settings for the Ruby iseq compiler.

You can find the source for the VM instructions in insns.def in the Ruby source.

The instruction sequence results will almost certainly change as Ruby changes, so example output in this documentation may be different from what you see.

In Files

  • iseq.c

Parent

Object

Public Class Methods

compile(source[, file[, path[, line[, options]]]]) → iseq click to toggle source
new(source[, file[, path[, line[, options]]]]) → iseq

Takes source, a String of Ruby code and compiles it to an InstructionSequence.

Optionally takes file, path, and line which describe the filename, absolute path and first line number of the ruby code in source which are metadata attached to the returned iseq.

options, which can be true, false or a Hash, is used to modify the default behavior of the Ruby iseq compiler.

For details regarding valid compile options see ::compile_option=.

RubyVM::InstructionSequence.compile("a = 1 + 2")
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>

static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
    if (NIL_P(file)) file = rb_str_new2("<compiled>");
    if (NIL_P(line)) line = INT2FIX(1);

    return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
}
compile_file(file[, options]) → iseq click to toggle source

Takes file, a String with the location of a Ruby source file, reads, parses and compiles the file, and returns iseq, the compiled InstructionSequence with source location metadata set.

Optionally takes options, which can be true, false or a Hash, to modify the default behavior of the Ruby iseq compiler.

For details regarding valid compile options see ::compile_option=.

# /tmp/hello.rb
puts "Hello, world!"

# elsewhere
RubyVM::InstructionSequence.compile_file("/tmp/hello.rb")
#=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>

static VALUE
iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
{
    VALUE file, line = INT2FIX(1), opt = Qnil;
    VALUE parser;
    VALUE f;
    NODE *node;
    const char *fname;
    rb_compile_option_t option;

    rb_secure(1);
    rb_scan_args(argc, argv, "11", &file, &opt);
    FilePathValue(file);
    fname = StringValueCStr(file);

    f = rb_file_open_str(file, "r");

    parser = rb_parser_new();
    node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
    make_compile_option(&option, opt);
    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
                                rb_realpath_internal(Qnil, file, 1), line, Qfalse,
                                ISEQ_TYPE_TOP, &option);
}
compile_option → options click to toggle source

Returns a hash of default options used by the Ruby iseq compiler.

For details, see ::compile_option=.

static VALUE
iseq_s_compile_option_get(VALUE self)
{
    return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
}
compile_option = options click to toggle source

Sets the default values for various optimizations in the Ruby iseq compiler.

Possible values for options include true, which enables all options, false which disables all options, and nil which leaves all options unchanged.

You can also pass a Hash of options that you want to change, any options not present in the hash will be left unchanged.

Possible option names (which are keys in options) which can be set to true or false include:

  • :inline_const_cache

  • :instructions_unification

  • :operands_unification

  • :peephole_optimization

  • :specialized_instruction

  • :stack_caching

  • :tailcall_optimization

  • :trace_instruction

Additionally, :debug_level can be set to an integer.

These default options can be overwritten for a single run of the iseq compiler by passing any of the above values as the options parameter to ::new, ::compile and ::compile_file.

static VALUE
iseq_s_compile_option_set(VALUE self, VALUE opt)
{
    rb_compile_option_t option;
    rb_secure(1);
    make_compile_option(&option, opt);
    COMPILE_OPTION_DEFAULT = option;
    return opt;
}
disasm(body) → str click to toggle source
disassemble(body) → str

Takes body, a Method or Proc object, and returns a String with the human readable instructions for body.

For a Method object:

# /tmp/method.rb
def hello
  puts "hello, world"
end

puts RubyVM::InstructionSequence.disasm(method(:hello))

Produces:

== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
0000 trace            8                                               (   1)
0002 trace            1                                               (   2)
0004 putself
0005 putstring        "hello, world"
0007 send             :puts, 1, nil, 8, <ic:0>
0013 trace            16                                              (   3)
0015 leave                                                            (   2)

For a Proc:

# /tmp/proc.rb
p = proc { num = 1 + 2 }
puts RubyVM::InstructionSequence.disasm(p)

Produces:

== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
== catch table
| catch type: redo   st: 0000 ed: 0012 sp: 0000 cont: 0000
| catch type: next   st: 0000 ed: 0012 sp: 0000 cont: 0012
|------------------------------------------------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] num
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 dup
0009 setlocal         num, 0
0012 leave
static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    VALUE iseqval = iseq_s_of(klass, body);
    return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
}
disasm(body) → str click to toggle source
disassemble(body) → str

Takes body, a Method or Proc object, and returns a String with the human readable instructions for body.

For a Method object:

# /tmp/method.rb
def hello
  puts "hello, world"
end

puts RubyVM::InstructionSequence.disasm(method(:hello))

Produces:

== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
0000 trace            8                                               (   1)
0002 trace            1                                               (   2)
0004 putself
0005 putstring        "hello, world"
0007 send             :puts, 1, nil, 8, <ic:0>
0013 trace            16                                              (   3)
0015 leave                                                            (   2)

For a Proc:

# /tmp/proc.rb
p = proc { num = 1 + 2 }
puts RubyVM::InstructionSequence.disasm(p)

Produces:

== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
== catch table
| catch type: redo   st: 0000 ed: 0012 sp: 0000 cont: 0000
| catch type: next   st: 0000 ed: 0012 sp: 0000 cont: 0012
|------------------------------------------------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] num
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 dup
0009 setlocal         num, 0
0012 leave
static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    VALUE iseqval = iseq_s_of(klass, body);
    return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
}
compile(source[, file[, path[, line[, options]]]]) → iseq click to toggle source
new(source[, file[, path[, line[, options]]]]) → iseq

Takes source, a String of Ruby code and compiles it to an InstructionSequence.

Optionally takes file, path, and line which describe the filename, absolute path and first line number of the ruby code in source which are metadata attached to the returned iseq.

options, which can be true, false or a Hash, is used to modify the default behavior of the Ruby iseq compiler.

For details regarding valid compile options see ::compile_option=.

RubyVM::InstructionSequence.compile("a = 1 + 2")
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>

static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
    if (NIL_P(file)) file = rb_str_new2("<compiled>");
    if (NIL_P(line)) line = INT2FIX(1);

    return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
}
of(p1) click to toggle source

Returns the instruction sequence containing the given proc or method.

For example, using irb:

# a proc
> p = proc { num = 1 + 2 }
> RubyVM::InstructionSequence.of(p)
> #=> <RubyVM::InstructionSequence:block in irb_binding@(irb)>

# for a method
> def foo(bar); puts bar; end
> RubyVM::InstructionSequence.of(method(:foo))
> #=> <RubyVM::InstructionSequence:foo@(irb)>

Using ::compile_file:

# /tmp/iseq_of.rb
def hello
  puts "hello, world"
end

$a_global_proc = proc { str = 'a' + 'b' }

# in irb
> require '/tmp/iseq_of.rb'

# first the method hello
> RubyVM::InstructionSequence.of(method(:hello))
> #=> #<RubyVM::InstructionSequence:0x007fb73d7cb1d0>

# then the global proc
> RubyVM::InstructionSequence.of($a_global_proc)
> #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78>

static VALUE
iseq_s_of(VALUE klass, VALUE body)
{
    VALUE ret = Qnil;
    rb_iseq_t *iseq;

    rb_secure(1);

    if (rb_obj_is_proc(body)) {
        rb_proc_t *proc;
        GetProcPtr(body, proc);
        iseq = proc->block.iseq;
        if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
            ret = iseq->self;
        }
    }
    else if ((iseq = rb_method_get_iseq(body)) != 0) {
        ret = iseq->self;
    }
    return ret;
}

Public Instance Methods

absolute_path() click to toggle source

Returns the absolute path of this instruction sequence.

nil if the iseq was evaluated from a string.

For example, using ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.absolute_path #=> /tmp/method.rb

static VALUE
iseq_absolute_path(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.absolute_path;
}
base_label() click to toggle source

Returns the base label of this instruction sequence.

For example, using irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.base_label
#=> "<compiled>"

Using ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.base_label #=> <main>

static VALUE
iseq_base_label(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.base_label;
}
disasm → str click to toggle source
disassemble → str

Returns the instruction sequence as a String in human readable form.

puts RubyVM::InstructionSequence.compile('1 + 2').disasm

Produces:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 leave
VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self);
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned long size;
    int i;
    long l;
    ID *tbl;
    size_t n;
    enum {header_minlen = 72};

    rb_secure(1);

    iseq = iseqdat->iseq;
    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "== catch table\n");
    }
    for (i = 0; i < iseqdat->catch_table_size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
                    iseqdat->local_size, iseqdat->argc,
                    iseqdat->arg_opts, iseqdat->arg_rest,
                    iseqdat->arg_post_len, iseqdat->arg_block,
                    iseqdat->arg_simple);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            long width;
            VALUE name = id_to_name(tbl[i], 0);
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->arg_opts) {
                int argc = iseqdat->argc;
                int opts = iseqdat->arg_opts;
                if (i >= argc && i < argc + opts - 1) {
                    snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
                             iseqdat->arg_opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->argc > i ? "Arg" : "",
                     opti,
                     iseqdat->arg_rest == i ? "Rest" : "",
                     (iseqdat->arg_post_start <= i &&
                      i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
                     iseqdat->arg_block == i ? "Block" : "");

            rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
            width = RSTRING_LEN(str) + 11;
            if (name)
                rb_str_append(str, name);
            else
                rb_str_cat2(str, "?");
            if (*argi) rb_str_catf(str, "<%s>", argi);
            if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    for (n = 0; n < size;) {
        n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}
disasm → str click to toggle source
disassemble → str

Returns the instruction sequence as a String in human readable form.

puts RubyVM::InstructionSequence.compile('1 + 2').disasm

Produces:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 leave
VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self);
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned long size;
    int i;
    long l;
    ID *tbl;
    size_t n;
    enum {header_minlen = 72};

    rb_secure(1);

    iseq = iseqdat->iseq;
    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "== catch table\n");
    }
    for (i = 0; i < iseqdat->catch_table_size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table_size != 0) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
                    iseqdat->local_size, iseqdat->argc,
                    iseqdat->arg_opts, iseqdat->arg_rest,
                    iseqdat->arg_post_len, iseqdat->arg_block,
                    iseqdat->arg_simple);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            long width;
            VALUE name = id_to_name(tbl[i], 0);
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->arg_opts) {
                int argc = iseqdat->argc;
                int opts = iseqdat->arg_opts;
                if (i >= argc && i < argc + opts - 1) {
                    snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
                             iseqdat->arg_opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->argc > i ? "Arg" : "",
                     opti,
                     iseqdat->arg_rest == i ? "Rest" : "",
                     (iseqdat->arg_post_start <= i &&
                      i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
                     iseqdat->arg_block == i ? "Block" : "");

            rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
            width = RSTRING_LEN(str) + 11;
            if (name)
                rb_str_append(str, name);
            else
                rb_str_cat2(str, "?");
            if (*argi) rb_str_catf(str, "<%s>", argi);
            if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    for (n = 0; n < size;) {
        n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}
eval → obj click to toggle source

Evaluates the instruction sequence and returns the result.

RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3

static VALUE
iseq_eval(VALUE self)
{
    rb_secure(1);
    return rb_iseq_eval(self);
}
first_lineno() click to toggle source

Returns the number of the first source line where the instruction sequence was loaded from.

For example, using irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.first_lineno
#=> 1

static VALUE
iseq_first_lineno(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.first_lineno;
}
inspect() click to toggle source

Returns a human-readable string representation of this instruction sequence, including the label and path.

static VALUE
iseq_inspect(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    if (!iseq->location.label) {
        return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
    }

    return rb_sprintf("<%s:%s@%s>",
                      rb_obj_classname(self),
                      RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
}
label() click to toggle source

Returns the label of this instruction sequence.

<main> if it's at the top level, <compiled> if it was evaluated from a string.

For example, using irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.label
#=> "<compiled>"

Using ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.label #=> <main>

static VALUE
iseq_label(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.label;
}
line_trace_all() click to toggle source

Experimental MRI specific feature, only available as C level api.

Returns all specified_line events.

VALUE
rb_iseq_line_trace_all(VALUE iseqval)
{
    VALUE result = rb_ary_new();
    rb_iseq_line_trace_each(iseqval, collect_trace, (void *)result);
    return result;
}
line_trace_specify(p1, p2) click to toggle source

Experimental MRI specific feature, only available as C level api.

Set a specified_line event at the given line position, if the set parameter is true.

This method is useful for building a debugger breakpoint at a specific line.

A TypeError is raised if set is not boolean.

If pos is a negative integer a TypeError exception is raised.

VALUE
rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
{
    struct set_specifc_data data;

    data.prev = 0;
    data.pos = NUM2INT(pos);
    if (data.pos < 0) rb_raise(rb_eTypeError, "`pos' is negative");

    switch (set) {
      case Qtrue:  data.set = 1; break;
      case Qfalse: data.set = 0; break;
      default:
        rb_raise(rb_eTypeError, "`set' should be true/false");
    }

    rb_iseq_line_trace_each(iseqval, line_trace_specify, (void *)&data);

    if (data.prev == 0) {
        rb_raise(rb_eTypeError, "`pos' is out of range.");
    }
    return data.prev == 1 ? Qtrue : Qfalse;
}
path() click to toggle source

Returns the path of this instruction sequence.

<compiled> if the iseq was evaluated from a string.

For example, using irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.path
#=> "<compiled>"

Using ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.path #=> /tmp/method.rb

static VALUE
iseq_path(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.path;
}
to_a → ary click to toggle source

Returns an Array with 14 elements representing the instruction sequence with the following data:

magic

A string identifying the data format. Always YARVInstructionSequence/SimpleDataFormat.

major_version

The major version of the instruction sequence.

minor_version

The minor version of the instruction sequence.

format_type

A number identifying the data format. Always 1.

misc

A hash containing:

:arg_size

the total number of arguments taken by the method or the block (0 if iseq doesn't represent a method or block)

:local_size

the number of local variables + 1

:stack_max

used in calculating the stack depth at which a SystemStackError is thrown.

label

The name of the context (block, method, class, module, etc.) that this instruction sequence belongs to.

<main> if it's at the top level, <compiled> if it was evaluated from a string.

path

The relative path to the Ruby file where the instruction sequence was loaded from.

<compiled> if the iseq was evaluated from a string.

absolute_path

The absolute path to the Ruby file where the instruction sequence was loaded from.

nil if the iseq was evaluated from a string.

first_lineno

The number of the first source line where the instruction sequence was loaded from.

type

The type of the instruction sequence.

Valid values are :top, :method, :block, :class, :rescue, :ensure, :eval, :main, and :defined_guard.

locals

An array containing the names of all arguments and local variables as symbols.

args

The arity if the method or block only has required arguments.

Otherwise an array of:

[required_argc, [optional_arg_labels, ...],
 splat_index, post_splat_argc, post_splat_index,
 block_index, simple]

More info about these values can be found in vm_core.h.

catch_table

A list of exceptions and control flow operators (rescue, next, redo, break, etc.).

bytecode

An array of arrays containing the instruction names and operands that make up the body of the instruction sequence.

static VALUE
iseq_to_a(VALUE self)
{
    rb_iseq_t *iseq = iseq_check(self);
    rb_secure(1);
    return iseq_data_to_ary(iseq);
}


class RuntimeError - Ruby 2.0.0-p576 Core API Reference API Reference

class RuntimeError

A generic error class raised when an invalid operation is attempted.

[1, 2, 3].freeze << 4

raises the exception:

RuntimeError: can't modify frozen array

Kernel#raise will raise a RuntimeError if no Exception class is specified.

raise "ouch"

raises the exception:

RuntimeError: ouch

In Files

  • error.c

Parent

StandardError


class ScriptError - Ruby 2.0.0-p576 Core API Reference API Reference

class ScriptError

ScriptError is the superclass for errors raised when a script can not be executed because of a LoadError, NotImplementedError or a SyntaxError. Note these type of ScriptErrors are not StandardError and will not be rescued unless it is specified explicitly (or its ancestor Exception).

In Files

  • error.c

Parent

Exception


class SecurityError - Ruby 2.0.0-p576 Core API Reference API Reference

class SecurityError

Raised when attempting a potential unsafe operation, typically when the $SAFE level is raised above 0.

foo = "bar"
proc = Proc.new do
  $SAFE = 4
  foo.gsub! "a", "*"
end
proc.call

raises the exception:

SecurityError: Insecure: can't modify string

In Files

  • error.c

Parent

Exception


module Signal - Ruby 2.0.0-p576 Core API Reference API Reference

module Signal

Many operating systems allow signals to be sent to running processes. Some signals have a defined effect on the process, while others may be trapped at the code level and acted upon. For example, your process may trap the USR1 signal and use it to toggle debugging, and may use TERM to initiate a controlled shutdown.

pid = fork do
  Signal.trap("USR1") do
    $debug = !$debug
    puts "Debug now: #$debug"
  end
  Signal.trap("TERM") do
    puts "Terminating..."
    shutdown()
  end
  # . . . do some work . . .
end

Process.detach(pid)

# Controlling program:
Process.kill("USR1", pid)
# ...
Process.kill("USR1", pid)
# ...
Process.kill("TERM", pid)

produces:

 Debug now: true
 Debug now: false
Terminating...

The list of available signal names and their interpretation is system dependent. Signal delivery semantics may also vary between systems; in particular signal delivery may not always be reliable.

In Files

  • signal.c

Public Class Methods

list → a_hash click to toggle source

Returns a list of signal names mapped to the corresponding underlying signal numbers.

Signal.list   #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29}

static VALUE
sig_list(void)
{
    VALUE h = rb_hash_new();
    const struct signals *sigs;

    for (sigs = siglist; sigs->signm; sigs++) {
        rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
    }
    return h;
}
signame(signo) → string click to toggle source

convert signal number to signal name

Signal.trap("INT") { |signo| puts Signal.signame(signo) }
Process.kill("INT", 0)

produces:

INT
static VALUE
sig_signame(VALUE recv, VALUE signo)
{
    const char *signame = signo2signm(NUM2INT(signo));
    return rb_str_new_cstr(signame);
}
trap( signal, command ) → obj click to toggle source
trap( signal ) {| | block } → obj

Specifies the handling of signals. The first parameter is a signal name (a string such as “SIGALRM'', “SIGUSR1'', and so on) or a signal number. The characters “SIG'' may be omitted from the signal name. The command or block specifies code to be run when the signal is raised. If the command is the string “IGNORE'' or “SIG_IGN'', the signal will be ignored. If the command is “DEFAULT'' or “SIG_DFL'', the Ruby's default handler will be invoked. If the command is “EXIT'', the script will be terminated by the signal. If the command is “SYSTEM_DEFAULT'', the operating system's default handler will be invoked. Otherwise, the given command or block will be run. The special signal name “EXIT'' or signal number zero will be invoked just prior to program termination. trap returns the previous handler for the given signal.

Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD")  { puts "Child died" }
fork && Process.wait

produces:

Terminating: 27461
Child died
Terminating: 27460
static VALUE
sig_trap(int argc, VALUE *argv)
{
    int sig;
    sighandler_t func;
    VALUE cmd;

    rb_secure(2);
    rb_check_arity(argc, 1, 2);

    sig = trap_signm(argv[0]);
    if (reserved_signal_p(sig)) {
        const char *name = signo2signm(sig);
        if (name)
            rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
        else
            rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
    }

    if (argc == 1) {
        cmd = rb_block_proc();
        func = sighandler;
    }
    else {
        cmd = argv[1];
        func = trap_handler(&cmd, sig);
    }

    if (OBJ_TAINTED(cmd)) {
        rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
    }

    return trap(sig, func, cmd);
}


class SignalException - Ruby 2.0.0-p576 Core API Reference API Reference

class SignalException

Raised when a signal is received.

begin
  Process.kill('HUP',Process.pid)
  sleep # wait for receiver to handle signal sent by Process.kill
rescue SignalException => e
  puts "received Exception #{e}"
end

produces:

received Exception SIGHUP

In Files

  • error.c
  • signal.c

Parent

Exception

Public Class Methods

new(sig_name) → signal_exception click to toggle source
new(sig_number [, name]) → signal_exception

Construct a new SignalException object. sig_name should be a known signal name.

static VALUE
esignal_init(int argc, VALUE *argv, VALUE self)
{
    int argnum = 1;
    VALUE sig = Qnil;
    int signo;
    const char *signm;

    if (argc > 0) {
        sig = rb_check_to_integer(argv[0], "to_int");
        if (!NIL_P(sig)) argnum = 2;
        else sig = argv[0];
    }
    rb_check_arity(argc, 1, argnum);
    if (argnum == 2) {
        signo = NUM2INT(sig);
        if (signo < 0 || signo > NSIG) {
            rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
        }
        if (argc > 1) {
            sig = argv[1];
        }
        else {
            signm = signo2signm(signo);
            if (signm) {
                sig = rb_sprintf("SIG%s", signm);
            }
            else {
                sig = rb_sprintf("SIG%u", signo);
            }
        }
    }
    else {
        signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
        if (strncmp(signm, "SIG", 3) == 0) signm += 3;
        signo = signm2signo(signm);
        if (!signo) {
            rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
        }
        sig = rb_sprintf("SIG%s", signm);
    }
    rb_call_super(1, &sig);
    rb_iv_set(self, "signo", INT2NUM(signo));

    return self;
}

Public Instance Methods

signo → num click to toggle source

Returns a signal number.

static VALUE
esignal_signo(VALUE self)
{
    return rb_iv_get(self, "signo");
}


class StandardError - Ruby 2.0.0-p576 Core API Reference API Reference

class StandardError

The most standard error types are subclasses of StandardError. A rescue clause without an explicit Exception class will rescue all StandardErrors (and only those).

def foo
  raise "Oups"
end
foo rescue "Hello"   #=> "Hello"

On the other hand:

require 'does/not/exist' rescue "Hi"

raises the exception:

LoadError: no such file to load -- does/not/exist

In Files

  • error.c

Parent

Exception


class StopIteration - Ruby 2.0.0-p576 Core API Reference API Reference

class StopIteration

Raised to stop the iteration, in particular by Enumerator#next. It is rescued by Kernel#loop.

loop do
  puts "Hello"
  raise StopIteration
  puts "World"
end
puts "Done!"

produces:

Hello
Done!

In Files

  • enumerator.c

Parent

IndexError

Public Instance Methods

result → value click to toggle source

Returns the return value of the iterator.

o = Object.new
def o.each
  yield 1
  yield 2
  yield 3
  100
end

e = o.to_enum

puts e.next                   #=> 1
puts e.next                   #=> 2
puts e.next                   #=> 3

begin
  e.next
rescue StopIteration => ex
  puts ex.result              #=> 100
end

static VALUE
stop_result(VALUE self)
{
    return rb_attr_get(self, id_result);
}


class String - Ruby 2.0.0-p576 Core API Reference API Reference

class String

A String object holds and manipulates an arbitrary sequence of bytes, typically representing characters. String objects may be created using String::new or as literals.

Because of aliasing issues, users of strings should be aware of the methods that modify the contents of a String object. Typically, methods with names ending in “!'' modify their receiver, while those without a “!'' return a new String. However, there are exceptions, such as String#[]=.

In Files

  • complex.c
  • pack.c
  • rational.c
  • string.c
  • transcode.c

Parent

Object

Included Modules

  • Comparable

Public Class Methods

new(str="") → new_str click to toggle source

Returns a new string object containing a copy of str.

static VALUE
rb_str_init(int argc, VALUE *argv, VALUE str)
{
    VALUE orig;

    if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1)
        rb_str_replace(str, orig);
    return str;
}
try_convert(obj) → string or nil click to toggle source

Try to convert obj into a String, using #to_str method. Returns converted string or nil if obj cannot be converted for any reason.

String.try_convert("str")     #=> "str"
String.try_convert(/re/)      #=> nil

static VALUE
rb_str_s_try_convert(VALUE dummy, VALUE str)
{
    return rb_check_string_type(str);
}

Public Instance Methods

str % arg → new_str click to toggle source

Format—Uses str as a format specification, and returns the result of applying it to arg. If the format specification contains more than one substitution, then arg must be an Array or Hash containing the values to be substituted. See Kernel::sprintf for details of the format string.

"%05d" % 123                              #=> "00123"
"%-5s: %08x" % [ "ID", self.object_id ]   #=> "ID   : 200e14d6"
"foo = %{foo}" % { :foo => 'bar' }        #=> "foo = bar"

static VALUE
rb_str_format_m(VALUE str, VALUE arg)
{
    volatile VALUE tmp = rb_check_array_type(arg);

    if (!NIL_P(tmp)) {
        return rb_str_format(RARRAY_LENINT(tmp), RARRAY_PTR(tmp), str);
    }
    return rb_str_format(1, &arg, str);
}
str * integer → new_str click to toggle source

Copy — Returns a new String containing integer copies of the receiver. integer must be greater than or equal to 0.

"Ho! " * 3   #=> "Ho! Ho! Ho! "
"Ho! " * 0   #=> ""

VALUE
rb_str_times(VALUE str, VALUE times)
{
    VALUE str2;
    long n, len;
    char *ptr2;

    len = NUM2LONG(times);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative argument");
    }
    if (len && LONG_MAX/len <  RSTRING_LEN(str)) {
        rb_raise(rb_eArgError, "argument too big");
    }

    str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str));
    ptr2 = RSTRING_PTR(str2);
    if (len) {
        n = RSTRING_LEN(str);
        memcpy(ptr2, RSTRING_PTR(str), n);
        while (n <= len/2) {
            memcpy(ptr2 + n, ptr2, n);
            n *= 2;
        }
        memcpy(ptr2 + n, ptr2, len-n);
    }
    ptr2[RSTRING_LEN(str2)] = '\0';
    OBJ_INFECT(str2, str);
    rb_enc_cr_str_copy_for_substr(str2, str);

    return str2;
}
str + other_str → new_str click to toggle source

Concatenation—Returns a new String containing other_str concatenated to str.

"Hello from " + self.to_s   #=> "Hello from main"

VALUE
rb_str_plus(VALUE str1, VALUE str2)
{
    VALUE str3;
    rb_encoding *enc;

    StringValue(str2);
    enc = rb_enc_check(str1, str2);
    str3 = rb_str_new(0, RSTRING_LEN(str1)+RSTRING_LEN(str2));
    memcpy(RSTRING_PTR(str3), RSTRING_PTR(str1), RSTRING_LEN(str1));
    memcpy(RSTRING_PTR(str3) + RSTRING_LEN(str1),
           RSTRING_PTR(str2), RSTRING_LEN(str2));
    RSTRING_PTR(str3)[RSTRING_LEN(str3)] = '\0';

    if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
        OBJ_TAINT(str3);
    ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
                           ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
    return str3;
}
str << integer → str click to toggle source
concat(integer) → str
str << obj → str
concat(obj) → str

Append—Concatenates the given object to str. If the object is a Integer, it is considered as a codepoint, and is converted to a character before concatenation.

a = "hello "
a << "world"   #=> "hello world"
a.concat(33)   #=> "hello world!"

VALUE
rb_str_concat(VALUE str1, VALUE str2)
{
    unsigned int code;
    rb_encoding *enc = STR_ENC_GET(str1);

    if (FIXNUM_P(str2) || RB_TYPE_P(str2, T_BIGNUM)) {
        if (rb_num_to_uint(str2, &code) == 0) {
        }
        else if (FIXNUM_P(str2)) {
            rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
        }
        else {
            rb_raise(rb_eRangeError, "bignum out of char range");
        }
    }
    else {
        return rb_str_append(str1, str2);
    }

    if (enc == rb_usascii_encoding()) {
        /* US-ASCII automatically extended to ASCII-8BIT */
        char buf[1];
        buf[0] = (char)code;
        if (code > 0xFF) {
            rb_raise(rb_eRangeError, "%u out of char range", code);
        }
        rb_str_cat(str1, buf, 1);
        if (code > 127) {
            rb_enc_associate(str1, rb_ascii8bit_encoding());
            ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
        }
    }
    else {
        long pos = RSTRING_LEN(str1);
        int cr = ENC_CODERANGE(str1);
        int len;
        char *buf;

        switch (len = rb_enc_codelen(code, enc)) {
          case ONIGERR_INVALID_CODE_POINT_VALUE:
            rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
            break;
          case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
          case 0:
            rb_raise(rb_eRangeError, "%u out of char range", code);
            break;
        }
        buf = ALLOCA_N(char, len + 1);
        rb_enc_mbcput(code, buf, enc);
        if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
            rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
        }
        rb_str_resize(str1, pos+len);
        memcpy(RSTRING_PTR(str1) + pos, buf, len);
        if (cr == ENC_CODERANGE_7BIT && code > 127)
            cr = ENC_CODERANGE_VALID;
        ENC_CODERANGE_SET(str1, cr);
    }
    return str1;
}
string <=> other_string → -1, 0, +1 or nil click to toggle source

Comparison—Returns -1, 0, +1 or nil depending on whether string is less than, equal to, or greater than other_string.

nil is returned if the two values are incomparable.

If the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered greater than the shorter one.

<=> is the basis for the methods <, <=, >, >=, and between?, included from module Comparable. The method String#== does not use Comparable#==.

"abcdef" <=> "abcde"     #=> 1
"abcdef" <=> "abcdef"    #=> 0
"abcdef" <=> "abcdefg"   #=> -1
"abcdef" <=> "ABCDEF"    #=> 1

static VALUE
rb_str_cmp_m(VALUE str1, VALUE str2)
{
    int result;

    if (!RB_TYPE_P(str2, T_STRING)) {
        VALUE tmp = rb_check_funcall(str2, rb_intern("to_str"), 0, 0);
        if (RB_TYPE_P(tmp, T_STRING)) {
            result = rb_str_cmp(str1, tmp);
        }
        else {
            return rb_invcmp(str1, str2);
        }
    }
    else {
        result = rb_str_cmp(str1, str2);
    }
    return INT2FIX(result);
}
str == obj → true or false click to toggle source

Equality—If obj is not a String, returns false. Otherwise, returns true if str <=> obj returns zero.

VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
    if (str1 == str2) return Qtrue;
    if (!RB_TYPE_P(str2, T_STRING)) {
        if (!rb_respond_to(str2, rb_intern("to_str"))) {
            return Qfalse;
        }
        return rb_equal(str2, str1);
    }
    return str_eql(str1, str2);
}
str == obj → true or false click to toggle source

Equality—If obj is not a String, returns false. Otherwise, returns true if str <=> obj returns zero.

VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
    if (str1 == str2) return Qtrue;
    if (!RB_TYPE_P(str2, T_STRING)) {
        if (!rb_respond_to(str2, rb_intern("to_str"))) {
            return Qfalse;
        }
        return rb_equal(str2, str1);
    }
    return str_eql(str1, str2);
}
str =~ obj → fixnum or nil click to toggle source

Match—If obj is a Regexp, use it as a pattern to match against str,and returns the position the match starts, or nil if there is no match. Otherwise, invokes obj.=~, passing str as an argument. The default =~ in Object returns nil.

Note: str =~ regexp is not the same as regexp =~ str. Strings captured from named capture groups are assigned to local variables only in the second case.

"cat o' 9 tails" =~ /\d/   #=> 7
"cat o' 9 tails" =~ 9      #=> nil

static VALUE
rb_str_match(VALUE x, VALUE y)
{
    if (SPECIAL_CONST_P(y)) goto generic;
    switch (BUILTIN_TYPE(y)) {
      case T_STRING:
        rb_raise(rb_eTypeError, "type mismatch: String given");

      case T_REGEXP:
        return rb_reg_match(y, x);

      generic:
      default:
        return rb_funcall(y, rb_intern("=~"), 1, x);
    }
}
str[index] → new_str or nil click to toggle source
str[start, length] → new_str or nil
str[range] → new_str or nil
str[regexp] → new_str or nil
str[regexp, capture] → new_str or nil
str[match_str] → new_str or nil
slice(index) → new_str or nil
slice(start, length) → new_str or nil
slice(range) → new_str or nil
slice(regexp) → new_str or nil
slice(regexp, capture) → new_str or nil
slice(match_str) → new_str or nil

Element Reference — If passed a single index, returns a substring of one character at that index. If passed a start index and a length, returns a substring containing length characters starting at the index. If passed a range, its beginning and end are interpreted as offsets delimiting the substring to be returned.

In these three cases, if an index is negative, it is counted from the end of the string. For the start and range cases the starting index is just before a character and an index matching the string's size. Additionally, an empty string is returned when the starting index for a character range is at the end of the string.

Returns nil if the initial index falls outside the string or the length is negative.

If a Regexp is supplied, the matching portion of the string is returned. If a capture follows the regular expression, which may be a capture group index or name, follows the regular expression that component of the MatchData is returned instead.

If a match_str is given, that string is returned if it occurs in the string.

Returns nil if the regular expression does not match or the match string cannot be found.

a = "hello there"

a[1]                   #=> "e"
a[2, 3]                #=> "llo"
a[2..3]                #=> "ll"

a[-3, 2]               #=> "er"
a[7..-2]               #=> "her"
a[-4..-2]              #=> "her"
a[-2..-4]              #=> ""

a[11, 0]               #=> ""
a[11]                  #=> nil
a[12, 0]               #=> nil
a[12..-1]              #=> nil

a[/[aeiou](.)\1/]      #=> "ell"
a[/[aeiou](.)\1/, 0]   #=> "ell"
a[/[aeiou](.)\1/, 1]   #=> "l"
a[/[aeiou](.)\1/, 2]   #=> nil

a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l"
a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"]     #=> "e"

a["lo"]                #=> "lo"
a["bye"]               #=> nil

static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
    if (argc == 2) {
        if (RB_TYPE_P(argv[0], T_REGEXP)) {
            return rb_str_subpat(str, argv[0], argv[1]);
        }
        return rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
    }
    rb_check_arity(argc, 1, 2);
    return rb_str_aref(str, argv[0]);
}
str[fixnum] = new_str click to toggle source
str[fixnum, fixnum] = new_str
str[range] = aString
str[regexp] = new_str
str[regexp, fixnum] = new_str
str[regexp, name] = new_str
str[other_str] = new_str

Element Assignment—Replaces some or all of the content of str. The portion of the string affected is determined using the same criteria as String#[]. If the replacement string is not the same length as the text it is replacing, the string will be adjusted accordingly. If the regular expression or string is used as the index doesn't match a position in the string, IndexError is raised. If the regular expression form is used, the optional second Fixnum allows you to specify which portion of the match to replace (effectively using the MatchData indexing rules. The forms that take a Fixnum will raise an IndexError if the value is out of range; the Range form will raise a RangeError, and the Regexp and String will raise an IndexError on negative match.

static VALUE
rb_str_aset_m(int argc, VALUE *argv, VALUE str)
{
    if (argc == 3) {
        if (RB_TYPE_P(argv[0], T_REGEXP)) {
            rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
        }
        else {
            rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
        }
        return argv[2];
    }
    rb_check_arity(argc, 2, 3);
    return rb_str_aset(str, argv[0], argv[1]);
}
ascii_only? → true or false click to toggle source

Returns true for a string which has only ASCII characters.

"abc".force_encoding("UTF-8").ascii_only?          #=> true
"abc\u{6666}".force_encoding("UTF-8").ascii_only?  #=> false

static VALUE
rb_str_is_ascii_only_p(VALUE str)
{
    int cr = rb_enc_str_coderange(str);

    return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
}
b → str click to toggle source

Returns a copied string whose encoding is ASCII-8BIT.

static VALUE
rb_str_b(VALUE str)
{
    VALUE str2 = str_alloc(rb_cString);
    str_replace_shared_without_enc(str2, str);
    OBJ_INFECT(str2, str);
    ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
    return str2;
}
bytes → an_array click to toggle source

Returns an array of bytes in str. This is a shorthand for str.each_byte.to_a.

If a block is given, which is a deprecated form, works the same as each_byte.

static VALUE
rb_str_bytes(VALUE str)
{
    return rb_str_enumerate_bytes(str, 1);
}
bytesize → integer click to toggle source

Returns the length of str in bytes.

"\x80\u3042".bytesize  #=> 4
"hello".bytesize       #=> 5

static VALUE
rb_str_bytesize(VALUE str)
{
    return LONG2NUM(RSTRING_LEN(str));
}
byteslice(fixnum) → new_str or nil click to toggle source
byteslice(fixnum, fixnum) → new_str or nil
byteslice(range) → new_str or nil

Byte Reference—If passed a single Fixnum, returns a substring of one byte at that position. If passed two Fixnum objects, returns a substring starting at the offset given by the first, and a length given by the second. If given a Range, a substring containing bytes at offsets given by the range is returned. In all three cases, if an offset is negative, it is counted from the end of str. Returns nil if the initial offset falls outside the string, the length is negative, or the beginning of the range is greater than the end. The encoding of the resulted string keeps original encoding.

"hello".byteslice(1)     #=> "e"
"hello".byteslice(-1)    #=> "o"
"hello".byteslice(1, 2)  #=> "el"
"\x80\u3042".byteslice(1, 3) #=> "\u3042"
"\x03\u3042\xff".byteslice(1..3) #=> "\u3042"

static VALUE
rb_str_byteslice(int argc, VALUE *argv, VALUE str)
{
    if (argc == 2) {
        return str_byte_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
    }
    rb_check_arity(argc, 1, 2);
    return str_byte_aref(str, argv[0]);
}
capitalize → new_str click to toggle source

Returns a copy of str with the first character converted to uppercase and the remainder to lowercase. Note: case conversion is effective only in ASCII region.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"

static VALUE
rb_str_capitalize(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_capitalize_bang(str);
    return str;
}
capitalize! → str or nil click to toggle source

Modifies str by converting the first character to uppercase and the remainder to lowercase. Returns nil if no changes are made. Note: case conversion is effective only in ASCII region.

a = "hello"
a.capitalize!   #=> "Hello"
a               #=> "Hello"
a.capitalize!   #=> nil

static VALUE
rb_str_capitalize_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *send;
    int modify = 0;
    unsigned int c;
    int n;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    rb_str_check_dummy_enc(enc);
    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
    s = RSTRING_PTR(str); send = RSTRING_END(str);

    c = rb_enc_codepoint_len(s, send, &n, enc);
    if (rb_enc_islower(c, enc)) {
        rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
        modify = 1;
    }
    s += n;
    while (s < send) {
        c = rb_enc_codepoint_len(s, send, &n, enc);
        if (rb_enc_isupper(c, enc)) {
            rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
            modify = 1;
        }
        s += n;
    }

    if (modify) return str;
    return Qnil;
}
casecmp(other_str) → -1, 0, +1 or nil click to toggle source

Case-insensitive version of String#<=>.

"abcdef".casecmp("abcde")     #=> 1
"aBcDeF".casecmp("abcdef")    #=> 0
"abcdef".casecmp("abcdefg")   #=> -1
"abcdef".casecmp("ABCDEF")    #=> 0

static VALUE
rb_str_casecmp(VALUE str1, VALUE str2)
{
    long len;
    rb_encoding *enc;
    char *p1, *p1end, *p2, *p2end;

    StringValue(str2);
    enc = rb_enc_compatible(str1, str2);
    if (!enc) {
        return Qnil;
    }

    p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
    p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
    if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
        while (p1 < p1end && p2 < p2end) {
            if (*p1 != *p2) {
                unsigned int c1 = TOUPPER(*p1 & 0xff);
                unsigned int c2 = TOUPPER(*p2 & 0xff);
                if (c1 != c2)
                    return INT2FIX(c1 < c2 ? -1 : 1);
            }
            p1++;
            p2++;
        }
    }
    else {
        while (p1 < p1end && p2 < p2end) {
            int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
            int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);

            if (0 <= c1 && 0 <= c2) {
                c1 = TOUPPER(c1);
                c2 = TOUPPER(c2);
                if (c1 != c2)
                    return INT2FIX(c1 < c2 ? -1 : 1);
            }
            else {
                int r;
                l1 = rb_enc_mbclen(p1, p1end, enc);
                l2 = rb_enc_mbclen(p2, p2end, enc);
                len = l1 < l2 ? l1 : l2;
                r = memcmp(p1, p2, len);
                if (r != 0)
                    return INT2FIX(r < 0 ? -1 : 1);
                if (l1 != l2)
                    return INT2FIX(l1 < l2 ? -1 : 1);
            }
            p1 += l1;
            p2 += l2;
        }
    }
    if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
    if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
    return INT2FIX(-1);
}
center(width, padstr=' ') → new_str click to toggle source

Centers str in width. If width is greater than the length of str, returns a new String of length width with str centered and padded with padstr; otherwise, returns str.

"hello".center(4)         #=> "hello"
"hello".center(20)        #=> "       hello        "
"hello".center(20, '123') #=> "1231231hello12312312"

static VALUE
rb_str_center(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'c');
}
chars → an_array click to toggle source

Returns an array of characters in str. This is a shorthand for str.each_char.to_a.

If a block is given, which is a deprecated form, works the same as each_char.

static VALUE
rb_str_chars(VALUE str)
{
    return rb_str_enumerate_chars(str, 1);
}
chomp(separator=$/) → new_str click to toggle source

Returns a new String with the given record separator removed from the end of str (if present). If $/ has not been changed from the default Ruby record separator, then chomp also removes carriage return characters (that is it will remove \n, \r, and \r\n).

"hello".chomp            #=> "hello"
"hello\n".chomp          #=> "hello"
"hello\r\n".chomp        #=> "hello"
"hello\n\r".chomp        #=> "hello\n"
"hello\r".chomp          #=> "hello"
"hello \n there".chomp   #=> "hello \n there"
"hello".chomp("llo")     #=> "he"

static VALUE
rb_str_chomp(int argc, VALUE *argv, VALUE str)
{
    str = rb_str_dup(str);
    rb_str_chomp_bang(argc, argv, str);
    return str;
}
chomp!(separator=$/) → str or nil click to toggle source

Modifies str in place as described for String#chomp, returning str, or nil if no modifications were made.

static VALUE
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    VALUE rs;
    int newline;
    char *p, *pp, *e;
    long len, rslen;

    str_modify_keep_cr(str);
    len = RSTRING_LEN(str);
    if (len == 0) return Qnil;
    p = RSTRING_PTR(str);
    e = p + len;
    if (argc == 0) {
        rs = rb_rs;
        if (rs == rb_default_rs) {
          smart_chomp:
            enc = rb_enc_get(str);
            if (rb_enc_mbminlen(enc) > 1) {
                pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
                if (rb_enc_is_newline(pp, e, enc)) {
                    e = pp;
                }
                pp = e - rb_enc_mbminlen(enc);
                if (pp >= p) {
                    pp = rb_enc_left_char_head(p, pp, e, enc);
                    if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
                        e = pp;
                    }
                }
                if (e == RSTRING_END(str)) {
                    return Qnil;
                }
                len = e - RSTRING_PTR(str);
                STR_SET_LEN(str, len);
            }
            else {
                if (RSTRING_PTR(str)[len-1] == '\n') {
                    STR_DEC_LEN(str);
                    if (RSTRING_LEN(str) > 0 &&
                        RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\r') {
                        STR_DEC_LEN(str);
                    }
                }
                else if (RSTRING_PTR(str)[len-1] == '\r') {
                    STR_DEC_LEN(str);
                }
                else {
                    return Qnil;
                }
            }
            RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
            return str;
        }
    }
    else {
        rb_scan_args(argc, argv, "01", &rs);
    }
    if (NIL_P(rs)) return Qnil;
    StringValue(rs);
    rslen = RSTRING_LEN(rs);
    if (rslen == 0) {
        while (len>0 && p[len-1] == '\n') {
            len--;
            if (len>0 && p[len-1] == '\r')
                len--;
        }
        if (len < RSTRING_LEN(str)) {
            STR_SET_LEN(str, len);
            RSTRING_PTR(str)[len] = '\0';
            return str;
        }
        return Qnil;
    }
    if (rslen > len) return Qnil;
    newline = RSTRING_PTR(rs)[rslen-1];
    if (rslen == 1 && newline == '\n')
        goto smart_chomp;

    enc = rb_enc_check(str, rs);
    if (is_broken_string(rs)) {
        return Qnil;
    }
    pp = e - rslen;
    if (p[len-1] == newline &&
        (rslen <= 1 ||
         memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
        if (rb_enc_left_char_head(p, pp, e, enc) != pp)
            return Qnil;
        if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
            ENC_CODERANGE_CLEAR(str);
        }
        STR_SET_LEN(str, RSTRING_LEN(str) - rslen);
        RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
        return str;
    }
    return Qnil;
}
chop → new_str click to toggle source

Returns a new String with the last character removed. If the string ends with \r\n, both characters are removed. Applying chop to an empty string returns an empty string. String#chomp is often a safer alternative, as it leaves the string unchanged if it doesn't end in a record separator.

"string\r\n".chop   #=> "string"
"string\n\r".chop   #=> "string\n"
"string\n".chop     #=> "string"
"string".chop       #=> "strin"
"x".chop.chop       #=> ""

static VALUE
rb_str_chop(VALUE str)
{
    return rb_str_subseq(str, 0, chopped_length(str));
}
chop! → str or nil click to toggle source

Processes str as for String#chop, returning str, or nil if str is the empty string. See also String#chomp!.

static VALUE
rb_str_chop_bang(VALUE str)
{
    str_modify_keep_cr(str);
    if (RSTRING_LEN(str) > 0) {
        long len;
        len = chopped_length(str);
        STR_SET_LEN(str, len);
        RSTRING_PTR(str)[len] = '\0';
        if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
            ENC_CODERANGE_CLEAR(str);
        }
        return str;
    }
    return Qnil;
}
chr → string click to toggle source

Returns a one-character string at the beginning of the string.

a = "abcde"
a.chr    #=> "a"

static VALUE
rb_str_chr(VALUE str)
{
    return rb_str_substr(str, 0, 1);
}
clear → string click to toggle source

Makes string empty.

a = "abcde"
a.clear    #=> ""

static VALUE
rb_str_clear(VALUE str)
{
    str_discard(str);
    STR_SET_EMBED(str);
    STR_SET_EMBED_LEN(str, 0);
    RSTRING_PTR(str)[0] = 0;
    if (rb_enc_asciicompat(STR_ENC_GET(str)))
        ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
    else
        ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
    return str;
}
codepoints → an_array click to toggle source

Returns an array of the Integer ordinals of the characters in str. This is a shorthand for str.each_codepoint.to_a.

If a block is given, which is a deprecated form, works the same as each_codepoint.

static VALUE
rb_str_codepoints(VALUE str)
{
    return rb_str_enumerate_codepoints(str, 1);
}
str << integer → str click to toggle source
concat(integer) → str
str << obj → str
concat(obj) → str

Append—Concatenates the given object to str. If the object is a Integer, it is considered as a codepoint, and is converted to a character before concatenation.

a = "hello "
a << "world"   #=> "hello world"
a.concat(33)   #=> "hello world!"

VALUE
rb_str_concat(VALUE str1, VALUE str2)
{
    unsigned int code;
    rb_encoding *enc = STR_ENC_GET(str1);

    if (FIXNUM_P(str2) || RB_TYPE_P(str2, T_BIGNUM)) {
        if (rb_num_to_uint(str2, &code) == 0) {
        }
        else if (FIXNUM_P(str2)) {
            rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
        }
        else {
            rb_raise(rb_eRangeError, "bignum out of char range");
        }
    }
    else {
        return rb_str_append(str1, str2);
    }

    if (enc == rb_usascii_encoding()) {
        /* US-ASCII automatically extended to ASCII-8BIT */
        char buf[1];
        buf[0] = (char)code;
        if (code > 0xFF) {
            rb_raise(rb_eRangeError, "%u out of char range", code);
        }
        rb_str_cat(str1, buf, 1);
        if (code > 127) {
            rb_enc_associate(str1, rb_ascii8bit_encoding());
            ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
        }
    }
    else {
        long pos = RSTRING_LEN(str1);
        int cr = ENC_CODERANGE(str1);
        int len;
        char *buf;

        switch (len = rb_enc_codelen(code, enc)) {
          case ONIGERR_INVALID_CODE_POINT_VALUE:
            rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
            break;
          case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
          case 0:
            rb_raise(rb_eRangeError, "%u out of char range", code);
            break;
        }
        buf = ALLOCA_N(char, len + 1);
        rb_enc_mbcput(code, buf, enc);
        if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
            rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
        }
        rb_str_resize(str1, pos+len);
        memcpy(RSTRING_PTR(str1) + pos, buf, len);
        if (cr == ENC_CODERANGE_7BIT && code > 127)
            cr = ENC_CODERANGE_VALID;
        ENC_CODERANGE_SET(str1, cr);
    }
    return str1;
}
count([other_str]+) → fixnum click to toggle source

Each other_str parameter defines a set of characters to count. The intersection of these sets defines the characters to count in str. Any other_str that starts with a caret ^ is negated. The sequence c1-c2 means all characters between c1 and c2. The backslash character </code> can be used to escape <code>^ or - and is otherwise ignored unless it appears at the end of a sequence or the end of a other_str.

a = "hello world"
a.count "lo"                   #=> 5
a.count "lo", "o"              #=> 2
a.count "hello", "^l"          #=> 4
a.count "ej-m"                 #=> 4

"hello^world".count "\\^aeiou" #=> 4
"hello-world".count "a\\-eo"   #=> 4

c = "hello world\\r\\n"
c.count "\\"                   #=> 2
c.count "\\A"                  #=> 0
c.count "X-\\w"                #=> 3

static VALUE
rb_str_count(int argc, VALUE *argv, VALUE str)
{
    char table[TR_TABLE_SIZE];
    rb_encoding *enc = 0;
    VALUE del = 0, nodel = 0, tstr;
    char *s, *send;
    int i;
    int ascompat;

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);

    tstr = argv[0];
    StringValue(tstr);
    enc = rb_enc_check(str, tstr);
    if (argc == 1) {
        const char *ptstr;
        if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
            (ptstr = RSTRING_PTR(tstr),
             ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
            !is_broken_string(str)) {
            int n = 0;
            int clen;
            unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);

            s = RSTRING_PTR(str);
            if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
            send = RSTRING_END(str);
            while (s < send) {
                if (*(unsigned char*)s++ == c) n++;
            }
            return INT2NUM(n);
        }
    }

    tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
    for (i=1; i<argc; i++) {
        tstr = argv[i];
        StringValue(tstr);
        enc = rb_enc_check(str, tstr);
        tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
    }

    s = RSTRING_PTR(str);
    if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
    send = RSTRING_END(str);
    ascompat = rb_enc_asciicompat(enc);
    i = 0;
    while (s < send) {
        unsigned int c;

        if (ascompat && (c = *(unsigned char*)s) < 0x80) {
            if (table[c]) {
                i++;
            }
            s++;
        }
        else {
            int clen;
            c = rb_enc_codepoint_len(s, send, &clen, enc);
            if (tr_find(c, table, del, nodel)) {
                i++;
            }
            s += clen;
        }
    }

    return INT2NUM(i);
}
crypt(salt_str) → new_str click to toggle source

Applies a one-way cryptographic hash to str by invoking the standard library function crypt(3) with the given salt string. While the format and the result are system and implementation dependent, using a salt matching the regular expression \A[a-zA-Z0-9./]{2} should be valid and safe on any platform, in which only the first two characters are significant.

This method is for use in system specific scripts, so if you want a cross-platform hash function consider using Digest or OpenSSL instead.

static VALUE
rb_str_crypt(VALUE str, VALUE salt)
{
    extern char *crypt(const char *, const char *);
    VALUE result;
    const char *s, *saltp;
    char *res;
#ifdef BROKEN_CRYPT
    char salt_8bit_clean[3];
#endif

    StringValue(salt);
    if (RSTRING_LEN(salt) < 2)
        rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");

    s = RSTRING_PTR(str);
    if (!s) s = "";
    saltp = RSTRING_PTR(salt);
#ifdef BROKEN_CRYPT
    if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
        salt_8bit_clean[0] = saltp[0] & 0x7f;
        salt_8bit_clean[1] = saltp[1] & 0x7f;
        salt_8bit_clean[2] = '\0';
        saltp = salt_8bit_clean;
    }
#endif
    res = crypt(s, saltp);
    if (!res) {
        rb_sys_fail("crypt");
    }
    result = rb_str_new2(res);
    OBJ_INFECT(result, str);
    OBJ_INFECT(result, salt);
    return result;
}
delete([other_str]+) → new_str click to toggle source

Returns a copy of str with all characters in the intersection of its arguments deleted. Uses the same rules for building the set of characters as String#count.

"hello".delete "l","lo"        #=> "heo"
"hello".delete "lo"            #=> "he"
"hello".delete "aeiou", "^e"   #=> "hell"
"hello".delete "ej-m"          #=> "ho"

static VALUE
rb_str_delete(int argc, VALUE *argv, VALUE str)
{
    str = rb_str_dup(str);
    rb_str_delete_bang(argc, argv, str);
    return str;
}
delete!([other_str]+) → str or nil click to toggle source

Performs a delete operation in place, returning str, or nil if str was not modified.

static VALUE
rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
{
    char squeez[TR_TABLE_SIZE];
    rb_encoding *enc = 0;
    char *s, *send, *t;
    VALUE del = 0, nodel = 0;
    int modify = 0;
    int i, ascompat, cr;

    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    for (i=0; i<argc; i++) {
        VALUE s = argv[i];

        StringValue(s);
        enc = rb_enc_check(str, s);
        tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
    }

    str_modify_keep_cr(str);
    ascompat = rb_enc_asciicompat(enc);
    s = t = RSTRING_PTR(str);
    send = RSTRING_END(str);
    cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
    while (s < send) {
        unsigned int c;
        int clen;

        if (ascompat && (c = *(unsigned char*)s) < 0x80) {
            if (squeez[c]) {
                modify = 1;
            }
            else {
                if (t != s) *t = c;
                t++;
            }
            s++;
        }
        else {
            c = rb_enc_codepoint_len(s, send, &clen, enc);

            if (tr_find(c, squeez, del, nodel)) {
                modify = 1;
            }
            else {
                if (t != s) rb_enc_mbcput(c, t, enc);
                t += clen;
                if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID;
            }
            s += clen;
        }
    }
    *t = '\0';
    STR_SET_LEN(str, t - RSTRING_PTR(str));
    ENC_CODERANGE_SET(str, cr);

    if (modify) return str;
    return Qnil;
}
downcase → new_str click to toggle source

Returns a copy of str with all uppercase letters replaced with their lowercase counterparts. The operation is locale insensitive—only characters “A'' to “Z'' are affected. Note: case replacement is effective only in ASCII region.

"hEllO".downcase   #=> "hello"

static VALUE
rb_str_downcase(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_downcase_bang(str);
    return str;
}
downcase! → str or nil click to toggle source

Downcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.

static VALUE
rb_str_downcase_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *send;
    int modify = 0;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    rb_str_check_dummy_enc(enc);
    s = RSTRING_PTR(str); send = RSTRING_END(str);
    if (single_byte_optimizable(str)) {
        while (s < send) {
            unsigned int c = *(unsigned char*)s;

            if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
                *s = 'a' + (c - 'A');
                modify = 1;
            }
            s++;
        }
    }
    else {
        int ascompat = rb_enc_asciicompat(enc);

        while (s < send) {
            unsigned int c;
            int n;

            if (ascompat && (c = *(unsigned char*)s) < 0x80) {
                if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
                    *s = 'a' + (c - 'A');
                    modify = 1;
                }
                s++;
            }
            else {
                c = rb_enc_codepoint_len(s, send, &n, enc);
                if (rb_enc_isupper(c, enc)) {
                    /* assuming toupper returns codepoint with same size */
                    rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
                    modify = 1;
                }
                s += n;
            }
        }
    }

    if (modify) return str;
    return Qnil;
}
dump → new_str click to toggle source

Produces a version of str with all non-printing characters replaced by \nnn notation and all special characters escaped.

"hello \n ''".dump  #=> "\"hello \\n ''\"

VALUE
rb_str_dump(VALUE str)
{
    rb_encoding *enc = rb_enc_get(str);
    long len;
    const char *p, *pend;
    char *q, *qend;
    VALUE result;
    int u8 = (enc == rb_utf8_encoding());

    len = 2;                    /* "" */
    p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    while (p < pend) {
        unsigned char c = *p++;
        switch (c) {
          case '"':  case '\\':
          case '\n': case '\r':
          case '\t': case '\f':
          case '\013': case '\010': case '\007': case '\033':
            len += 2;
            break;

          case '#':
            len += IS_EVSTR(p, pend) ? 2 : 1;
            break;

          default:
            if (ISPRINT(c)) {
                len++;
            }
            else {
                if (u8) {     /* \u{NN} */
                    int n = rb_enc_precise_mbclen(p-1, pend, enc);
                    if (MBCLEN_CHARFOUND_P(n-1)) {
                        unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
                        while (cc >>= 4) len++;
                        len += 5;
                        p += MBCLEN_CHARFOUND_LEN(n)-1;
                        break;
                    }
                }
                len += 4;     /* \xNN */
            }
            break;
        }
    }
    if (!rb_enc_asciicompat(enc)) {
        len += 19;             /* ".force_encoding('')" */
        len += strlen(enc->name);
    }

    result = rb_str_new5(str, 0, len);
    p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    q = RSTRING_PTR(result); qend = q + len + 1;

    *q++ = '"';
    while (p < pend) {
        unsigned char c = *p++;

        if (c == '"' || c == '\\') {
            *q++ = '\\';
            *q++ = c;
        }
        else if (c == '#') {
            if (IS_EVSTR(p, pend)) *q++ = '\\';
            *q++ = '#';
        }
        else if (c == '\n') {
            *q++ = '\\';
            *q++ = 'n';
        }
        else if (c == '\r') {
            *q++ = '\\';
            *q++ = 'r';
        }
        else if (c == '\t') {
            *q++ = '\\';
            *q++ = 't';
        }
        else if (c == '\f') {
            *q++ = '\\';
            *q++ = 'f';
        }
        else if (c == '\013') {
            *q++ = '\\';
            *q++ = 'v';
        }
        else if (c == '\010') {
            *q++ = '\\';
            *q++ = 'b';
        }
        else if (c == '\007') {
            *q++ = '\\';
            *q++ = 'a';
        }
        else if (c == '\033') {
            *q++ = '\\';
            *q++ = 'e';
        }
        else if (ISPRINT(c)) {
            *q++ = c;
        }
        else {
            *q++ = '\\';
            if (u8) {
                int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
                if (MBCLEN_CHARFOUND_P(n)) {
                    int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
                    p += n;
                    snprintf(q, qend-q, "u{%x}", cc);
                    q += strlen(q);
                    continue;
                }
            }
            snprintf(q, qend-q, "x%02X", c);
            q += 3;
        }
    }
    *q++ = '"';
    *q = '\0';
    if (!rb_enc_asciicompat(enc)) {
        snprintf(q, qend-q, ".force_encoding(\"%s\")", enc->name);
        enc = rb_ascii8bit_encoding();
    }
    OBJ_INFECT(result, str);
    /* result from dump is ASCII */
    rb_enc_associate(result, enc);
    ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
    return result;
}
each_byte {|fixnum| block } → str click to toggle source
each_byte → an_enumerator

Passes each byte in str to the given block, or returns an enumerator if no block is given.

"hello".each_byte {|c| print c, ' ' }

produces:

104 101 108 108 111
static VALUE
rb_str_each_byte(VALUE str)
{
    return rb_str_enumerate_bytes(str, 0);
}
each_char {|cstr| block } → str click to toggle source
each_char → an_enumerator

Passes each character in str to the given block, or returns an enumerator if no block is given.

"hello".each_char {|c| print c, ' ' }

produces:

h e l l o
static VALUE
rb_str_each_char(VALUE str)
{
    return rb_str_enumerate_chars(str, 0);
}
each_codepoint {|integer| block } → str click to toggle source
each_codepoint → an_enumerator

Passes the Integer ordinal of each character in str, also known as a codepoint when applied to Unicode strings to the given block.

If no block is given, an enumerator is returned instead.

"hello\u0639".each_codepoint {|c| print c, ' ' }

produces:

104 101 108 108 111 1593
static VALUE
rb_str_each_codepoint(VALUE str)
{
    return rb_str_enumerate_codepoints(str, 0);
}
each_line(separator=$/) {|substr| block } → str click to toggle source
each_line(separator=$/) → an_enumerator

Splits str using the supplied parameter as the record separator ($/ by default), passing each substring in turn to the supplied block. If a zero-length record separator is supplied, the string is split into paragraphs delimited by multiple successive newlines.

If no block is given, an enumerator is returned instead.

print "Example one\n"
"hello\nworld".each_line {|s| p s}
print "Example two\n"
"hello\nworld".each_line('l') {|s| p s}
print "Example three\n"
"hello\n\n\nworld".each_line('') {|s| p s}

produces:

Example one
"hello\n"
"world"
Example two
"hel"
"l"
"o\nworl"
"d"
Example three
"hello\n\n\n"
"world"
static VALUE
rb_str_each_line(int argc, VALUE *argv, VALUE str)
{
    return rb_str_enumerate_lines(argc, argv, str, 0);
}
empty? → true or false click to toggle source

Returns true if str has a length of zero.

"hello".empty?   #=> false
" ".empty?       #=> false
"".empty?        #=> true

static VALUE
rb_str_empty(VALUE str)
{
    if (RSTRING_LEN(str) == 0)
        return Qtrue;
    return Qfalse;
}
encode(encoding [, options] ) → str click to toggle source
encode(dst_encoding, src_encoding [, options] ) → str
encode([options]) → str

The first form returns a copy of str transcoded to encoding encoding. The second form returns a copy of str transcoded from src_encoding to dst_encoding. The last form returns a copy of str transcoded to Encoding.default_internal.

By default, the first and second form raise Encoding::UndefinedConversionError for characters that are undefined in the destination encoding, and Encoding::InvalidByteSequenceError for invalid byte sequences in the source encoding. The last form by default does not raise exceptions but uses replacement strings.

Please note that conversion from an encoding enc to the same encoding enc is a no-op, i.e. the receiver is returned without any changes, and no exceptions are raised, even if there are invalid bytes.

The options Hash gives details for conversion and can have the following keys:

:invalid

If the value is :replace, encode replaces invalid byte sequences in str with the replacement character. The default is to raise the Encoding::InvalidByteSequenceError exception

:undef

If the value is :replace, encode replaces characters which are undefined in the destination encoding with the replacement character. The default is to raise the Encoding::UndefinedConversionError.

:replace

Sets the replacement string to the given value. The default replacement string is “uFFFD” for Unicode encoding forms, and “?” otherwise.

:fallback

Sets the replacement string by the given object for undefined character. The object should be a Hash, a Proc, a Method, or an object which has [] method. Its key is an undefined character encoded in the source encoding of current transcoder. Its value can be any encoding until it can be converted into the destination encoding of the transcoder.

:xml

The value must be :text or :attr. If the value is :text encode replaces undefined characters with their (upper-case hexadecimal) numeric character references. '&', '<', and '>' are converted to “&amp;”, “&lt;”, and “&gt;”, respectively. If the value is :attr, encode also quotes the replacement result (using '“'), and replaces '”' with “&quot;”.

:cr_newline

Replaces LF (“n”) with CR (“r”) if value is true.

:crlf_newline

Replaces LF (“n”) with CRLF (“rn”) if value is true.

:universal_newline

Replaces CRLF (“rn”) and CR (“r”) with LF (“n”) if value is true.

static VALUE
str_encode(int argc, VALUE *argv, VALUE str)
{
    VALUE newstr = str;
    int encidx = str_transcode(argc, argv, &newstr);
    return encoded_dup(newstr, str, encidx);
}
encode!(encoding [, options] ) → str click to toggle source
encode!(dst_encoding, src_encoding [, options] ) → str

The first form transcodes the contents of str from str.encoding to encoding. The second form transcodes the contents of str from src_encoding to dst_encoding. The options Hash gives details for conversion. See #encode for details. Returns the string even if no changes were made.

static VALUE
str_encode_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE newstr;
    int encidx;

    rb_check_frozen(str);

    newstr = str;
    encidx = str_transcode(argc, argv, &newstr);

    if (encidx < 0) return str;
    if (newstr == str) {
        rb_enc_associate_index(str, encidx);
        return str;
    }
    rb_str_shared_replace(str, newstr);
    return str_encode_associate(str, encidx);
}
encoding → encoding click to toggle source

Returns the Encoding object that represents the encoding of obj.

VALUE
rb_obj_encoding(VALUE obj)
{
    int idx = rb_enc_get_index(obj);
    if (idx < 0) {
    rb_raise(rb_eTypeError, "unknown encoding");
    }
    return rb_enc_from_encoding_index(idx);
}
end_with?([suffixes]+) → true or false click to toggle source

Returns true if str ends with one of the suffixes given.

static VALUE
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
    int i;
    char *p, *s, *e;
    rb_encoding *enc;

    for (i=0; i<argc; i++) {
        VALUE tmp = argv[i];
        StringValue(tmp);
        enc = rb_enc_check(str, tmp);
        if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
        p = RSTRING_PTR(str);
        e = p + RSTRING_LEN(str);
        s = e - RSTRING_LEN(tmp);
        if (rb_enc_left_char_head(p, s, e, enc) != s)
            continue;
        if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
            return Qtrue;
    }
    return Qfalse;
}
eql?(other) → true or false click to toggle source

Two strings are equal if they have the same length and content.

static VALUE
rb_str_eql(VALUE str1, VALUE str2)
{
    if (str1 == str2) return Qtrue;
    if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
    return str_eql(str1, str2);
}
force_encoding(encoding) → str click to toggle source

Changes the encoding to encoding and returns self.

static VALUE
rb_str_force_encoding(VALUE str, VALUE enc)
{
    str_modifiable(str);
    rb_enc_associate(str, rb_to_encoding(enc));
    ENC_CODERANGE_CLEAR(str);
    return str;
}
getbyte(index) → 0 .. 255 click to toggle source

returns the indexth byte as an integer.

static VALUE
rb_str_getbyte(VALUE str, VALUE index)
{
    long pos = NUM2LONG(index);

    if (pos < 0)
        pos += RSTRING_LEN(str);
    if (pos < 0 ||  RSTRING_LEN(str) <= pos)
        return Qnil;

    return INT2FIX((unsigned char)RSTRING_PTR(str)[pos]);
}
gsub(pattern, replacement) → new_str click to toggle source
gsub(pattern, hash) → new_str
gsub(pattern) {|match| block } → new_str
gsub(pattern) → enumerator

Returns a copy of str with the all occurrences of pattern substituted for the second argument. The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\\d' will match a backlash followed by 'd', instead of a digit.

If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern's capture groups of the form \\d, where d is a group number, or \\k<n>, where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash. However, within replacement the special match variables, such as $&, will not refer to the current match.

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $' will be set appropriately. The value returned by the block will be substituted for the match on each call.

The result inherits any tainting in the original string or any supplied replacement string.

When neither a block nor a second argument is supplied, an Enumerator is returned.

"hello".gsub(/[aeiou]/, '*')                  #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>')             #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '}      #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}')  #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"

static VALUE
rb_str_gsub(int argc, VALUE *argv, VALUE str)
{
    return str_gsub(argc, argv, str, 0);
}
gsub!(pattern, replacement) → str or nil click to toggle source
gsub!(pattern) {|match| block } → str or nil
gsub!(pattern) → an_enumerator

Performs the substitutions of String#gsub in place, returning str, or nil if no substitutions were performed. If no block and no replacement is given, an enumerator is returned instead.

static VALUE
rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
{
    str_modify_keep_cr(str);
    return str_gsub(argc, argv, str, 1);
}
hash → fixnum click to toggle source

Return a hash based on the string's length and content.

static VALUE
rb_str_hash_m(VALUE str)
{
    st_index_t hval = rb_str_hash(str);
    return INT2FIX(hval);
}
hex → integer click to toggle source

Treats leading characters from str as a string of hexadecimal digits (with an optional sign and an optional 0x) and returns the corresponding number. Zero is returned on error.

"0x0a".hex     #=> 10
"-1234".hex    #=> -4660
"0".hex        #=> 0
"wombat".hex   #=> 0

static VALUE
rb_str_hex(VALUE str)
{
    return rb_str_to_inum(str, 16, FALSE);
}
include? other_str → true or false click to toggle source

Returns true if str contains the given string or character.

"hello".include? "lo"   #=> true
"hello".include? "ol"   #=> false
"hello".include? h     #=> true

static VALUE
rb_str_include(VALUE str, VALUE arg)
{
    long i;

    StringValue(arg);
    i = rb_str_index(str, arg, 0);

    if (i == -1) return Qfalse;
    return Qtrue;
}
index(substring [, offset]) → fixnum or nil click to toggle source
index(regexp [, offset]) → fixnum or nil

Returns the index of the first occurrence of the given substring or pattern (regexp) in str. Returns nil if not found. If the second parameter is present, it specifies the position in the string to begin the search.

"hello".index('e')             #=> 1
"hello".index('lo')            #=> 3
"hello".index('a')             #=> nil
"hello".index(e)              #=> 1
"hello".index(/[aeiou]/, -3)   #=> 4

static VALUE
rb_str_index_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE initpos;
    long pos;

    if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
        pos = NUM2LONG(initpos);
    }
    else {
        pos = 0;
    }
    if (pos < 0) {
        pos += str_strlen(str, STR_ENC_GET(str));
        if (pos < 0) {
            if (RB_TYPE_P(sub, T_REGEXP)) {
                rb_backref_set(Qnil);
            }
            return Qnil;
        }
    }

    if (SPECIAL_CONST_P(sub)) goto generic;
    switch (BUILTIN_TYPE(sub)) {
      case T_REGEXP:
        if (pos > str_strlen(str, STR_ENC_GET(str)))
            return Qnil;
        pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
                         rb_enc_check(str, sub), single_byte_optimizable(str));

        pos = rb_reg_search(sub, str, pos, 0);
        pos = rb_str_sublen(str, pos);
        break;

      generic:
      default: {
        VALUE tmp;

        tmp = rb_check_string_type(sub);
        if (NIL_P(tmp)) {
            rb_raise(rb_eTypeError, "type mismatch: %s given",
                     rb_obj_classname(sub));
        }
        sub = tmp;
      }
        /* fall through */
      case T_STRING:
        pos = rb_str_index(str, sub, pos);
        pos = rb_str_sublen(str, pos);
        break;
    }

    if (pos == -1) return Qnil;
    return LONG2NUM(pos);
}
replace(other_str) → str click to toggle source

Replaces the contents and taintedness of str with the corresponding values in other_str.

s = "hello"         #=> "hello"
s.replace "world"   #=> "world"

VALUE
rb_str_replace(VALUE str, VALUE str2)
{
    str_modifiable(str);
    if (str == str2) return str;

    StringValue(str2);
    str_discard(str);
    return str_replace(str, str2);
}
insert(index, other_str) → str click to toggle source

Inserts other_str before the character at the given index, modifying str. Negative indices count from the end of the string, and insert after the given character. The intent is insert aString so that it starts at the given index.

"abcd".insert(0, 'X')    #=> "Xabcd"
"abcd".insert(3, 'X')    #=> "abcXd"
"abcd".insert(4, 'X')    #=> "abcdX"
"abcd".insert(-3, 'X')   #=> "abXcd"
"abcd".insert(-1, 'X')   #=> "abcdX"

static VALUE
rb_str_insert(VALUE str, VALUE idx, VALUE str2)
{
    long pos = NUM2LONG(idx);

    if (pos == -1) {
        return rb_str_append(str, str2);
    }
    else if (pos < 0) {
        pos++;
    }
    rb_str_splice(str, pos, 0, str2);
    return str;
}
inspect → string click to toggle source

Returns a printable version of str, surrounded by quote marks, with special characters escaped.

str = "hello"
str[3] = "\b"
str.inspect       #=> "\"hel\\bo\""

VALUE
rb_str_inspect(VALUE str)
{
    rb_encoding *enc = STR_ENC_GET(str);
    const char *p, *pend, *prev;
    char buf[CHAR_ESC_LEN + 1];
    VALUE result = rb_str_buf_new(0);
    rb_encoding *resenc = rb_default_internal_encoding();
    int unicode_p = rb_enc_unicode_p(enc);
    int asciicompat = rb_enc_asciicompat(enc);
    static rb_encoding *utf16, *utf32;

    if (!utf16) utf16 = rb_enc_find("UTF-16");
    if (!utf32) utf32 = rb_enc_find("UTF-32");
    if (resenc == NULL) resenc = rb_default_external_encoding();
    if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
    rb_enc_associate(result, resenc);
    str_buf_cat2(result, "\"");

    p = RSTRING_PTR(str); pend = RSTRING_END(str);
    prev = p;
    if (enc == utf16) {
        const unsigned char *q = (const unsigned char *)p;
        if (q[0] == 0xFE && q[1] == 0xFF)
            enc = rb_enc_find("UTF-16BE");
        else if (q[0] == 0xFF && q[1] == 0xFE)
            enc = rb_enc_find("UTF-16LE");
        else
            unicode_p = 0;
    }
    else if (enc == utf32) {
        const unsigned char *q = (const unsigned char *)p;
        if (q[0] == 0 && q[1] == 0 && q[2] == 0xFE && q[3] == 0xFF)
            enc = rb_enc_find("UTF-32BE");
        else if (q[3] == 0 && q[2] == 0 && q[1] == 0xFE && q[0] == 0xFF)
            enc = rb_enc_find("UTF-32LE");
        else
            unicode_p = 0;
    }
    while (p < pend) {
        unsigned int c, cc;
        int n;

        n = rb_enc_precise_mbclen(p, pend, enc);
        if (!MBCLEN_CHARFOUND_P(n)) {
            if (p > prev) str_buf_cat(result, prev, p - prev);
            n = rb_enc_mbminlen(enc);
            if (pend < p + n)
                n = (int)(pend - p);
            while (n--) {
                snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377);
                str_buf_cat(result, buf, strlen(buf));
                prev = ++p;
            }
            continue;
        }
        n = MBCLEN_CHARFOUND_LEN(n);
        c = rb_enc_mbc_to_codepoint(p, pend, enc);
        p += n;
        if ((asciicompat || unicode_p) &&
          (c == '"'|| c == '\\' ||
            (c == '#' &&
             p < pend &&
             MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
             (cc = rb_enc_codepoint(p,pend,enc),
              (cc == '$' || cc == '@' || cc == '{'))))) {
            if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
            str_buf_cat2(result, "\\");
            if (asciicompat || enc == resenc) {
                prev = p - n;
                continue;
            }
        }
        switch (c) {
          case '\n': cc = 'n'; break;
          case '\r': cc = 'r'; break;
          case '\t': cc = 't'; break;
          case '\f': cc = 'f'; break;
          case '\013': cc = 'v'; break;
          case '\010': cc = 'b'; break;
          case '\007': cc = 'a'; break;
          case 033: cc = 'e'; break;
          default: cc = 0; break;
        }
        if (cc) {
            if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
            buf[0] = '\\';
            buf[1] = (char)cc;
            str_buf_cat(result, buf, 2);
            prev = p;
            continue;
        }
        if ((enc == resenc && rb_enc_isprint(c, enc)) ||
            (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
            continue;
        }
        else {
            if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
            rb_str_buf_cat_escaped_char(result, c, unicode_p);
            prev = p;
            continue;
        }
    }
    if (p > prev) str_buf_cat(result, prev, p - prev);
    str_buf_cat2(result, "\"");

    OBJ_INFECT(result, str);
    return result;
}
intern → symbol click to toggle source
to_sym → symbol

Returns the Symbol corresponding to str, creating the symbol if it did not previously exist. See Symbol#id2name.

"Koala".intern         #=> :Koala
s = 'cat'.to_sym       #=> :cat
s == :cat              #=> true
s = '@cat'.to_sym      #=> :@cat
s == :@cat             #=> true

This can also be used to create symbols that cannot be represented using the :xxx notation.

'cat and dog'.to_sym   #=> :"cat and dog"

VALUE
rb_str_intern(VALUE s)
{
    VALUE str = RB_GC_GUARD(s);
    ID id;

    id = rb_intern_str(str);
    return ID2SYM(id);
}
length → integer click to toggle source
size → integer

Returns the character length of str.

VALUE
rb_str_length(VALUE str)
{
    long len;

    len = str_strlen(str, STR_ENC_GET(str));
    return LONG2NUM(len);
}
lines(separator=$/) → an_array click to toggle source

Returns an array of lines in str split using the supplied record separator ($/ by default). This is a shorthand for str.each_line(separator).to_a.

If a block is given, which is a deprecated form, works the same as each_line.

static VALUE
rb_str_lines(int argc, VALUE *argv, VALUE str)
{
    return rb_str_enumerate_lines(argc, argv, str, 1);
}
ljust(integer, padstr=' ') → new_str click to toggle source

If integer is greater than the length of str, returns a new String of length integer with str left justified and padded with padstr; otherwise, returns str.

"hello".ljust(4)            #=> "hello"
"hello".ljust(20)           #=> "hello               "
"hello".ljust(20, '1234')   #=> "hello123412341234123"

static VALUE
rb_str_ljust(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'l');
}
lstrip → new_str click to toggle source

Returns a copy of str with leading whitespace removed. See also String#rstrip and String#strip.

"  hello  ".lstrip   #=> "hello  "
"hello".lstrip       #=> "hello"

static VALUE
rb_str_lstrip(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_lstrip_bang(str);
    return str;
}
lstrip! → self or nil click to toggle source

Removes leading whitespace from str, returning nil if no change was made. See also String#rstrip! and String#strip!.

"  hello  ".lstrip   #=> "hello  "
"hello".lstrip!      #=> nil

static VALUE
rb_str_lstrip_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *t, *e;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    s = RSTRING_PTR(str);
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
    e = t = RSTRING_END(str);
    /* remove spaces at head */
    while (s < e) {
        int n;
        unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);

        if (!rb_isspace(cc)) break;
        s += n;
    }

    if (s > RSTRING_PTR(str)) {
        STR_SET_LEN(str, t-s);
        memmove(RSTRING_PTR(str), s, RSTRING_LEN(str));
        RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
        return str;
    }
    return Qnil;
}
match(pattern) → matchdata or nil click to toggle source
match(pattern, pos) → matchdata or nil

Converts pattern to a Regexp (if it isn't already one), then invokes its match method on str. If the second parameter is present, it specifies the position in the string to begin the search.

'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
'hello'.match('(.)\1')[0]   #=> "ll"
'hello'.match(/(.)\1/)[0]   #=> "ll"
'hello'.match('xx')         #=> nil

If a block is given, invoke the block with MatchData if match succeed, so that you can write

str.match(pat) {|m| ...}

instead of

if m = str.match(pat)
  ...
end

The return value is a value from block execution in this case.

static VALUE
rb_str_match_m(int argc, VALUE *argv, VALUE str)
{
    VALUE re, result;
    if (argc < 1)
        rb_check_arity(argc, 1, 2);
    re = argv[0];
    argv[0] = str;
    result = rb_funcall2(get_pat(re, 0), rb_intern("match"), argc, argv);
    if (!NIL_P(result) && rb_block_given_p()) {
        return rb_yield(result);
    }
    return result;
}
succ → new_str click to toggle source
next → new_str

Returns the successor to str. The successor is calculated by incrementing characters starting from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the string. Incrementing a digit always results in another digit, and incrementing a letter results in another letter of the same case. Incrementing nonalphanumerics uses the underlying character set's collating sequence.

If the increment generates a “carry,'' the character to the left of it is incremented. This process repeats until there is no carry, adding an additional character if necessary.

"abcd".succ        #=> "abce"
"THX1138".succ     #=> "THX1139"
"<<koala>>".succ   #=> "<<koalb>>"
"1999zzz".succ     #=> "2000aaa"
"ZZZ9999".succ     #=> "AAAA0000"
"***".succ         #=> "**+"

VALUE
rb_str_succ(VALUE orig)
{
    rb_encoding *enc;
    VALUE str;
    char *sbeg, *s, *e, *last_alnum = 0;
    int c = -1;
    long l;
    char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
    long carry_pos = 0, carry_len = 1;
    enum neighbor_char neighbor = NEIGHBOR_FOUND;

    str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
    rb_enc_cr_str_copy_for_substr(str, orig);
    OBJ_INFECT(str, orig);
    if (RSTRING_LEN(str) == 0) return str;

    enc = STR_ENC_GET(orig);
    sbeg = RSTRING_PTR(str);
    s = e = sbeg + RSTRING_LEN(str);

    while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
        if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
            if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
                ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
                s = last_alnum;
                break;
            }
        }
        if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
        neighbor = enc_succ_alnum_char(s, l, enc, carry);
        switch (neighbor) {
          case NEIGHBOR_NOT_CHAR:
            continue;
          case NEIGHBOR_FOUND:
            return str;
          case NEIGHBOR_WRAPPED:
            last_alnum = s;
            break;
        }
        c = 1;
        carry_pos = s - sbeg;
        carry_len = l;
    }
    if (c == -1) {              /* str contains no alnum */
        s = e;
        while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
            enum neighbor_char neighbor;
            if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
            neighbor = enc_succ_char(s, l, enc);
            if (neighbor == NEIGHBOR_FOUND)
                return str;
            if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
                /* wrapped to \0...\0.  search next valid char. */
                enc_succ_char(s, l, enc);
            }
            if (!rb_enc_asciicompat(enc)) {
                MEMCPY(carry, s, char, l);
                carry_len = l;
            }
            carry_pos = s - sbeg;
        }
    }
    RESIZE_CAPA(str, RSTRING_LEN(str) + carry_len);
    s = RSTRING_PTR(str) + carry_pos;
    memmove(s + carry_len, s, RSTRING_LEN(str) - carry_pos);
    memmove(s, carry, carry_len);
    STR_SET_LEN(str, RSTRING_LEN(str) + carry_len);
    RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
    rb_enc_str_coderange(str);
    return str;
}
succ! → str click to toggle source
next! → str

Equivalent to String#succ, but modifies the receiver in place.

static VALUE
rb_str_succ_bang(VALUE str)
{
    rb_str_shared_replace(str, rb_str_succ(str));

    return str;
}
oct → integer click to toggle source

Treats leading characters of str as a string of octal digits (with an optional sign) and returns the corresponding number. Returns 0 if the conversion fails.

"123".oct       #=> 83
"-377".oct      #=> -255
"bad".oct       #=> 0
"0377bad".oct   #=> 255

static VALUE
rb_str_oct(VALUE str)
{
    return rb_str_to_inum(str, -8, FALSE);
}
ord → integer click to toggle source

Return the Integer ordinal of a one-character string.

"a".ord         #=> 97

VALUE
rb_str_ord(VALUE s)
{
    unsigned int c;

    c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
    return UINT2NUM(c);
}
partition(sep) → [head, sep, tail] click to toggle source
partition(regexp) → [head, match, tail]

Searches sep or pattern (regexp) in the string and returns the part before it, the match, and the part after it. If it is not found, returns two empty strings and str.

"hello".partition("l")         #=> ["he", "l", "lo"]
"hello".partition("x")         #=> ["hello", "", ""]
"hello".partition(/.l/)        #=> ["h", "el", "lo"]

static VALUE
rb_str_partition(VALUE str, VALUE sep)
{
    long pos;
    int regex = FALSE;

    if (RB_TYPE_P(sep, T_REGEXP)) {
        pos = rb_reg_search(sep, str, 0, 0);
        regex = TRUE;
    }
    else {
        VALUE tmp;

        tmp = rb_check_string_type(sep);
        if (NIL_P(tmp)) {
            rb_raise(rb_eTypeError, "type mismatch: %s given",
                     rb_obj_classname(sep));
        }
        sep = tmp;
        pos = rb_str_index(str, sep, 0);
    }
    if (pos < 0) {
      failed:
        return rb_ary_new3(3, str, str_new_empty(str), str_new_empty(str));
    }
    if (regex) {
        sep = rb_str_subpat(str, sep, INT2FIX(0));
        if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
    }
    return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
                          sep,
                          rb_str_subseq(str, pos+RSTRING_LEN(sep),
                                             RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
}
prepend(other_str) → str click to toggle source

Prepend—Prepend the given string to str.

a = "world"
a.prepend("hello ") #=> "hello world"
a                   #=> "hello world"

static VALUE
rb_str_prepend(VALUE str, VALUE str2)
{
    StringValue(str2);
    StringValue(str);
    rb_str_update(str, 0L, 0L, str2);
    return str;
}
replace(other_str) → str click to toggle source

Replaces the contents and taintedness of str with the corresponding values in other_str.

s = "hello"         #=> "hello"
s.replace "world"   #=> "world"

VALUE
rb_str_replace(VALUE str, VALUE str2)
{
    str_modifiable(str);
    if (str == str2) return str;

    StringValue(str2);
    str_discard(str);
    return str_replace(str, str2);
}
reverse → new_str click to toggle source

Returns a new string with the characters from str in reverse order.

"stressed".reverse   #=> "desserts"

static VALUE
rb_str_reverse(VALUE str)
{
    rb_encoding *enc;
    VALUE rev;
    char *s, *e, *p;
    int single = 1;

    if (RSTRING_LEN(str) <= 1) return rb_str_dup(str);
    enc = STR_ENC_GET(str);
    rev = rb_str_new5(str, 0, RSTRING_LEN(str));
    s = RSTRING_PTR(str); e = RSTRING_END(str);
    p = RSTRING_END(rev);

    if (RSTRING_LEN(str) > 1) {
        if (single_byte_optimizable(str)) {
            while (s < e) {
                *--p = *s++;
            }
        }
        else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID) {
            while (s < e) {
                int clen = rb_enc_fast_mbclen(s, e, enc);

                if (clen > 1 || (*s & 0x80)) single = 0;
                p -= clen;
                memcpy(p, s, clen);
                s += clen;
            }
        }
        else {
            while (s < e) {
                int clen = rb_enc_mbclen(s, e, enc);

                if (clen > 1 || (*s & 0x80)) single = 0;
                p -= clen;
                memcpy(p, s, clen);
                s += clen;
            }
        }
    }
    STR_SET_LEN(rev, RSTRING_LEN(str));
    OBJ_INFECT(rev, str);
    if (ENC_CODERANGE(str) == ENC_CODERANGE_UNKNOWN) {
        if (single) {
            ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
        }
        else {
            ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
        }
    }
    rb_enc_cr_str_copy_for_substr(rev, str);

    return rev;
}
reverse! → str click to toggle source

Reverses str in place.

static VALUE
rb_str_reverse_bang(VALUE str)
{
    if (RSTRING_LEN(str) > 1) {
        if (single_byte_optimizable(str)) {
            char *s, *e, c;

            str_modify_keep_cr(str);
            s = RSTRING_PTR(str);
            e = RSTRING_END(str) - 1;
            while (s < e) {
                c = *s;
                *s++ = *e;
                *e-- = c;
            }
        }
        else {
            rb_str_shared_replace(str, rb_str_reverse(str));
        }
    }
    else {
        str_modify_keep_cr(str);
    }
    return str;
}
rindex(substring [, fixnum]) → fixnum or nil click to toggle source
rindex(regexp [, fixnum]) → fixnum or nil

Returns the index of the last occurrence of the given substring or pattern (regexp) in str. Returns nil if not found. If the second parameter is present, it specifies the position in the string to end the search—characters beyond this point will not be considered.

"hello".rindex('e')             #=> 1
"hello".rindex('l')             #=> 3
"hello".rindex('a')             #=> nil
"hello".rindex(e)              #=> 1
"hello".rindex(/[aeiou]/, -2)   #=> 1

static VALUE
rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
{
    VALUE sub;
    VALUE vpos;
    rb_encoding *enc = STR_ENC_GET(str);
    long pos, len = str_strlen(str, enc);

    if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
        pos = NUM2LONG(vpos);
        if (pos < 0) {
            pos += len;
            if (pos < 0) {
                if (RB_TYPE_P(sub, T_REGEXP)) {
                    rb_backref_set(Qnil);
                }
                return Qnil;
            }
        }
        if (pos > len) pos = len;
    }
    else {
        pos = len;
    }

    if (SPECIAL_CONST_P(sub)) goto generic;
    switch (BUILTIN_TYPE(sub)) {
      case T_REGEXP:
        /* enc = rb_get_check(str, sub); */
        pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
                         STR_ENC_GET(str), single_byte_optimizable(str));

        if (!RREGEXP(sub)->ptr || RREGEXP_SRC_LEN(sub)) {
            pos = rb_reg_search(sub, str, pos, 1);
            pos = rb_str_sublen(str, pos);
        }
        if (pos >= 0) return LONG2NUM(pos);
        break;

      generic:
      default: {
        VALUE tmp;

        tmp = rb_check_string_type(sub);
        if (NIL_P(tmp)) {
            rb_raise(rb_eTypeError, "type mismatch: %s given",
                     rb_obj_classname(sub));
        }
        sub = tmp;
      }
        /* fall through */
      case T_STRING:
        pos = rb_str_rindex(str, sub, pos);
        if (pos >= 0) return LONG2NUM(pos);
        break;
    }
    return Qnil;
}
rjust(integer, padstr=' ') → new_str click to toggle source

If integer is greater than the length of str, returns a new String of length integer with str right justified and padded with padstr; otherwise, returns str.

"hello".rjust(4)            #=> "hello"
"hello".rjust(20)           #=> "               hello"
"hello".rjust(20, '1234')   #=> "123412341234123hello"

static VALUE
rb_str_rjust(int argc, VALUE *argv, VALUE str)
{
    return rb_str_justify(argc, argv, str, 'r');
}
rpartition(sep) → [head, sep, tail] click to toggle source
rpartition(regexp) → [head, match, tail]

Searches sep or pattern (regexp) in the string from the end of the string, and returns the part before it, the match, and the part after it. If it is not found, returns two empty strings and str.

"hello".rpartition("l")         #=> ["hel", "l", "o"]
"hello".rpartition("x")         #=> ["", "", "hello"]
"hello".rpartition(/.l/)        #=> ["he", "ll", "o"]

static VALUE
rb_str_rpartition(VALUE str, VALUE sep)
{
    long pos = RSTRING_LEN(str);
    int regex = FALSE;

    if (RB_TYPE_P(sep, T_REGEXP)) {
        pos = rb_reg_search(sep, str, pos, 1);
        regex = TRUE;
    }
    else {
        VALUE tmp;

        tmp = rb_check_string_type(sep);
        if (NIL_P(tmp)) {
            rb_raise(rb_eTypeError, "type mismatch: %s given",
                     rb_obj_classname(sep));
        }
        sep = tmp;
        pos = rb_str_sublen(str, pos);
        pos = rb_str_rindex(str, sep, pos);
    }
    if (pos < 0) {
        return rb_ary_new3(3, str_new_empty(str), str_new_empty(str), str);
    }
    if (regex) {
        sep = rb_reg_nth_match(0, rb_backref_get());
    }
    return rb_ary_new3(3, rb_str_substr(str, 0, pos),
                          sep,
                          rb_str_substr(str,pos+str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
}
rstrip → new_str click to toggle source

Returns a copy of str with trailing whitespace removed. See also String#lstrip and String#strip.

"  hello  ".rstrip   #=> "  hello"
"hello".rstrip       #=> "hello"

static VALUE
rb_str_rstrip(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_rstrip_bang(str);
    return str;
}
rstrip! → self or nil click to toggle source

Removes trailing whitespace from str, returning nil if no change was made. See also String#lstrip! and String#strip!.

"  hello  ".rstrip   #=> "  hello"
"hello".rstrip!      #=> nil

static VALUE
rb_str_rstrip_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *t, *e;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    rb_str_check_dummy_enc(enc);
    s = RSTRING_PTR(str);
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
    t = e = RSTRING_END(str);

    /* remove trailing spaces or '\0's */
    if (single_byte_optimizable(str)) {
        unsigned char c;
        while (s < t && ((c = *(t-1)) == '\0' || ascii_isspace(c))) t--;
    }
    else {
        char *tp;

        while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
            unsigned int c = rb_enc_codepoint(tp, e, enc);
            if (c && !rb_isspace(c)) break;
            t = tp;
        }
    }
    if (t < e) {
        long len = t-RSTRING_PTR(str);

        STR_SET_LEN(str, len);
        RSTRING_PTR(str)[len] = '\0';
        return str;
    }
    return Qnil;
}
scan(pattern) → array click to toggle source
scan(pattern) {|match, ...| block } → str

Both forms iterate through str, matching the pattern (which may be a Regexp or a String). For each match, a result is generated and either added to the result array or passed to the block. If the pattern contains no groups, each individual result consists of the matched string, $&. If the pattern contains groups, each individual result is itself an array containing one entry per group.

a = "cruel world"
a.scan(/\w+/)        #=> ["cruel", "world"]
a.scan(/.../)        #=> ["cru", "el ", "wor"]
a.scan(/(...)/)      #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/)   #=> [["cr", "ue"], ["l ", "wo"]]

And the block form:

a.scan(/\w+/) {|w| print "<<#{w}>> " }
print "\n"
a.scan(/(.)(.)/) {|x,y| print y, x }
print "\n"

produces:

<<cruel>> <<world>>
rceu lowlr
static VALUE
rb_str_scan(VALUE str, VALUE pat)
{
    VALUE result;
    long start = 0;
    long last = -1, prev = 0;
    char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);

    pat = get_pat(pat, 1);
    if (!rb_block_given_p()) {
        VALUE ary = rb_ary_new();

        while (!NIL_P(result = scan_once(str, pat, &start))) {
            last = prev;
            prev = start;
            rb_ary_push(ary, result);
        }
        if (last >= 0) rb_reg_search(pat, str, last, 0);
        return ary;
    }

    while (!NIL_P(result = scan_once(str, pat, &start))) {
        last = prev;
        prev = start;
        rb_yield(result);
        str_mod_check(str, p, len);
    }
    if (last >= 0) rb_reg_search(pat, str, last, 0);
    return str;
}
setbyte(index, integer) → integer click to toggle source

modifies the indexth byte as integer.

static VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
{
    long pos = NUM2LONG(index);
    int byte = NUM2INT(value);

    rb_str_modify(str);

    if (pos < -RSTRING_LEN(str) || RSTRING_LEN(str) <= pos)
        rb_raise(rb_eIndexError, "index %ld out of string", pos);
    if (pos < 0)
        pos += RSTRING_LEN(str);

    RSTRING_PTR(str)[pos] = byte;

    return value;
}
length → integer click to toggle source
size → integer

Returns the character length of str.

VALUE
rb_str_length(VALUE str)
{
    long len;

    len = str_strlen(str, STR_ENC_GET(str));
    return LONG2NUM(len);
}
str[index] → new_str or nil click to toggle source
str[start, length] → new_str or nil
str[range] → new_str or nil
str[regexp] → new_str or nil
str[regexp, capture] → new_str or nil
str[match_str] → new_str or nil
slice(index) → new_str or nil
slice(start, length) → new_str or nil
slice(range) → new_str or nil
slice(regexp) → new_str or nil
slice(regexp, capture) → new_str or nil
slice(match_str) → new_str or nil

Element Reference — If passed a single index, returns a substring of one character at that index. If passed a start index and a length, returns a substring containing length characters starting at the index. If passed a range, its beginning and end are interpreted as offsets delimiting the substring to be returned.

In these three cases, if an index is negative, it is counted from the end of the string. For the start and range cases the starting index is just before a character and an index matching the string's size. Additionally, an empty string is returned when the starting index for a character range is at the end of the string.

Returns nil if the initial index falls outside the string or the length is negative.

If a Regexp is supplied, the matching portion of the string is returned. If a capture follows the regular expression, which may be a capture group index or name, follows the regular expression that component of the MatchData is returned instead.

If a match_str is given, that string is returned if it occurs in the string.

Returns nil if the regular expression does not match or the match string cannot be found.

a = "hello there"

a[1]                   #=> "e"
a[2, 3]                #=> "llo"
a[2..3]                #=> "ll"

a[-3, 2]               #=> "er"
a[7..-2]               #=> "her"
a[-4..-2]              #=> "her"
a[-2..-4]              #=> ""

a[11, 0]               #=> ""
a[11]                  #=> nil
a[12, 0]               #=> nil
a[12..-1]              #=> nil

a[/[aeiou](.)\1/]      #=> "ell"
a[/[aeiou](.)\1/, 0]   #=> "ell"
a[/[aeiou](.)\1/, 1]   #=> "l"
a[/[aeiou](.)\1/, 2]   #=> nil

a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l"
a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"]     #=> "e"

a["lo"]                #=> "lo"
a["bye"]               #=> nil

static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
    if (argc == 2) {
        if (RB_TYPE_P(argv[0], T_REGEXP)) {
            return rb_str_subpat(str, argv[0], argv[1]);
        }
        return rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
    }
    rb_check_arity(argc, 1, 2);
    return rb_str_aref(str, argv[0]);
}
slice!(fixnum) → fixnum or nil click to toggle source
slice!(fixnum, fixnum) → new_str or nil
slice!(range) → new_str or nil
slice!(regexp) → new_str or nil
slice!(other_str) → new_str or nil

Deletes the specified portion from str, and returns the portion deleted.

string = "this is a string"
string.slice!(2)        #=> "i"
string.slice!(3..6)     #=> " is "
string.slice!(/s.*t/)   #=> "sa st"
string.slice!("r")      #=> "r"
string                  #=> "thing"

static VALUE
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE result;
    VALUE buf[3];
    int i;

    rb_check_arity(argc, 1, 2);
    for (i=0; i<argc; i++) {
        buf[i] = argv[i];
    }
    str_modify_keep_cr(str);
    result = rb_str_aref_m(argc, buf, str);
    if (!NIL_P(result)) {
        buf[i] = rb_str_new(0,0);
        rb_str_aset_m(argc+1, buf, str);
    }
    return result;
}
split(pattern=$;, [limit]) → anArray click to toggle source

Divides str into substrings based on a delimiter, returning an array of these substrings.

If pattern is a String, then its contents are used as the delimiter when splitting str. If pattern is a single space, str is split on whitespace, with leading whitespace and runs of contiguous whitespace characters ignored.

If pattern is a Regexp, str is divided where the pattern matches. Whenever the pattern matches a zero-length string, str is split into individual characters. If pattern contains groups, the respective matches will be returned in the array as well.

If pattern is omitted, the value of $; is used. If $; is nil (which is the default), str is split on whitespace as if ` ' were specified.

If the limit parameter is omitted, trailing null fields are suppressed. If limit is a positive number, at most that number of fields will be returned (if limit is 1, the entire string is returned as the only entry in an array). If negative, there is no limit to the number of fields returned, and trailing null fields are not suppressed.

When the input str is empty an empty Array is returned as the string is considered to have no fields to split.

" now's  the time".split        #=> ["now's", "the", "time"]
" now's  the time".split(' ')   #=> ["now's", "the", "time"]
" now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
"1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
"hello".split(//)               #=> ["h", "e", "l", "l", "o"]
"hello".split(//, 3)            #=> ["h", "e", "llo"]
"hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]

"mellow yellow".split("ello")   #=> ["m", "w y", "w"]
"1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
"1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]

"".split(',', -1)               #=> []

static VALUE
rb_str_split_m(int argc, VALUE *argv, VALUE str)
{
    rb_encoding *enc;
    VALUE spat;
    VALUE limit;
    enum {awk, string, regexp} split_type;
    long beg, end, i = 0;
    int lim = 0;
    VALUE result, tmp;

    if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
        lim = NUM2INT(limit);
        if (lim <= 0) limit = Qnil;
        else if (lim == 1) {
            if (RSTRING_LEN(str) == 0)
                return rb_ary_new2(0);
            return rb_ary_new3(1, str);
        }
        i = 1;
    }

    enc = STR_ENC_GET(str);
    if (NIL_P(spat)) {
        if (!NIL_P(rb_fs)) {
            spat = rb_fs;
            goto fs_set;
        }
        split_type = awk;
    }
    else {
      fs_set:
        if (RB_TYPE_P(spat, T_STRING)) {
            rb_encoding *enc2 = STR_ENC_GET(spat);

            split_type = string;
            if (RSTRING_LEN(spat) == 0) {
                /* Special case - split into chars */
                spat = rb_reg_regcomp(spat);
                split_type = regexp;
            }
            else if (rb_enc_asciicompat(enc2) == 1) {
                if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
                    split_type = awk;
                }
            }
            else {
                int l;
                if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
                    RSTRING_LEN(spat) == l) {
                    split_type = awk;
                }
            }
        }
        else {
            spat = get_pat(spat, 1);
            split_type = regexp;
        }
    }

    result = rb_ary_new();
    beg = 0;
    if (split_type == awk) {
        char *ptr = RSTRING_PTR(str);
        char *eptr = RSTRING_END(str);
        char *bptr = ptr;
        int skip = 1;
        unsigned int c;

        end = beg;
        if (is_ascii_string(str)) {
            while (ptr < eptr) {
                c = (unsigned char)*ptr++;
                if (skip) {
                    if (ascii_isspace(c)) {
                        beg = ptr - bptr;
                    }
                    else {
                        end = ptr - bptr;
                        skip = 0;
                        if (!NIL_P(limit) && lim <= i) break;
                    }
                }
                else if (ascii_isspace(c)) {
                    rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
                    skip = 1;
                    beg = ptr - bptr;
                    if (!NIL_P(limit)) ++i;
                }
                else {
                    end = ptr - bptr;
                }
            }
        }
        else {
            while (ptr < eptr) {
                int n;

                c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
                ptr += n;
                if (skip) {
                    if (rb_isspace(c)) {
                        beg = ptr - bptr;
                    }
                    else {
                        end = ptr - bptr;
                        skip = 0;
                        if (!NIL_P(limit) && lim <= i) break;
                    }
                }
                else if (rb_isspace(c)) {
                    rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
                    skip = 1;
                    beg = ptr - bptr;
                    if (!NIL_P(limit)) ++i;
                }
                else {
                    end = ptr - bptr;
                }
            }
        }
    }
    else if (split_type == string) {
        char *ptr = RSTRING_PTR(str);
        char *temp = ptr;
        char *eptr = RSTRING_END(str);
        char *sptr = RSTRING_PTR(spat);
        long slen = RSTRING_LEN(spat);

        if (is_broken_string(str)) {
            rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
        }
        if (is_broken_string(spat)) {
            rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(spat)));
        }
        enc = rb_enc_check(str, spat);
        while (ptr < eptr &&
               (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
            /* Check we are at the start of a char */
            char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
            if (t != ptr + end) {
                ptr = t;
                continue;
            }
            rb_ary_push(result, rb_str_subseq(str, ptr - temp, end));
            ptr += end + slen;
            if (!NIL_P(limit) && lim <= ++i) break;
        }
        beg = ptr - temp;
    }
    else {
        char *ptr = RSTRING_PTR(str);
        long len = RSTRING_LEN(str);
        long start = beg;
        long idx;
        int last_null = 0;
        struct re_registers *regs;

        while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
            regs = RMATCH_REGS(rb_backref_get());
            if (start == end && BEG(0) == END(0)) {
                if (!ptr) {
                    rb_ary_push(result, str_new_empty(str));
                    break;
                }
                else if (last_null == 1) {
                    rb_ary_push(result, rb_str_subseq(str, beg,
                                                      rb_enc_fast_mbclen(ptr+beg,
                                                                         ptr+len,
                                                                         enc)));
                    beg = start;
                }
                else {
                    if (ptr+start == ptr+len)
                        start++;
                    else
                        start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
                    last_null = 1;
                    continue;
                }
            }
            else {
                rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
                beg = start = END(0);
            }
            last_null = 0;

            for (idx=1; idx < regs->num_regs; idx++) {
                if (BEG(idx) == -1) continue;
                if (BEG(idx) == END(idx))
                    tmp = str_new_empty(str);
                else
                    tmp = rb_str_subseq(str, BEG(idx), END(idx)-BEG(idx));
                rb_ary_push(result, tmp);
            }
            if (!NIL_P(limit) && lim <= ++i) break;
        }
    }
    if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
        if (RSTRING_LEN(str) == beg)
            tmp = str_new_empty(str);
        else
            tmp = rb_str_subseq(str, beg, RSTRING_LEN(str)-beg);
        rb_ary_push(result, tmp);
    }
    if (NIL_P(limit) && lim == 0) {
        long len;
        while ((len = RARRAY_LEN(result)) > 0 &&
               (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
            rb_ary_pop(result);
    }

    return result;
}
squeeze([other_str]*) → new_str click to toggle source

Builds a set of characters from the other_str parameter(s) using the procedure described for String#count. Returns a new string where runs of the same character that occur in this set are replaced by a single character. If no arguments are given, all runs of identical characters are replaced by a single character.

"yellow moon".squeeze                  #=> "yelow mon"
"  now   is  the".squeeze(" ")         #=> " now is the"
"putters shoot balls".squeeze("m-z")   #=> "puters shot balls"

static VALUE
rb_str_squeeze(int argc, VALUE *argv, VALUE str)
{
    str = rb_str_dup(str);
    rb_str_squeeze_bang(argc, argv, str);
    return str;
}
squeeze!([other_str]*) → str or nil click to toggle source

Squeezes str in place, returning either str, or nil if no changes were made.

static VALUE
rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
{
    char squeez[TR_TABLE_SIZE];
    rb_encoding *enc = 0;
    VALUE del = 0, nodel = 0;
    char *s, *send, *t;
    int i, modify = 0;
    int ascompat, singlebyte = single_byte_optimizable(str);
    unsigned int save;

    if (argc == 0) {
        enc = STR_ENC_GET(str);
    }
    else {
        for (i=0; i<argc; i++) {
            VALUE s = argv[i];

            StringValue(s);
            enc = rb_enc_check(str, s);
            if (singlebyte && !single_byte_optimizable(s))
                singlebyte = 0;
            tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
        }
    }

    str_modify_keep_cr(str);
    s = t = RSTRING_PTR(str);
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
    send = RSTRING_END(str);
    save = -1;
    ascompat = rb_enc_asciicompat(enc);

    if (singlebyte) {
        while (s < send) {
            unsigned int c = *(unsigned char*)s++;
            if (c != save || (argc > 0 && !squeez[c])) {
                *t++ = save = c;
            }
        }
    } else {
        while (s < send) {
            unsigned int c;
            int clen;

            if (ascompat && (c = *(unsigned char*)s) < 0x80) {
                if (c != save || (argc > 0 && !squeez[c])) {
                    *t++ = save = c;
                }
                s++;
            }
            else {
                c = rb_enc_codepoint_len(s, send, &clen, enc);

                if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
                    if (t != s) rb_enc_mbcput(c, t, enc);
                    save = c;
                    t += clen;
                }
                s += clen;
            }
        }
    }

    *t = '\0';
    if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
        STR_SET_LEN(str, t - RSTRING_PTR(str));
        modify = 1;
    }

    if (modify) return str;
    return Qnil;
}
start_with?([prefixes]+) → true or false click to toggle source

Returns true if str starts with one of the prefixes given.

"hello".start_with?("hell")               #=> true

# returns true if one of the prefixes matches.
"hello".start_with?("heaven", "hell")     #=> true
"hello".start_with?("heaven", "paradise") #=> false

static VALUE
rb_str_start_with(int argc, VALUE *argv, VALUE str)
{
    int i;

    for (i=0; i<argc; i++) {
        VALUE tmp = argv[i];
        StringValue(tmp);
        rb_enc_check(str, tmp);
        if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
        if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
            return Qtrue;
    }
    return Qfalse;
}
strip → new_str click to toggle source

Returns a copy of str with leading and trailing whitespace removed.

"    hello    ".strip   #=> "hello"
"\tgoodbye\r\n".strip   #=> "goodbye"

static VALUE
rb_str_strip(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_strip_bang(str);
    return str;
}
strip! → str or nil click to toggle source

Removes leading and trailing whitespace from str. Returns nil if str was not altered.

static VALUE
rb_str_strip_bang(VALUE str)
{
    VALUE l = rb_str_lstrip_bang(str);
    VALUE r = rb_str_rstrip_bang(str);

    if (NIL_P(l) && NIL_P(r)) return Qnil;
    return str;
}
sub(pattern, replacement) → new_str click to toggle source
sub(pattern, hash) → new_str
sub(pattern) {|match| block } → new_str

Returns a copy of str with the first occurrence of pattern replaced by the second argument. The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\\d' will match a backlash followed by 'd', instead of a digit.

If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern's capture groups of the form "\d", where d is a group number, or "\k<n>", where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash. However, within replacement the special match variables, such as &$, will not refer to the current match.

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $' will be set appropriately. The value returned by the block will be substituted for the match on each call.

The result inherits any tainting in the original string or any supplied replacement string.

"hello".sub(/[aeiou]/, '*')                  #=> "h*llo"
"hello".sub(/([aeiou])/, '<\1>')             #=> "h<e>llo"
"hello".sub(/./) {|s| s.ord.to_s + ' ' }     #=> "104 ello"
"hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*')  #=> "h*e*llo"
'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
 #=> "Is /bin/bash your preferred shell?"

static VALUE
rb_str_sub(int argc, VALUE *argv, VALUE str)
{
    str = rb_str_dup(str);
    rb_str_sub_bang(argc, argv, str);
    return str;
}
sub!(pattern, replacement) → str or nil click to toggle source
sub!(pattern) {|match| block } → str or nil

Performs the same substitution as #sub in-place.

Returns str if a substitution was performed or nil if no substitution was performed.

static VALUE
rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
{
    VALUE pat, repl, hash = Qnil;
    int iter = 0;
    int tainted = 0;
    int untrusted = 0;
    long plen;
    int min_arity = rb_block_given_p() ? 1 : 2;

    rb_check_arity(argc, min_arity, 2);
    if (argc == 1) {
        iter = 1;
    }
    else {
        repl = argv[1];
        hash = rb_check_hash_type(argv[1]);
        if (NIL_P(hash)) {
            StringValue(repl);
        }
        if (OBJ_TAINTED(repl)) tainted = 1;
        if (OBJ_UNTRUSTED(repl)) untrusted = 1;
    }

    pat = get_pat(argv[0], 1);
    str_modifiable(str);
    if (rb_reg_search(pat, str, 0, 0) >= 0) {
        rb_encoding *enc;
        int cr = ENC_CODERANGE(str);
        VALUE match = rb_backref_get();
        struct re_registers *regs = RMATCH_REGS(match);
        long beg0 = BEG(0);
        long end0 = END(0);
        char *p, *rp;
        long len, rlen;

        if (iter || !NIL_P(hash)) {
            p = RSTRING_PTR(str); len = RSTRING_LEN(str);

            if (iter) {
                repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
            }
            else {
                repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
                repl = rb_obj_as_string(repl);
            }
            str_mod_check(str, p, len);
            rb_check_frozen(str);
        }
        else {
            repl = rb_reg_regsub(repl, str, regs, pat);
        }
        enc = rb_enc_compatible(str, repl);
        if (!enc) {
            rb_encoding *str_enc = STR_ENC_GET(str);
            p = RSTRING_PTR(str); len = RSTRING_LEN(str);
            if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
                coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
                rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
                         rb_enc_name(str_enc),
                         rb_enc_name(STR_ENC_GET(repl)));
            }
            enc = STR_ENC_GET(repl);
        }
        rb_str_modify(str);
        rb_enc_associate(str, enc);
        if (OBJ_TAINTED(repl)) tainted = 1;
        if (OBJ_UNTRUSTED(repl)) untrusted = 1;
        if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
            int cr2 = ENC_CODERANGE(repl);
            if (cr2 == ENC_CODERANGE_BROKEN ||
                (cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
                cr = ENC_CODERANGE_UNKNOWN;
            else
                cr = cr2;
        }
        plen = end0 - beg0;
        rp = RSTRING_PTR(repl); rlen = RSTRING_LEN(repl);
        len = RSTRING_LEN(str);
        if (rlen > plen) {
            RESIZE_CAPA(str, len + rlen - plen);
        }
        p = RSTRING_PTR(str);
        if (rlen != plen) {
            memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
        }
        memcpy(p + beg0, rp, rlen);
        len += rlen - plen;
        STR_SET_LEN(str, len);
        RSTRING_PTR(str)[len] = '\0';
        ENC_CODERANGE_SET(str, cr);
        if (tainted) OBJ_TAINT(str);
        if (untrusted) OBJ_UNTRUST(str);

        return str;
    }
    return Qnil;
}
succ → new_str click to toggle source
next → new_str

Returns the successor to str. The successor is calculated by incrementing characters starting from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the string. Incrementing a digit always results in another digit, and incrementing a letter results in another letter of the same case. Incrementing nonalphanumerics uses the underlying character set's collating sequence.

If the increment generates a “carry,'' the character to the left of it is incremented. This process repeats until there is no carry, adding an additional character if necessary.

"abcd".succ        #=> "abce"
"THX1138".succ     #=> "THX1139"
"<<koala>>".succ   #=> "<<koalb>>"
"1999zzz".succ     #=> "2000aaa"
"ZZZ9999".succ     #=> "AAAA0000"
"***".succ         #=> "**+"

VALUE
rb_str_succ(VALUE orig)
{
    rb_encoding *enc;
    VALUE str;
    char *sbeg, *s, *e, *last_alnum = 0;
    int c = -1;
    long l;
    char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
    long carry_pos = 0, carry_len = 1;
    enum neighbor_char neighbor = NEIGHBOR_FOUND;

    str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
    rb_enc_cr_str_copy_for_substr(str, orig);
    OBJ_INFECT(str, orig);
    if (RSTRING_LEN(str) == 0) return str;

    enc = STR_ENC_GET(orig);
    sbeg = RSTRING_PTR(str);
    s = e = sbeg + RSTRING_LEN(str);

    while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
        if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
            if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
                ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
                s = last_alnum;
                break;
            }
        }
        if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
        neighbor = enc_succ_alnum_char(s, l, enc, carry);
        switch (neighbor) {
          case NEIGHBOR_NOT_CHAR:
            continue;
          case NEIGHBOR_FOUND:
            return str;
          case NEIGHBOR_WRAPPED:
            last_alnum = s;
            break;
        }
        c = 1;
        carry_pos = s - sbeg;
        carry_len = l;
    }
    if (c == -1) {              /* str contains no alnum */
        s = e;
        while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
            enum neighbor_char neighbor;
            if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
            neighbor = enc_succ_char(s, l, enc);
            if (neighbor == NEIGHBOR_FOUND)
                return str;
            if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
                /* wrapped to \0...\0.  search next valid char. */
                enc_succ_char(s, l, enc);
            }
            if (!rb_enc_asciicompat(enc)) {
                MEMCPY(carry, s, char, l);
                carry_len = l;
            }
            carry_pos = s - sbeg;
        }
    }
    RESIZE_CAPA(str, RSTRING_LEN(str) + carry_len);
    s = RSTRING_PTR(str) + carry_pos;
    memmove(s + carry_len, s, RSTRING_LEN(str) - carry_pos);
    memmove(s, carry, carry_len);
    STR_SET_LEN(str, RSTRING_LEN(str) + carry_len);
    RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
    rb_enc_str_coderange(str);
    return str;
}
succ! → str click to toggle source
next! → str

Equivalent to String#succ, but modifies the receiver in place.

static VALUE
rb_str_succ_bang(VALUE str)
{
    rb_str_shared_replace(str, rb_str_succ(str));

    return str;
}
sum(n=16) → integer click to toggle source

Returns a basic n-bit checksum of the characters in str, where n is the optional Fixnum parameter, defaulting to 16. The result is simply the sum of the binary value of each character in str modulo 2**n - 1. This is not a particularly good checksum.

static VALUE
rb_str_sum(int argc, VALUE *argv, VALUE str)
{
    VALUE vbits;
    int bits;
    char *ptr, *p, *pend;
    long len;
    VALUE sum = INT2FIX(0);
    unsigned long sum0 = 0;

    if (argc == 0) {
        bits = 16;
    }
    else {
        rb_scan_args(argc, argv, "01", &vbits);
        bits = NUM2INT(vbits);
    }
    ptr = p = RSTRING_PTR(str);
    len = RSTRING_LEN(str);
    pend = p + len;

    while (p < pend) {
        if (FIXNUM_MAX - UCHAR_MAX < sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            str_mod_check(str, ptr, len);
            sum0 = 0;
        }
        sum0 += (unsigned char)*p;
        p++;
    }

    if (bits == 0) {
        if (sum0) {
            sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
        }
    }
    else {
        if (sum == INT2FIX(0)) {
            if (bits < (int)sizeof(long)*CHAR_BIT) {
                sum0 &= (((unsigned long)1)<<bits)-1;
            }
            sum = LONG2FIX(sum0);
        }
        else {
            VALUE mod;

            if (sum0) {
                sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
            }

            mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits));
            mod = rb_funcall(mod, '-', 1, INT2FIX(1));
            sum = rb_funcall(sum, '&', 1, mod);
        }
    }
    return sum;
}
swapcase → new_str click to toggle source

Returns a copy of str with uppercase alphabetic characters converted to lowercase and lowercase characters converted to uppercase. Note: case conversion is effective only in ASCII region.

"Hello".swapcase          #=> "hELLO"
"cYbEr_PuNk11".swapcase   #=> "CyBeR_pUnK11"

static VALUE
rb_str_swapcase(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_swapcase_bang(str);
    return str;
}
swapcase! → str or nil click to toggle source

Equivalent to String#swapcase, but modifies the receiver in place, returning str, or nil if no changes were made. Note: case conversion is effective only in ASCII region.

static VALUE
rb_str_swapcase_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *send;
    int modify = 0;
    int n;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    rb_str_check_dummy_enc(enc);
    s = RSTRING_PTR(str); send = RSTRING_END(str);
    while (s < send) {
        unsigned int c = rb_enc_codepoint_len(s, send, &n, enc);

        if (rb_enc_isupper(c, enc)) {
            /* assuming toupper returns codepoint with same size */
            rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
            modify = 1;
        }
        else if (rb_enc_islower(c, enc)) {
            /* assuming tolower returns codepoint with same size */
            rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
            modify = 1;
        }
        s += n;
    }

    if (modify) return str;
    return Qnil;
}
to_c → complex click to toggle source

Returns a complex which denotes the string form. The parser ignores leading whitespaces and trailing garbage. Any digit sequences can be separated by an underscore. Returns zero for null or garbage string.

'9'.to_c           #=> (9+0i)
'2.5'.to_c         #=> (2.5+0i)
'2.5/1'.to_c       #=> ((5/2)+0i)
'-3/2'.to_c        #=> ((-3/2)+0i)
'-i'.to_c          #=> (0-1i)
'45i'.to_c         #=> (0+45i)
'3-4i'.to_c        #=> (3-4i)
'-4e2-4e-2i'.to_c  #=> (-400.0-0.04i)
'-0.0-0.0i'.to_c   #=> (-0.0-0.0i)
'1/2+3/4i'.to_c    #=> ((1/2)+(3/4)*i)
'ruby'.to_c        #=> (0+0i)

See Kernel.Complex.

static VALUE
string_to_c(VALUE self)
{
    char *s;
    VALUE num;

    rb_must_asciicompat(self);

    s = RSTRING_PTR(self);

    if (s && s[RSTRING_LEN(self)]) {
        rb_str_modify(self);
        s = RSTRING_PTR(self);
        s[RSTRING_LEN(self)] = '\0';
    }

    if (!s)
        s = (char *)"";

    (void)parse_comp(s, 0, &num);

    return num;
}
to_f → float click to toggle source

Returns the result of interpreting leading characters in str as a floating point number. Extraneous characters past the end of a valid number are ignored. If there is not a valid number at the start of str, 0.0 is returned. This method never raises an exception.

"123.45e1".to_f        #=> 1234.5
"45.67 degrees".to_f   #=> 45.67
"thx1138".to_f         #=> 0.0

static VALUE
rb_str_to_f(VALUE str)
{
    return DBL2NUM(rb_str_to_dbl(str, FALSE));
}
to_i(base=10) → integer click to toggle source

Returns the result of interpreting leading characters in str as an integer base base (between 2 and 36). Extraneous characters past the end of a valid number are ignored. If there is not a valid number at the start of str, 0 is returned. This method never raises an exception when base is valid.

"12345".to_i             #=> 12345
"99 red balloons".to_i   #=> 99
"0a".to_i                #=> 0
"0a".to_i(16)            #=> 10
"hello".to_i             #=> 0
"1100101".to_i(2)        #=> 101
"1100101".to_i(8)        #=> 294977
"1100101".to_i(10)       #=> 1100101
"1100101".to_i(16)       #=> 17826049

static VALUE
rb_str_to_i(int argc, VALUE *argv, VALUE str)
{
    int base;

    if (argc == 0) base = 10;
    else {
        VALUE b;

        rb_scan_args(argc, argv, "01", &b);
        base = NUM2INT(b);
    }
    if (base < 0) {
        rb_raise(rb_eArgError, "invalid radix %d", base);
    }
    return rb_str_to_inum(str, base, FALSE);
}
to_r → rational click to toggle source

Returns a rational which denotes the string form. The parser ignores leading whitespaces and trailing garbage. Any digit sequences can be separated by an underscore. Returns zero for null or garbage string.

NOTE: '0.3'.#to_r isn't the same as 0.3.to_r. The former is equivalent to '3/10'.#to_r, but the latter isn't so.

'  2  '.to_r       #=> (2/1)
'300/2'.to_r       #=> (150/1)
'-9.2'.to_r        #=> (-46/5)
'-9.2e2'.to_r      #=> (-920/1)
'1_234_567'.to_r   #=> (1234567/1)
'21 june 09'.to_r  #=> (21/1)
'21/06/09'.to_r    #=> (7/2)
'bwv 1079'.to_r    #=> (0/1)

See Kernel.Rational.

static VALUE
string_to_r(VALUE self)
{
    char *s;
    VALUE num;

    rb_must_asciicompat(self);

    s = RSTRING_PTR(self);

    if (s && s[RSTRING_LEN(self)]) {
        rb_str_modify(self);
        s = RSTRING_PTR(self);
        s[RSTRING_LEN(self)] = '\0';
    }

    if (!s)
        s = (char *)"";

    (void)parse_rat(s, 0, &num);

    if (RB_TYPE_P(num, T_FLOAT))
        rb_raise(rb_eFloatDomainError, "Infinity");
    return num;
}
to_s → str click to toggle source
to_str → str

Returns the receiver.

static VALUE
rb_str_to_s(VALUE str)
{
    if (rb_obj_class(str) != rb_cString) {
        return str_duplicate(rb_cString, str);
    }
    return str;
}
to_s → str click to toggle source
to_str → str

Returns the receiver.

static VALUE
rb_str_to_s(VALUE str)
{
    if (rb_obj_class(str) != rb_cString) {
        return str_duplicate(rb_cString, str);
    }
    return str;
}
intern → symbol click to toggle source
to_sym → symbol

Returns the Symbol corresponding to str, creating the symbol if it did not previously exist. See Symbol#id2name.

"Koala".intern         #=> :Koala
s = 'cat'.to_sym       #=> :cat
s == :cat              #=> true
s = '@cat'.to_sym      #=> :@cat
s == :@cat             #=> true

This can also be used to create symbols that cannot be represented using the :xxx notation.

'cat and dog'.to_sym   #=> :"cat and dog"

VALUE
rb_str_intern(VALUE s)
{
    VALUE str = RB_GC_GUARD(s);
    ID id;

    id = rb_intern_str(str);
    return ID2SYM(id);
}
tr(from_str, to_str) → new_str click to toggle source

Returns a copy of str with the characters in from_str replaced by the corresponding characters in to_str. If to_str is shorter than from_str, it is padded with its last character in order to maintain the correspondence.

"hello".tr('el', 'ip')      #=> "hippo"
"hello".tr('aeiou', '*')    #=> "h*ll*"
"hello".tr('aeiou', 'AA*')  #=> "hAll*"

Both strings may use the c1-c2 notation to denote ranges of characters, and from_str may start with a ^, which denotes all characters except those listed.

"hello".tr('a-y', 'b-z')    #=> "ifmmp"
"hello".tr('^aeiou', '*')   #=> "*e**o"

The backslash character </code> can be used to escape <code>^ or - and is otherwise ignored unless it appears at the end of a range or the end of the from_str or to_str:

"hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
"hello-world".tr("a\\-eo", "*")   #=> "h*ll**w*rld"

"hello\r\nworld".tr("\r", "")   #=> "hello\nworld"
"hello\r\nworld".tr("\\r", "")  #=> "hello\r\nwold"
"hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"

"X['\\b']".tr("X\\", "")   #=> "['b']"
"X['\\b']".tr("X-\\]", "") #=> "'b'"

static VALUE
rb_str_tr(VALUE str, VALUE src, VALUE repl)
{
    str = rb_str_dup(str);
    tr_trans(str, src, repl, 0);
    return str;
}
tr!(from_str, to_str) → str or nil click to toggle source

Translates str in place, using the same rules as String#tr. Returns str, or nil if no changes were made.

static VALUE
rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
{
    return tr_trans(str, src, repl, 0);
}
tr_s(from_str, to_str) → new_str click to toggle source

Processes a copy of str as described under String#tr, then removes duplicate characters in regions that were affected by the translation.

"hello".tr_s('l', 'r')     #=> "hero"
"hello".tr_s('el', '*')    #=> "h*o"
"hello".tr_s('el', 'hx')   #=> "hhxo"

static VALUE
rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
{
    str = rb_str_dup(str);
    tr_trans(str, src, repl, 1);
    return str;
}
tr_s!(from_str, to_str) → str or nil click to toggle source

Performs String#tr_s processing on str in place, returning str, or nil if no changes were made.

static VALUE
rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
{
    return tr_trans(str, src, repl, 1);
}
unpack(format) → anArray click to toggle source

Decodes str (which may contain binary data) according to the format string, returning an array of each value extracted. The format string consists of a sequence of single-character directives, summarized in the table at the end of this entry. Each directive may be followed by a number, indicating the number of times to repeat with this directive. An asterisk (“*'') will use up all remaining elements. The directives sSiIlL may each be followed by an underscore (“_'') or exclamation mark (“!'') to use the underlying platform's native size for the specified type; otherwise, it uses a platform-independent consistent size. Spaces are ignored in the format string. See also Array#pack.

"abc \00\\00aabc \00\\00"".unpack('A6Z6')   #=> ["abc", "abc "]
"abc \00\\00"".unpack('a3a3')           #=> ["abc", " \000\000"]
"abc \00aabc \00"".unpack('Z*Z*')       #=> ["abc ", "abc "]
"aa".unpack('b8B8')                 #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c')               #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS')     #=> [-2, 65534]
"now=20is".unpack('M*')             #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a')    #=> ["h", "e", "l", "l", "o"]

This table summarizes the various formats and the Ruby classes returned by each.

Integer      |         |
Directive    | Returns | Meaning
-----------------------------------------------------------------
   C         | Integer | 8-bit unsigned (unsigned char)
   S         | Integer | 16-bit unsigned, native endian (uint16_t)
   L         | Integer | 32-bit unsigned, native endian (uint32_t)
   Q         | Integer | 64-bit unsigned, native endian (uint64_t)
             |         |
   c         | Integer | 8-bit signed (signed char)
   s         | Integer | 16-bit signed, native endian (int16_t)
   l         | Integer | 32-bit signed, native endian (int32_t)
   q         | Integer | 64-bit signed, native endian (int64_t)
             |         |
   S_, S!    | Integer | unsigned short, native endian
   I, I_, I! | Integer | unsigned int, native endian
   L_, L!    | Integer | unsigned long, native endian
             |         |
   s_, s!    | Integer | signed short, native endian
   i, i_, i! | Integer | signed int, native endian
   l_, l!    | Integer | signed long, native endian
             |         |
   S> L> Q>  | Integer | same as the directives without ">" except
   s> l> q>  |         | big endian
   S!> I!>   |         | (available since Ruby 1.9.3)
   L!> Q!>   |         | "S>" is same as "n"
   s!> i!>   |         | "L>" is same as "N"
   l!> q!>   |         |
             |         |
   S< L< Q<  | Integer | same as the directives without "<" except
   s< l< q<  |         | little endian
   S!< I!<   |         | (available since Ruby 1.9.3)
   L!< Q!<   |         | "S<" is same as "v"
   s!< i!<   |         | "L<" is same as "V"
   l!< q!<   |         |
             |         |
   n         | Integer | 16-bit unsigned, network (big-endian) byte order
   N         | Integer | 32-bit unsigned, network (big-endian) byte order
   v         | Integer | 16-bit unsigned, VAX (little-endian) byte order
   V         | Integer | 32-bit unsigned, VAX (little-endian) byte order
             |         |
   U         | Integer | UTF-8 character
   w         | Integer | BER-compressed integer (see Array.pack)

Float        |         |
Directive    | Returns | Meaning
-----------------------------------------------------------------
   D, d      | Float   | double-precision, native format
   F, f      | Float   | single-precision, native format
   E         | Float   | double-precision, little-endian byte order
   e         | Float   | single-precision, little-endian byte order
   G         | Float   | double-precision, network (big-endian) byte order
   g         | Float   | single-precision, network (big-endian) byte order

String       |         |
Directive    | Returns | Meaning
-----------------------------------------------------------------
   A         | String  | arbitrary binary string (remove trailing nulls and ASCII spaces)
   a         | String  | arbitrary binary string
   Z         | String  | null-terminated string
   B         | String  | bit string (MSB first)
   b         | String  | bit string (LSB first)
   H         | String  | hex string (high nibble first)
   h         | String  | hex string (low nibble first)
   u         | String  | UU-encoded string
   M         | String  | quoted-printable, MIME encoding (see RFC2045)
   m         | String  | base64 encoded string (RFC 2045) (default)
             |         | base64 encoded string (RFC 4648) if followed by 0
   P         | String  | pointer to a structure (fixed-length string)
   p         | String  | pointer to a null-terminated string

Misc.        |         |
Directive    | Returns | Meaning
-----------------------------------------------------------------
   @         | ---     | skip to the offset given by the length argument
   X         | ---     | skip backward one byte
   x         | ---     | skip forward one byte
static VALUE
pack_unpack(VALUE str, VALUE fmt)
{
    static const char hexdigits[] = "0123456789abcdef";
    char *s, *send;
    char *p, *pend;
    VALUE ary;
    char type;
    long len, tmp_len;
    int star;
#ifdef NATINT_PACK
    int natint;                 /* native integer */
#endif
    int block_p = rb_block_given_p();
    int signed_p, integer_size, bigendian_p;
#define UNPACK_PUSH(item) do {\
        VALUE item_val = (item);\
        if (block_p) {\
            rb_yield(item_val);\
        }\
        else {\
            rb_ary_push(ary, item_val);\
        }\
    } while (0)

    StringValue(str);
    StringValue(fmt);
    s = RSTRING_PTR(str);
    send = s + RSTRING_LEN(str);
    p = RSTRING_PTR(fmt);
    pend = p + RSTRING_LEN(fmt);

    ary = block_p ? Qnil : rb_ary_new();
    while (p < pend) {
        int explicit_endian = 0;
        type = *p++;
#ifdef NATINT_PACK
        natint = 0;
#endif

        if (ISSPACE(type)) continue;
        if (type == '#') {
            while ((p < pend) && (*p != '\n')) {
                p++;
            }
            continue;
        }

        star = 0;
        {
            static const char natstr[] = "sSiIlL";
            static const char endstr[] = "sSiIlLqQ";

          modifiers:
            switch (*p) {
              case '_':
              case '!':

                if (strchr(natstr, type)) {
#ifdef NATINT_PACK
                    natint = 1;
#endif
                    p++;
                }
                else {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
                }
                goto modifiers;

              case '<':
              case '>':
                if (!strchr(endstr, type)) {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
                }
                if (explicit_endian) {
                    rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
                }
                explicit_endian = *p++;
                goto modifiers;
            }
        }

        if (p >= pend)
            len = 1;
        else if (*p == '*') {
            star = 1;
            len = send - s;
            p++;
        }
        else if (ISDIGIT(*p)) {
            errno = 0;
            len = STRTOUL(p, (char**)&p, 10);
            if (errno) {
                rb_raise(rb_eRangeError, "pack length too big");
            }
        }
        else {
            len = (type != '@');
        }

        switch (type) {
          case '%':
            rb_raise(rb_eArgError, "%% is not supported");
            break;

          case 'A':
            if (len > send - s) len = send - s;
            {
                long end = len;
                char *t = s + len - 1;

                while (t >= s) {
                    if (*t != ' ' && *t != '\0') break;
                    t--; len--;
                }
                UNPACK_PUSH(infected_str_new(s, len, str));
                s += end;
            }
            break;

          case 'Z':
            {
                char *t = s;

                if (len > send-s) len = send-s;
                while (t < s+len && *t) t++;
                UNPACK_PUSH(infected_str_new(s, t-s, str));
                if (t < send) t++;
                s = star ? t : s+len;
            }
            break;

          case 'a':
            if (len > send - s) len = send - s;
            UNPACK_PUSH(infected_str_new(s, len, str));
            s += len;
            break;

          case 'b':
            {
                VALUE bitstr;
                char *t;
                int bits;
                long i;

                if (p[-1] == '*' || len > (send - s) * 8)
                    len = (send - s) * 8;
                bits = 0;
                UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
                t = RSTRING_PTR(bitstr);
                for (i=0; i<len; i++) {
                    if (i & 7) bits >>= 1;
                    else bits = *s++;
                    *t++ = (bits & 1) ? '1' : '0';
                }
            }
            break;

          case 'B':
            {
                VALUE bitstr;
                char *t;
                int bits;
                long i;

                if (p[-1] == '*' || len > (send - s) * 8)
                    len = (send - s) * 8;
                bits = 0;
                UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
                t = RSTRING_PTR(bitstr);
                for (i=0; i<len; i++) {
                    if (i & 7) bits <<= 1;
                    else bits = *s++;
                    *t++ = (bits & 128) ? '1' : '0';
                }
            }
            break;

          case 'h':
            {
                VALUE bitstr;
                char *t;
                int bits;
                long i;

                if (p[-1] == '*' || len > (send - s) * 2)
                    len = (send - s) * 2;
                bits = 0;
                UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
                t = RSTRING_PTR(bitstr);
                for (i=0; i<len; i++) {
                    if (i & 1)
                        bits >>= 4;
                    else
                        bits = *s++;
                    *t++ = hexdigits[bits & 15];
                }
            }
            break;

          case 'H':
            {
                VALUE bitstr;
                char *t;
                int bits;
                long i;

                if (p[-1] == '*' || len > (send - s) * 2)
                    len = (send - s) * 2;
                bits = 0;
                UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
                t = RSTRING_PTR(bitstr);
                for (i=0; i<len; i++) {
                    if (i & 1)
                        bits <<= 4;
                    else
                        bits = *s++;
                    *t++ = hexdigits[(bits >> 4) & 15];
                }
            }
            break;

          case 'c':
            PACK_LENGTH_ADJUST_SIZE(sizeof(char));
            while (len-- > 0) {
                int c = *s++;
                if (c > (char)127) c-=256;
                UNPACK_PUSH(INT2FIX(c));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'C':
            PACK_LENGTH_ADJUST_SIZE(sizeof(unsigned char));
            while (len-- > 0) {
                unsigned char c = *s++;
                UNPACK_PUSH(INT2FIX(c));
            }
            PACK_ITEM_ADJUST();
            break;

          case 's':
            signed_p = 1;
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'S':
            signed_p = 0;
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'i':
            signed_p = 1;
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'I':
            signed_p = 0;
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'l':
            signed_p = 1;
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'L':
            signed_p = 0;
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'q':
            signed_p = 1;
            integer_size = 8;
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'Q':
            signed_p = 0;
            integer_size = 8;
            bigendian_p = BIGENDIAN_P();
            goto unpack_integer;

          case 'n':
            signed_p = 0;
            integer_size = 2;
            bigendian_p = 1;
            goto unpack_integer;

          case 'N':
            signed_p = 0;
            integer_size = 4;
            bigendian_p = 1;
            goto unpack_integer;

          case 'v':
            signed_p = 0;
            integer_size = 2;
            bigendian_p = 0;
            goto unpack_integer;

          case 'V':
            signed_p = 0;
            integer_size = 4;
            bigendian_p = 0;
            goto unpack_integer;

          unpack_integer:
            if (explicit_endian) {
                bigendian_p = explicit_endian == '>';
            }

            switch (integer_size) {
#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT16_T:
                if (signed_p) {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t));
                    while (len-- > 0) {
                        union {
                            int16_t i;
                            char a[sizeof(int16_t)];
                        } v;
                        memcpy(v.a, s, sizeof(int16_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
                        s += sizeof(int16_t);
                        UNPACK_PUSH(INT2FIX(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                else {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint16_t));
                    while (len-- > 0) {
                        union {
                            uint16_t i;
                            char a[sizeof(uint16_t)];
                        } v;
                        memcpy(v.a, s, sizeof(uint16_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
                        s += sizeof(uint16_t);
                        UNPACK_PUSH(INT2FIX(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                break;
#endif

#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT32_T:
                if (signed_p) {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t));
                    while (len-- > 0) {
                        union {
                            int32_t i;
                            char a[sizeof(int32_t)];
                        } v;
                        memcpy(v.a, s, sizeof(int32_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
                        s += sizeof(int32_t);
                        UNPACK_PUSH(INT2NUM(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                else {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint32_t));
                    while (len-- > 0) {
                        union {
                            uint32_t i;
                            char a[sizeof(uint32_t)];
                        } v;
                        memcpy(v.a, s, sizeof(uint32_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
                        s += sizeof(uint32_t);
                        UNPACK_PUSH(UINT2NUM(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                break;
#endif

#if defined(HAVE_INT64_T) && !defined(FORCE_BIG_PACK)
              case SIZEOF_INT64_T:
                if (signed_p) {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(int64_t));
                    while (len-- > 0) {
                        union {
                            int64_t i;
                            char a[sizeof(int64_t)];
                        } v;
                        memcpy(v.a, s, sizeof(int64_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
                        s += sizeof(int64_t);
                        UNPACK_PUSH(INT64toNUM(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                else {
                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint64_t));
                    while (len-- > 0) {
                        union {
                            uint64_t i;
                            char a[sizeof(uint64_t)];
                        } v;
                        memcpy(v.a, s, sizeof(uint64_t));
                        if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
                        s += sizeof(uint64_t);
                        UNPACK_PUSH(UINT64toNUM(v.i));
                    }
                    PACK_ITEM_ADJUST();
                }
                break;
#endif

              default:
                if (integer_size > MAX_INTEGER_PACK_SIZE)
                    rb_bug("unexpected integer size for pack: %d", integer_size);
                PACK_LENGTH_ADJUST_SIZE(integer_size);
                while (len-- > 0) {
                    union {
                        unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG];
                        char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG*SIZEOF_LONG];
                    } v;
                    int num_longs = (integer_size+SIZEOF_LONG)/SIZEOF_LONG;
                    int i;

                    if (signed_p && (signed char)s[bigendian_p ? 0 : (integer_size-1)] < 0)
                        memset(v.a, 0xff, sizeof(long)*num_longs);
                    else
                        memset(v.a, 0, sizeof(long)*num_longs);
                    if (bigendian_p)
                        memcpy(v.a + sizeof(long)*num_longs - integer_size, s, integer_size);
                    else
                        memcpy(v.a, s, integer_size);
                    if (bigendian_p) {
                        for (i = 0; i < num_longs/2; i++) {
                            unsigned long t = v.i[i];
                            v.i[i] = v.i[num_longs-1-i];
                            v.i[num_longs-1-i] = t;
                        }
                    }
                    if (bigendian_p != BIGENDIAN_P()) {
                        for (i = 0; i < num_longs; i++)
                            v.i[i] = swapl(v.i[i]);
                    }
                    s += integer_size;
                    UNPACK_PUSH(rb_big_unpack(v.i, num_longs));
                }
                PACK_ITEM_ADJUST();
                break;
            }
            break;

          case 'f':
          case 'F':
            PACK_LENGTH_ADJUST_SIZE(sizeof(float));
            while (len-- > 0) {
                float tmp;
                memcpy(&tmp, s, sizeof(float));
                s += sizeof(float);
                UNPACK_PUSH(DBL2NUM((double)tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'e':
            PACK_LENGTH_ADJUST_SIZE(sizeof(float));
            while (len-- > 0) {
                float tmp;
                FLOAT_CONVWITH(ftmp);

                memcpy(&tmp, s, sizeof(float));
                s += sizeof(float);
                tmp = VTOHF(tmp,ftmp);
                UNPACK_PUSH(DBL2NUM((double)tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'E':
            PACK_LENGTH_ADJUST_SIZE(sizeof(double));
            while (len-- > 0) {
                double tmp;
                DOUBLE_CONVWITH(dtmp);

                memcpy(&tmp, s, sizeof(double));
                s += sizeof(double);
                tmp = VTOHD(tmp,dtmp);
                UNPACK_PUSH(DBL2NUM(tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'D':
          case 'd':
            PACK_LENGTH_ADJUST_SIZE(sizeof(double));
            while (len-- > 0) {
                double tmp;
                memcpy(&tmp, s, sizeof(double));
                s += sizeof(double);
                UNPACK_PUSH(DBL2NUM(tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'g':
            PACK_LENGTH_ADJUST_SIZE(sizeof(float));
            while (len-- > 0) {
                float tmp;
                FLOAT_CONVWITH(ftmp);

                memcpy(&tmp, s, sizeof(float));
                s += sizeof(float);
                tmp = NTOHF(tmp,ftmp);
                UNPACK_PUSH(DBL2NUM((double)tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'G':
            PACK_LENGTH_ADJUST_SIZE(sizeof(double));
            while (len-- > 0) {
                double tmp;
                DOUBLE_CONVWITH(dtmp);

                memcpy(&tmp, s, sizeof(double));
                s += sizeof(double);
                tmp = NTOHD(tmp,dtmp);
                UNPACK_PUSH(DBL2NUM(tmp));
            }
            PACK_ITEM_ADJUST();
            break;

          case 'U':
            if (len > send - s) len = send - s;
            while (len > 0 && s < send) {
                long alen = send - s;
                unsigned long l;

                l = utf8_to_uv(s, &alen);
                s += alen; len--;
                UNPACK_PUSH(ULONG2NUM(l));
            }
            break;

          case 'u':
            {
                VALUE buf = infected_str_new(0, (send - s)*3/4, str);
                char *ptr = RSTRING_PTR(buf);
                long total = 0;

                while (s < send && *s > ' ' && *s < 'a') {
                    long a,b,c,d;
                    char hunk[4];

                    hunk[3] = '\0';
                    len = (*s++ - ' ') & 077;
                    total += len;
                    if (total > RSTRING_LEN(buf)) {
                        len -= total - RSTRING_LEN(buf);
                        total = RSTRING_LEN(buf);
                    }

                    while (len > 0) {
                        long mlen = len > 3 ? 3 : len;

                        if (s < send && *s >= ' ')
                            a = (*s++ - ' ') & 077;
                        else
                            a = 0;
                        if (s < send && *s >= ' ')
                            b = (*s++ - ' ') & 077;
                        else
                            b = 0;
                        if (s < send && *s >= ' ')
                            c = (*s++ - ' ') & 077;
                        else
                            c = 0;
                        if (s < send && *s >= ' ')
                            d = (*s++ - ' ') & 077;
                        else
                            d = 0;
                        hunk[0] = (char)(a << 2 | b >> 4);
                        hunk[1] = (char)(b << 4 | c >> 2);
                        hunk[2] = (char)(c << 6 | d);
                        memcpy(ptr, hunk, mlen);
                        ptr += mlen;
                        len -= mlen;
                    }
                    if (*s == '\r') s++;
                    if (*s == '\n') s++;
                    else if (s < send && (s+1 == send || s[1] == '\n'))
                        s += 2;      /* possible checksum byte */
                }

                rb_str_set_len(buf, total);
                UNPACK_PUSH(buf);
            }
            break;

          case 'm':
            {
                VALUE buf = infected_str_new(0, (send - s)*3/4, str);
                char *ptr = RSTRING_PTR(buf);
                int a = -1,b = -1,c = 0,d = 0;
                static signed char b64_xtable[256];

                if (b64_xtable['/'] <= 0) {
                    int i;

                    for (i = 0; i < 256; i++) {
                        b64_xtable[i] = -1;
                    }
                    for (i = 0; i < 64; i++) {
                        b64_xtable[(unsigned char)b64_table[i]] = (char)i;
                    }
                }
                if (len == 0) {
                    while (s < send) {
                        a = b = c = d = -1;
                        a = b64_xtable[(unsigned char)*s++];
                        if (s >= send || a == -1) rb_raise(rb_eArgError, "invalid base64");
                        b = b64_xtable[(unsigned char)*s++];
                        if (s >= send || b == -1) rb_raise(rb_eArgError, "invalid base64");
                        if (*s == '=') {
                            if (s + 2 == send && *(s + 1) == '=') break;
                            rb_raise(rb_eArgError, "invalid base64");
                        }
                        c = b64_xtable[(unsigned char)*s++];
                        if (s >= send || c == -1) rb_raise(rb_eArgError, "invalid base64");
                        if (s + 1 == send && *s == '=') break;
                        d = b64_xtable[(unsigned char)*s++];
                        if (d == -1) rb_raise(rb_eArgError, "invalid base64");
                        *ptr++ = castchar(a << 2 | b >> 4);
                        *ptr++ = castchar(b << 4 | c >> 2);
                        *ptr++ = castchar(c << 6 | d);
                    }
                    if (c == -1) {
                        *ptr++ = castchar(a << 2 | b >> 4);
                        if (b & 0xf) rb_raise(rb_eArgError, "invalid base64");
                    }
                    else if (d == -1) {
                        *ptr++ = castchar(a << 2 | b >> 4);
                        *ptr++ = castchar(b << 4 | c >> 2);
                        if (c & 0x3) rb_raise(rb_eArgError, "invalid base64");
                    }
                }
                else {
                    while (s < send) {
                        a = b = c = d = -1;
                        while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
                        if (s >= send) break;
                        s++;
                        while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
                        if (s >= send) break;
                        s++;
                        while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
                        if (*s == '=' || s >= send) break;
                        s++;
                        while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
                        if (*s == '=' || s >= send) break;
                        s++;
                        *ptr++ = castchar(a << 2 | b >> 4);
                        *ptr++ = castchar(b << 4 | c >> 2);
                        *ptr++ = castchar(c << 6 | d);
                    }
                    if (a != -1 && b != -1) {
                        if (c == -1 && *s == '=')
                            *ptr++ = castchar(a << 2 | b >> 4);
                        else if (c != -1 && *s == '=') {
                            *ptr++ = castchar(a << 2 | b >> 4);
                            *ptr++ = castchar(b << 4 | c >> 2);
                        }
                    }
                }
                rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
                UNPACK_PUSH(buf);
            }
            break;

          case 'M':
            {
                VALUE buf = infected_str_new(0, send - s, str);
                char *ptr = RSTRING_PTR(buf), *ss = s;
                int c1, c2;

                while (s < send) {
                    if (*s == '=') {
                        if (++s == send) break;
                        if (s+1 < send && *s == '\r' && *(s+1) == '\n')
                            s++;
                        if (*s != '\n') {
                            if ((c1 = hex2num(*s)) == -1) break;
                            if (++s == send) break;
                            if ((c2 = hex2num(*s)) == -1) break;
                            *ptr++ = castchar(c1 << 4 | c2);
                        }
                    }
                    else {
                        *ptr++ = *s;
                    }
                    s++;
                    ss = s;
                }
                rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
                rb_str_buf_cat(buf, ss, send-ss);
                ENCODING_CODERANGE_SET(buf, rb_ascii8bit_encindex(), ENC_CODERANGE_VALID);
                UNPACK_PUSH(buf);
            }
            break;

          case '@':
            if (len > RSTRING_LEN(str))
                rb_raise(rb_eArgError, "@ outside of string");
            s = RSTRING_PTR(str) + len;
            break;

          case 'X':
            if (len > s - RSTRING_PTR(str))
                rb_raise(rb_eArgError, "X outside of string");
            s -= len;
            break;

          case 'x':
            if (len > send - s)
                rb_raise(rb_eArgError, "x outside of string");
            s += len;
            break;

          case 'P':
            if (sizeof(char *) <= (size_t)(send - s)) {
                VALUE tmp = Qnil;
                char *t;

                memcpy(&t, s, sizeof(char *));
                s += sizeof(char *);

                if (t) {
                    VALUE a, *p, *pend;

                    if (!(a = rb_str_associated(str))) {
                        rb_raise(rb_eArgError, "no associated pointer");
                    }
                    p = RARRAY_PTR(a);
                    pend = p + RARRAY_LEN(a);
                    while (p < pend) {
                        if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
                            if (len < RSTRING_LEN(*p)) {
                                tmp = rb_tainted_str_new(t, len);
                                rb_str_associate(tmp, a);
                            }
                            else {
                                tmp = *p;
                            }
                            break;
                        }
                        p++;
                    }
                    if (p == pend) {
                        rb_raise(rb_eArgError, "non associated pointer");
                    }
                }
                UNPACK_PUSH(tmp);
            }
            break;

          case 'p':
            if (len > (long)((send - s) / sizeof(char *)))
                len = (send - s) / sizeof(char *);
            while (len-- > 0) {
                if ((size_t)(send - s) < sizeof(char *))
                    break;
                else {
                    VALUE tmp = Qnil;
                    char *t;

                    memcpy(&t, s, sizeof(char *));
                    s += sizeof(char *);

                    if (t) {
                        VALUE a, *p, *pend;

                        if (!(a = rb_str_associated(str))) {
                            rb_raise(rb_eArgError, "no associated pointer");
                        }
                        p = RARRAY_PTR(a);
                        pend = p + RARRAY_LEN(a);
                        while (p < pend) {
                            if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
                                tmp = *p;
                                break;
                            }
                            p++;
                        }
                        if (p == pend) {
                            rb_raise(rb_eArgError, "non associated pointer");
                        }
                    }
                    UNPACK_PUSH(tmp);
                }
            }
            break;

          case 'w':
            {
                unsigned long ul = 0;
                unsigned long ulmask = 0xfeUL << ((sizeof(unsigned long) - 1) * 8);

                while (len > 0 && s < send) {
                    ul <<= 7;
                    ul |= (*s & 0x7f);
                    if (!(*s++ & 0x80)) {
                        UNPACK_PUSH(ULONG2NUM(ul));
                        len--;
                        ul = 0;
                    }
                    else if (ul & ulmask) {
                        VALUE big = rb_uint2big(ul);
                        VALUE big128 = rb_uint2big(128);
                        while (s < send) {
                            big = rb_big_mul(big, big128);
                            big = rb_big_plus(big, rb_uint2big(*s & 0x7f));
                            if (!(*s++ & 0x80)) {
                                UNPACK_PUSH(big);
                                len--;
                                ul = 0;
                                break;
                            }
                        }
                    }
                }
            }
            break;

          default:
            rb_warning("unknown unpack directive '%c' in '%s'",
                type, RSTRING_PTR(fmt));
            break;
        }
    }

    return ary;
}
upcase → new_str click to toggle source

Returns a copy of str with all lowercase letters replaced with their uppercase counterparts. The operation is locale insensitive—only characters “a'' to “z'' are affected. Note: case replacement is effective only in ASCII region.

"hEllO".upcase   #=> "HELLO"

static VALUE
rb_str_upcase(VALUE str)
{
    str = rb_str_dup(str);
    rb_str_upcase_bang(str);
    return str;
}
upcase! → str or nil click to toggle source

Upcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.

static VALUE
rb_str_upcase_bang(VALUE str)
{
    rb_encoding *enc;
    char *s, *send;
    int modify = 0;
    int n;

    str_modify_keep_cr(str);
    enc = STR_ENC_GET(str);
    rb_str_check_dummy_enc(enc);
    s = RSTRING_PTR(str); send = RSTRING_END(str);
    if (single_byte_optimizable(str)) {
        while (s < send) {
            unsigned int c = *(unsigned char*)s;

            if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
                *s = 'A' + (c - 'a');
                modify = 1;
            }
            s++;
        }
    }
    else {
        int ascompat = rb_enc_asciicompat(enc);

        while (s < send) {
            unsigned int c;

            if (ascompat && (c = *(unsigned char*)s) < 0x80) {
                if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
                    *s = 'A' + (c - 'a');
                    modify = 1;
                }
                s++;
            }
            else {
                c = rb_enc_codepoint_len(s, send, &n, enc);
                if (rb_enc_islower(c, enc)) {
                    /* assuming toupper returns codepoint with same size */
                    rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
                    modify = 1;
                }
                s += n;
            }
        }
    }

    if (modify) return str;
    return Qnil;
}
upto(other_str, exclusive=false) {|s| block } → str click to toggle source
upto(other_str, exclusive=false) → an_enumerator

Iterates through successive values, starting at str and ending at other_str inclusive, passing each value in turn to the block. The String#succ method is used to generate each value. If optional second argument exclusive is omitted or is false, the last value will be included; otherwise it will be excluded.

If no block is given, an enumerator is returned instead.

"a8".upto("b6") {|s| print s, ' ' }
for s in "a8".."b6"
  print s, ' '
end

produces:

a8 a9 b0 b1 b2 b3 b4 b5 b6
a8 a9 b0 b1 b2 b3 b4 b5 b6

If str and other_str contains only ascii numeric characters, both are recognized as decimal numbers. In addition, the width of string (e.g. leading zeros) is handled appropriately.

"9".upto("11").to_a   #=> ["9", "10", "11"]
"25".upto("5").to_a   #=> []
"07".upto("11").to_a  #=> ["07", "08", "09", "10", "11"]

static VALUE
rb_str_upto(int argc, VALUE *argv, VALUE beg)
{
    VALUE end, exclusive;
    VALUE current, after_end;
    ID succ;
    int n, excl, ascii;
    rb_encoding *enc;

    rb_scan_args(argc, argv, "11", &end, &exclusive);
    RETURN_ENUMERATOR(beg, argc, argv);
    excl = RTEST(exclusive);
    CONST_ID(succ, "succ");
    StringValue(end);
    enc = rb_enc_check(beg, end);
    ascii = (is_ascii_string(beg) && is_ascii_string(end));
    /* single character */
    if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
        char c = RSTRING_PTR(beg)[0];
        char e = RSTRING_PTR(end)[0];

        if (c > e || (excl && c == e)) return beg;
        for (;;) {
            rb_yield(rb_enc_str_new(&c, 1, enc));
            if (!excl && c == e) break;
            c++;
            if (excl && c == e) break;
        }
        return beg;
    }
    /* both edges are all digits */
    if (ascii && ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0])) {
        char *s, *send;
        VALUE b, e;
        int width;

        s = RSTRING_PTR(beg); send = RSTRING_END(beg);
        width = rb_long2int(send - s);
        while (s < send) {
            if (!ISDIGIT(*s)) goto no_digits;
            s++;
        }
        s = RSTRING_PTR(end); send = RSTRING_END(end);
        while (s < send) {
            if (!ISDIGIT(*s)) goto no_digits;
            s++;
        }
        b = rb_str_to_inum(beg, 10, FALSE);
        e = rb_str_to_inum(end, 10, FALSE);
        if (FIXNUM_P(b) && FIXNUM_P(e)) {
            long bi = FIX2LONG(b);
            long ei = FIX2LONG(e);
            rb_encoding *usascii = rb_usascii_encoding();

            while (bi <= ei) {
                if (excl && bi == ei) break;
                rb_yield(rb_enc_sprintf(usascii, "%.*ld", width, bi));
                bi++;
            }
        }
        else {
            ID op = excl ? '<' : rb_intern("<=");
            VALUE args[2], fmt = rb_obj_freeze(rb_usascii_str_new_cstr("%.*d"));

            args[0] = INT2FIX(width);
            while (rb_funcall(b, op, 1, e)) {
                args[1] = b;
                rb_yield(rb_str_format(numberof(args), args, fmt));
                b = rb_funcall(b, succ, 0, 0);
            }
        }
        return beg;
    }
    /* normal case */
  no_digits:
    n = rb_str_cmp(beg, end);
    if (n > 0 || (excl && n == 0)) return beg;

    after_end = rb_funcall(end, succ, 0, 0);
    current = rb_str_dup(beg);
    while (!rb_str_equal(current, after_end)) {
        VALUE next = Qnil;
        if (excl || !rb_str_equal(current, end))
            next = rb_funcall(current, succ, 0, 0);
        rb_yield(current);
        if (NIL_P(next)) break;
        current = next;
        StringValue(current);
        if (excl && rb_str_equal(current, end)) break;
        if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
            break;
    }

    return beg;
}
valid_encoding? → true or false click to toggle source

Returns true for a string which encoded correctly.

"\xc2\xa1".force_encoding("UTF-8").valid_encoding?  #=> true
"\xc2".force_encoding("UTF-8").valid_encoding?      #=> false
"\x80".force_encoding("UTF-8").valid_encoding?      #=> false

static VALUE
rb_str_valid_encoding_p(VALUE str)
{
    int cr = rb_enc_str_coderange(str);

    return cr == ENC_CODERANGE_BROKEN ? Qfalse : Qtrue;
}


class Struct - Ruby 2.0.0-p576 Core API Reference API Reference

class Struct

A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.

The Struct class is a generator of specific classes, each one of which is defined to hold a set of variables and their accessors. In these examples, we'll call the generated class “Customer Class,'' and we'll show an example instance of that class as “CustomerInst.''

In the descriptions that follow, the parameter symbol refers to a symbol, which is either a quoted string or a Symbol (such as :name).

In Files

  • struct.c

Parent

Object

Included Modules

  • Enumerable

Public Class Methods

new( [aString] [, aSym]+> ) → StructClass click to toggle source
new( [aString] [, aSym]+> ) {|StructClass| block } → StructClass
new(arg, ...) → obj
StructClass[arg, ...] → obj

Creates a new class, named by aString, containing accessor methods for the given symbols. If the name aString is omitted, an anonymous structure class will be created. Otherwise, the name of this struct will appear as a constant in class Struct, so it must be unique for all Structs in the system and should start with a capital letter. Assigning a structure class to a constant effectively gives the class the name of the constant.

If a block is given, it will be evaluated in the context of StructClass, passing StructClass as a parameter.

Customer = Struct.new(:name, :address) do
  def greeting
    "Hello #{name}!"
  end
end
Customer.new("Dave", "123 Main").greeting  # => "Hello Dave!"

Struct::new returns a new Class object, which can then be used to create specific instances of the new structure. The number of actual parameters must be less than or equal to the number of attributes defined for this class; unset parameters default to nil. Passing too many parameters will raise an ArgumentError.

The remaining methods listed in this section (class and instance) are defined for this generated class.

# Create a structure with a name in Struct
Struct.new("Customer", :name, :address)    #=> Struct::Customer
Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">

# Create a structure named by its constant
Customer = Struct.new(:name, :address)     #=> Customer
Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">

static VALUE
rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
{
    VALUE name, rest;
    long i;
    VALUE st;
    ID id;

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    name = argv[0];
    if (SYMBOL_P(name)) {
        name = Qnil;
    }
    else {
        --argc;
        ++argv;
    }
    rest = rb_ary_tmp_new(argc);
    for (i=0; i<argc; i++) {
        id = rb_to_id(argv[i]);
        RARRAY_PTR(rest)[i] = ID2SYM(id);
        rb_ary_set_len(rest, i+1);
    }
    if (NIL_P(name)) {
        st = anonymous_struct(klass);
    }
    else {
        st = new_struct(name, klass);
    }
    setup_struct(st, rest);
    if (rb_block_given_p()) {
        rb_mod_module_eval(0, 0, st);
    }

    return st;
}

Public Instance Methods

struct == other_struct → true or false click to toggle source

Equality—Returns true if other_struct is equal to this one: they must be of the same class as generated by Struct::new, and the values of all instance variables must be equal (according to Object#==).

Customer = Struct.new(:name, :address, :zip)
joe   = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
jane  = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
joe == joejr   #=> true
joe == jane    #=> false

static VALUE
rb_struct_equal(VALUE s, VALUE s2)
{
    if (s == s2) return Qtrue;
    if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
    if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
        rb_bug("inconsistent struct"); /* should never happen */
    }

    return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
}
struct[symbol] → anObject click to toggle source
struct[fixnum] → anObject

Attribute Reference—Returns the value of the instance variable named by symbol, or indexed (0..length-1) by fixnum. Will raise NameError if the named variable does not exist, or IndexError if the index is out of range.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe["name"]   #=> "Joe Smith"
joe[:name]    #=> "Joe Smith"
joe[0]        #=> "Joe Smith"

VALUE
rb_struct_aref(VALUE s, VALUE idx)
{
    long i;

    if (RB_TYPE_P(idx, T_SYMBOL)) {
        return rb_struct_aref_id(s, SYM2ID(idx));
    }
    else if (RB_TYPE_P(idx, T_STRING)) {
        ID id = rb_check_id(&idx);
        if (!id) {
            rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
                              QUOTE(idx));
        }
        return rb_struct_aref_id(s, id);
    }

    i = NUM2LONG(idx);
    if (i < 0) i = RSTRUCT_LEN(s) + i;
    if (i < 0)
        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
                 i, RSTRUCT_LEN(s));
    if (RSTRUCT_LEN(s) <= i)
        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
                 i, RSTRUCT_LEN(s));
    return RSTRUCT_PTR(s)[i];
}
struct[symbol] = obj → obj click to toggle source
struct[fixnum] = obj → obj

Attribute Assignment—Assigns to the instance variable named by symbol or fixnum the value obj and returns it. Will raise a NameError if the named variable does not exist, or an IndexError if the index is out of range.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe["name"] = "Luke"
joe[:zip]   = "90210"

joe.name   #=> "Luke"
joe.zip    #=> "90210"

VALUE
rb_struct_aset(VALUE s, VALUE idx, VALUE val)
{
    long i;

    if (RB_TYPE_P(idx, T_SYMBOL)) {
        return rb_struct_aset_id(s, SYM2ID(idx), val);
    }
    if (RB_TYPE_P(idx, T_STRING)) {
        ID id = rb_check_id(&idx);
        if (!id) {
            rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
                              QUOTE(idx));
        }
        return rb_struct_aset_id(s, id, val);
    }

    i = NUM2LONG(idx);
    if (i < 0) i = RSTRUCT_LEN(s) + i;
    if (i < 0) {
        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
                 i, RSTRUCT_LEN(s));
    }
    if (RSTRUCT_LEN(s) <= i) {
        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
                 i, RSTRUCT_LEN(s));
    }
    rb_struct_modify(s);
    return RSTRUCT_PTR(s)[i] = val;
}
each {|obj| block } → struct click to toggle source
each → an_enumerator

Calls block once for each instance variable, passing the value as a parameter.

If no block is given, an enumerator is returned instead.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each {|x| puts(x) }

produces:

Joe Smith
123 Maple, Anytown NC
12345
static VALUE
rb_struct_each(VALUE s)
{
    long i;

    RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
    for (i=0; i<RSTRUCT_LEN(s); i++) {
        rb_yield(RSTRUCT_PTR(s)[i]);
    }
    return s;
}
each_pair {|sym, obj| block } → struct click to toggle source
each_pair → an_enumerator

Calls block once for each instance variable, passing the name (as a symbol) and the value as parameters.

If no block is given, an enumerator is returned instead.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each_pair {|name, value| puts("#{name} => #{value}") }

produces:

name => Joe Smith
address => 123 Maple, Anytown NC
zip => 12345

static VALUE
rb_struct_each_pair(VALUE s)
{
    VALUE members;
    long i;

    RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
    members = rb_struct_members(s);
    for (i=0; i<RSTRUCT_LEN(s); i++) {
        VALUE key = rb_ary_entry(members, i);
        VALUE value = RSTRUCT_PTR(s)[i];
        rb_yield(rb_assoc_new(key, value));
    }
    return s;
}
eql?(other) → true or false click to toggle source

Two structures are equal if they are the same object, or if all their fields are equal (using eql?).

static VALUE
rb_struct_eql(VALUE s, VALUE s2)
{
    if (s == s2) return Qtrue;
    if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
    if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
        rb_bug("inconsistent struct"); /* should never happen */
    }

    return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
}
hash → fixnum click to toggle source

Return a hash value based on this struct's contents.

static VALUE
rb_struct_hash(VALUE s)
{
    return rb_exec_recursive_outer(recursive_hash, s, 0);
}
to_s → string click to toggle source
inspect → string

Describe the contents of this struct in a string.

static VALUE
rb_struct_inspect(VALUE s)
{
    return rb_exec_recursive(inspect_struct, s, 0);
}
Also aliased as: to_s
length → fixnum click to toggle source
size → fixnum

Returns the number of instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.length   #=> 3

static VALUE
rb_struct_size(VALUE s)
{
    return LONG2FIX(RSTRUCT_LEN(s));
}
members → array click to toggle source

Returns an array of symbols representing the names of the instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.members   #=> [:name, :address, :zip]

static VALUE
rb_struct_members_m(VALUE obj)
{
    return rb_struct_s_members_m(rb_obj_class(obj));
}
select {|i| block } → array click to toggle source
select → an_enumerator

Invokes the block passing in successive elements from struct, returning an array containing those elements for which the block returns a true value (equivalent to Enumerable#select).

Lots = Struct.new(:a, :b, :c, :d, :e, :f)
l = Lots.new(11, 22, 33, 44, 55, 66)
l.select {|v| (v % 2).zero? }   #=> [22, 44, 66]

static VALUE
rb_struct_select(int argc, VALUE *argv, VALUE s)
{
    VALUE result;
    long i;

    rb_check_arity(argc, 0, 0);
    RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
    result = rb_ary_new();
    for (i = 0; i < RSTRUCT_LEN(s); i++) {
        if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
            rb_ary_push(result, RSTRUCT_PTR(s)[i]);
        }
    }

    return result;
}
length → fixnum click to toggle source
size → fixnum

Returns the number of instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.length   #=> 3

static VALUE
rb_struct_size(VALUE s)
{
    return LONG2FIX(RSTRUCT_LEN(s));
}
to_a → array click to toggle source
values → array

Returns the values for this instance as an array.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_a[1]   #=> "123 Maple, Anytown NC"

static VALUE
rb_struct_to_a(VALUE s)
{
    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
}
to_h → hash click to toggle source

Returns the values for this instance as a hash with keys corresponding to the instance variable name.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_h[:address]   #=> "123 Maple, Anytown NC"

static VALUE
rb_struct_to_h(VALUE s)
{
    VALUE h = rb_hash_new();
    VALUE members = rb_struct_members(s);
    long i;

    for (i=0; i<RSTRUCT_LEN(s); i++) {
        rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
    }
    return h;
}
to_s() click to toggle source
Alias for: inspect
to_a → array click to toggle source
values → array

Returns the values for this instance as an array.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_a[1]   #=> "123 Maple, Anytown NC"

static VALUE
rb_struct_to_a(VALUE s)
{
    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
}
values_at(selector,... ) → an_array click to toggle source

Returns an array containing the elements in self corresponding to the given selector(s). The selectors may be either integer indices or ranges. See also </code>.select<code>.

a = %w{ a b c d e f }
a.values_at(1, 3, 5)
a.values_at(1, 3, 5, 7)
a.values_at(-1, -3, -5, -7)
a.values_at(1..3, 2...5)
static VALUE
rb_struct_values_at(int argc, VALUE *argv, VALUE s)
{
    return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
}


class Symbol - Ruby 2.0.0-p576 Core API Reference API Reference

class Symbol

Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program's execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.

module One
  class Fred
  end
  $f1 = :Fred
end
module Two
  Fred = 1
  $f2 = :Fred
end
def Fred()
end
$f3 = :Fred
$f1.object_id   #=> 2514190
$f2.object_id   #=> 2514190
$f3.object_id   #=> 2514190

In Files

  • string.c

Parent

Object

Included Modules

  • Comparable

Public Class Methods

all_symbols → array click to toggle source

Returns an array of all the symbols currently in Ruby's symbol table.

Symbol.all_symbols.size    #=> 903
Symbol.all_symbols[1,20]   #=> [:floor, :ARGV, :Binding, :symlink,
                                :chown, :EOFError, :$;, :String,
                                :LOCK_SH, :"setuid?", :$<,
                                :default_proc, :compact, :extend,
                                :Tms, :getwd, :$=, :ThreadGroup,
                                :wait2, :$>]

VALUE
rb_sym_all_symbols(void)
{
    VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);

    st_foreach(global_symbols.sym_id, symbols_i, ary);
    return ary;
}

Public Instance Methods

symbol <=> other_symbol → -1, 0, +1 or nil click to toggle source

Compares symbol with other_symbol after calling to_s on each of the symbols. Returns -1, 0, +1 or nil depending on whether symbol is less than, equal to, or greater than other_symbol.

+nil+ is returned if the two values are incomparable.

See String#<=> for more information.

static VALUE
sym_cmp(VALUE sym, VALUE other)
{
    if (!SYMBOL_P(other)) {
        return Qnil;
    }
    return rb_str_cmp_m(rb_sym_to_s(sym), rb_sym_to_s(other));
}
sym == obj → true or false click to toggle source

Equality—If sym and obj are exactly the same symbol, returns true.

static VALUE
sym_equal(VALUE sym1, VALUE sym2)
{
    if (sym1 == sym2) return Qtrue;
    return Qfalse;
}
sym == obj → true or false click to toggle source

Equality—If sym and obj are exactly the same symbol, returns true.

static VALUE
sym_equal(VALUE sym1, VALUE sym2)
{
    if (sym1 == sym2) return Qtrue;
    return Qfalse;
}
sym =~ obj → fixnum or nil click to toggle source

Returns sym.to_s =~ obj.

static VALUE
sym_match(VALUE sym, VALUE other)
{
    return rb_str_match(rb_sym_to_s(sym), other);
}
sym[idx] → char click to toggle source
sym[b, n] → char

Returns sym.to_s[].

static VALUE
sym_aref(int argc, VALUE *argv, VALUE sym)
{
    return rb_str_aref_m(argc, argv, rb_sym_to_s(sym));
}
capitalize → symbol click to toggle source

Same as sym.to_s.capitalize.intern.

static VALUE
sym_capitalize(VALUE sym)
{
    return rb_str_intern(rb_str_capitalize(rb_id2str(SYM2ID(sym))));
}
casecmp(other) → -1, 0, +1 or nil click to toggle source

Case-insensitive version of Symbol#<=>.

static VALUE
sym_casecmp(VALUE sym, VALUE other)
{
    if (!SYMBOL_P(other)) {
        return Qnil;
    }
    return rb_str_casecmp(rb_sym_to_s(sym), rb_sym_to_s(other));
}
downcase → symbol click to toggle source

Same as sym.to_s.downcase.intern.

static VALUE
sym_downcase(VALUE sym)
{
    return rb_str_intern(rb_str_downcase(rb_id2str(SYM2ID(sym))));
}
empty? → true or false click to toggle source

Returns that sym is :“” or not.

static VALUE
sym_empty(VALUE sym)
{
    return rb_str_empty(rb_id2str(SYM2ID(sym)));
}
encoding → encoding click to toggle source

Returns the Encoding object that represents the encoding of sym.

static VALUE
sym_encoding(VALUE sym)
{
    return rb_obj_encoding(rb_id2str(SYM2ID(sym)));
}
id2name → string click to toggle source
to_s → string

Returns the name or string corresponding to sym.

:fred.id2name   #=> "fred"

VALUE
rb_sym_to_s(VALUE sym)
{
    ID id = SYM2ID(sym);

    return str_new3(rb_cString, rb_id2str(id));
}
inspect → string click to toggle source

Returns the representation of sym as a symbol literal.

:fred.inspect   #=> ":fred"

static VALUE
sym_inspect(VALUE sym)
{
    VALUE str;
    const char *ptr;
    long len;
    ID id = SYM2ID(sym);
    char *dest;

    sym = rb_id2str(id);
    if (!rb_str_symname_p(sym)) {
        str = rb_str_inspect(sym);
        len = RSTRING_LEN(str);
        rb_str_resize(str, len + 1);
        dest = RSTRING_PTR(str);
        memmove(dest + 1, dest, len);
        dest[0] = ':';
    }
    else {
        rb_encoding *enc = STR_ENC_GET(sym);
        ptr = RSTRING_PTR(sym);
        len = RSTRING_LEN(sym);
        str = rb_enc_str_new(0, len + 1, enc);
        dest = RSTRING_PTR(str);
        dest[0] = ':';
        memcpy(dest + 1, ptr, len);
    }
    return str;
}
to_sym → sym click to toggle source
intern → sym

In general, to_sym returns the Symbol corresponding to an object. As sym is already a symbol, self is returned in this case.

static VALUE
sym_to_sym(VALUE sym)
{
    return sym;
}
length → integer click to toggle source

Same as sym.to_s.length.

static VALUE
sym_length(VALUE sym)
{
    return rb_str_length(rb_id2str(SYM2ID(sym)));
}
sym =~ obj → fixnum or nil click to toggle source

Returns sym.to_s =~ obj.

static VALUE
sym_match(VALUE sym, VALUE other)
{
    return rb_str_match(rb_sym_to_s(sym), other);
}
succ click to toggle source

Same as sym.to_s.succ.intern.

static VALUE
sym_succ(VALUE sym)
{
    return rb_str_intern(rb_str_succ(rb_sym_to_s(sym)));
}
length → integer click to toggle source

Same as sym.to_s.length.

static VALUE
sym_length(VALUE sym)
{
    return rb_str_length(rb_id2str(SYM2ID(sym)));
}
sym[idx] → char click to toggle source
sym[b, n] → char

Returns sym.to_s[].

static VALUE
sym_aref(int argc, VALUE *argv, VALUE sym)
{
    return rb_str_aref_m(argc, argv, rb_sym_to_s(sym));
}
succ click to toggle source

Same as sym.to_s.succ.intern.

static VALUE
sym_succ(VALUE sym)
{
    return rb_str_intern(rb_str_succ(rb_sym_to_s(sym)));
}
swapcase → symbol click to toggle source

Same as sym.to_s.swapcase.intern.

static VALUE
sym_swapcase(VALUE sym)
{
    return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym))));
}
to_proc click to toggle source

Returns a Proc object which respond to the given method by sym.

(1..3).collect(&:to_s)  #=> ["1", "2", "3"]

static VALUE
sym_to_proc(VALUE sym)
{
    static VALUE sym_proc_cache = Qfalse;
    enum {SYM_PROC_CACHE_SIZE = 67};
    VALUE proc;
    long id, index;
    VALUE *aryp;

    if (!sym_proc_cache) {
        sym_proc_cache = rb_ary_tmp_new(SYM_PROC_CACHE_SIZE * 2);
        rb_gc_register_mark_object(sym_proc_cache);
        rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
    }

    id = SYM2ID(sym);
    index = (id % SYM_PROC_CACHE_SIZE) << 1;

    aryp = RARRAY_PTR(sym_proc_cache);
    if (aryp[index] == sym) {
        return aryp[index + 1];
    }
    else {
        proc = rb_proc_new(sym_call, (VALUE)id);
        aryp[index] = sym;
        aryp[index + 1] = proc;
        return proc;
    }
}
id2name → string click to toggle source
to_s → string

Returns the name or string corresponding to sym.

:fred.id2name   #=> "fred"

VALUE
rb_sym_to_s(VALUE sym)
{
    ID id = SYM2ID(sym);

    return str_new3(rb_cString, rb_id2str(id));
}
to_sym → sym click to toggle source
intern → sym

In general, to_sym returns the Symbol corresponding to an object. As sym is already a symbol, self is returned in this case.

static VALUE
sym_to_sym(VALUE sym)
{
    return sym;
}
upcase → symbol click to toggle source

Same as sym.to_s.upcase.intern.

static VALUE
sym_upcase(VALUE sym)
{
    return rb_str_intern(rb_str_upcase(rb_id2str(SYM2ID(sym))));
}


class SyntaxError - Ruby 2.0.0-p576 Core API Reference API Reference

class SyntaxError

Raised when encountering Ruby code with an invalid syntax.

eval("1+1=2")

raises the exception:

SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end

In Files

  • error.c

Parent

ScriptError


class SystemCallError - Ruby 2.0.0-p576 Core API Reference API Reference

class SystemCallError

SystemCallError is the base class for all low-level platform-dependent errors.

The errors available on the current platform are subclasses of SystemCallError and are defined in the Errno module.

File.open("does/not/exist")

raises the exception:

Errno::ENOENT: No such file or directory - does/not/exist

In Files

  • error.c

Parent

StandardError

Public Class Methods

system_call_error === other → true or false click to toggle source

Return true if the receiver is a generic SystemCallError, or if the error numbers self and other are the same.

static VALUE
syserr_eqq(VALUE self, VALUE exc)
{
    VALUE num, e;
    ID en;

    CONST_ID(en, "errno");

    if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
        if (!rb_respond_to(exc, en)) return Qfalse;
    }
    else if (self == rb_eSystemCallError) return Qtrue;

    num = rb_attr_get(exc, rb_intern("errno"));
    if (NIL_P(num)) {
        num = rb_funcall(exc, en, 0, 0);
    }
    e = rb_const_get(self, rb_intern("Errno"));
    if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
        return Qtrue;
    return Qfalse;
}
new(msg, errno) → system_call_error_subclass click to toggle source

If errno corresponds to a known system error code, constructs the appropriate Errno class for that error, otherwise constructs a generic SystemCallError object. The error number is subsequently available via the errno method.

static VALUE
syserr_initialize(int argc, VALUE *argv, VALUE self)
{
#if !defined(_WIN32)
    char *strerror();
#endif
    const char *err;
    VALUE mesg, error;
    VALUE klass = rb_obj_class(self);

    if (klass == rb_eSystemCallError) {
        st_data_t data = (st_data_t)klass;
        rb_scan_args(argc, argv, "11", &mesg, &error);
        if (argc == 1 && FIXNUM_P(mesg)) {
            error = mesg; mesg = Qnil;
        }
        if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
            klass = (VALUE)data;
            /* change class */
            if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
                rb_raise(rb_eTypeError, "invalid instance type");
            }
            RBASIC(self)->klass = klass;
        }
    }
    else {
        rb_scan_args(argc, argv, "01", &mesg);
        error = rb_const_get(klass, rb_intern("Errno"));
    }
    if (!NIL_P(error)) err = strerror(NUM2INT(error));
    else err = "unknown error";
    if (!NIL_P(mesg)) {
        rb_encoding *le = rb_locale_encoding();
        VALUE str = StringValue(mesg);
        rb_encoding *me = rb_enc_get(mesg);

        mesg = rb_sprintf("%s - %"PRIsVALUE, err, mesg);
        if (le != me && rb_enc_asciicompat(me)) {
            le = me;
        }/* else assume err is non ASCII string. */
        OBJ_INFECT(mesg, str);
        rb_enc_associate(mesg, le);
    }
    else {
        mesg = rb_str_new2(err);
        rb_enc_associate(mesg, rb_locale_encoding());
    }
    rb_call_super(1, &mesg);
    rb_iv_set(self, "errno", error);
    return self;
}

Public Instance Methods

errno → fixnum click to toggle source

Return this SystemCallError's error number.

static VALUE
syserr_errno(VALUE self)
{
    return rb_attr_get(self, rb_intern("errno"));
}


class SystemExit - Ruby 2.0.0-p576 Core API Reference API Reference

class SystemExit

Raised by exit to initiate the termination of the script.

In Files

  • error.c

Parent

Exception

Public Class Methods

new → system_exit click to toggle source
new(status) → system_exit
new(status, msg) → system_exit
new(msg) → system_exit

Create a new SystemExit exception with the given status and message. Status is true, false, or an integer. If status is not given, true is used.

static VALUE
exit_initialize(int argc, VALUE *argv, VALUE exc)
{
    VALUE status;
    if (argc > 0) {
        status = *argv;

        switch (status) {
          case Qtrue:
            status = INT2FIX(EXIT_SUCCESS);
            ++argv;
            --argc;
            break;
          case Qfalse:
            status = INT2FIX(EXIT_FAILURE);
            ++argv;
            --argc;
            break;
          default:
            status = rb_check_to_int(status);
            if (NIL_P(status)) {
                status = INT2FIX(EXIT_SUCCESS);
            }
            else {
#if EXIT_SUCCESS != 0
                if (status == INT2FIX(0))
                    status = INT2FIX(EXIT_SUCCESS);
#endif
                ++argv;
                --argc;
            }
            break;
        }
    }
    else {
        status = INT2FIX(EXIT_SUCCESS);
    }
    rb_call_super(argc, argv);
    rb_iv_set(exc, "status", status);
    return exc;
}

Public Instance Methods

status → fixnum click to toggle source

Return the status value associated with this system exit.

static VALUE
exit_status(VALUE exc)
{
    return rb_attr_get(exc, rb_intern("status"));
}
success? → true or false click to toggle source

Returns true if exiting successful, false if not.

static VALUE
exit_success_p(VALUE exc)
{
    VALUE status_val = rb_attr_get(exc, rb_intern("status"));
    int status;

    if (NIL_P(status_val))
        return Qtrue;
    status = NUM2INT(status_val);
    if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
        return Qtrue;

    return Qfalse;
}


class SystemStackError - Ruby 2.0.0-p576 Core API Reference API Reference

class SystemStackError

Raised in case of a stack overflow.

def me_myself_and_i
  me_myself_and_i
end
me_myself_and_i

raises the exception:

SystemStackError: stack level too deep

In Files

  • proc.c

Parent

Exception


class Thread - Ruby 2.0.0-p576 Core API Reference API Reference

class Thread

::RubyVM

In Files

  • thread.c
  • vm.c
  • vm_trace.c

Parent

Object

Public Class Methods

DEBUG → num click to toggle source

Returns the thread debug level. Available only if compiled with THREAD_DEBUG=-1.

static VALUE
rb_thread_s_debug(void)
{
    return INT2NUM(rb_thread_debug_enabled);
}
DEBUG = num click to toggle source

Sets the thread debug level. Available only if compiled with THREAD_DEBUG=-1.

static VALUE
rb_thread_s_debug_set(VALUE self, VALUE val)
{
    rb_thread_debug_enabled = RTEST(val) ? NUM2INT(val) : 0;
    return val;
}
abort_on_exception → true or false click to toggle source

Returns the status of the global “abort on exception'' condition. The default is false. When set to true, or if the global $DEBUG flag is true (perhaps because the command line option -d was specified) all threads will abort (the process will exit(0)) if an exception is raised in any thread. See also Thread::abort_on_exception=.

static VALUE
rb_thread_s_abort_exc(void)
{
    return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse;
}
abort_on_exception= boolean → true or false click to toggle source

When set to true, all threads will abort if an exception is raised. Returns the new state.

Thread.abort_on_exception = true
t1 = Thread.new do
  puts  "In new thread"
  raise "Exception from thread"
end
sleep(1)
puts "not reached"

produces:

In new thread
prog.rb:4: Exception from thread (RuntimeError)
 from prog.rb:2:in `initialize'
 from prog.rb:2:in `new'
 from prog.rb:2
static VALUE
rb_thread_s_abort_exc_set(VALUE self, VALUE val)
{
    rb_secure(4);
    GET_THREAD()->vm->thread_abort_on_exception = RTEST(val);
    return val;
}
current → thread click to toggle source

Returns the currently executing thread.

Thread.current   #=> #<Thread:0x401bdf4c run>

static VALUE
thread_s_current(VALUE klass)
{
    return rb_thread_current();
}
exit → thread click to toggle source

Terminates the currently running thread and schedules another thread to be run. If this thread is already marked to be killed, exit returns the Thread. If this is the main thread, or the last thread, exit the process.

static VALUE
rb_thread_exit(void)
{
    rb_thread_t *th = GET_THREAD();
    return rb_thread_kill(th->self);
}
start([args]*) {|args| block } → thread click to toggle source
fork([args]*) {|args| block } → thread

Basically the same as ::new. However, if class Thread is subclassed, then calling start in that subclass will not invoke the subclass's initialize method.

static VALUE
thread_start(VALUE klass, VALUE args)
{
    return thread_create_core(rb_thread_alloc(klass), args, 0);
}
handle_interrupt(hash) { ... } → result of the block click to toggle source

Changes asynchronous interrupt timing.

interrupt means asynchronous event and corresponding procedure by #raise, #kill, signal trap (not supported yet) and main thread termination (if main thread terminates, then all other thread will be killed).

The given hash has pairs like ExceptionClass => :TimingSymbol. Where the ExceptionClass is the interrupt handled by the given block. The TimingSymbol can be one of the following symbols:

:immediate

Invoke interrupts immediately.

:on_blocking

Invoke interrupts while BlockingOperation.

:never

Never invoke all interrupts.

BlockingOperation means that the operation will block the calling thread, such as read and write. On CRuby implementation, BlockingOperation is any operation executed without GVL.

Masked asynchronous interrupts are delayed until they are enabled. This method is similar to sigprocmask(3).

NOTE

Asynchronous interrupts are difficult to use.

If you need to communicate between threads, please consider to use another way such as Queue.

Or use them with deep understanding about this method.

Usage

In this example, we can guard from #raise exceptions.

Using the :never TimingSymbol the RuntimeError exception will always be ignored in the first block of the main thread. In the second ::handle_interrupt block we can purposefully handle RuntimeError exceptions.

th = Thread.new do
  Thead.handle_interrupt(RuntimeError => :never) {
    begin
      # You can write resource allocation code safely.
      Thread.handle_interrupt(RuntimeError => :immediate) {
        # ...
      }
    ensure
      # You can write resource deallocation code safely.
    end
  }
end
Thread.pass
# ...
th.raise "stop"

While we are ignoring the RuntimeError exception, it's safe to write our resource allocation code. Then, the ensure block is where we can safely deallocate your resources.

Guarding from TimeoutError

In the next example, we will guard from the TimeoutError exception. This will help prevent from leaking resources when TimeoutError exceptions occur during normal ensure clause. For this example we use the help of the standard library Timeout, from lib/timeout.rb

require 'timeout'
Thread.handle_interrupt(TimeoutError => :never) {
  timeout(10){
    # TimeoutError doesn't occur here
    Thread.handle_interrupt(TimeoutError => :on_blocking) {
      # possible to be killed by TimeoutError
      # while blocking operation
    }
    # TimeoutError doesn't occur here
  }
}

In the first part of the timeout block, we can rely on TimeoutError being ignored. Then in the TimeoutError => :on_blocking block, any operation that will block the calling thread is susceptible to a TimeoutError exception being raised.

Stack control settings

It's possible to stack multiple levels of ::handle_interrupt blocks in order to control more than one ExceptionClass and TimingSymbol at a time.

Thread.handle_interrupt(FooError => :never) {
  Thread.handle_interrupt(BarError => :never) {
     # FooError and BarError are prohibited.
  }
}

Inheritance with ExceptionClass

All exceptions inherited from the ExceptionClass parameter will be considered.

Thread.handle_interrupt(Exception => :never) {
  # all exceptions inherited from Exception are prohibited.
}

static VALUE
rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg)
{
    VALUE mask;
    rb_thread_t *th = GET_THREAD();
    VALUE r = Qnil;
    int state;

    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "block is needed.");
    }

    mask = rb_convert_type(mask_arg, T_HASH, "Hash", "to_hash");
    rb_hash_foreach(mask, handle_interrupt_arg_check_i, 0);
    rb_ary_push(th->pending_interrupt_mask_stack, mask);
    if (!rb_threadptr_pending_interrupt_empty_p(th)) {
        th->pending_interrupt_queue_checked = 0;
        RUBY_VM_SET_INTERRUPT(th);
    }

    TH_PUSH_TAG(th);
    if ((state = EXEC_TAG()) == 0) {
        r = rb_yield(Qnil);
    }
    TH_POP_TAG();

    rb_ary_pop(th->pending_interrupt_mask_stack);
    if (!rb_threadptr_pending_interrupt_empty_p(th)) {
        th->pending_interrupt_queue_checked = 0;
        RUBY_VM_SET_INTERRUPT(th);
    }

    RUBY_VM_CHECK_INTS(th);

    if (state) {
        JUMP_TAG(state);
    }

    return r;
}
kill(thread) → thread click to toggle source

Causes the given thread to exit (see Thread::exit).

count = 0
a = Thread.new { loop { count += 1 } }
sleep(0.1)       #=> 0
Thread.kill(a)   #=> #<Thread:0x401b3d30 dead>
count            #=> 93947
a.alive?         #=> false

static VALUE
rb_thread_s_kill(VALUE obj, VALUE th)
{
    return rb_thread_kill(th);
}
list → array click to toggle source

Returns an array of Thread objects for all threads that are either runnable or stopped.

Thread.new { sleep(200) }
Thread.new { 1000000.times {|i| i*i } }
Thread.new { Thread.stop }
Thread.list.each {|t| p t}

produces:

#<Thread:0x401b3e84 sleep>
#<Thread:0x401b3f38 run>
#<Thread:0x401b3fb0 sleep>
#<Thread:0x401bdf4c run>
VALUE
rb_thread_list(void)
{
    VALUE ary = rb_ary_new();
    st_foreach(GET_THREAD()->vm->living_threads, thread_list_i, ary);
    return ary;
}
main → thread click to toggle source

Returns the main thread.

static VALUE
rb_thread_s_main(VALUE klass)
{
    return rb_thread_main();
}
new { ... } → thread click to toggle source
new(*args, &proc) → thread
new(*args) { |args| ... } → thread

Creates a new thread executing the given block.

Any args given to ::new will be passed to the block:

arr = []
a, b, c = 1, 2, 3
Thread.new(a,b,c) { |d,e,f| arr << d << e << f }.join
arr #=> [1, 2, 3]

A ThreadError exception is raised if ::new is called without a block.

If you're going to subclass Thread, be sure to call super in your initialize method, otherwise a ThreadError will be raised.

static VALUE
thread_s_new(int argc, VALUE *argv, VALUE klass)
{
    rb_thread_t *th;
    VALUE thread = rb_thread_alloc(klass);

    if (GET_VM()->main_thread->status == THREAD_KILLED)
        rb_raise(rb_eThreadError, "can't alloc thread");

    rb_obj_call_init(thread, argc, argv);
    GetThreadPtr(thread, th);
    if (!th->first_args) {
        rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
                 rb_class2name(klass));
    }
    return thread;
}
pass → nil click to toggle source

Give the thread scheduler a hint to pass execution to another thread. A running thread may or may not switch, it depends on OS and processor.

static VALUE
thread_s_pass(VALUE klass)
{
    rb_thread_schedule();
    return Qnil;
}
pending_interrupt?(error = nil) → true/false click to toggle source

Returns whether or not the asynchronous queue is empty.

Since ::handle_interrupt can be used to defer asynchronous events. This method can be used to determine if there are any deferred events.

If you find this method returns true, then you may finish :never blocks.

For example, the following method processes deferred asynchronous events immediately.

def Thread.kick_interrupt_immediately
  Thread.handle_interrupt(Object => :immediate) {
    Thread.pass
  }
end

If error is given, then check only for error type deferred events.

Usage

th = Thread.new{
  Thread.handle_interrupt(RuntimeError => :on_blocking){
    while true
      ...
      # reach safe point to invoke interrupt
      if Thread.pending_interrupt?
        Thread.handle_interrupt(Object => :immediate){}
      end
      ...
    end
  }
}
...
th.raise # stop thread

This example can also be written as the following, which you should use to avoid asynchronous interrupts.

flag = true
th = Thread.new{
  Thread.handle_interrupt(RuntimeError => :on_blocking){
    while true
      ...
      # reach safe point to invoke interrupt
      break if flag == false
      ...
    end
  }
}
...
flag = false # stop thread

static VALUE
rb_thread_s_pending_interrupt_p(int argc, VALUE *argv, VALUE self)
{
    return rb_thread_pending_interrupt_p(argc, argv, GET_THREAD()->self);
}
start([args]*) {|args| block } → thread click to toggle source
fork([args]*) {|args| block } → thread

Basically the same as ::new. However, if class Thread is subclassed, then calling start in that subclass will not invoke the subclass's initialize method.

static VALUE
thread_start(VALUE klass, VALUE args)
{
    return thread_create_core(rb_thread_alloc(klass), args, 0);
}
stop → nil click to toggle source

Stops execution of the current thread, putting it into a “sleep'' state, and schedules execution of another thread.

a = Thread.new { print "a"; Thread.stop; print "c" }
sleep 0.1 while a.status!='sleep'
print "b"
a.run
a.join

produces:

abc
VALUE
rb_thread_stop(void)
{
    if (rb_thread_alone()) {
        rb_raise(rb_eThreadError,
                 "stopping only thread\n\tnote: use sleep to stop forever");
    }
    rb_thread_sleep_deadly();
    return Qnil;
}

Public Instance Methods

thr[sym] → obj or nil click to toggle source

Attribute Reference—Returns the value of a fiber-local variable (current thread's root fiber if not explicitely inside a Fiber), using either a symbol or a string name. If the specified variable does not exist, returns nil.

[
  Thread.new { Thread.current["name"] = "A" },
  Thread.new { Thread.current[:name]  = "B" },
  Thread.new { Thread.current["name"] = "C" }
].each do |th|
  th.join
  puts "#{th.inspect}: #{th[:name]}"
end

produces:

#<Thread:0x00000002a54220 dead>: A
#<Thread:0x00000002a541a8 dead>: B
#<Thread:0x00000002a54130 dead>: C

Thread#[] and Thread#[]= are not thread-local but fiber-local. This confusion did not exist in Ruby 1.8 because fibers were only available since Ruby 1.9. Ruby 1.9 chooses that the methods behaves fiber-local to save following idiom for dynamic scope.

def meth(newvalue)
  begin
    oldvalue = Thread.current[:name]
    Thread.current[:name] = newvalue
    yield
  ensure
    Thread.current[:name] = oldvalue
  end
end

The idiom may not work as dynamic scope if the methods are thread-local and a given block switches fiber.

f = Fiber.new {
  meth(1) {
    Fiber.yield
  }
}
meth(2) {
  f.resume
}
f.resume
p Thread.current[:name]
#=> nil if fiber-local
#=> 2 if thread-local (The value 2 is leaked to outside of meth method.)

For thread-local variables, please see Thread#thread_local_get and Thread#thread_local_set.

static VALUE
rb_thread_aref(VALUE thread, VALUE id)
{
    return rb_thread_local_aref(thread, rb_to_id(id));
}
thr[sym] = obj → obj click to toggle source

Attribute Assignment—Sets or creates the value of a fiber-local variable, using either a symbol or a string. See also Thread#[]. For thread-local variables, please see Thread#thread_variable_set and Thread#thread_variable_get.

static VALUE
rb_thread_aset(VALUE self, VALUE id, VALUE val)
{
    return rb_thread_local_aset(self, rb_to_id(id), val);
}
abort_on_exception → true or false click to toggle source

Returns the status of the thread-local “abort on exception'' condition for thr. The default is false. See also Thread::abort_on_exception=.

static VALUE
rb_thread_abort_exc(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);
    return th->abort_on_exception ? Qtrue : Qfalse;
}
abort_on_exception= boolean → true or false click to toggle source

When set to true, causes all threads (including the main program) to abort if an exception is raised in thr. The process will effectively exit(0).

static VALUE
rb_thread_abort_exc_set(VALUE thread, VALUE val)
{
    rb_thread_t *th;
    rb_secure(4);

    GetThreadPtr(thread, th);
    th->abort_on_exception = RTEST(val);
    return val;
}
add_trace_func(proc) → proc click to toggle source

Adds proc as a handler for tracing. See Thread#set_trace_func and set_trace_func.

static VALUE
thread_add_trace_func_m(VALUE obj, VALUE trace)
{
    rb_thread_t *th;

    rb_secure(4);
    GetThreadPtr(obj, th);
    thread_add_trace_func(th, trace);
    return trace;
}
alive? → true or false click to toggle source

Returns true if thr is running or sleeping.

thr = Thread.new { }
thr.join                #=> #<Thread:0x401b3fb0 dead>
Thread.current.alive?   #=> true
thr.alive?              #=> false

static VALUE
rb_thread_alive_p(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);

    if (rb_threadptr_dead(th))
        return Qfalse;
    return Qtrue;
}
backtrace → array click to toggle source

Returns the current backtrace of the target thread.

static VALUE
rb_thread_backtrace_m(int argc, VALUE *argv, VALUE thval)
{
    return vm_thread_backtrace(argc, argv, thval);
}
backtrace_locations(*args) → array or nil click to toggle source

Returns the execution stack for the target thread—an array containing backtrace location objects.

See Thread::Backtrace::Location for more information.

This method behaves similarly to Kernel#caller_locations except it applies to a specific thread.

static VALUE
rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
{
    return vm_thread_backtrace_locations(argc, argv, thval);
}
exit → thr or nil click to toggle source
kill → thr or nil
terminate → thr or nil

Terminates thr and schedules another thread to be run. If this thread is already marked to be killed, exit returns the Thread. If this is the main thread, or the last thread, exits the process.

VALUE
rb_thread_kill(VALUE thread)
{
    rb_thread_t *th;

    GetThreadPtr(thread, th);

    if (th != GET_THREAD() && th->safe_level < 4) {
        rb_secure(4);
    }
    if (th->to_kill || th->status == THREAD_KILLED) {
        return thread;
    }
    if (th == th->vm->main_thread) {
        rb_exit(EXIT_SUCCESS);
    }

    thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);

    if (th == GET_THREAD()) {
        /* kill myself immediately */
        rb_threadptr_to_kill(th);
    }
    else {
        rb_threadptr_pending_interrupt_enque(th, eKillSignal);
        rb_threadptr_interrupt(th);
    }
    return thread;
}
group → thgrp or nil click to toggle source

Returns the ThreadGroup which contains thr, or nil if the thread is not a member of any group.

Thread.main.group   #=> #<ThreadGroup:0x4029d914>

VALUE
rb_thread_group(VALUE thread)
{
    rb_thread_t *th;
    VALUE group;
    GetThreadPtr(thread, th);
    group = th->thgroup;

    if (!group) {
        group = Qnil;
    }
    return group;
}
inspect → string click to toggle source

Dump the name, id, and status of thr to a string.

static VALUE
rb_thread_inspect(VALUE thread)
{
    const char *cname = rb_obj_classname(thread);
    rb_thread_t *th;
    const char *status;
    VALUE str;

    GetThreadPtr(thread, th);
    status = thread_status_name(th);
    str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
    OBJ_INFECT(str, thread);

    return str;
}
join → thr click to toggle source
join(limit) → thr

The calling thread will suspend execution and run thr. Does not return until thr exits or until limit seconds have passed. If the time limit expires, nil will be returned, otherwise thr is returned.

Any threads not joined will be killed when the main program exits. If thr had previously raised an exception and the abort_on_exception and $DEBUG flags are not set (so the exception has not yet been processed) it will be processed at this time.

a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
x.join # Let x thread finish, a will be killed on exit.

produces:

axyz

The following example illustrates the limit parameter.

y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
puts "Waiting" until y.join(0.15)

produces:

tick...
Waiting
tick...
Waitingtick...

tick...
static VALUE
thread_join_m(int argc, VALUE *argv, VALUE self)
{
    rb_thread_t *target_th;
    double delay = DELAY_INFTY;
    VALUE limit;

    GetThreadPtr(self, target_th);

    rb_scan_args(argc, argv, "01", &limit);
    if (!NIL_P(limit)) {
        delay = rb_num2dbl(limit);
    }

    return thread_join(target_th, delay);
}
key?(sym) → true or false click to toggle source

Returns true if the given string (or symbol) exists as a fiber-local variable.

me = Thread.current
me[:oliver] = "a"
me.key?(:oliver)    #=> true
me.key?(:stanley)   #=> false

static VALUE
rb_thread_key_p(VALUE self, VALUE key)
{
    rb_thread_t *th;
    ID id = rb_to_id(key);

    GetThreadPtr(self, th);

    if (!th->local_storage) {
        return Qfalse;
    }
    if (st_lookup(th->local_storage, id, 0)) {
        return Qtrue;
    }
    return Qfalse;
}
keys → array click to toggle source

Returns an an array of the names of the fiber-local variables (as Symbols).

thr = Thread.new do
  Thread.current[:cat] = 'meow'
  Thread.current["dog"] = 'woof'
end
thr.join   #=> #<Thread:0x401b3f10 dead>
thr.keys   #=> [:dog, :cat]

static VALUE
rb_thread_keys(VALUE self)
{
    rb_thread_t *th;
    VALUE ary = rb_ary_new();
    GetThreadPtr(self, th);

    if (th->local_storage) {
        st_foreach(th->local_storage, thread_keys_i, ary);
    }
    return ary;
}
exit → thr or nil click to toggle source
kill → thr or nil
terminate → thr or nil

Terminates thr and schedules another thread to be run. If this thread is already marked to be killed, exit returns the Thread. If this is the main thread, or the last thread, exits the process.

VALUE
rb_thread_kill(VALUE thread)
{
    rb_thread_t *th;

    GetThreadPtr(thread, th);

    if (th != GET_THREAD() && th->safe_level < 4) {
        rb_secure(4);
    }
    if (th->to_kill || th->status == THREAD_KILLED) {
        return thread;
    }
    if (th == th->vm->main_thread) {
        rb_exit(EXIT_SUCCESS);
    }

    thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);

    if (th == GET_THREAD()) {
        /* kill myself immediately */
        rb_threadptr_to_kill(th);
    }
    else {
        rb_threadptr_pending_interrupt_enque(th, eKillSignal);
        rb_threadptr_interrupt(th);
    }
    return thread;
}
pending_interrupt?(error = nil) → true/false click to toggle source

Returns whether or not the asychronous queue is empty for the target thread.

If error is given, then check only for error type deferred events.

See ::pending_interrupt? for more information.

static VALUE
rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
{
    rb_thread_t *target_th;

    GetThreadPtr(target_thread, target_th);

    if (rb_threadptr_pending_interrupt_empty_p(target_th)) {
        return Qfalse;
    }
    else {
        if (argc == 1) {
            VALUE err;
            rb_scan_args(argc, argv, "01", &err);
            if (!rb_obj_is_kind_of(err, rb_cModule)) {
                rb_raise(rb_eTypeError, "class or module required for rescue clause");
            }
            if (rb_threadptr_pending_interrupt_include_p(target_th, err)) {
                return Qtrue;
            }
            else {
                return Qfalse;
            }
        }
        return Qtrue;
    }
}
priority → integer click to toggle source

Returns the priority of thr. Default is inherited from the current thread which creating the new thread, or zero for the initial main thread; higher-priority thread will run more frequently than lower-priority threads (but lower-priority threads can also run).

This is just hint for Ruby thread scheduler. It may be ignored on some platform.

Thread.current.priority   #=> 0

static VALUE
rb_thread_priority(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);
    return INT2NUM(th->priority);
}
priority= integer → thr click to toggle source

Sets the priority of thr to integer. Higher-priority threads will run more frequently than lower-priority threads (but lower-priority threads can also run).

This is just hint for Ruby thread scheduler. It may be ignored on some platform.

count1 = count2 = 0
a = Thread.new do
      loop { count1 += 1 }
    end
a.priority = -1

b = Thread.new do
      loop { count2 += 1 }
    end
b.priority = -2
sleep 1   #=> 1
count1    #=> 622504
count2    #=> 5832

static VALUE
rb_thread_priority_set(VALUE thread, VALUE prio)
{
    rb_thread_t *th;
    int priority;
    GetThreadPtr(thread, th);

    rb_secure(4);

#if USE_NATIVE_THREAD_PRIORITY
    th->priority = NUM2INT(prio);
    native_thread_apply_priority(th);
#else
    priority = NUM2INT(prio);
    if (priority > RUBY_THREAD_PRIORITY_MAX) {
        priority = RUBY_THREAD_PRIORITY_MAX;
    }
    else if (priority < RUBY_THREAD_PRIORITY_MIN) {
        priority = RUBY_THREAD_PRIORITY_MIN;
    }
    th->priority = priority;
#endif
    return INT2NUM(th->priority);
}
raise click to toggle source
raise(string)
raise(exception [, string [, array]])

Raises an exception (see Kernel::raise) from thr. The caller does not have to be thr.

Thread.abort_on_exception = true
a = Thread.new { sleep(200) }
a.raise("Gotcha")

produces:

prog.rb:3: Gotcha (RuntimeError)
 from prog.rb:2:in `initialize'
 from prog.rb:2:in `new'
 from prog.rb:2
static VALUE
thread_raise_m(int argc, VALUE *argv, VALUE self)
{
    rb_thread_t *target_th;
    rb_thread_t *th = GET_THREAD();
    GetThreadPtr(self, target_th);
    rb_threadptr_raise(target_th, argc, argv);

    /* To perform Thread.current.raise as Kernel.raise */
    if (th == target_th) {
        RUBY_VM_CHECK_INTS(th);
    }
    return Qnil;
}
run → thr click to toggle source

Wakes up thr, making it eligible for scheduling.

a = Thread.new { puts "a"; Thread.stop; puts "c" }
sleep 0.1 while a.status!='sleep'
puts "Got here"
a.run
a.join

produces:

a
Got here
c
VALUE
rb_thread_run(VALUE thread)
{
    rb_thread_wakeup(thread);
    rb_thread_schedule();
    return thread;
}
safe_level → integer click to toggle source

Returns the safe level in effect for thr. Setting thread-local safe levels can help when implementing sandboxes which run insecure code.

thr = Thread.new { $SAFE = 3; sleep }
Thread.current.safe_level   #=> 0
thr.safe_level              #=> 3

static VALUE
rb_thread_safe_level(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);

    return INT2NUM(th->safe_level);
}
set_trace_func(proc) → proc click to toggle source
set_trace_func(nil) → nil

Establishes proc on thr as the handler for tracing, or disables tracing if the parameter is nil. See set_trace_func.

static VALUE
thread_set_trace_func_m(VALUE obj, VALUE trace)
{
    rb_thread_t *th;

    rb_secure(4);
    GetThreadPtr(obj, th);
    rb_threadptr_remove_event_hook(th, call_trace_func, Qundef);

    if (NIL_P(trace)) {
        return Qnil;
    }

    thread_add_trace_func(th, trace);
    return trace;
}
status → string, false or nil click to toggle source

Returns the status of thr: “sleep'' if thr is sleeping or waiting on I/O, “run'' if thr is executing, “aborting'' if thr is aborting, false if thr terminated normally, and nil if thr terminated with an exception.

a = Thread.new { raise("die now") }
b = Thread.new { Thread.stop }
c = Thread.new { Thread.exit }
d = Thread.new { sleep }
d.kill                  #=> #<Thread:0x401b3678 aborting>
a.status                #=> nil
b.status                #=> "sleep"
c.status                #=> false
d.status                #=> "aborting"
Thread.current.status   #=> "run"

static VALUE
rb_thread_status(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);

    if (rb_threadptr_dead(th)) {
        if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo)
            /* TODO */ ) {
            return Qnil;
        }
        return Qfalse;
    }
    return rb_str_new2(thread_status_name(th));
}
stop? → true or false click to toggle source

Returns true if thr is dead or sleeping.

a = Thread.new { Thread.stop }
b = Thread.current
a.stop?   #=> true
b.stop?   #=> false

static VALUE
rb_thread_stop_p(VALUE thread)
{
    rb_thread_t *th;
    GetThreadPtr(thread, th);

    if (rb_threadptr_dead(th))
        return Qtrue;
    if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
        return Qtrue;
    return Qfalse;
}
exit → thr or nil click to toggle source
kill → thr or nil
terminate → thr or nil

Terminates thr and schedules another thread to be run. If this thread is already marked to be killed, exit returns the Thread. If this is the main thread, or the last thread, exits the process.

VALUE
rb_thread_kill(VALUE thread)
{
    rb_thread_t *th;

    GetThreadPtr(thread, th);

    if (th != GET_THREAD() && th->safe_level < 4) {
        rb_secure(4);
    }
    if (th->to_kill || th->status == THREAD_KILLED) {
        return thread;
    }
    if (th == th->vm->main_thread) {
        rb_exit(EXIT_SUCCESS);
    }

    thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);

    if (th == GET_THREAD()) {
        /* kill myself immediately */
        rb_threadptr_to_kill(th);
    }
    else {
        rb_threadptr_pending_interrupt_enque(th, eKillSignal);
        rb_threadptr_interrupt(th);
    }
    return thread;
}
thread_variable?(key) → true or false click to toggle source

Returns true if the given string (or symbol) exists as a thread-local variable.

me = Thread.current
me.thread_variable_set(:oliver, "a")
me.thread_variable?(:oliver)    #=> true
me.thread_variable?(:stanley)   #=> false

Note that these are not fiber local variables. Please see Thread#[] and #thread_variable_get for more details.

static VALUE
rb_thread_variable_p(VALUE thread, VALUE key)
{
    VALUE locals;

    locals = rb_iv_get(thread, "locals");

    if (!RHASH(locals)->ntbl)
        return Qfalse;

    if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) {
        return Qtrue;
    }

    return Qfalse;
}
thread_variable_get(key) → obj or nil click to toggle source

Returns the value of a thread local variable that has been set. Note that these are different than fiber local values. For fiber local values, please see Thread#[] and Thread#[]=.

Thread local values are carried along with threads, and do not respect fibers. For example:

Thread.new {
  Thread.current.thread_variable_set("foo", "bar") # set a thread local
  Thread.current["foo"] = "bar"                    # set a fiber local

  Fiber.new {
    Fiber.yield [
      Thread.current.thread_variable_get("foo"), # get the thread local
      Thread.current["foo"],                     # get the fiber local
    ]
  }.resume
}.join.value # => ['bar', nil]

The value “bar” is returned for the thread local, where nil is returned for the fiber local. The fiber is executed in the same thread, so the thread local values are available.

See also Thread#[]

static VALUE
rb_thread_variable_get(VALUE thread, VALUE id)
{
    VALUE locals;
    rb_thread_t *th;

    GetThreadPtr(thread, th);

    if (rb_safe_level() >= 4 && th != GET_THREAD()) {
        rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
    }

    locals = rb_iv_get(thread, "locals");
    return rb_hash_aref(locals, ID2SYM(rb_to_id(id)));
}
thread_variable_set(key, value) click to toggle source

Sets a thread local with key to value. Note that these are local to threads, and not to fibers. Please see #thread_variable_get and Thread#[] for more information.

static VALUE
rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
{
    VALUE locals;
    rb_thread_t *th;

    GetThreadPtr(thread, th);

    if (rb_safe_level() >= 4 && th != GET_THREAD()) {
        rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
    }
    if (OBJ_FROZEN(thread)) {
        rb_error_frozen("thread locals");
    }

    locals = rb_iv_get(thread, "locals");
    return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val);
}
thread_variables → array click to toggle source

Returns an an array of the names of the thread-local variables (as Symbols).

thr = Thread.new do
  Thread.current.thread_variable_set(:cat, 'meow')
  Thread.current.thread_variable_set("dog", 'woof')
end
thr.join               #=> #<Thread:0x401b3f10 dead>
thr.thread_variables   #=> [:dog, :cat]

Note that these are not fiber local variables. Please see Thread#[] and #thread_variable_get for more details.

static VALUE
rb_thread_variables(VALUE thread)
{
    VALUE locals;
    VALUE ary;

    locals = rb_iv_get(thread, "locals");
    ary = rb_ary_new();
    rb_hash_foreach(locals, keys_i, ary);

    return ary;
}
value → obj click to toggle source

Waits for thr to complete (via Thread#join) and returns its value.

a = Thread.new { 2 + 2 }
a.value   #=> 4

static VALUE
thread_value(VALUE self)
{
    rb_thread_t *th;
    GetThreadPtr(self, th);
    thread_join(th, DELAY_INFTY);
    return th->value;
}
wakeup → thr click to toggle source

Marks thr as eligible for scheduling (it may still remain blocked on I/O, however). Does not invoke the scheduler (see Thread#run).

c = Thread.new { Thread.stop; puts "hey!" }
sleep 0.1 while c.status!='sleep'
c.wakeup
c.join

produces:

hey!
VALUE
rb_thread_wakeup(VALUE thread)
{
    if (!RTEST(rb_thread_wakeup_alive(thread))) {
        rb_raise(rb_eThreadError, "killed thread");
    }
    return thread;
}


class ThreadError - Ruby 2.0.0-p576 Core API Reference API Reference

class ThreadError

Raised when an invalid operation is attempted on a thread.

For example, when no other thread has been started:

Thread.stop

raises the exception:

ThreadError: stopping only thread

In Files

  • thread.c

Parent

StandardError


class ThreadGroup - Ruby 2.0.0-p576 Core API Reference API Reference

class ThreadGroup

ThreadGroup provides a means of keeping track of a number of threads as a group. A Thread can belong to only one ThreadGroup at a time; adding a thread to a new group will remove it from any previous group.

Newly created threads belong to the same group as the thread from which they were created.

In Files

  • thread.c

Parent

Object

Constants

Default

The default ThreadGroup created when Ruby starts; all Threads belong to it by default.

Public Instance Methods

add(thread) → thgrp click to toggle source

Adds the given thread to this group, removing it from any other group to which it may have previously belonged.

puts "Initial group is #{ThreadGroup::Default.list}"
tg = ThreadGroup.new
t1 = Thread.new { sleep }
t2 = Thread.new { sleep }
puts "t1 is #{t1}"
puts "t2 is #{t2}"
tg.add(t1)
puts "Initial group now #{ThreadGroup::Default.list}"
puts "tg group now #{tg.list}"

produces:

Initial group is #<Thread:0x401bdf4c>
t1 is #<Thread:0x401b3c90>
t2 is #<Thread:0x401b3c18>
Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
tg group now #<Thread:0x401b3c90>
static VALUE
thgroup_add(VALUE group, VALUE thread)
{
    rb_thread_t *th;
    struct thgroup *data;

    rb_secure(4);
    GetThreadPtr(thread, th);

    if (OBJ_FROZEN(group)) {
        rb_raise(rb_eThreadError, "can't move to the frozen thread group");
    }
    TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
    if (data->enclosed) {
        rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
    }

    if (!th->thgroup) {
        return Qnil;
    }

    if (OBJ_FROZEN(th->thgroup)) {
        rb_raise(rb_eThreadError, "can't move from the frozen thread group");
    }
    TypedData_Get_Struct(th->thgroup, struct thgroup, &thgroup_data_type, data);
    if (data->enclosed) {
        rb_raise(rb_eThreadError,
                 "can't move from the enclosed thread group");
    }

    th->thgroup = group;
    return group;
}
enclose → thgrp click to toggle source

Prevents threads from being added to or removed from the receiving ThreadGroup. New threads can still be started in an enclosed ThreadGroup.

ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
tg.add thr

produces:

ThreadError: can't move from the enclosed thread group
static VALUE
thgroup_enclose(VALUE group)
{
    struct thgroup *data;

    TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
    data->enclosed = 1;

    return group;
}
enclosed? → true or false click to toggle source

Returns true if thgrp is enclosed. See also #enclose.

static VALUE
thgroup_enclosed_p(VALUE group)
{
    struct thgroup *data;

    TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
    if (data->enclosed)
        return Qtrue;
    return Qfalse;
}
list → array click to toggle source

Returns an array of all existing Thread objects that belong to this group.

ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]

static VALUE
thgroup_list(VALUE group)
{
    VALUE ary = rb_ary_new();
    struct thgroup_list_params param;

    param.ary = ary;
    param.group = group;
    st_foreach(GET_THREAD()->vm->living_threads, thgroup_list_i, (st_data_t) & param);
    return ary;
}


class Time - Ruby 2.0.0-p576 Core API Reference API Reference

class Time

Time is an abstraction of dates and times. Time is stored internally as the number of seconds with fraction since the Epoch, January 1, 1970 00:00 UTC. Also see the library module Date. The Time class treats GMT (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent. GMT is the older way of referring to these baseline times but persists in the names of calls on POSIX systems.

All times may have fraction. Be aware of this fact when comparing times with each other – times that are apparently equal when displayed may be different when compared.

Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, Bignum or Rational. The integer is a number of nanoseconds since the Epoch which can represent 1823-11-12 to 2116-02-20. When Bignum or Rational is used (before 1823, after 2116, under nanosecond), Time works slower as when integer is used.

Examples

All of these examples were done using the EST timezone which is GMT-5.

Creating a new Time instance

You can create a new instance of Time with ::new. This will use the current system time. ::now is an alias for this. You can also pass parts of the time to ::new such as year, month, minute, etc. When you want to construct a time this way you must pass at least a year. If you pass the year with nothing else time will default to January 1 of that year at 00:00:00 with the current system timezone. Here are some examples:

Time.new(2002)         #=> 2002-01-01 00:00:00 -0500
Time.new(2002, 10)     #=> 2002-10-01 00:00:00 -0500
Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500
Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 -0200

You can also use gm, local and utc to infer GMT, local and UTC timezones instead of using the current system setting.

You can also create a new time using ::at which takes the number of seconds (or fraction of seconds) since the Unix Epoch.

Time.at(628232400) #=> 1989-11-28 00:00:00 -0500

Working with an instance of Time

Once you have an instance of Time there is a multitude of things you can do with it. Below are some examples. For all of the following examples, we will work on the assumption that you have done the following:

t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")

Was that a monday?

t.monday? #=> false

What year was that again?

t.year #=> 1993

Was is daylight savings at the time?

t.dst? #=> false

What's the day a year later?

t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900

How many seconds was that since the Unix Epoch?

t.to_i #=> 730522800

You can also do standard functions like compare two times.

t1 = Time.new(2010)
t2 = Time.new(2011)

t1 == t2 #=> false
t1 == t1 #=> true
t1 <  t2 #=> true
t1 >  t2 #=> false

Time.new(2010,10,31).between?(t1, t2) #=> true

In Files

  • time.c

Parent

Object

Included Modules

  • Comparable

Public Class Methods

at(time) → time click to toggle source
at(seconds_with_frac) → time
at(seconds, microseconds_with_frac) → time

Creates a new Time object with the value given by time, the given number of seconds_with_frac, or seconds and microseconds_with_frac since the Epoch. seconds_with_frac and microseconds_with_frac can be an Integer, Float, Rational, or other Numeric. non-portable feature allows the offset to be negative on some systems.

If a numeric argument is given, the result is in local time.

Time.at(0)                           #=> 1969-12-31 18:00:00 -0600
Time.at(Time.at(0))                  #=> 1969-12-31 18:00:00 -0600
Time.at(946702800)                   #=> 1999-12-31 23:00:00 -0600
Time.at(-284061600)                  #=> 1960-12-31 00:00:00 -0600
Time.at(946684800.2).usec            #=> 200000
Time.at(946684800, 123456.789).nsec  #=> 123456789

static VALUE
time_s_at(int argc, VALUE *argv, VALUE klass)
{
    VALUE time, t;
    wideval_t timew;

    if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
        time = num_exact(time);
        t = num_exact(t);
        timew = wadd(rb_time_magnify(v2w(time)), wmulquoll(v2w(t), TIME_SCALE, 1000000));
        t = time_new_timew(klass, timew);
    }
    else if (IsTimeval(time)) {
        struct time_object *tobj, *tobj2;
        GetTimeval(time, tobj);
        t = time_new_timew(klass, tobj->timew);
        GetTimeval(t, tobj2);
        TIME_COPY_GMT(tobj2, tobj);
    }
    else {
        timew = rb_time_magnify(v2w(num_exact(time)));
        t = time_new_timew(klass, timew);
    }

    return t;
}
utc(year) → time click to toggle source
utc(year, month) → time
utc(year, month, day) → time
utc(year, month, day, hour) → time
utc(year, month, day, hour, min) → time
utc(year, month, day, hour, min, sec_with_frac) → time
utc(year, month, day, hour, min, sec, usec_with_frac) → time
utc(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time
gm(year) → time
gm(year, month) → time
gm(year, month, day) → time
gm(year, month, day, hour) → time
gm(year, month, day, hour, min) → time
gm(year, month, day, hour, min, sec_with_frac) → time
gm(year, month, day, hour, min, sec, usec_with_frac) → time
gm(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time

Creates a Time object based on given values, interpreted as UTC (GMT). The year must be specified. Other values default to the minimum value for that field (and may be nil or omitted). Months may be specified by numbers from 1 to 12, or by the three-letter English month names. Hours are specified on a 24-hour clock (0..23). Raises an ArgumentError if any values are out of range. Will also accept ten arguments in the order output by #to_a.

sec_with_frac and usec_with_frac can have a fractional part.

Time.utc(2000,"jan",1,20,15,1)  #=> 2000-01-01 20:15:01 UTC
Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC

static VALUE
time_s_mkutc(int argc, VALUE *argv, VALUE klass)
{
    return time_utc_or_local(argc, argv, TRUE, klass);
}
local(year) → time click to toggle source
local(year, month) → time
local(year, month, day) → time
local(year, month, day, hour) → time
local(year, month, day, hour, min) → time
local(year, month, day, hour, min, sec_with_frac) → time
local(year, month, day, hour, min, sec, usec_with_frac) → time
local(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time
mktime(year) → time
mktime(year, month) → time
mktime(year, month, day) → time
mktime(year, month, day, hour) → time
mktime(year, month, day, hour, min) → time
mktime(year, month, day, hour, min, sec_with_frac) → time
mktime(year, month, day, hour, min, sec, usec_with_frac) → time
mktime(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time

Same as ::gm, but interprets the values in the local time zone.

Time.local(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 -0600

static VALUE
time_s_mktime(int argc, VALUE *argv, VALUE klass)
{
    return time_utc_or_local(argc, argv, FALSE, klass);
}
local(year) → time click to toggle source
local(year, month) → time
local(year, month, day) → time
local(year, month, day, hour) → time
local(year, month, day, hour, min) → time
local(year, month, day, hour, min, sec_with_frac) → time
local(year, month, day, hour, min, sec, usec_with_frac) → time
local(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time
mktime(year) → time
mktime(year, month) → time
mktime(year, month, day) → time
mktime(year, month, day, hour) → time
mktime(year, month, day, hour, min) → time
mktime(year, month, day, hour, min, sec_with_frac) → time
mktime(year, month, day, hour, min, sec, usec_with_frac) → time
mktime(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time

Same as ::gm, but interprets the values in the local time zone.

Time.local(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 -0600

static VALUE
time_s_mktime(int argc, VALUE *argv, VALUE klass)
{
    return time_utc_or_local(argc, argv, FALSE, klass);
}
new → time click to toggle source
new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, utc_offset=nil) → time

Returns a Time object.

It is initialized to the current system time if no argument is given.

Note: The new object will use the resolution available on your system clock, and may include fractional seconds.

If one or more arguments specified, the time is initialized to the specified time.

sec may have fraction if it is a rational.

utc_offset is the offset from UTC. It can be a string such as “+09:00” or a number of seconds such as 32400.

a = Time.new      #=> 2007-11-19 07:50:02 -0600
b = Time.new      #=> 2007-11-19 07:50:02 -0600
a == b            #=> false
"%.6f" % a.to_f   #=> "1195480202.282373"
"%.6f" % b.to_f   #=> "1195480202.283415"

Time.new(2008,6,21, 13,30,0, "+09:00") #=> 2008-06-21 13:30:00 +0900

# A trip for RubyConf 2007
t1 = Time.new(2007,11,1,15,25,0, "+09:00") # JST (Narita)
t2 = Time.new(2007,11,1,12, 5,0, "-05:00") # CDT (Minneapolis)
t3 = Time.new(2007,11,1,13,25,0, "-05:00") # CDT (Minneapolis)
t4 = Time.new(2007,11,1,16,53,0, "-04:00") # EDT (Charlotte)
t5 = Time.new(2007,11,5, 9,24,0, "-05:00") # EST (Charlotte)
t6 = Time.new(2007,11,5,11,21,0, "-05:00") # EST (Detroit)
t7 = Time.new(2007,11,5,13,45,0, "-05:00") # EST (Detroit)
t8 = Time.new(2007,11,6,17,10,0, "+09:00") # JST (Narita)
p((t2-t1)/3600.0)                          #=> 10.666666666666666
p((t4-t3)/3600.0)                          #=> 2.466666666666667
p((t6-t5)/3600.0)                          #=> 1.95
p((t8-t7)/3600.0)                          #=> 13.416666666666666

static VALUE
time_init(int argc, VALUE *argv, VALUE time)
{
    if (argc == 0)
        return time_init_0(time);
    else
        return time_init_1(argc, argv, time);
}
now() click to toggle source

Alias for ::new. Returns a Time object initialized to the current system time.

static VALUE
time_s_now(VALUE klass)
{
    return rb_class_new_instance(0, NULL, klass);
}
utc(year) → time click to toggle source
utc(year, month) → time
utc(year, month, day) → time
utc(year, month, day, hour) → time
utc(year, month, day, hour, min) → time
utc(year, month, day, hour, min, sec_with_frac) → time
utc(year, month, day, hour, min, sec, usec_with_frac) → time
utc(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time
gm(year) → time
gm(year, month) → time
gm(year, month, day) → time
gm(year, month, day, hour) → time
gm(year, month, day, hour, min) → time
gm(year, month, day, hour, min, sec_with_frac) → time
gm(year, month, day, hour, min, sec, usec_with_frac) → time
gm(sec, min, hour, day, month, year, wday, yday, isdst, tz) → time

Creates a Time object based on given values, interpreted as UTC (GMT). The year must be specified. Other values default to the minimum value for that field (and may be nil or omitted). Months may be specified by numbers from 1 to 12, or by the three-letter English month names. Hours are specified on a 24-hour clock (0..23). Raises an ArgumentError if any values are out of range. Will also accept ten arguments in the order output by #to_a.

sec_with_frac and usec_with_frac can have a fractional part.

Time.utc(2000,"jan",1,20,15,1)  #=> 2000-01-01 20:15:01 UTC
Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC

static VALUE
time_s_mkutc(int argc, VALUE *argv, VALUE klass)
{
    return time_utc_or_local(argc, argv, TRUE, klass);
}

Public Instance Methods

time + numeric → time click to toggle source

Addition — Adds some number of seconds (possibly fractional) to time and returns that value as a new Time object.

t = Time.now         #=> 2007-11-19 08:22:21 -0600
t + (60 * 60 * 24)   #=> 2007-11-20 08:22:21 -0600

static VALUE
time_plus(VALUE time1, VALUE time2)
{
    struct time_object *tobj;
    GetTimeval(time1, tobj);

    if (IsTimeval(time2)) {
        rb_raise(rb_eTypeError, "time + time?");
    }
    return time_add(tobj, time2, 1);
}
time - other_time → float click to toggle source
time - numeric → time

Difference — Returns a new Time object that represents the difference between time and other_time, or subtracts the given number of seconds in numeric from time.

t = Time.now       #=> 2007-11-19 08:23:10 -0600
t2 = t + 2592000   #=> 2007-12-19 08:23:10 -0600
t2 - t             #=> 2592000.0
t2 - 2592000       #=> 2007-11-19 08:23:10 -0600

static VALUE
time_minus(VALUE time1, VALUE time2)
{
    struct time_object *tobj;

    GetTimeval(time1, tobj);
    if (IsTimeval(time2)) {
        struct time_object *tobj2;

        GetTimeval(time2, tobj2);
        return rb_Float(rb_time_unmagnify_to_float(wsub(tobj->timew, tobj2->timew)));
    }
    return time_add(tobj, time2, -1);
}
time <=> other_time → -1, 0, +1 or nil click to toggle source

Comparison—Compares time with other_time.

-1, 0, +1 or nil depending on whether time is less than, equal to, or greater than other_time.

nil is returned if the two values are incomparable.

t = Time.now       #=> 2007-11-19 08:12:12 -0600
t2 = t + 2592000   #=> 2007-12-19 08:12:12 -0600
t <=> t2           #=> -1
t2 <=> t           #=> 1

t = Time.now       #=> 2007-11-19 08:13:38 -0600
t2 = t + 0.1       #=> 2007-11-19 08:13:38 -0600
t.nsec             #=> 98222999
t2.nsec            #=> 198222999
t <=> t2           #=> -1
t2 <=> t           #=> 1
t <=> t            #=> 0

static VALUE
time_cmp(VALUE time1, VALUE time2)
{
    struct time_object *tobj1, *tobj2;
    int n;

    GetTimeval(time1, tobj1);
    if (IsTimeval(time2)) {
        GetTimeval(time2, tobj2);
        n = wcmp(tobj1->timew, tobj2->timew);
    }
    else {
        return rb_invcmp(time1, time2);
    }
    if (n == 0) return INT2FIX(0);
    if (n > 0) return INT2FIX(1);
    return INT2FIX(-1);
}
asctime → string click to toggle source
ctime → string

Returns a canonical string representation of time.

Time.now.asctime   #=> "Wed Apr  9 08:56:03 2003"

static VALUE
time_asctime(VALUE time)
{
    return strftimev("%a %b %e %T %Y", time, rb_usascii_encoding());
}
asctime → string click to toggle source
ctime → string

Returns a canonical string representation of time.

Time.now.asctime   #=> "Wed Apr  9 08:56:03 2003"

static VALUE
time_asctime(VALUE time)
{
    return strftimev("%a %b %e %T %Y", time, rb_usascii_encoding());
}
day → fixnum click to toggle source
mday → fixnum

Returns the day of the month (1..n) for time.

t = Time.now   #=> 2007-11-19 08:27:03 -0600
t.day          #=> 19
t.mday         #=> 19

static VALUE
time_mday(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.mday);
}
isdst → true or false click to toggle source
dst? → true or false

Returns true if time occurs during Daylight Saving Time in its time zone.

# CST6CDT:
  Time.local(2000, 1, 1).zone    #=> "CST"
  Time.local(2000, 1, 1).isdst   #=> false
  Time.local(2000, 1, 1).dst?    #=> false
  Time.local(2000, 7, 1).zone    #=> "CDT"
  Time.local(2000, 7, 1).isdst   #=> true
  Time.local(2000, 7, 1).dst?    #=> true

# Asia/Tokyo:
  Time.local(2000, 1, 1).zone    #=> "JST"
  Time.local(2000, 1, 1).isdst   #=> false
  Time.local(2000, 1, 1).dst?    #=> false
  Time.local(2000, 7, 1).zone    #=> "JST"
  Time.local(2000, 7, 1).isdst   #=> false
  Time.local(2000, 7, 1).dst?    #=> false

static VALUE
time_isdst(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return tobj->vtm.isdst ? Qtrue : Qfalse;
}
eql?(other_time) click to toggle source

Returns true if time and other_time are both Time objects with the same seconds and fractional seconds.

static VALUE
time_eql(VALUE time1, VALUE time2)
{
    struct time_object *tobj1, *tobj2;

    GetTimeval(time1, tobj1);
    if (IsTimeval(time2)) {
        GetTimeval(time2, tobj2);
        return rb_equal(w2v(tobj1->timew), w2v(tobj2->timew));
    }
    return Qfalse;
}
friday? → true or false click to toggle source

Returns true if time represents Friday.

t = Time.local(1987, 12, 18)     #=> 1987-12-18 00:00:00 -0600
t.friday?                        #=> true

static VALUE
time_friday(VALUE time)
{
    wday_p(5);
}
getgm → new_time click to toggle source
getutc → new_time

Returns a new Time object representing time in UTC.

t = Time.local(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 -0600
t.gmt?                             #=> false
y = t.getgm                        #=> 2000-01-02 02:15:01 UTC
y.gmt?                             #=> true
t == y                             #=> true

static VALUE
time_getgmtime(VALUE time)
{
    return time_gmtime(time_dup(time));
}
getlocal → new_time click to toggle source
getlocal(utc_offset) → new_time

Returns a new Time object representing time in local time (using the local time zone in effect for this process).

If utc_offset is given, it is used instead of the local time.

t = Time.utc(2000,1,1,20,15,1)  #=> 2000-01-01 20:15:01 UTC
t.utc?                          #=> true

l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
l.utc?                          #=> false
t == l                          #=> true

j = t.getlocal("+09:00")        #=> 2000-01-02 05:15:01 +0900
j.utc?                          #=> false
t == j                          #=> true

static VALUE
time_getlocaltime(int argc, VALUE *argv, VALUE time)
{
    VALUE off;
    rb_scan_args(argc, argv, "01", &off);

    if (!NIL_P(off)) {
        off = utc_offset_arg(off);
        validate_utc_offset(off);

        time = time_dup(time);
        time_set_utc_offset(time, off);
        return time_fixoff(time);
    }

    return time_localtime(time_dup(time));
}
getgm → new_time click to toggle source
getutc → new_time

Returns a new Time object representing time in UTC.

t = Time.local(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 -0600
t.gmt?                             #=> false
y = t.getgm                        #=> 2000-01-02 02:15:01 UTC
y.gmt?                             #=> true
t == y                             #=> true

static VALUE
time_getgmtime(VALUE time)
{
    return time_gmtime(time_dup(time));
}
utc? → true or false click to toggle source
gmt? → true or false

Returns true if time represents a time in UTC (GMT).

t = Time.now                        #=> 2007-11-19 08:15:23 -0600
t.utc?                              #=> false
t = Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
t.utc?                              #=> true

t = Time.now                        #=> 2007-11-19 08:16:03 -0600
t.gmt?                              #=> false
t = Time.gm(2000,1,1,20,15,1)       #=> 2000-01-01 20:15:01 UTC
t.gmt?                              #=> true

static VALUE
time_utc_p(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj)) return Qtrue;
    return Qfalse;
}
gmt_offset → fixnum click to toggle source
gmtoff → fixnum
utc_offset → fixnum

Returns the offset in seconds between the timezone of time and UTC.

t = Time.gm(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
t.gmt_offset                    #=> 0
l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
l.gmt_offset                    #=> -21600

static VALUE
time_utc_offset(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);

    if (TIME_UTC_P(tobj)) {
        return INT2FIX(0);
    }
    else {
        return tobj->vtm.utc_offset;
    }
}
gmtime → time click to toggle source
utc → time

Converts time to UTC (GMT), modifying the receiver.

t = Time.now   #=> 2007-11-19 08:18:31 -0600
t.gmt?         #=> false
t.gmtime       #=> 2007-11-19 14:18:31 UTC
t.gmt?         #=> true

t = Time.now   #=> 2007-11-19 08:18:51 -0600
t.utc?         #=> false
t.utc          #=> 2007-11-19 14:18:51 UTC
t.utc?         #=> true

static VALUE
time_gmtime(VALUE time)
{
    struct time_object *tobj;
    struct vtm vtm;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj)) {
        if (tobj->tm_got)
            return time;
    }
    else {
        time_modify(time);
    }

    if (!gmtimew(tobj->timew, &vtm))
        rb_raise(rb_eArgError, "gmtime error");
    tobj->vtm = vtm;

    tobj->tm_got = 1;
    TIME_SET_UTC(tobj);
    return time;
}
gmt_offset → fixnum click to toggle source
gmtoff → fixnum
utc_offset → fixnum

Returns the offset in seconds between the timezone of time and UTC.

t = Time.gm(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
t.gmt_offset                    #=> 0
l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
l.gmt_offset                    #=> -21600

static VALUE
time_utc_offset(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);

    if (TIME_UTC_P(tobj)) {
        return INT2FIX(0);
    }
    else {
        return tobj->vtm.utc_offset;
    }
}
hash → fixnum click to toggle source

Returns a hash code for this Time object.

static VALUE
time_hash(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return rb_hash(w2v(tobj->timew));
}
hour → fixnum click to toggle source

Returns the hour of the day (0..23) for time.

t = Time.now   #=> 2007-11-19 08:26:20 -0600
t.hour         #=> 8

static VALUE
time_hour(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.hour);
}
inspect → string click to toggle source
to_s → string

Returns a string representing time. Equivalent to calling strftime with the appropriate format string.

t = Time.now
t.to_s                              => "2012-11-10 18:16:12 +0100"
t.strftime "%Y-%m-%d %H:%M:%S %z"   => "2012-11-10 18:16:12 +0100"

t.utc.to_s                          => "2012-11-10 17:16:12 UTC"
t.strftime "%Y-%m-%d %H:%M:%S UTC"  => "2012-11-10 17:16:12 UTC"

static VALUE
time_to_s(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj))
        return strftimev("%Y-%m-%d %H:%M:%S UTC", time, rb_usascii_encoding());
    else
        return strftimev("%Y-%m-%d %H:%M:%S %z", time, rb_usascii_encoding());
}
isdst → true or false click to toggle source
dst? → true or false

Returns true if time occurs during Daylight Saving Time in its time zone.

# CST6CDT:
  Time.local(2000, 1, 1).zone    #=> "CST"
  Time.local(2000, 1, 1).isdst   #=> false
  Time.local(2000, 1, 1).dst?    #=> false
  Time.local(2000, 7, 1).zone    #=> "CDT"
  Time.local(2000, 7, 1).isdst   #=> true
  Time.local(2000, 7, 1).dst?    #=> true

# Asia/Tokyo:
  Time.local(2000, 1, 1).zone    #=> "JST"
  Time.local(2000, 1, 1).isdst   #=> false
  Time.local(2000, 1, 1).dst?    #=> false
  Time.local(2000, 7, 1).zone    #=> "JST"
  Time.local(2000, 7, 1).isdst   #=> false
  Time.local(2000, 7, 1).dst?    #=> false

static VALUE
time_isdst(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return tobj->vtm.isdst ? Qtrue : Qfalse;
}
localtime → time click to toggle source
localtime(utc_offset) → time

Converts time to local time (using the local time zone in effect for this process) modifying the receiver.

If utc_offset is given, it is used instead of the local time.

t = Time.utc(2000, "jan", 1, 20, 15, 1) #=> 2000-01-01 20:15:01 UTC
t.utc?                                  #=> true

t.localtime                             #=> 2000-01-01 14:15:01 -0600
t.utc?                                  #=> false

t.localtime("+09:00")                   #=> 2000-01-02 05:15:01 +0900
t.utc?                                  #=> false

static VALUE
time_localtime_m(int argc, VALUE *argv, VALUE time)
{
    VALUE off;
    rb_scan_args(argc, argv, "01", &off);

    if (!NIL_P(off)) {
        off = utc_offset_arg(off);
        validate_utc_offset(off);

        time_set_utc_offset(time, off);
        return time_fixoff(time);
    }

    return time_localtime(time);
}
day → fixnum click to toggle source
mday → fixnum

Returns the day of the month (1..n) for time.

t = Time.now   #=> 2007-11-19 08:27:03 -0600
t.day          #=> 19
t.mday         #=> 19

static VALUE
time_mday(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.mday);
}
min → fixnum click to toggle source

Returns the minute of the hour (0..59) for time.

t = Time.now   #=> 2007-11-19 08:25:51 -0600
t.min          #=> 25

static VALUE
time_min(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.min);
}
mon → fixnum click to toggle source
month → fixnum

Returns the month of the year (1..12) for time.

t = Time.now   #=> 2007-11-19 08:27:30 -0600
t.mon          #=> 11
t.month        #=> 11

static VALUE
time_mon(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.mon);
}
monday? → true or false click to toggle source

Returns true if time represents Monday.

t = Time.local(2003, 8, 4)       #=> 2003-08-04 00:00:00 -0500
p t.monday?                      #=> true

static VALUE
time_monday(VALUE time)
{
    wday_p(1);
}
mon → fixnum click to toggle source
month → fixnum

Returns the month of the year (1..12) for time.

t = Time.now   #=> 2007-11-19 08:27:30 -0600
t.mon          #=> 11
t.month        #=> 11

static VALUE
time_mon(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.mon);
}
nsec → int click to toggle source
tv_nsec → int

Returns the number of nanoseconds for time.

t = Time.now        #=> 2007-11-17 15:18:03 +0900
"%10.9f" % t.to_f   #=> "1195280283.536151409"
t.nsec              #=> 536151406

The lowest digits of to_f and nsec are different because IEEE 754 double is not accurate enough to represent the exact number of nanoseconds since the Epoch.

The more accurate value is returned by nsec.

static VALUE
time_nsec(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return rb_to_int(w2v(wmulquoll(wmod(tobj->timew, WINT2WV(TIME_SCALE)), 1000000000, TIME_SCALE)));
}
round([ndigits]) → new_time click to toggle source

Rounds sub seconds to a given precision in decimal digits (0 digits by default). It returns a new Time object. ndigits should be zero or positive integer.

require 'time'

t = Time.utc(2010,3,30, 5,43,"25.123456789".to_r)
p t.iso8601(10)           #=> "2010-03-30T05:43:25.1234567890Z"
p t.round.iso8601(10)     #=> "2010-03-30T05:43:25.0000000000Z"
p t.round(0).iso8601(10)  #=> "2010-03-30T05:43:25.0000000000Z"
p t.round(1).iso8601(10)  #=> "2010-03-30T05:43:25.1000000000Z"
p t.round(2).iso8601(10)  #=> "2010-03-30T05:43:25.1200000000Z"
p t.round(3).iso8601(10)  #=> "2010-03-30T05:43:25.1230000000Z"
p t.round(4).iso8601(10)  #=> "2010-03-30T05:43:25.1235000000Z"
p t.round(5).iso8601(10)  #=> "2010-03-30T05:43:25.1234600000Z"
p t.round(6).iso8601(10)  #=> "2010-03-30T05:43:25.1234570000Z"
p t.round(7).iso8601(10)  #=> "2010-03-30T05:43:25.1234568000Z"
p t.round(8).iso8601(10)  #=> "2010-03-30T05:43:25.1234567900Z"
p t.round(9).iso8601(10)  #=> "2010-03-30T05:43:25.1234567890Z"
p t.round(10).iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"

t = Time.utc(1999,12,31, 23,59,59)
p((t + 0.4).round.iso8601(3))    #=> "1999-12-31T23:59:59.000Z"
p((t + 0.49).round.iso8601(3))   #=> "1999-12-31T23:59:59.000Z"
p((t + 0.5).round.iso8601(3))    #=> "2000-01-01T00:00:00.000Z"
p((t + 1.4).round.iso8601(3))    #=> "2000-01-01T00:00:00.000Z"
p((t + 1.49).round.iso8601(3))   #=> "2000-01-01T00:00:00.000Z"
p((t + 1.5).round.iso8601(3))    #=> "2000-01-01T00:00:01.000Z"

t = Time.utc(1999,12,31, 23,59,59)
p (t + 0.123456789).round(4).iso8601(6)  #=> "1999-12-31T23:59:59.123500Z"

static VALUE
time_round(int argc, VALUE *argv, VALUE time)
{
    VALUE ndigits, v, a, b, den;
    long nd;
    struct time_object *tobj;

    rb_scan_args(argc, argv, "01", &ndigits);

    if (NIL_P(ndigits))
        ndigits = INT2FIX(0);
    else
        ndigits = rb_to_int(ndigits);

    nd = NUM2LONG(ndigits);
    if (nd < 0)
        rb_raise(rb_eArgError, "negative ndigits given");

    GetTimeval(time, tobj);
    v = w2v(rb_time_unmagnify(tobj->timew));

    a = INT2FIX(1);
    b = INT2FIX(10);
    while (0 < nd) {
        if (nd & 1)
            a = mul(a, b);
        b = mul(b, b);
        nd = nd >> 1;
    }
    den = quo(INT2FIX(1), a);
    v = mod(v, den);
    if (lt(v, quo(den, INT2FIX(2))))
        return time_add(tobj, v, -1);
    else
        return time_add(tobj, sub(den, v), 1);
}
saturday? → true or false click to toggle source

Returns true if time represents Saturday.

t = Time.local(2006, 6, 10)      #=> 2006-06-10 00:00:00 -0500
t.saturday?                      #=> true

static VALUE
time_saturday(VALUE time)
{
    wday_p(6);
}
sec → fixnum click to toggle source

Returns the second of the minute (0..60) for time.

Note: Seconds range from zero to 60 to allow the system to inject leap seconds. See en.wikipedia.org/wiki/Leap_second for further details.

t = Time.now   #=> 2007-11-19 08:25:02 -0600
t.sec          #=> 2

static VALUE
time_sec(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.sec);
}
strftime( string ) → string click to toggle source

Formats time according to the directives in the given format string.

The directives begin with a percent (%) character. Any text not listed as a directive will be passed through to the output string.

The directive consists of a percent (%) character, zero or more flags, optional minimum field width, optional modifier and a conversion specifier as follows:

%<flags><width><modifier><conversion>

Flags:

-  don't pad a numerical output
_  use spaces for padding
0  use zeros for padding
^  upcase the result string
#  change case
:  use colons for %z

The minimum field width specifies the minimum width.

The modifiers are “E” and “O”. They are ignored.

Format directives:

Date (Year, Month, Day):
  %Y - Year with century (can be negative, 4 digits at least)
          -0001, 0000, 1995, 2009, 14292, etc.
  %C - year / 100 (rounded down such as 20 in 2009)
  %y - year % 100 (00..99)

  %m - Month of the year, zero-padded (01..12)
          %_m  blank-padded ( 1..12)
          %-m  no-padded (1..12)
  %B - The full month name (``January'')
          %^B  uppercased (``JANUARY'')
  %b - The abbreviated month name (``Jan'')
          %^b  uppercased (``JAN'')
  %h - Equivalent to %b

  %d - Day of the month, zero-padded (01..31)
          %-d  no-padded (1..31)
  %e - Day of the month, blank-padded ( 1..31)

  %j - Day of the year (001..366)

Time (Hour, Minute, Second, Subsecond):
  %H - Hour of the day, 24-hour clock, zero-padded (00..23)
  %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
  %I - Hour of the day, 12-hour clock, zero-padded (01..12)
  %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
  %P - Meridian indicator, lowercase (``am'' or ``pm'')
  %p - Meridian indicator, uppercase (``AM'' or ``PM'')

  %M - Minute of the hour (00..59)

  %S - Second of the minute (00..60)

  %L - Millisecond of the second (000..999)
  %N - Fractional seconds digits, default is 9 digits (nanosecond)
          %3N  milli second (3 digits)
          %6N  micro second (6 digits)
          %9N  nano second (9 digits)
          %12N pico second (12 digits)
          %15N femto second (15 digits)
          %18N atto second (18 digits)
          %21N zepto second (21 digits)
          %24N yocto second (24 digits)

Time zone:
  %z - Time zone as hour and minute offset from UTC (e.g. +0900)
          %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
          %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
  %Z - Abbreviated time zone name or similar information.

Weekday:
  %A - The full weekday name (``Sunday'')
          %^A  uppercased (``SUNDAY'')
  %a - The abbreviated name (``Sun'')
          %^a  uppercased (``SUN'')
  %u - Day of the week (Monday is 1, 1..7)
  %w - Day of the week (Sunday is 0, 0..6)

ISO 8601 week-based year and week number:
The first week of YYYY starts with a Monday and includes YYYY-01-04.
The days in the year before the first week are in the last week of
the previous year.
  %G - The week-based year
  %g - The last 2 digits of the week-based year (00..99)
  %V - Week number of the week-based year (01..53)

Week number:
The first week of YYYY that starts with a Sunday or Monday (according to %U
or %W). The days in the year before the first week are in week 0.
  %U - Week number of the year. The week starts with Sunday. (00..53)
  %W - Week number of the year. The week starts with Monday. (00..53)

Seconds since the Epoch:
  %s - Number of seconds since 1970-01-01 00:00:00 UTC.

Literal string:
  %n - Newline character (\n)
  %t - Tab character (\t)
  %% - Literal ``%'' character

Combination:
  %c - date and time (%a %b %e %T %Y)
  %D - Date (%m/%d/%y)
  %F - The ISO 8601 date format (%Y-%m-%d)
  %v - VMS date (%e-%^b-%4Y)
  %x - Same as %D
  %X - Same as %T
  %r - 12-hour time (%I:%M:%S %p)
  %R - 24-hour time (%H:%M)
  %T - 24-hour time (%H:%M:%S)

This method is similar to strftime() function defined in ISO C and POSIX.

While all directives are locale independant since Ruby 1.9 %Z is platform dependant. So, the result may differ even if the same format string is used in other systems such as C.

%z is recommended over %Z. %Z doesn't identify the timezone. For example, “CST” is used at America/Chicago (-06:00), America/Havana (-05:00), Asia/Harbin (+08:00), Australia/Darwin (+09:30) and Australia/Adelaide (+10:30). Also, %Z is highly dependent on the operating system. For example, it may generate a non ASCII string on Japanese Windows. i.e. the result can be different to “JST”. So the numeric time zone offset, %z, is recommended.

Examples:

t = Time.new(2007,11,19,8,37,48,"-06:00") #=> 2007-11-19 08:37:48 -0600
t.strftime("Printed on %m/%d/%Y")   #=> "Printed on 11/19/2007"
t.strftime("at %I:%M%p")            #=> "at 08:37AM"

Various ISO 8601 formats:

%Y%m%d           => 20071119                  Calendar date (basic)
%F               => 2007-11-19                Calendar date (extended)
%Y-%m            => 2007-11                   Calendar date, reduced accuracy, specific month
%Y               => 2007                      Calendar date, reduced accuracy, specific year
%C               => 20                        Calendar date, reduced accuracy, specific century
%Y%j             => 2007323                   Ordinal date (basic)
%Y-%j            => 2007-323                  Ordinal date (extended)
%GW%V%u          => 2007W471                  Week date (basic)
%G-W%V-%u        => 2007-W47-1                Week date (extended)
%GW%V            => 2007W47                   Week date, reduced accuracy, specific week (basic)
%G-W%V           => 2007-W47                  Week date, reduced accuracy, specific week (extended)
%H%M%S           => 083748                    Local time (basic)
%T               => 08:37:48                  Local time (extended)
%H%M             => 0837                      Local time, reduced accuracy, specific minute (basic)
%H:%M            => 08:37                     Local time, reduced accuracy, specific minute (extended)
%H               => 08                        Local time, reduced accuracy, specific hour
%H%M%S,%L        => 083748,000                Local time with decimal fraction, comma as decimal sign (basic)
%T,%L            => 08:37:48,000              Local time with decimal fraction, comma as decimal sign (extended)
%H%M%S.%L        => 083748.000                Local time with decimal fraction, full stop as decimal sign (basic)
%T.%L            => 08:37:48.000              Local time with decimal fraction, full stop as decimal sign (extended)
%H%M%S%z         => 083748-0600               Local time and the difference from UTC (basic)
%T%:z            => 08:37:48-06:00            Local time and the difference from UTC (extended)
%Y%m%dT%H%M%S%z  => 20071119T083748-0600      Date and time of day for calendar date (basic)
%FT%T%:z         => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
%Y%jT%H%M%S%z    => 2007323T083748-0600       Date and time of day for ordinal date (basic)
%Y-%jT%T%:z      => 2007-323T08:37:48-06:00   Date and time of day for ordinal date (extended)
%GW%V%uT%H%M%S%z => 2007W471T083748-0600      Date and time of day for week date (basic)
%G-W%V-%uT%T%:z  => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
%Y%m%dT%H%M      => 20071119T0837             Calendar date and local time (basic)
%FT%R            => 2007-11-19T08:37          Calendar date and local time (extended)
%Y%jT%H%MZ       => 2007323T0837Z             Ordinal date and UTC of day (basic)
%Y-%jT%RZ        => 2007-323T08:37Z           Ordinal date and UTC of day (extended)
%GW%V%uT%H%M%z   => 2007W471T0837-0600        Week date and local time and difference from UTC (basic)
%G-W%V-%uT%R%:z  => 2007-W47-1T08:37-06:00    Week date and local time and difference from UTC (extended)

static VALUE
time_strftime(VALUE time, VALUE format)
{
    struct time_object *tobj;
    char buffer[SMALLBUF], *buf = buffer;
    const char *fmt;
    long len;
    rb_encoding *enc;
    VALUE str;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    StringValue(format);
    if (!rb_enc_str_asciicompat_p(format)) {
        rb_raise(rb_eArgError, "format should have ASCII compatible encoding");
    }
    format = rb_str_new4(format);
    fmt = RSTRING_PTR(format);
    len = RSTRING_LEN(format);
    enc = rb_enc_get(format);
    if (len == 0) {
        rb_warning("strftime called with empty format string");
    }
    else if (memchr(fmt, '\0', len)) {
        /* Ruby string may contain \0's. */
        const char *p = fmt, *pe = fmt + len;

        str = rb_str_new(0, 0);
        while (p < pe) {
            len = rb_strftime_alloc(&buf, format, p, enc,
                                    &tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
            rb_str_cat(str, buf, len);
            p += strlen(p);
            if (buf != buffer) {
                xfree(buf);
                buf = buffer;
            }
            for (fmt = p; p < pe && !*p; ++p);
            if (p > fmt) rb_str_cat(str, fmt, p - fmt);
        }
        return str;
    }
    else {
        len = rb_strftime_alloc(&buf, format, RSTRING_PTR(format), enc,
                                &tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
    }
    str = rb_enc_str_new(buf, len, enc);
    if (buf != buffer) xfree(buf);
    return str;
}
subsec → number click to toggle source

Returns the fraction for time.

The return value can be a rational number.

t = Time.now        #=> 2009-03-26 22:33:12 +0900
"%10.9f" % t.to_f   #=> "1238074392.940563917"
t.subsec            #=> (94056401/100000000)

The lowest digits of to_f and subsec are different because IEEE 754 double is not accurate enough to represent the rational number.

The more accurate value is returned by subsec.

static VALUE
time_subsec(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return quo(w2v(wmod(tobj->timew, WINT2FIXWV(TIME_SCALE))), INT2FIX(TIME_SCALE));
}
succ → new_time click to toggle source

Returns a new Time object, one second later than time. #succ is obsolete since 1.9.2 for time is not a discrete value.

t = Time.now       #=> 2007-11-19 08:23:57 -0600
t.succ             #=> 2007-11-19 08:23:58 -0600

Use instead time + 1

t + 1              #=> 2007-11-19 08:23:58 -0600

VALUE
rb_time_succ(VALUE time)
{
    struct time_object *tobj;
    struct time_object *tobj2;

    rb_warn("Time#succ is obsolete; use time + 1");
    GetTimeval(time, tobj);
    time = time_new_timew(rb_cTime, wadd(tobj->timew, WINT2FIXWV(TIME_SCALE)));
    GetTimeval(time, tobj2);
    TIME_COPY_GMT(tobj2, tobj);
    return time;
}
sunday? → true or false click to toggle source

Returns true if time represents Sunday.

t = Time.local(1990, 4, 1)       #=> 1990-04-01 00:00:00 -0600
t.sunday?                        #=> true

static VALUE
time_sunday(VALUE time)
{
    wday_p(0);
}
thursday? → true or false click to toggle source

Returns true if time represents Thursday.

t = Time.local(1995, 12, 21)     #=> 1995-12-21 00:00:00 -0600
p t.thursday?                    #=> true

static VALUE
time_thursday(VALUE time)
{
    wday_p(4);
}
to_a → array click to toggle source

Returns a ten-element array of values for time:

[sec, min, hour, day, month, year, wday, yday, isdst, zone]

See the individual methods for an explanation of the valid ranges of each value. The ten elements can be passed directly to ::utc or ::local to create a new Time object.

t = Time.now     #=> 2007-11-19 08:36:01 -0600
now = t.to_a     #=> [1, 36, 8, 19, 11, 2007, 1, 323, false, "CST"]

static VALUE
time_to_a(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return rb_ary_new3(10,
                    INT2FIX(tobj->vtm.sec),
                    INT2FIX(tobj->vtm.min),
                    INT2FIX(tobj->vtm.hour),
                    INT2FIX(tobj->vtm.mday),
                    INT2FIX(tobj->vtm.mon),
                    tobj->vtm.year,
                    INT2FIX(tobj->vtm.wday),
                    INT2FIX(tobj->vtm.yday),
                    tobj->vtm.isdst?Qtrue:Qfalse,
                    time_zone(time));
}
to_f → float click to toggle source

Returns the value of time as a floating point number of seconds since the Epoch.

t = Time.now
"%10.5f" % t.to_f   #=> "1270968744.77658"
t.to_i              #=> 1270968744

Note that IEEE 754 double is not accurate enough to represent the number of nanoseconds since the Epoch.

static VALUE
time_to_f(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return rb_Float(rb_time_unmagnify_to_float(tobj->timew));
}
to_i → int click to toggle source
tv_sec → int

Returns the value of time as an integer number of seconds since the Epoch.

t = Time.now
"%10.5f" % t.to_f   #=> "1270968656.89607"
t.to_i              #=> 1270968656

static VALUE
time_to_i(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return w2v(wdiv(tobj->timew, WINT2FIXWV(TIME_SCALE)));
}
to_r → a_rational click to toggle source

Returns the value of time as a rational number of seconds since the Epoch.

t = Time.now
p t.to_r            #=> (1270968792716287611/1000000000)

This methods is intended to be used to get an accurate value representing the nanoseconds since the Epoch. You can use this method to convert time to another Epoch.

static VALUE
time_to_r(VALUE time)
{
    struct time_object *tobj;
    VALUE v;

    GetTimeval(time, tobj);
    v = w2v(rb_time_unmagnify(tobj->timew));
    if (!RB_TYPE_P(v, T_RATIONAL)) {
        v = rb_Rational1(v);
    }
    return v;
}
inspect → string click to toggle source
to_s → string

Returns a string representing time. Equivalent to calling strftime with the appropriate format string.

t = Time.now
t.to_s                              => "2012-11-10 18:16:12 +0100"
t.strftime "%Y-%m-%d %H:%M:%S %z"   => "2012-11-10 18:16:12 +0100"

t.utc.to_s                          => "2012-11-10 17:16:12 UTC"
t.strftime "%Y-%m-%d %H:%M:%S UTC"  => "2012-11-10 17:16:12 UTC"

static VALUE
time_to_s(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj))
        return strftimev("%Y-%m-%d %H:%M:%S UTC", time, rb_usascii_encoding());
    else
        return strftimev("%Y-%m-%d %H:%M:%S %z", time, rb_usascii_encoding());
}
tuesday? → true or false click to toggle source

Returns true if time represents Tuesday.

t = Time.local(1991, 2, 19)      #=> 1991-02-19 00:00:00 -0600
p t.tuesday?                     #=> true

static VALUE
time_tuesday(VALUE time)
{
    wday_p(2);
}
nsec → int click to toggle source
tv_nsec → int

Returns the number of nanoseconds for time.

t = Time.now        #=> 2007-11-17 15:18:03 +0900
"%10.9f" % t.to_f   #=> "1195280283.536151409"
t.nsec              #=> 536151406

The lowest digits of to_f and nsec are different because IEEE 754 double is not accurate enough to represent the exact number of nanoseconds since the Epoch.

The more accurate value is returned by nsec.

static VALUE
time_nsec(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return rb_to_int(w2v(wmulquoll(wmod(tobj->timew, WINT2WV(TIME_SCALE)), 1000000000, TIME_SCALE)));
}
to_i → int click to toggle source
tv_sec → int

Returns the value of time as an integer number of seconds since the Epoch.

t = Time.now
"%10.5f" % t.to_f   #=> "1270968656.89607"
t.to_i              #=> 1270968656

static VALUE
time_to_i(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    return w2v(wdiv(tobj->timew, WINT2FIXWV(TIME_SCALE)));
}
usec → int click to toggle source
tv_usec → int

Returns the number of microseconds for time.

t = Time.now        #=> 2007-11-19 08:03:26 -0600
"%10.6f" % t.to_f   #=> "1195481006.775195"
t.usec              #=> 775195

static VALUE
time_usec(VALUE time)
{
    struct time_object *tobj;
    wideval_t w, q, r;

    GetTimeval(time, tobj);

    w = wmod(tobj->timew, WINT2WV(TIME_SCALE));
    wmuldivmod(w, WINT2FIXWV(1000000), WINT2FIXWV(TIME_SCALE), &q, &r);
    return rb_to_int(w2v(q));
}
usec → int click to toggle source
tv_usec → int

Returns the number of microseconds for time.

t = Time.now        #=> 2007-11-19 08:03:26 -0600
"%10.6f" % t.to_f   #=> "1195481006.775195"
t.usec              #=> 775195

static VALUE
time_usec(VALUE time)
{
    struct time_object *tobj;
    wideval_t w, q, r;

    GetTimeval(time, tobj);

    w = wmod(tobj->timew, WINT2WV(TIME_SCALE));
    wmuldivmod(w, WINT2FIXWV(1000000), WINT2FIXWV(TIME_SCALE), &q, &r);
    return rb_to_int(w2v(q));
}
gmtime → time click to toggle source
utc → time

Converts time to UTC (GMT), modifying the receiver.

t = Time.now   #=> 2007-11-19 08:18:31 -0600
t.gmt?         #=> false
t.gmtime       #=> 2007-11-19 14:18:31 UTC
t.gmt?         #=> true

t = Time.now   #=> 2007-11-19 08:18:51 -0600
t.utc?         #=> false
t.utc          #=> 2007-11-19 14:18:51 UTC
t.utc?         #=> true

static VALUE
time_gmtime(VALUE time)
{
    struct time_object *tobj;
    struct vtm vtm;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj)) {
        if (tobj->tm_got)
            return time;
    }
    else {
        time_modify(time);
    }

    if (!gmtimew(tobj->timew, &vtm))
        rb_raise(rb_eArgError, "gmtime error");
    tobj->vtm = vtm;

    tobj->tm_got = 1;
    TIME_SET_UTC(tobj);
    return time;
}
utc? → true or false click to toggle source
gmt? → true or false

Returns true if time represents a time in UTC (GMT).

t = Time.now                        #=> 2007-11-19 08:15:23 -0600
t.utc?                              #=> false
t = Time.gm(2000,"jan",1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
t.utc?                              #=> true

t = Time.now                        #=> 2007-11-19 08:16:03 -0600
t.gmt?                              #=> false
t = Time.gm(2000,1,1,20,15,1)       #=> 2000-01-01 20:15:01 UTC
t.gmt?                              #=> true

static VALUE
time_utc_p(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    if (TIME_UTC_P(tobj)) return Qtrue;
    return Qfalse;
}
gmt_offset → fixnum click to toggle source
gmtoff → fixnum
utc_offset → fixnum

Returns the offset in seconds between the timezone of time and UTC.

t = Time.gm(2000,1,1,20,15,1)   #=> 2000-01-01 20:15:01 UTC
t.gmt_offset                    #=> 0
l = t.getlocal                  #=> 2000-01-01 14:15:01 -0600
l.gmt_offset                    #=> -21600

static VALUE
time_utc_offset(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);

    if (TIME_UTC_P(tobj)) {
        return INT2FIX(0);
    }
    else {
        return tobj->vtm.utc_offset;
    }
}
wday → fixnum click to toggle source

Returns an integer representing the day of the week, 0..6, with Sunday == 0.

t = Time.now   #=> 2007-11-20 02:35:35 -0600
t.wday         #=> 2
t.sunday?      #=> false
t.monday?      #=> false
t.tuesday?     #=> true
t.wednesday?   #=> false
t.thursday?    #=> false
t.friday?      #=> false
t.saturday?    #=> false

static VALUE
time_wday(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.wday);
}
wednesday? → true or false click to toggle source

Returns true if time represents Wednesday.

t = Time.local(1993, 2, 24)      #=> 1993-02-24 00:00:00 -0600
p t.wednesday?                   #=> true

static VALUE
time_wednesday(VALUE time)
{
    wday_p(3);
}
yday → fixnum click to toggle source

Returns an integer representing the day of the year, 1..366.

t = Time.now   #=> 2007-11-19 08:32:31 -0600
t.yday         #=> 323

static VALUE
time_yday(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return INT2FIX(tobj->vtm.yday);
}
year → fixnum click to toggle source

Returns the year for time (including the century).

t = Time.now   #=> 2007-11-19 08:27:51 -0600
t.year         #=> 2007

static VALUE
time_year(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);
    return tobj->vtm.year;
}
zone → string click to toggle source

Returns the name of the time zone used for time. As of Ruby 1.8, returns “UTC'' rather than “GMT'' for UTC times.

t = Time.gm(2000, "jan", 1, 20, 15, 1)
t.zone   #=> "UTC"
t = Time.local(2000, "jan", 1, 20, 15, 1)
t.zone   #=> "CST"

static VALUE
time_zone(VALUE time)
{
    struct time_object *tobj;

    GetTimeval(time, tobj);
    MAKE_TM(time, tobj);

    if (TIME_UTC_P(tobj)) {
        return rb_obj_untaint(rb_locale_str_new_cstr("UTC"));
    }
    if (tobj->vtm.zone == NULL)
        return Qnil;
    return rb_obj_untaint(rb_locale_str_new_cstr(tobj->vtm.zone));
}


class TracePoint - Ruby 2.0.0-p576 Core API Reference API Reference

class TracePoint

A class that provides the functionality of Kernel#set_trace_func in a nice Object-Oriented API.

Example

We can use TracePoint to gather information specifically for exceptions:

trace = TracePoint.new(:raise) do |tp|
    p [tp.lineno, tp.event, tp.raised_exception]
end
#=> #<TracePoint:0x007f786a452448>

trace.enable
#=> #<TracePoint:0x007f786a452448>

0 / 0
#=> [5, :raise, #<ZeroDivisionError: divided by 0>]

Events

If you don't specify the type of events you want to listen for, TracePoint will include all available events.

Note do not depend on current event set, as this list is subject to change. Instead, it is recommended you specify the type of events you want to use.

To filter what is traced, you can pass any of the following as events:

:line

execute code on a new line

:class

start a class or module definition

:end

finish a class or module definition

:call

call a Ruby method

:return

return from a Ruby method

:c_call

call a C-language routine

:c_return

return from a C-language routine

:raise

raise an exception

:b_call

event hook at block entry

:b_return

event hook at block ending

:thread_begin

event hook at thread beginning

:thread_end

event hook at thread ending

In Files

  • vm_trace.c

Parent

Object

Public Class Methods

new(*events) { |obj| block } → obj click to toggle source

Returns a new TracePoint object, not enabled by default.

Next, in order to activate the trace, you must use #enable

trace = TracePoint.new(:call) do |tp|
    p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
end
#=> #<TracePoint:0x007f17372cdb20>

trace.enable
#=> #<TracePoint:0x007f17372cdb20>

puts "Hello, TracePoint!"
# ...
# [48, IRB::Notifier::AbstractNotifier, :printf, :call]
# ...

When you want to deactivate the trace, you must use #disable

trace.disable

See Events at TracePoint for possible events and more information.

A block must be given, otherwise a ThreadError is raised.

If the trace method isn't included in the given events filter, a RuntimeError is raised.

TracePoint.trace(:line) do |tp|
    p tp.raised_exception
end
#=> RuntimeError: 'raised_exception' not supported by this event

If the trace method is called outside block, a RuntimeError is raised.

TracePoint.trace(:line) do |tp|
  $tp = tp
end
$tp.line #=> access from outside (RuntimeError)

Access from other threads is also forbidden.

static VALUE
tracepoint_new_s(int argc, VALUE *argv, VALUE self)
{
    rb_event_flag_t events = 0;
    int i;

    if (argc > 0) {
        for (i=0; i<argc; i++) {
            events |= symbol2event_flag(argv[i]);
        }
    }
    else {
        events = RUBY_EVENT_TRACEPOINT_ALL;
    }

    if (!rb_block_given_p()) {
        rb_raise(rb_eThreadError, "must be called with a block");
    }

    return tracepoint_new(self, 0, events, 0, 0, rb_block_proc());
}
trace(*events) { |obj| block } → obj click to toggle source

A convenience method for ::new, that activates the trace automatically.

trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
#=> #<TracePoint:0x007f786a452448>

trace.enabled? #=> true

static VALUE
tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
{
    VALUE trace = tracepoint_new_s(argc, argv, self);
    rb_tracepoint_enable(trace);
    return trace;
}

Public Instance Methods

binding() click to toggle source

Return the generated binding object from event

static VALUE
tracepoint_attr_binding(VALUE tpval)
{
    return rb_tracearg_binding(get_trace_arg());
}
defined_class() click to toggle source

Return class or module of the method being called.

class C; def foo; end; end
trace = TracePoint.new(:call) do |tp|
  p tp.defined_class #=> C
end.enable do
  C.new.foo
end

If method is defined by a module, then that module is returned.

module M; def foo; end; end
class C; include M; end;
trace = TracePoint.new(:call) do |tp|
  p tp.defined_class #=> M
end.enable do
  C.new.foo
end

Note: defined_class returns singleton class.

6th block parameter of Kernel#set_trace_func passes original class of attached by singleton class.

This is a difference between Kernel#set_trace_func and TracePoint.

class C; def self.foo; end; end
trace = TracePoint.new(:call) do |tp|
  p tp.defined_class #=> #<Class:C>
end.enable do
  C.foo
end

static VALUE
tracepoint_attr_defined_class(VALUE tpval)
{
    return rb_tracearg_defined_class(get_trace_arg());
}
disable → true or false click to toggle source
disable { block } → obj

Deactivates the trace

Return true if trace was enabled. Return false if trace was disabled.

trace.enabled?       #=> true
trace.disable        #=> false (previous status)
trace.enabled?       #=> false
trace.disable        #=> false

If a block is given, the trace will only be disable within the scope of the block.

trace.enabled?
#=> true

trace.disable do
    trace.enabled?
    # only disabled for this block
end

trace.enabled?
#=> true

Note: You cannot access event hooks within the block.

trace.disable { p tp.lineno }
#=> RuntimeError: access from outside

static VALUE
tracepoint_disable_m(VALUE tpval)
{
    rb_tp_t *tp = tpptr(tpval);
    int previous_tracing = tp->tracing;
    rb_tracepoint_disable(tpval);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, Qnil,
                         previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
                         tpval);
    }
    else {
        return previous_tracing ? Qtrue : Qfalse;
    }
}
enable → true or false click to toggle source
enable { block } → obj

Activates the trace

Return true if trace was enabled. Return false if trace was disabled.

trace.enabled?  #=> false
trace.enable    #=> false (previous state)
                #   trace is enabled
trace.enabled?  #=> true
trace.enable    #=> true (previous state)
                #   trace is still enabled

If a block is given, the trace will only be enabled within the scope of the block.

trace.enabled?
#=> false

trace.enable do
    trace.enabled?
    # only enabled for this block
end

trace.enabled?
#=> false

Note: You cannot access event hooks within the block.

trace.enable { p tp.lineno }
#=> RuntimeError: access from outside

static VALUE
tracepoint_enable_m(VALUE tpval)
{
    rb_tp_t *tp = tpptr(tpval);
    int previous_tracing = tp->tracing;
    rb_tracepoint_enable(tpval);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, Qnil,
                         previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
                         tpval);
    }
    else {
        return previous_tracing ? Qtrue : Qfalse;
    }
}
enabled? → true or false click to toggle source

The current status of the trace

VALUE
rb_tracepoint_enabled_p(VALUE tpval)
{
    rb_tp_t *tp = tpptr(tpval);
    return tp->tracing ? Qtrue : Qfalse;
}
event() click to toggle source

Type of event

See Events at TracePoint for more information.

static VALUE
tracepoint_attr_event(VALUE tpval)
{
    return rb_tracearg_event(get_trace_arg());
}
inspect → string click to toggle source

Return a string containing a human-readable TracePoint status.

static VALUE
tracepoint_inspect(VALUE self)
{
    rb_tp_t *tp = tpptr(self);
    rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;

    if (trace_arg) {
        switch (trace_arg->event) {
          case RUBY_EVENT_LINE:
          case RUBY_EVENT_SPECIFIED_LINE:
            {
                VALUE sym = rb_tracearg_method_id(trace_arg);
                if (NIL_P(sym))
                  goto default_inspect;
                return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d in `%"PRIsVALUE"'>",
                                  rb_tracearg_event(trace_arg),
                                  rb_tracearg_path(trace_arg),
                                  FIX2INT(rb_tracearg_lineno(trace_arg)),
                                  sym);
            }
          case RUBY_EVENT_CALL:
          case RUBY_EVENT_C_CALL:
          case RUBY_EVENT_RETURN:
          case RUBY_EVENT_C_RETURN:
            return rb_sprintf("#<TracePoint:%"PRIsVALUE" `%"PRIsVALUE"'@%"PRIsVALUE":%d>",
                              rb_tracearg_event(trace_arg),
                              rb_tracearg_method_id(trace_arg),
                              rb_tracearg_path(trace_arg),
                              FIX2INT(rb_tracearg_lineno(trace_arg)));
          case RUBY_EVENT_THREAD_BEGIN:
          case RUBY_EVENT_THREAD_END:
            return rb_sprintf("#<TracePoint:%"PRIsVALUE" %"PRIsVALUE">",
                              rb_tracearg_event(trace_arg),
                              rb_tracearg_self(trace_arg));
          default:
          default_inspect:
            return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d>",
                              rb_tracearg_event(trace_arg),
                              rb_tracearg_path(trace_arg),
                              FIX2INT(rb_tracearg_lineno(trace_arg)));
        }
    }
    else {
        return rb_sprintf("#<TracePoint:%s>", tp->tracing ? "enabled" : "disabled");
    }
}
lineno() click to toggle source

Line number of the event

static VALUE
tracepoint_attr_lineno(VALUE tpval)
{
    return rb_tracearg_lineno(get_trace_arg());
}
method_id() click to toggle source

Return the name of the method being called

static VALUE
tracepoint_attr_method_id(VALUE tpval)
{
    return rb_tracearg_method_id(get_trace_arg());
}
path() click to toggle source

Path of the file being run

static VALUE
tracepoint_attr_path(VALUE tpval)
{
    return rb_tracearg_path(get_trace_arg());
}
raised_exception() click to toggle source

Value from exception raised on the :raise event

static VALUE
tracepoint_attr_raised_exception(VALUE tpval)
{
    return rb_tracearg_raised_exception(get_trace_arg());
}
return_value() click to toggle source

Return value from :return, c_return, and b_return event

static VALUE
tracepoint_attr_return_value(VALUE tpval)
{
    return rb_tracearg_return_value(get_trace_arg());
}
self() click to toggle source

Return the trace object during event

Same as #binding:

trace.binding.eval('self')
static VALUE
tracepoint_attr_self(VALUE tpval)
{
    return rb_tracearg_self(get_trace_arg());
}


class TrueClass - Ruby 2.0.0-p576 Core API Reference API Reference

class TrueClass

The global value true is the only instance of class TrueClass and represents a logically true value in boolean expressions. The class provides operators allowing true to be used in logical expressions.

In Files

  • object.c

Parent

Object

Public Instance Methods

true & obj → true or false click to toggle source

And—Returns false if obj is nil or false, true otherwise.

static VALUE
true_and(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qtrue:Qfalse;
}
true ^ obj → !obj click to toggle source

Exclusive Or—Returns true if obj is nil or false, false otherwise.

static VALUE
true_xor(VALUE obj, VALUE obj2)
{
    return RTEST(obj2)?Qfalse:Qtrue;
}
inspect() click to toggle source
Alias for: to_s
to_s → "true" click to toggle source

The string representation of true is “true”.

static VALUE
true_to_s(VALUE obj)
{
    return rb_usascii_str_new2("true");
}
Also aliased as: inspect
true | obj → true click to toggle source

Or—Returns true. As anObject is an argument to a method call, it is always evaluated; there is no short-circuit evaluation in this case.

true |  puts("or")
true || puts("logical or")

produces:

or
static VALUE
true_or(VALUE obj, VALUE obj2)
{
    return Qtrue;
}


class TypeError - Ruby 2.0.0-p576 Core API Reference API Reference

class TypeError

Raised when encountering an object that is not of the expected type.

[1, 2, 3].first("two")

raises the exception:

TypeError: no implicit conversion of String into Integer

In Files

  • error.c

Parent

StandardError


class UnboundMethod - Ruby 2.0.0-p576 Core API Reference API Reference

class UnboundMethod

Ruby supports two forms of objectified methods. Class Method is used to represent methods that are associated with a particular object: these method objects are bound to that object. Bound method objects for an object can be created using Object#method.

Ruby also supports unbound methods; methods objects that are not associated with a particular object. These can be created either by calling Module#instance_method or by calling unbind on a bound method object. The result of both of these is an UnboundMethod object.

Unbound methods can only be called after they are bound to an object. That object must be be a kind_of? the method's original class.

class Square
  def area
    @side * @side
  end
  def initialize(side)
    @side = side
  end
end

area_un = Square.instance_method(:area)

s = Square.new(12)
area = area_un.bind(s)
area.call   #=> 144

Unbound methods are a reference to the method at the time it was objectified: subsequent changes to the underlying class will not affect the unbound method.

class Test
  def test
    :original
  end
end
um = Test.instance_method(:test)
class Test
  def test
    :modified
  end
end
t = Test.new
t.test            #=> :modified
um.bind(t).call   #=> :original

In Files

  • proc.c

Parent

Object

Public Instance Methods

meth == other_meth → true or false click to toggle source

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
        return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
        return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
        m1->rclass != m2->rclass ||
        m1->recv != m2->recv) {
        return Qfalse;
    }

    return Qtrue;
}
arity → fixnum click to toggle source

Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. For methods written in C, returns -1 if the call takes a variable number of arguments.

class C
  def one;    end
  def two(a); end
  def three(*a);  end
  def four(a, b); end
  def five(a, b, *c);    end
  def six(a, b, *c, &d); end
end
c = C.new
c.method(:one).arity     #=> 0
c.method(:two).arity     #=> 1
c.method(:three).arity   #=> -1
c.method(:four).arity    #=> 2
c.method(:five).arity    #=> -3
c.method(:six).arity     #=> -3

"cat".method(:size).arity      #=> 0
"cat".method(:replace).arity   #=> 1
"cat".method(:squeeze).arity   #=> -1
"cat".method(:count).arity     #=> -1

static VALUE
method_arity_m(VALUE method)
{
    int n = method_arity(method);
    return INT2FIX(n);
}
bind(obj) → method click to toggle source

Bind umeth to obj. If Klass was the class from which umeth was obtained, obj.kind_of?(Klass) must be true.

class A
  def test
    puts "In test, class = #{self.class}"
  end
end
class B < A
end
class C < B
end

um = B.instance_method(:test)
bm = um.bind(C.new)
bm.call
bm = um.bind(B.new)
bm.call
bm = um.bind(A.new)
bm.call

produces:

In test, class = C
In test, class = B
prog.rb:16:in %xbind': bind argument must be an instance of B (TypeError)
 from prog.rb:16

static VALUE
umethod_bind(VALUE method, VALUE recv)
{
    struct METHOD *data, *bound;
    VALUE methclass;
    VALUE rclass;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);

    methclass = data->rclass;
    if (!RB_TYPE_P(methclass, T_MODULE) &&
        methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
        if (FL_TEST(methclass, FL_SINGLETON)) {
            rb_raise(rb_eTypeError,
                     "singleton method called for a different object");
        }
        else {
            rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
                     rb_class2name(methclass));
        }
    }

    method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
    *bound = *data;
    bound->me = ALLOC(rb_method_entry_t);
    *bound->me = *data->me;
    if (bound->me->def) bound->me->def->alias_count++;
    rclass = CLASS_OF(recv);
    if (BUILTIN_TYPE(bound->defined_class) == T_MODULE) {
        VALUE ic = rb_class_search_ancestor(rclass, bound->defined_class);
        if (ic) {
            rclass = ic;
        }
        else {
            rclass = rb_include_class_new(methclass, rclass);
        }
    }
    bound->recv = recv;
    bound->rclass = rclass;
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);

    return method;
}
clone → new_method click to toggle source

Returns a clone of this method.

class A
  def foo
    return "bar"
  end
end

m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"

static VALUE
method_clone(VALUE self)
{
    VALUE clone;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(self, struct METHOD, &method_data_type, orig);
    clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
    CLONESETUP(clone, self);
    *data = *orig;
    data->me = ALLOC(rb_method_entry_t);
    *data->me = *orig->me;
    if (data->me->def) data->me->def->alias_count++;
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);

    return clone;
}
meth == other_meth → true or false click to toggle source

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
        return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
        return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
        m1->rclass != m2->rclass ||
        m1->recv != m2->recv) {
        return Qfalse;
    }

    return Qtrue;
}
hash → integer click to toggle source

Returns a hash value corresponding to the method object.

static VALUE
method_hash(VALUE method)
{
    struct METHOD *m;
    st_index_t hash;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
    hash = rb_hash_start((st_index_t)m->rclass);
    hash = rb_hash_uint(hash, (st_index_t)m->recv);
    hash = rb_hash_method_entry(hash, m->me);
    hash = rb_hash_end(hash);

    return INT2FIX(hash);
}
to_s → string click to toggle source
inspect → string

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
        VALUE v = rb_ivar_get(data->me->klass, attached);

        if (data->recv == Qundef) {
            rb_str_buf_append(str, rb_inspect(data->me->klass));
        }
        else if (data->recv == v) {
            rb_str_buf_append(str, rb_inspect(v));
            sharp = ".";
        }
        else {
            rb_str_buf_append(str, rb_inspect(data->recv));
            rb_str_buf_cat2(str, "(");
            rb_str_buf_append(str, rb_inspect(v));
            rb_str_buf_cat2(str, ")");
            sharp = ".";
        }
    }
    else {
        rb_str_buf_cat2(str, rb_class2name(data->rclass));
        if (data->rclass != data->me->klass) {
            rb_str_buf_cat2(str, "(");
            rb_str_buf_cat2(str, rb_class2name(data->me->klass));
            rb_str_buf_cat2(str, ")");
        }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}
name → symbol click to toggle source

Returns the name of the method.

static VALUE
method_name(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return ID2SYM(data->id);
}
owner → class_or_module click to toggle source

Returns the class or module that defines the method.

static VALUE
method_owner(VALUE obj)
{
    struct METHOD *data;
    VALUE defined_class;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    defined_class = data->defined_class;

    if (RB_TYPE_P(defined_class, T_ICLASS)) {
        defined_class = RBASIC(defined_class)->klass;
    }

    return defined_class;
}
parameters → array click to toggle source

Returns the parameter information of this method.

static VALUE
rb_method_parameters(VALUE method)
{
    rb_iseq_t *iseq = rb_method_get_iseq(method);
    if (!iseq) {
        return unnamed_parameters(method_arity(method));
    }
    return rb_iseq_parameters(iseq, 0);
}
source_location → [String, Fixnum] click to toggle source

Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)

VALUE
rb_method_location(VALUE method)
{
    rb_method_definition_t *def = method_get_def(method);
    return method_def_location(def);
}
to_s → string click to toggle source
inspect → string

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
        VALUE v = rb_ivar_get(data->me->klass, attached);

        if (data->recv == Qundef) {
            rb_str_buf_append(str, rb_inspect(data->me->klass));
        }
        else if (data->recv == v) {
            rb_str_buf_append(str, rb_inspect(v));
            sharp = ".";
        }
        else {
            rb_str_buf_append(str, rb_inspect(data->recv));
            rb_str_buf_cat2(str, "(");
            rb_str_buf_append(str, rb_inspect(v));
            rb_str_buf_cat2(str, ")");
            sharp = ".";
        }
    }
    else {
        rb_str_buf_cat2(str, rb_class2name(data->rclass));
        if (data->rclass != data->me->klass) {
            rb_str_buf_cat2(str, "(");
            rb_str_buf_cat2(str, rb_class2name(data->me->klass));
            rb_str_buf_cat2(str, ")");
        }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}


class ZeroDivisionError - Ruby 2.0.0-p576 Core API Reference API Reference

class ZeroDivisionError

Raised when attempting to divide an integer by 0.

42 / 0

raises the exception:

ZeroDivisionError: divided by 0

Note that only division by an exact 0 will raise that exception:

42 /  0.0 #=> Float::INFINITY
42 / -0.0 #=> -Float::INFINITY
0  /  0.0 #=> NaN

In Files

  • numeric.c

Parent

StandardError


class fatal - Ruby 2.0.0-p576 Core API Reference API Reference

class fatal

fatal is an Exception that is raised when ruby has encountered a fatal error and must exit. You are not able to rescue fatal.

In Files

  • error.c

Parent

Exception


class fatal - Ruby 2.0.0-p576 Core API Reference API Reference

Ruby 2.0.0-p576 Core API Reference API Reference

This is the API documentation for 'Ruby 2.0.0-p576 Core API Reference API Reference'.


Ruby 2.0.0-p576 Core API Reference API Reference

This is the API documentation for 'Ruby 2.0.0-p576 Core API Reference API Reference'.

Classes/Modules

  • Encoding
  • Encoding::CompatibilityError
  • Encoding::Converter
  • Encoding::ConverterNotFoundError
  • Encoding::InvalidByteSequenceError
  • Encoding::UndefinedConversionError
  • Process
  • Process::GID
  • Process::Status
  • Process::Sys
  • Process::UID
  • Enumerator
  • Enumerator::Generator
  • Enumerator::Lazy
  • Enumerator::Yielder
  • File
  • File::Constants
  • File::Stat
  • IO
  • IO::WaitReadable
  • IO::WaitWritable
  • RubyVM
  • RubyVM::Env
  • RubyVM::InstructionSequence
  • Complex
  • Complex::compatible
  • GC
  • GC::Profiler
  • Math
  • Math::DomainError
  • ObjectSpace
  • ObjectSpace::WeakMap
  • Rational
  • Rational::compatible
  • ARGF
  • ArgumentError
  • Array
  • BasicObject
  • Bignum
  • Binding
  • Class
  • Comparable
  • Continuation
  • Data
  • Dir
  • ENV
  • EOFError
  • EncodingError
  • Enumerable
  • Errno
  • Exception
  • FalseClass
  • Fiber
  • FiberError
  • FileTest
  • Fixnum
  • Float
  • FloatDomainError
  • Hash
  • IOError
  • IndexError
  • Integer
  • Interrupt
  • Kernel
  • KeyError
  • LoadError
  • LocalJumpError
  • Marshal
  • MatchData
  • Method
  • Module
  • Mutex
  • NameError
  • NilClass
  • NoMemoryError
  • NoMethodError
  • NotImplementedError
  • Numeric
  • Object
  • Proc
  • Random
  • Range
  • RangeError
  • Regexp
  • RegexpError
  • Ripper
  • RuntimeError
  • ScriptError
  • SecurityError
  • Signal
  • SignalException
  • StandardError
  • StopIteration
  • String
  • Struct
  • Symbol
  • SyntaxError
  • SystemCallError
  • SystemExit
  • SystemStackError
  • Thread
  • ThreadError
  • ThreadGroup
  • Time
  • TracePoint
  • TrueClass
  • TypeError
  • UnboundMethod
  • ZeroDivisionError
  • fatal