Skip to content

Commit

Permalink
Add setBytes method to DataView
Browse files Browse the repository at this point in the history
- Writes multiple bytes at once
- Bytes can be either an array or string
  • Loading branch information
andrepiske committed Mar 18, 2020
1 parent 653e5b8 commit 1be85b2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
32 changes: 32 additions & 0 deletions ext/arraybuffer/dataview.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,37 @@ t_dv_setu32(VALUE self, VALUE index, VALUE value) {
return self;
}

static VALUE
t_dv_setbytes(VALUE self, VALUE index, VALUE bytes) {
DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
unsigned int idx0 = dv->offset + (unsigned int)idx;
CHECKBOUNDSBB(idx0);

if (RB_TYPE_P(bytes, T_ARRAY)) {
const unsigned int length = (unsigned int)rb_array_len(bytes);
const VALUE* items = rb_array_const_ptr(bytes);
CHECKBOUNDSBB(idx0 + length);

for (unsigned int i = 0; i < length; i++) {
int num = NUM2INT(items[i]);
ADJUSTBOUNDS(num, 0xFF);
bb->ptr[idx0 + i] = (unsigned char)num;
}
} else if (RB_TYPE_P(bytes, T_STRING)) {
const char *str_ptr = RSTRING_PTR(bytes);
const unsigned int length = (unsigned int)RSTRING_LEN(bytes);
CHECKBOUNDSBB(idx0 + length);

for (unsigned int i = 0; i < length; i++) {
bb->ptr[idx0 + i] = (unsigned char)str_ptr[i];
}
} else {
rb_raise(rb_eArgError, "Invalid type");
}

return self;
}

void
Init_dataview() {
idEndianess = rb_intern("endianess");
Expand All @@ -455,6 +486,7 @@ Init_dataview() {
rb_define_method(cDataView, "setU16", t_dv_setu16, 2);
rb_define_method(cDataView, "setU24", t_dv_setu24, 2);
rb_define_method(cDataView, "setU32", t_dv_setu32, 2);
rb_define_method(cDataView, "setBytes", t_dv_setbytes, 2);

rb_define_method(cDataView, "endianess", t_dv_endianess, 0);
rb_define_method(cDataView, "offset=", t_dv_setoffset, 1);
Expand Down
29 changes: 29 additions & 0 deletions spec/dataview_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,35 @@
end
end

describe "setBytes" do
let(:dv) { described_class.new(buffer, 1) }
let(:new_bytes) { [40, 0, 13, 25, 250, 127, 128] }
let(:expected_bytes) { [1, 40, 0, 13, 25, 250, 127, 128, 99, 192, 32, 12, 0, 49] }

context "when argument is an array" do
it "sets the bytes" do
dv.setBytes(0, new_bytes)
expect(buffer.bytes.split('').map(&:ord)).to eq(expected_bytes)
end
end

context "when argument is a string" do
it "sets the bytes" do
dv.setBytes(0, new_bytes.map(&:chr).join)
expect(buffer.bytes.split('').map(&:ord)).to eq(expected_bytes)
end
end

context "when argument is an utf-8 string" do
let(:expected_bytes) { [1, 233, 139, 184, 105, 27, 175, 88, 99, 192, 32, 12, 0, 49] }

it "sets the bytes" do
dv.setBytes(0, "鋸i")
expect(buffer.bytes.split('').map(&:ord)).to eq(expected_bytes)
end
end
end

shared_examples "offset out of bounds" do
context "when offset is greater than the underlying buffer" do
let(:offset) { 1000 }
Expand Down

0 comments on commit 1be85b2

Please sign in to comment.