Class: DataView

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
ext/arraybuffer/dataview.c

Instance Method Summary collapse

Constructor Details

#initialize(buffer, offset, size, endianess: ) ⇒ Object

Constructs a new DataView that provides a view of the data in a ArrayBuffer.

Example:

buffer = ArrayBuffer.new(10)
buffer[1] = 20
buffer[2] = 55
view = DataView.new(buffer, 1, endianess: :little)
view.getU8() == ( 20 & (55 << 8) ) # true

Or:

view = DataView.new(buffer, 1) # default endianess is "big endian"
view.getU8() == ( (20 << 8) | 55 ) # true

Parameters:

  • buffer (ArrayBuffer)

    The array buffer where to operate

  • offset (Integer)

    Optional. The byte offset from the array buffer. The default value is zero

  • size (Integer)

    Optional. The size in bytes that this DataView can see into the array buffer. If left blank, the current size of the array buffer will be used

  • endianess (:big, :little)

    Optional. The default value is big



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'ext/arraybuffer/dataview.c', line 72

static VALUE
t_dv_initialize(int argc, VALUE *argv, VALUE self) {
  DECLAREDV(self);
  VALUE bb_obj;
  VALUE offset;
  VALUE size;
  VALUE kwargs;
  static ID keyword_ids[] = { 0 };

  rb_scan_args(argc, argv, "12:", &bb_obj, &offset, &size, &kwargs);

  DECLAREBB(bb_obj);

  int size_val = NIL_P(size) ? (int)bb->size : NUM2INT(size);
  if (size_val < 0)
    size_val += (int)bb->size;
  if (size_val < 0)
    rb_raise(rb_eArgError, "calculated size is negative: %d", size_val);

  int offset_val = NIL_P(offset) ? 0 : NUM2INT(offset);
  if (offset_val < 0)
    offset_val += (int)bb->size;
  if (offset_val < 0)
    rb_raise(rb_eArgError, "calculated offset is negative: %d", offset_val);

  dv->offset = (unsigned long)offset_val;
  dv->size = (unsigned long)size_val;
  dv->bb_obj = bb_obj;

  if (!keyword_ids[0]) {
    keyword_ids[0] = idEndianess;
  }

  if (!NIL_P(kwargs)) {
    VALUE endianess;
    rb_get_kwargs(kwargs, keyword_ids, 0, 1, &endianess);
    if (endianess != Qundef) {
      Check_Type(endianess, T_SYMBOL);
      ID id = SYM2ID(endianess);
      if (id == idLittle)
        dv->flags |= FLAG_LITTLE_ENDIAN;
      else if (id != idBig)
        rb_raise(rb_eArgError, "endianess must be either :big or :little");
    }
  }

  return self;
}

Instance Method Details

#eachObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'ext/arraybuffer/dataview.c', line 141

static VALUE
t_dv_each(VALUE self) {
  DECLAREDV(self);
  DECLAREBB(dv->bb_obj);

  int size = dv->size;
  if (size + dv->offset >= bb->size)
    size = bb->size - dv->offset;

  if (rb_block_given_p()) {
    for (int i = 0; i < size; i++) {
      unsigned int val = (unsigned int)bb->ptr[i + dv->offset];
      rb_yield(UINT2NUM(val));
    }
  } else {
    rb_raise(rb_eArgError, "no block given");
  }
  return self;
}

#endianessObject



133
134
135
136
137
138
139
# File 'ext/arraybuffer/dataview.c', line 133

static VALUE
t_dv_endianess(VALUE self) {
  DECLAREDV(self);
  return CHECK_LITTLEENDIAN(dv) ?
    ID2SYM(idLittle) :
    ID2SYM(idBig);
}

#getBit(index) ⇒ Integer

Reads a bit at index.

This method differs from the other in that the index is given in bits, not in bytes. Thus it’s possible to read from index 0 to (size * 8) - 1

Returns:

  • (Integer)

    Either 0 or 1



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'ext/arraybuffer/dataview.c', line 223

static VALUE
t_dv_getbit(VALUE self, VALUE index) {
  DECLAREDV(self); DECLAREBB(dv->bb_obj);
  int idx = NUM2INT(index);
  if (idx < 0)
    idx += (int)dv->size * 8;
  if (idx < 0 || idx >= dv->size * 8)
    rb_raise(rb_eArgError, "index out of bounds: %d", idx);

  unsigned int bit_idx = ((unsigned int)idx) & 7;
  unsigned int byte_idx = (((unsigned int)idx) >> 3) + dv->offset;
  unsigned char bit_mask = 1 << bit_idx;

  CHECKBOUNDSBB(byte_idx);
  return (bb->ptr[byte_idx] & bit_mask) ? UINT2NUM(1) : UINT2NUM(0);
}

#getU16(index) ⇒ Integer

Reads two bytes starting at index as an unsigned short

Returns:

  • (Integer)

    Integer between 0 and 65535



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'ext/arraybuffer/dataview.c', line 258

static VALUE
t_dv_getu16(VALUE self, VALUE index) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx1);
  unsigned short val = 0;
  if (CHECK_LITTLEENDIAN(dv)) {
    val |= bb->ptr[idx0];
    val |= bb->ptr[idx1] << 8;
  } else {
    val |= bb->ptr[idx0] << 8;
    val |= bb->ptr[idx1];
  }
  return UINT2NUM(val);
}

#getU24(index) ⇒ Integer

Reads three bytes starting at index as a 3 bytes long unsigned integer

Returns:

  • (Integer)

    Integer between 0 and 16777215



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'ext/arraybuffer/dataview.c', line 281

static VALUE
t_dv_getu24(VALUE self, VALUE index) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx2);
  unsigned int val = 0;
  if (CHECK_LITTLEENDIAN(dv)) {
    val |= bb->ptr[idx0];
    val |= bb->ptr[idx1] << 8;
    val |= bb->ptr[idx2] << 16;
  } else {
    val |= bb->ptr[idx0] << 16;
    val |= bb->ptr[idx1] << 8;
    val |= bb->ptr[idx2];
  }
  return UINT2NUM(val);
}

#getU32(index) ⇒ Integer

Reads four bytes starting at index as a 4 bytes long unsigned integer

Returns:

  • (Integer)

    Integer between 0 and 4294967295



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'ext/arraybuffer/dataview.c', line 307

static VALUE
t_dv_getu32(VALUE self, VALUE index) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
  unsigned int idx3 = dv->offset + (unsigned int)idx + 3;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx3);
  unsigned int val = 0;
  if (CHECK_LITTLEENDIAN(dv)) {
    val |= bb->ptr[idx0];
    val |= bb->ptr[idx1] << 8;
    val |= bb->ptr[idx2] << 16;
    val |= bb->ptr[idx3] << 24;
  } else {
    val |= bb->ptr[idx0] << 24;
    val |= bb->ptr[idx1] << 16;
    val |= bb->ptr[idx2] << 8;
    val |= bb->ptr[idx3];
  }
  return UINT2NUM(val);
}

#getU8(index) ⇒ Integer

Reads the byte at index as an unsigned char

Returns:

  • (Integer)

    Integer between 0 and 255



245
246
247
248
249
250
251
# File 'ext/arraybuffer/dataview.c', line 245

static VALUE
t_dv_getu8(VALUE self, VALUE index) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int real_idx = dv->offset + (unsigned int)idx;
  CHECKBOUNDSBB(real_idx);
  return UINT2NUM(bb->ptr[real_idx]);
}

#offsetObject



127
128
129
130
131
# File 'ext/arraybuffer/dataview.c', line 127

static VALUE
t_dv_offset(VALUE self) {
  DECLAREDV(self);
  return UINT2NUM(dv->offset);
}

#offset=(offset) ⇒ Object

Defined the new offset for the DataView.

Changing the offset does not affect the size. If passed a negative value, it will be summed with the underlying buffer size. The final value must not be lower than zero.

Parameters:

  • offset (Integer)

    The new offset



170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'ext/arraybuffer/dataview.c', line 170

static VALUE
t_dv_setoffset(VALUE self, VALUE offset) {
  DECLAREDV(self);
  DECLAREBB(dv->bb_obj);
  int offset_val = NIL_P(offset) ? 0 : NUM2INT(offset);
  if (offset_val < 0)
    offset_val += (int)bb->size;
  if (offset_val < 0)
    rb_raise(rb_eArgError, "calculated offset is negative: %d", offset_val);

  dv->offset = (unsigned long)offset_val;
  return self;
}

#setU16(index, value) ⇒ Object

Interprets two bytes starting at index and sets them an unsigned value

Values lower than zero will be set to 0 and values greater than 65535 will be capped.



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'ext/arraybuffer/dataview.c', line 356

static VALUE
t_dv_setu16(VALUE self, VALUE index, VALUE value) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx1);
  int val = NUM2INT(value);
  ADJUSTBOUNDS(val, 0xFFFF);
  unsigned int uval = (unsigned int)val;
  if (CHECK_LITTLEENDIAN(dv)) {
    bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
    bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
  } else {
    bb->ptr[idx0] = (unsigned char)((uval >> 8) & 0xFF);
    bb->ptr[idx1] = (unsigned char)(uval & 0xFF);
  }
  return self;
}

#setU24(index, value) ⇒ Object

Interprets three bytes starting at index and sets them an unsigned value

Values lower than zero will be set to 0 and values greater than 16777215 will be capped.



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'ext/arraybuffer/dataview.c', line 382

static VALUE
t_dv_setu24(VALUE self, VALUE index, VALUE value) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx2);
  int val = NUM2INT(value);
  ADJUSTBOUNDS(val, 0xFFFFFF);
  unsigned int uval = (unsigned int)val;
  if (CHECK_LITTLEENDIAN(dv)) {
    bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
    bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
    bb->ptr[idx2] = (unsigned char)((uval >> 16) & 0xFF);
  } else {
    bb->ptr[idx0] = (unsigned char)((uval >> 16) & 0xFF);
    bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
    bb->ptr[idx2] = (unsigned char)(uval & 0xFF);
  }
  return self;
}

#setU32(index, value) ⇒ Object

Interprets four bytes starting at index and sets them an unsigned value

Values lower than zero will be set to 0 and values greater than 4294967295 will be capped.



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'ext/arraybuffer/dataview.c', line 411

static VALUE
t_dv_setu32(VALUE self, VALUE index, VALUE value) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
  unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
  unsigned int idx3 = dv->offset + (unsigned int)idx + 3;
  CHECKBOUNDSBB(idx0);
  CHECKBOUNDSBB(idx3);
  long val = NUM2LONG(value);
  ADJUSTBOUNDS(val, 0xFFFFFFFF);
  unsigned long uval = (unsigned long)val;
  if (CHECK_LITTLEENDIAN(dv)) {
    bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
    bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
    bb->ptr[idx2] = (unsigned char)((uval >> 16) & 0xFF);
    bb->ptr[idx3] = (unsigned char)((uval >> 24) & 0xFF);
  } else {
    bb->ptr[idx0] = (unsigned char)((uval >> 24) & 0xFF);
    bb->ptr[idx1] = (unsigned char)((uval >> 16) & 0xFF);
    bb->ptr[idx2] = (unsigned char)((uval >> 8) & 0xFF);
    bb->ptr[idx3] = (unsigned char)(uval & 0xFF);
  }
  return self;
}

#setU8(index, value) ⇒ Object

Interprets one byte at index and assigns it an unsigned value

Values lower than zero will be set to 0 and values greater than 255 will be capped.



339
340
341
342
343
344
345
346
347
348
# File 'ext/arraybuffer/dataview.c', line 339

static VALUE
t_dv_setu8(VALUE self, VALUE index, VALUE value) {
  DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
  unsigned int idx0 = dv->offset + (unsigned int)idx;
  CHECKBOUNDSBB(idx0);
  int val = NUM2INT(value);
  ADJUSTBOUNDS(val, 0xFF);
  bb->ptr[idx0] = (unsigned char)val;
  return self;
}

#sizeObject Also known as: length



121
122
123
124
125
# File 'ext/arraybuffer/dataview.c', line 121

static VALUE
t_dv_size(VALUE self) {
  DECLAREDV(self);
  return UINT2NUM(dv->size);
}

#size=(size) ⇒ Object Also known as: length=

Defined the new offset for the DataView.

Changing the size does not affect the offset. If passed a negative value, it will be summed with the underlying buffer size. The final value must not be lower than zero.

Parameters:

  • size (Integer)

    The new size. Must be zero or greater



193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'ext/arraybuffer/dataview.c', line 193

static VALUE
t_dv_setsize(VALUE self, VALUE size) {
  DECLAREDV(self);
  DECLAREBB(dv->bb_obj);
  int size_val = NIL_P(size) ? (int)bb->size : NUM2INT(size);
  if (size_val < 0)
    size_val += (int)bb->size;
  if (size_val < 0)
    rb_raise(rb_eArgError, "calculated size is negative: %d", size_val);

  dv->size = (unsigned long)size_val;
  return self;
}