123456789_123456789_123456789_123456789_123456789_

Class: IO::Buffer::Slice

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ::IO::Buffer
Instance Chain:
Inherits: IO::Buffer
Defined in: io_buffer.c

Overview

A zero-copy, parent-relative view of an ::IO::Buffer or another Slice. Create a view with #slice or .new:

buffer = IO::Buffer.new(6)
buffer.set_string("abcdef")
parent = buffer.slice(1, 4)
child = parent.slice(1, 2)
child.source.equal?(parent) # => true
child.get_string            # => "cd"
parent.advance(1)
child.get_string            # => "de"

A slice retains its immediate source and follows that source's current view. Its range is valid only while every parent is valid and the range fits within its source. Moving the backing allocation does not itself invalidate a slice. Shrinking a parent can invalidate descendants; growing it again can restore their validity.

Slice inherits Buffer's byte-access interface but does not manage storage. Resizing a slice only changes its extent within its parent's bounds, and advancing it consumes bytes from the front of its view. Neither operation allocates or releases storage. Slice has no free or transfer method, nor Storage's predicates such as mapped? or internal?.

Writes modify the source's bytes and respect its current permissions. Locking a slice protects the backing allocation; #locked? reports that shared lock state. Locked or read-only views may still be resized or advanced, but frozen views cannot change their range. Locking does not serialize access to bytes or view metadata.

Duplicating or cloning a Slice copies its view rather than its bytes. Both Slice and Storage are subclasses of ::IO::Buffer.

Constant Summary

::IO::Buffer - Inherited

BIG_ENDIAN, DEFAULT_SIZE, EXTERNAL, HOST_ENDIAN, INTERNAL, LITTLE_ENDIAN, MAPPED, MAP_ALIGNMENT, NETWORK_ENDIAN, PAGE_SIZE, PRIVATE, READONLY, SHARED, VERSION

Class Method Summary

::IO::Buffer - Inherited

.for

Creates a zero-copy ::IO::Buffer from the given string's memory.

.map

Create an ::IO::Buffer for reading from file by memory-mapping the file.

.new

Creates an Storage with the given size and flags.

.size_of

Returns the size of the given buffer type(s) in bytes.

.string

Creates a new string of the given length and yields a zero-copy ::IO::Buffer instance to the block which uses the string as a source.

Instance Attribute Summary

::IO::Buffer - Inherited

#empty?,
#locked

Prevents the buffer or its buffer source from being moved or freed while the block is executing.

#locked?, #null?, #readonly?, #valid?

Instance Method Summary

::IO::Buffer - Inherited

#&

Generate a new buffer the same size as the source by applying the binary AND operation to the source, using the mask, repeating as necessary.

#<=>

Returns a negative integer, zero, or a positive integer if the receiver is less than, equal to, or greater than other, respectively.

#^

Generate a new buffer the same size as the source by applying the binary XOR operation to the source, using the mask, repeating as necessary.

#advance

Advances the beginning of a non-owning buffer view by amount bytes, reducing its size by the same amount.

#and!

Modify the source buffer in place by applying the binary AND operation to the source, using the mask, repeating as necessary.

#bit_count

Returns the number of set bits (1s) in the buffer, also known as the Hamming weight or population count.

#clear

Fill buffer with value, starting with offset and going for length bytes.

#copy

Efficiently copy from a source ::IO::Buffer into the buffer, at offset using memmove.

#get_string

Read a chunk or all of the buffer into a string, in the specified encoding.

#get_value

Read from buffer a value of type at offset.

#get_values

Similar to #get_value, except that it can handle multiple buffer types and returns an array of values.

#hexdump

Returns a human-readable string representation of the buffer.

#not!

Modify the source buffer in place by applying the unary NOT operation to the source.

#or!

Modify the source buffer in place by applying the binary OR operation to the source, using the mask, repeating as necessary.

#read

Perform one read operation of at most length bytes from io into the buffer starting at offset.

#set_string

Efficiently copy from a source ::String into the buffer, at offset using memmove.

#set_value,
#set_values

Write #values of buffer_types at offset to the buffer.

#size,
#slice

Produce another ::IO::Buffer which is a slice (or view into) the current one starting at offset bytes and going for length bytes.

#source

Returns the object backing this view, or nil for a source-less buffer.

#to_s,
#values

Returns an array of values of buffer_type starting from offset.

#write

Perform one write operation of at most length bytes to io from the buffer starting at offset.

#xor!

Modify the source buffer in place by applying the binary XOR operation to the source, using the mask, repeating as necessary.

#|

Generate a new buffer the same size as the source by applying the binary OR operation to the source, using the mask, repeating as necessary.

#~

Generate a new buffer the same size as the source by applying the unary NOT operation to the source.

::Comparable - Included

#<

Returns whether self is "less than" other; equivalent to (self <=> other) < 0:

#<=

Returns whether self is "less than or equal to" other; equivalent to (self <=> other) <= 0:

#==

Compares two objects based on the receiver's #<=> method, returning true if it returns 0.

#>

Returns whether self is "greater than" other; equivalent to (self <=> other) > 0:

#>=

Returns whether self is "greater than or equal to" other; equivalent to (self <=> other) >= 0:

#between?

Returns false if obj #<=> min is less than zero or if obj #<=> max is greater than zero, true otherwise.

#clamp

In (min, max) form, returns min if obj #<=> min is less than zero, max if obj #<=> max is greater than zero, and obj otherwise.

Constructor Details

.new(source, [offset, [length]]) ⇒ Slice

Creates a parent-relative view of a ::IO::Buffer or another Slice. The source is retained, not copied. Resizing or advancing this view never allocates storage.

[ GitHub ]

  
# File 'io_buffer.c', line 2153

static VALUE
io_buffer_slice_initialize(int argc, VALUE *argv, VALUE self)
{
    rb_check_frozen(self);
    rb_check_arity(argc, 1, 3);
    struct rb_io_buffer_view *slice = get_io_buffer_view(self);
    if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");

    VALUE source = argv[0];
    size_t offset, length;
    struct rb_io_buffer_view *parent = io_buffer_extract_offset_length(source, argc-1, argv+1, &offset, &length);
    io_buffer_validate_range(parent, offset, length);

    slice = get_io_buffer_view(self);
    if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");
    slice->base = (void *)(uintptr_t)offset;
    slice->size = length;
    RB_OBJ_WRITE(self, &slice->source, source);
    return self;
}

Instance Method Details

#dup ⇒ Slice #clone ⇒ Slice

Copies the view, retaining the same source, offset, and size without copying the underlying bytes. Advancing or resizing the copy does not change the original view; writes through either view affect shared storage.

buffer = IO::Buffer.new(6)
buffer.set_string("abcdef")
slice = buffer.slice(1, 3)
copy = slice.dup
copy.source.equal?(slice.source) # => true
copy.advance(1)
copy.get_string                 # => "cd"
slice.get_string                # => "bcd"
copy.set_string("XY")
buffer.get_string               # => "abXYef"

This differs from IO::Buffer::Storage#dup, which copies the bytes into independent storage. The usual Object#dup and Object#clone frozen-state rules apply.

[ GitHub ]

  
# File 'io_buffer.c', line 2197

static VALUE
io_buffer_slice_initialize_copy(VALUE self, VALUE other)
{
    if (self == other) return self;
    rb_check_frozen(self);
    struct rb_io_buffer_view *slice = get_io_buffer_view(self);
    const struct rb_io_buffer_view *original = get_io_buffer_view(other);
    if (!io_buffer_slice_p(original)) rb_raise(rb_eTypeError, "Expected IO::Buffer::Slice!");
    if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");

    slice->base = original->base;
    slice->size = original->size;
    slice->flags = original->flags;
    RB_OBJ_WRITE(self, &slice->source, original->source);
    return self;
}

#resize(new_size) ⇒ self

Alias for Storage#resize.