123456789_123456789_123456789_123456789_123456789_

Class: NIO::ByteBuffer

Relationships & Source Files
Namespace Children
Exceptions:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, Enumerable, Enumerable
Inherits: Object
Defined in: lib/nio/bytebuffer.rb,
ext/nio4r/bytebuffer.c

Overview

Efficient byte buffers for performant I/O operations

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(capacity)

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 131

static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE capacity)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    buffer->capacity = NUM2INT(capacity);
    buffer->buffer = xmalloc(buffer->capacity);

    NIO_ByteBuffer_clear(self);

    return self;
}

#initialize(capacity) ⇒ ByteBuffer

Create a new ByteBuffer, either with a specified capacity or populating it from a given string

Parameters:

  • capacity (Integer)

    size of buffer in bytes

Raises:

  • (TypeError)
[ GitHub ]

  
# File 'lib/nio/bytebuffer.rb', line 31

def initialize(capacity)
  raise TypeError, "no implicit conversion of #{capacity.class} to Integer" unless capacity.is_a?(Integer)

  @capacity = capacity
  clear
end

Instance Attribute Details

#capacity (readonly)

Alias for #size.

#full?true, false (readonly)

Does the ByteBuffer have any space remaining?

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 244

static VALUE NIO_ByteBuffer_full(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return buffer->position == buffer->limit ? Qtrue : Qfalse;
}

#limit (rw)

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 191

static VALUE NIO_ByteBuffer_get_limit(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return INT2NUM(buffer->limit);
}

#limit=(new_limit) (rw)

Set the limit to the given value. New limit must be less than capacity. Preserves limit and mark if they're less than the new limit, otherwise sets position to the new limit and clears the mark.

Parameters:

  • new_limit (Integer)

    position in the buffer

Raises:

  • (ArgumentError)

    new limit was invalid

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 199

static VALUE NIO_ByteBuffer_set_limit(VALUE self, VALUE new_limit)
{
    int lim;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    lim = NUM2INT(new_limit);

    if (lim < 0) {
        rb_raise(rb_eArgError, "negative limit given");
    }

    if (lim > buffer->capacity) {
        rb_raise(rb_eArgError, "specified limit exceeds capacity");
    }

    buffer->limit = lim;

    if (buffer->position > lim) {
        buffer->position = lim;
    }

    if (buffer->mark > lim) {
        buffer->mark = MARK_UNSET;
    }

    return new_limit;
}

#position (rw)

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 158

static VALUE NIO_ByteBuffer_get_position(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return INT2NUM(buffer->position);
}

#position=(new_position) (rw)

Set the position to the given value. New position must be less than limit. Preserves mark if it's less than the new position, otherwise clears it.

Parameters:

  • new_position (Integer)

    position in the buffer

Raises:

  • (ArgumentError)

    new position was invalid

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 166

static VALUE NIO_ByteBuffer_set_position(VALUE self, VALUE new_position)
{
    int pos;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    pos = NUM2INT(new_position);

    if (pos < 0) {
        rb_raise(rb_eArgError, "negative position given");
    }

    if (pos > buffer->limit) {
        rb_raise(rb_eArgError, "specified position exceeds limit");
    }

    buffer->position = pos;

    if (buffer->mark > buffer->position) {
        buffer->mark = MARK_UNSET;
    }

    return new_position;
}

#size (readonly) Also known as: #capacity

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 228

static VALUE NIO_ByteBuffer_capacity(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return INT2NUM(buffer->capacity);
}

Instance Method Details

#<<(str)

Alias for #put.

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 300

static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string)
{
    long length;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    StringValue(string);
    length = RSTRING_LEN(string);

    if (length > buffer->limit - buffer->position) {
        rb_raise(cNIO_ByteBuffer_OverflowError, "buffer is full");
    }

    memcpy(buffer->buffer + buffer->position, StringValuePtr(string), length);
    buffer->position += length;

    return self;
}

#[](index) ⇒ Integer

Obtain the byte at a given index in the buffer as an Integer

Returns:

  • (Integer)

    byte at the given index

Raises:

  • (ArgumentError)

    index is invalid (either negative or larger than limit)

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 281

static VALUE NIO_ByteBuffer_fetch(VALUE self, VALUE index)
{
    int i;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    i = NUM2INT(index);

    if (i < 0) {
        rb_raise(rb_eArgError, "negative index given");
    }

    if (i >= buffer->limit) {
        rb_raise(rb_eArgError, "specified index exceeds limit");
    }

    return INT2NUM(buffer->buffer[i]);
}

#clear

Clear the buffer, resetting it to the default state

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 144

static VALUE NIO_ByteBuffer_clear(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    memset(buffer->buffer, 0, buffer->capacity);

    buffer->position = 0;
    buffer->limit = buffer->capacity;
    buffer->mark = MARK_UNSET;

    return self;
}

#compact

Move data between the position and limit to the beginning of the buffer Sets the position to the end of the moved data, and the limit to the capacity

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 424

static VALUE NIO_ByteBuffer_compact(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    memmove(buffer->buffer, buffer->buffer + buffer->position, buffer->limit - buffer->position);
    buffer->position = buffer->limit - buffer->position;
    buffer->limit = buffer->capacity;

    return self;
}

#each(&block) ⇒ self

Iterate over the bytes in the buffer (as Integers)

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 436

static VALUE NIO_ByteBuffer_each(VALUE self)
{
    int i;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    if (rb_block_given_p()) {
        for (i = 0; i < buffer->limit; i++) {
            rb_yield(INT2NUM(buffer->buffer[i]));
        }
    } else {
        rb_raise(rb_eArgError, "no block given");
    }

    return self;
}

#flip

Set the buffer's current position as the limit and set the position to 0

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 378

static VALUE NIO_ByteBuffer_flip(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    buffer->limit = buffer->position;
    buffer->position = 0;
    buffer->mark = MARK_UNSET;

    return self;
}

#get(length = remaining) ⇒ String

Obtain the requested number of bytes from the buffer, advancing the position. If no length is given, all remaining bytes are consumed.

Returns:

  • (String)

    bytes read from buffer

Raises:

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 252

static VALUE NIO_ByteBuffer_get(int argc, VALUE *argv, VALUE self)
{
    int len;
    VALUE length, result;
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

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

    if (length == Qnil) {
        len = buffer->limit - buffer->position;
    } else {
        len = NUM2INT(length);
    }

    if (len < 0) {
        rb_raise(rb_eArgError, "negative length given");
    }

    if (len > buffer->limit - buffer->position) {
        rb_raise(cNIO_ByteBuffer_UnderflowError, "not enough data in buffer");
    }

    result = rb_str_new(buffer->buffer + buffer->position, len);
    buffer->position += len;

    return result;
}

#inspectString

Inspect the state of the buffer

Returns:

  • (String)

    string describing the state of the buffer

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 453

static VALUE NIO_ByteBuffer_inspect(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return rb_sprintf(
        "#<%s:%p @position=%d @limit=%d @capacity=%d>",
        rb_class2name(CLASS_OF(self)),
        (void *)self,
        buffer->position,
        buffer->limit,
        buffer->capacity);
}

#mark

Mark a position to return to using the #reset method

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 401

static VALUE NIO_ByteBuffer_mark(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    buffer->mark = buffer->position;
    return self;
}

#put(str) ⇒ self Also known as: #<<

Add a String to the buffer

Parameters:

  • str (#to_str)

    data to add to the buffer

Raises:

[ GitHub ]

  
# File 'lib/nio/bytebuffer.rb', line 127

def put(str)
  raise TypeError, "expected String, got #{str.class}" unless str.respond_to?(:to_str)

  str = str.to_str

  raise OverflowError, "buffer is full" if str.length > @limit - @position

  @buffer[@position...str.length] = str
  @position += str.length
  self
end

#read_from(io) ⇒ Integer

Perform a non-blocking read from the given IO object into the buffer Reads as much data as is immediately available and returns

Parameters:

  • Ruby (IO)

    IO object to read from

Returns:

  • (Integer)

    number of bytes read (0 if none were available)

Raises:

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 319

static VALUE NIO_ByteBuffer_read_from(VALUE self, VALUE io)
{
    struct NIO_ByteBuffer *buffer;
    ssize_t nbytes, bytes_read;

    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    io = rb_convert_type(io, T_FILE, "IO", "to_io");
    io_set_nonblock(io);

    nbytes = buffer->limit - buffer->position;
    if (nbytes == 0) {
        rb_raise(cNIO_ByteBuffer_OverflowError, "buffer is full");
    }

    bytes_read = read(rb_io_descriptor(io), buffer->buffer + buffer->position, nbytes);

    if (bytes_read < 0) {
        if (errno == EAGAIN) {
            return INT2NUM(0);
        } else {
            rb_sys_fail("write");
        }
    }

    buffer->position += bytes_read;

    return SIZET2NUM(bytes_read);
}

#remainingInteger

Number of bytes remaining in the buffer before the limit

Returns:

  • (Integer)

    number of bytes remaining

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 236

static VALUE NIO_ByteBuffer_remaining(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    return INT2NUM(buffer->limit - buffer->position);
}

#reset

Reset position to the previously marked location

Raises:

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 410

static VALUE NIO_ByteBuffer_reset(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    if (buffer->mark < 0) {
        rb_raise(cNIO_ByteBuffer_MarkUnsetError, "mark has not been set");
    } else {
        buffer->position = buffer->mark;
    }

    return self;
}

#rewind

Set the buffer's current position to 0, leaving the limit unchanged

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 390

static VALUE NIO_ByteBuffer_rewind(VALUE self)
{
    struct NIO_ByteBuffer *buffer;
    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);

    buffer->position = 0;
    buffer->mark = MARK_UNSET;

    return self;
}

#write_to(io) ⇒ Integer

Perform a non-blocking write of the buffer's contents to the given I/O object Writes as much data as is immediately possible and returns

Parameters:

  • Ruby (IO)

    IO object to write to

Returns:

  • (Integer)

    number of bytes written (0 if the write would block)

Raises:

[ GitHub ]

  
# File 'ext/nio4r/bytebuffer.c', line 349

static VALUE NIO_ByteBuffer_write_to(VALUE self, VALUE io)
{
    struct NIO_ByteBuffer *buffer;
    ssize_t nbytes, bytes_written;

    TypedData_Get_Struct(self, struct NIO_ByteBuffer, &NIO_ByteBuffer_type, buffer);
    io = rb_convert_type(io, T_FILE, "IO", "to_io");
    io_set_nonblock(io);

    nbytes = buffer->limit - buffer->position;
    if (nbytes == 0) {
        rb_raise(cNIO_ByteBuffer_UnderflowError, "no data remaining in buffer");
    }

    bytes_written = write(rb_io_descriptor(io), buffer->buffer + buffer->position, nbytes);

    if (bytes_written < 0) {
        if (errno == EAGAIN) {
            return INT2NUM(0);
        } else {
            rb_sys_fail("write");
        }
    }

    buffer->position += bytes_written;

    return SIZET2NUM(bytes_written);
}