arraybuffer 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19ea4341e8a445c5f0f7fb037201da95de458b1c598b19dfcdede555a7ada4af
4
+ data.tar.gz: 55c21ac531706d232aeb9997c214ea99124e5c5d72ca94266abcf91b47431408
5
+ SHA512:
6
+ metadata.gz: 761a077323636bb899b3c764f1b6225e0af328468d70a82a8d2cad42e70c585eeda68c6bbb8bf23c2ba3b80f495fc93402ef9b7e92cea77936d1e22a7a8b48fc
7
+ data.tar.gz: c1f26cdd5a15d3cb1068be495f8b1aee915b29a647fec7fc146420f0b39bf67a186a64b7b7fd52d58e744a380c3a5426ec0a906f0d71ac87313dca883093883a
@@ -0,0 +1,159 @@
1
+ #include "arraybuffer.h"
2
+ #include "extconf.h"
3
+ #include <string.h>
4
+
5
+ extern VALUE cArrayBuffer;
6
+
7
+ #define DECLAREBB(self) \
8
+ struct LLC_ArrayBuffer *bb = (struct LLC_ArrayBuffer*)rb_data_object_get((self))
9
+
10
+ #define CHECKBOUNDS(bb, idx) \
11
+ if (!(bb)->ptr || (idx) < 0 || (idx) >= (bb)->size) { \
12
+ rb_raise(rb_eArgError, "Index out of bounds: %d", (idx)); \
13
+ }
14
+
15
+ static void
16
+ t_bb_gc_mark(struct LLC_ArrayBuffer *bb) {
17
+ }
18
+
19
+ static void
20
+ t_bb_free(struct LLC_ArrayBuffer *bb) {
21
+ if (bb->ptr)
22
+ xfree(bb->ptr);
23
+
24
+ xfree(bb);
25
+ }
26
+
27
+ static VALUE
28
+ t_bb_allocator(VALUE klass) {
29
+ struct LLC_ArrayBuffer *bb = (struct LLC_ArrayBuffer*)xmalloc(sizeof(struct LLC_ArrayBuffer));
30
+ bb->ptr = NULL;
31
+ bb->size = 0;
32
+
33
+ return Data_Wrap_Struct(klass, t_bb_gc_mark, t_bb_free, bb);
34
+ }
35
+
36
+ static VALUE
37
+ t_bb_initialize(VALUE self, VALUE size) {
38
+ DECLAREBB(self);
39
+ unsigned int s = NUM2UINT(size);
40
+ bb->size = s;
41
+ if (bb->ptr)
42
+ xfree(bb->ptr);
43
+ bb->ptr = xmalloc(s);
44
+ memset(bb->ptr, 0, (size_t)s);
45
+ return self;
46
+ }
47
+
48
+ static VALUE
49
+ t_bb_getbyte(VALUE self, VALUE index) {
50
+ DECLAREBB(self);
51
+ int idx = NUM2INT(index);
52
+ if (idx < 0)
53
+ idx += (int)bb->size;
54
+ CHECKBOUNDS(bb, idx);
55
+ return UINT2NUM((unsigned int)bb->ptr[idx]);
56
+ }
57
+
58
+ static VALUE
59
+ t_bb_setbyte(VALUE self, VALUE index, VALUE value) {
60
+ DECLAREBB(self);
61
+ int idx = NUM2INT(index);
62
+ unsigned int val = NUM2UINT(value);
63
+ if (idx < 0)
64
+ idx += (int)bb->size;
65
+ CHECKBOUNDS(bb, idx);
66
+ bb->ptr[idx] = (unsigned char)val;
67
+ return self;
68
+ }
69
+
70
+ static VALUE
71
+ t_bb_size(VALUE self) {
72
+ DECLAREBB(self);
73
+ return UINT2NUM(bb->size);
74
+ }
75
+
76
+ static VALUE
77
+ t_bb_each(VALUE self) {
78
+ DECLAREBB(self);
79
+
80
+ if (rb_block_given_p()) {
81
+ for (int i = 0; i < bb->size; i++) {
82
+ unsigned int val = (unsigned int)bb->ptr[i];
83
+ rb_yield(UINT2NUM(val));
84
+ }
85
+ } else {
86
+ rb_raise(rb_eArgError, "no block given");
87
+ }
88
+
89
+ return self;
90
+ }
91
+
92
+ static VALUE
93
+ t_bb_realloc(VALUE self, VALUE _new_size) {
94
+ DECLAREBB(self);
95
+ unsigned int new_size = NUM2UINT(_new_size);
96
+ if (new_size == bb->size)
97
+ return self;
98
+
99
+ void *old_ptr = (void*)bb->ptr;
100
+ if (new_size > 0) {
101
+ char *new_ptr = (void*)xmalloc(new_size);
102
+ if (old_ptr) {
103
+ if (new_size > bb->size) {
104
+ size_t diff = (size_t)(new_size - bb->size);
105
+ memcpy(new_ptr, old_ptr, (size_t)bb->size);
106
+ xfree(old_ptr);
107
+ old_ptr = NULL;
108
+ memset((char*)new_ptr + (size_t)bb->size, 0, diff);
109
+ } else {
110
+ memcpy(new_ptr, old_ptr, (size_t)new_size);
111
+ }
112
+ } else {
113
+ memset(new_ptr, 0, new_size);
114
+ }
115
+ bb->size = new_size;
116
+ bb->ptr = (unsigned char*)new_ptr;
117
+ } else {
118
+ bb->size = 0;
119
+ bb->ptr = NULL;
120
+ }
121
+
122
+ if (old_ptr)
123
+ xfree(old_ptr);
124
+
125
+ return self;
126
+ }
127
+
128
+ /*
129
+ * Returns a ASCII-8BIT string with the contents of the buffer
130
+ *
131
+ * The returned string is a copy of the buffer. It's encoding is always
132
+ * ASCII-8BIT.
133
+ * If the buffer has size zero, an empty string is returned.
134
+ *
135
+ * @return [String]
136
+ */
137
+ static VALUE
138
+ t_bb_bytes(VALUE self) {
139
+ DECLAREBB(self);
140
+ return rb_tainted_str_new(
141
+ (const char*)bb->ptr,
142
+ bb->size);
143
+ }
144
+
145
+ void
146
+ Init_arraybuffer() {
147
+ cArrayBuffer = rb_define_class("ArrayBuffer", rb_cObject);
148
+ rb_define_alloc_func(cArrayBuffer, t_bb_allocator);
149
+ rb_include_module(cArrayBuffer, rb_mEnumerable);
150
+
151
+ rb_define_method(cArrayBuffer, "initialize", t_bb_initialize, 1);
152
+ rb_define_method(cArrayBuffer, "[]", t_bb_getbyte, 1);
153
+ rb_define_method(cArrayBuffer, "[]=", t_bb_setbyte, 2);
154
+ rb_define_method(cArrayBuffer, "size", t_bb_size, 0);
155
+ rb_define_alias(cArrayBuffer, "length", "size");
156
+ rb_define_method(cArrayBuffer, "each", t_bb_each, 0);
157
+ rb_define_method(cArrayBuffer, "realloc", t_bb_realloc, 1);
158
+ rb_define_method(cArrayBuffer, "bytes", t_bb_bytes, 0);
159
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef LLC_ARRAYBUFFER_H
2
+ #define LLC_ARRAYBUFFER_H
3
+
4
+ #include <ruby.h>
5
+
6
+ struct LLC_ArrayBuffer {
7
+ unsigned char *ptr;
8
+ unsigned int size;
9
+ };
10
+
11
+ #endif
@@ -0,0 +1,14 @@
1
+ #include <ruby.h>
2
+ #include "extconf.h"
3
+
4
+ VALUE cArrayBuffer = Qundef;
5
+ VALUE cDataView = Qundef;
6
+
7
+ void Init_dataview();
8
+ void Init_arraybuffer();
9
+
10
+ void
11
+ Init_arraybuffer_ext() {
12
+ Init_arraybuffer();
13
+ Init_dataview();
14
+ }
@@ -0,0 +1,467 @@
1
+ #include "dataview.h"
2
+ #include "arraybuffer.h"
3
+ #include "extconf.h"
4
+
5
+ #ifdef HAVE_STRING_H
6
+ #include <string.h>
7
+ #endif
8
+
9
+ extern VALUE cArrayBuffer;
10
+ extern VALUE cDataView;
11
+
12
+ static ID idEndianess = Qundef;
13
+ static ID idBig = Qundef;
14
+ static ID idLittle = Qundef;
15
+
16
+ #define FLAG_LITTLE_ENDIAN 1
17
+
18
+ #define DECLAREDV(o) \
19
+ struct LLC_DataView *dv = (struct LLC_DataView*)rb_data_object_get((o))
20
+ #define DECLAREBB(o) \
21
+ struct LLC_ArrayBuffer *bb = (struct LLC_ArrayBuffer*)rb_data_object_get((o))
22
+ #define CHECK_LITTLEENDIAN(dv) ((dv)->flags & FLAG_LITTLE_ENDIAN)
23
+
24
+ static void
25
+ t_dv_gc_mark(struct LLC_DataView *dv) {
26
+ if (dv->bb_obj)
27
+ rb_gc_mark(dv->bb_obj);
28
+ }
29
+
30
+ static void
31
+ t_dv_free(struct LLC_DataView *dv) {
32
+ xfree(dv);
33
+ }
34
+
35
+ static VALUE
36
+ t_dv_allocator(VALUE klass) {
37
+ struct LLC_DataView *dv = (struct LLC_DataView*)xmalloc(sizeof(struct LLC_DataView));
38
+ dv->bb_obj = Qundef;
39
+ dv->size = 0;
40
+ dv->offset = 0;
41
+ dv->flags = 0;
42
+ return Data_Wrap_Struct(klass, t_dv_gc_mark, t_dv_free, dv);
43
+ }
44
+
45
+ /*
46
+ * call-seq:
47
+ * initialize(buffer, offset, size, endianess:)
48
+ *
49
+ * Constructs a new DataView that provides a view of the data in a ArrayBuffer.
50
+ *
51
+ * Example:
52
+ * buffer = ArrayBuffer.new(10)
53
+ * buffer[1] = 20
54
+ * buffer[2] = 55
55
+ * view = DataView.new(buffer, 1, endianess: :little)
56
+ * view.getU8() == ( 20 & (55 << 8) ) # true
57
+ *
58
+ * Or:
59
+ *
60
+ * view = DataView.new(buffer, 1) # default endianess is "big endian"
61
+ * view.getU8() == ( (20 << 8) | 55 ) # true
62
+ *
63
+ * @param buffer [ArrayBuffer] The array buffer where to operate
64
+ * @param offset [Integer] Optional. The byte offset from the array buffer. The
65
+ * default value is zero
66
+ * @param size [Integer] Optional. The size in bytes that this DataView can
67
+ * see into the array buffer. If left blank, the current size of the array
68
+ * buffer will be used
69
+ * @param endianess [:big, :little] Optional. The default value is big
70
+ *
71
+ */
72
+ static VALUE
73
+ t_dv_initialize(int argc, VALUE *argv, VALUE self) {
74
+ DECLAREDV(self);
75
+ VALUE bb_obj;
76
+ VALUE offset;
77
+ VALUE size;
78
+ VALUE kwargs;
79
+ static ID keyword_ids[] = { 0 };
80
+
81
+ rb_scan_args(argc, argv, "12:", &bb_obj, &offset, &size, &kwargs);
82
+
83
+ DECLAREBB(bb_obj);
84
+
85
+ int size_val = NIL_P(size) ? (int)bb->size : NUM2INT(size);
86
+ if (size_val < 0)
87
+ size_val += (int)bb->size;
88
+ if (size_val < 0)
89
+ rb_raise(rb_eArgError, "calculated size is negative: %d", size_val);
90
+
91
+ int offset_val = NIL_P(offset) ? 0 : NUM2INT(offset);
92
+ if (offset_val < 0)
93
+ offset_val += (int)bb->size;
94
+ if (offset_val < 0)
95
+ rb_raise(rb_eArgError, "calculated offset is negative: %d", offset_val);
96
+
97
+ dv->offset = (unsigned long)offset_val;
98
+ dv->size = (unsigned long)size_val;
99
+ dv->bb_obj = bb_obj;
100
+
101
+ if (!keyword_ids[0]) {
102
+ keyword_ids[0] = idEndianess;
103
+ }
104
+
105
+ if (!NIL_P(kwargs)) {
106
+ VALUE endianess;
107
+ rb_get_kwargs(kwargs, keyword_ids, 0, 1, &endianess);
108
+ if (endianess != Qundef) {
109
+ Check_Type(endianess, T_SYMBOL);
110
+ ID id = SYM2ID(endianess);
111
+ if (id == idLittle)
112
+ dv->flags |= FLAG_LITTLE_ENDIAN;
113
+ else if (id != idBig)
114
+ rb_raise(rb_eArgError, "endianess must be either :big or :little");
115
+ }
116
+ }
117
+
118
+ return self;
119
+ }
120
+
121
+ static VALUE
122
+ t_dv_size(VALUE self) {
123
+ DECLAREDV(self);
124
+ return UINT2NUM(dv->size);
125
+ }
126
+
127
+ static VALUE
128
+ t_dv_offset(VALUE self) {
129
+ DECLAREDV(self);
130
+ return UINT2NUM(dv->offset);
131
+ }
132
+
133
+ static VALUE
134
+ t_dv_endianess(VALUE self) {
135
+ DECLAREDV(self);
136
+ return CHECK_LITTLEENDIAN(dv) ?
137
+ ID2SYM(idLittle) :
138
+ ID2SYM(idBig);
139
+ }
140
+
141
+ static VALUE
142
+ t_dv_each(VALUE self) {
143
+ DECLAREDV(self);
144
+ DECLAREBB(dv->bb_obj);
145
+
146
+ int size = dv->size;
147
+ if (size + dv->offset >= bb->size)
148
+ size = bb->size - dv->offset;
149
+
150
+ if (rb_block_given_p()) {
151
+ for (int i = 0; i < size; i++) {
152
+ unsigned int val = (unsigned int)bb->ptr[i + dv->offset];
153
+ rb_yield(UINT2NUM(val));
154
+ }
155
+ } else {
156
+ rb_raise(rb_eArgError, "no block given");
157
+ }
158
+ return self;
159
+ }
160
+
161
+ /*
162
+ * Defined the new offset for the DataView.
163
+ *
164
+ * Changing the offset does not affect the size.
165
+ * If passed a negative value, it will be summed with the underlying buffer
166
+ * size. The final value must not be lower than zero.
167
+ *
168
+ * @param offset [Integer] The new offset
169
+ */
170
+ static VALUE
171
+ t_dv_setoffset(VALUE self, VALUE offset) {
172
+ DECLAREDV(self);
173
+ DECLAREBB(dv->bb_obj);
174
+ int offset_val = NIL_P(offset) ? 0 : NUM2INT(offset);
175
+ if (offset_val < 0)
176
+ offset_val += (int)bb->size;
177
+ if (offset_val < 0)
178
+ rb_raise(rb_eArgError, "calculated offset is negative: %d", offset_val);
179
+
180
+ dv->offset = (unsigned long)offset_val;
181
+ return self;
182
+ }
183
+
184
+ /*
185
+ * Defined the new offset for the DataView.
186
+ *
187
+ * Changing the size does not affect the offset.
188
+ * If passed a negative value, it will be summed with the underlying buffer
189
+ * size. The final value must not be lower than zero.
190
+ *
191
+ * @param size [Integer] The new size. Must be zero or greater
192
+ */
193
+ static VALUE
194
+ t_dv_setsize(VALUE self, VALUE size) {
195
+ DECLAREDV(self);
196
+ DECLAREBB(dv->bb_obj);
197
+ int size_val = NIL_P(size) ? (int)bb->size : NUM2INT(size);
198
+ if (size_val < 0)
199
+ size_val += (int)bb->size;
200
+ if (size_val < 0)
201
+ rb_raise(rb_eArgError, "calculated size is negative: %d", size_val);
202
+
203
+ dv->size = (unsigned long)size_val;
204
+ return self;
205
+ }
206
+
207
+ #define DECLARENCHECKIDX(index) int idx = NUM2INT(index); \
208
+ if (idx < 0) idx += (int)dv->size; \
209
+ if (idx < 0 || idx >= dv->size) rb_raise(rb_eArgError, "index out of bounds: %d", idx);
210
+
211
+ #define CHECKBOUNDSBB(v) if ((v) < 0 || (v) >= (bb)->size) \
212
+ rb_raise(rb_eArgError, "index out of underlying buffer bounds: %d", (v));
213
+
214
+ /*
215
+ * Reads a bit at index.
216
+ *
217
+ * This method differs from the other in that the +index+ is given in bits, not
218
+ * in bytes.
219
+ * Thus it's possible to read from index +0+ to +(size * 8) - 1+
220
+ *
221
+ * @return [Integer] Either 0 or 1
222
+ */
223
+ static VALUE
224
+ t_dv_getbit(VALUE self, VALUE index) {
225
+ DECLAREDV(self); DECLAREBB(dv->bb_obj);
226
+ int idx = NUM2INT(index);
227
+ if (idx < 0)
228
+ idx += (int)dv->size * 8;
229
+ if (idx < 0 || idx >= dv->size * 8)
230
+ rb_raise(rb_eArgError, "index out of bounds: %d", idx);
231
+
232
+ unsigned int bit_idx = ((unsigned int)idx) & 7;
233
+ unsigned int byte_idx = (((unsigned int)idx) >> 3) + dv->offset;
234
+ unsigned char bit_mask = 1 << bit_idx;
235
+
236
+ CHECKBOUNDSBB(byte_idx);
237
+ return (bb->ptr[byte_idx] & bit_mask) ? UINT2NUM(1) : UINT2NUM(0);
238
+ }
239
+
240
+ /*
241
+ * Reads the byte at index as an +unsigned char+
242
+ *
243
+ * @return [Integer] Integer between 0 and 255
244
+ */
245
+ static VALUE
246
+ t_dv_getu8(VALUE self, VALUE index) {
247
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
248
+ unsigned int real_idx = dv->offset + (unsigned int)idx;
249
+ CHECKBOUNDSBB(real_idx);
250
+ return UINT2NUM(bb->ptr[real_idx]);
251
+ }
252
+
253
+ /*
254
+ * Reads two bytes starting at index as an +unsigned short+
255
+ *
256
+ * @return [Integer] Integer between 0 and 65535
257
+ */
258
+ static VALUE
259
+ t_dv_getu16(VALUE self, VALUE index) {
260
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
261
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
262
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
263
+ CHECKBOUNDSBB(idx0);
264
+ CHECKBOUNDSBB(idx1);
265
+ unsigned short val = 0;
266
+ if (CHECK_LITTLEENDIAN(dv)) {
267
+ val |= bb->ptr[idx0];
268
+ val |= bb->ptr[idx1] << 8;
269
+ } else {
270
+ val |= bb->ptr[idx0] << 8;
271
+ val |= bb->ptr[idx1];
272
+ }
273
+ return UINT2NUM(val);
274
+ }
275
+
276
+ /*
277
+ * Reads three bytes starting at index as a 3 bytes long unsigned integer
278
+ *
279
+ * @return [Integer] Integer between 0 and 16777215
280
+ */
281
+ static VALUE
282
+ t_dv_getu24(VALUE self, VALUE index) {
283
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
284
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
285
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
286
+ unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
287
+ CHECKBOUNDSBB(idx0);
288
+ CHECKBOUNDSBB(idx2);
289
+ unsigned int val = 0;
290
+ if (CHECK_LITTLEENDIAN(dv)) {
291
+ val |= bb->ptr[idx0];
292
+ val |= bb->ptr[idx1] << 8;
293
+ val |= bb->ptr[idx2] << 16;
294
+ } else {
295
+ val |= bb->ptr[idx0] << 16;
296
+ val |= bb->ptr[idx1] << 8;
297
+ val |= bb->ptr[idx2];
298
+ }
299
+ return UINT2NUM(val);
300
+ }
301
+
302
+ /*
303
+ * Reads four bytes starting at index as a 4 bytes long unsigned integer
304
+ *
305
+ * @return [Integer] Integer between 0 and 4294967295
306
+ */
307
+ static VALUE
308
+ t_dv_getu32(VALUE self, VALUE index) {
309
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
310
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
311
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
312
+ unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
313
+ unsigned int idx3 = dv->offset + (unsigned int)idx + 3;
314
+ CHECKBOUNDSBB(idx0);
315
+ CHECKBOUNDSBB(idx3);
316
+ unsigned int val = 0;
317
+ if (CHECK_LITTLEENDIAN(dv)) {
318
+ val |= bb->ptr[idx0];
319
+ val |= bb->ptr[idx1] << 8;
320
+ val |= bb->ptr[idx2] << 16;
321
+ val |= bb->ptr[idx3] << 24;
322
+ } else {
323
+ val |= bb->ptr[idx0] << 24;
324
+ val |= bb->ptr[idx1] << 16;
325
+ val |= bb->ptr[idx2] << 8;
326
+ val |= bb->ptr[idx3];
327
+ }
328
+ return UINT2NUM(val);
329
+ }
330
+
331
+ #define ADJUSTBOUNDS(val, max) if (val < 0) val = 0; else if (val > max) val = max;
332
+
333
+ /*
334
+ * Interprets one byte at index and assigns it an unsigned value
335
+ *
336
+ * Values lower than zero will be set to 0 and values greater than 255
337
+ * will be capped.
338
+ */
339
+ static VALUE
340
+ t_dv_setu8(VALUE self, VALUE index, VALUE value) {
341
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
342
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
343
+ CHECKBOUNDSBB(idx0);
344
+ int val = NUM2INT(value);
345
+ ADJUSTBOUNDS(val, 0xFF);
346
+ bb->ptr[idx0] = (unsigned char)val;
347
+ return self;
348
+ }
349
+
350
+ /*
351
+ * Interprets two bytes starting at index and sets them an unsigned value
352
+ *
353
+ * Values lower than zero will be set to 0 and values greater than 65535
354
+ * will be capped.
355
+ */
356
+ static VALUE
357
+ t_dv_setu16(VALUE self, VALUE index, VALUE value) {
358
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
359
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
360
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
361
+ CHECKBOUNDSBB(idx0);
362
+ CHECKBOUNDSBB(idx1);
363
+ int val = NUM2INT(value);
364
+ ADJUSTBOUNDS(val, 0xFFFF);
365
+ unsigned int uval = (unsigned int)val;
366
+ if (CHECK_LITTLEENDIAN(dv)) {
367
+ bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
368
+ bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
369
+ } else {
370
+ bb->ptr[idx0] = (unsigned char)((uval >> 8) & 0xFF);
371
+ bb->ptr[idx1] = (unsigned char)(uval & 0xFF);
372
+ }
373
+ return self;
374
+ }
375
+
376
+ /*
377
+ * Interprets three bytes starting at index and sets them an unsigned value
378
+ *
379
+ * Values lower than zero will be set to 0 and values greater than 16777215
380
+ * will be capped.
381
+ */
382
+ static VALUE
383
+ t_dv_setu24(VALUE self, VALUE index, VALUE value) {
384
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
385
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
386
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
387
+ unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
388
+ CHECKBOUNDSBB(idx0);
389
+ CHECKBOUNDSBB(idx2);
390
+ int val = NUM2INT(value);
391
+ ADJUSTBOUNDS(val, 0xFFFFFF);
392
+ unsigned int uval = (unsigned int)val;
393
+ if (CHECK_LITTLEENDIAN(dv)) {
394
+ bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
395
+ bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
396
+ bb->ptr[idx2] = (unsigned char)((uval >> 16) & 0xFF);
397
+ } else {
398
+ bb->ptr[idx0] = (unsigned char)((uval >> 16) & 0xFF);
399
+ bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
400
+ bb->ptr[idx2] = (unsigned char)(uval & 0xFF);
401
+ }
402
+ return self;
403
+ }
404
+
405
+ /*
406
+ * Interprets four bytes starting at index and sets them an unsigned value
407
+ *
408
+ * Values lower than zero will be set to 0 and values greater than 4294967295
409
+ * will be capped.
410
+ */
411
+ static VALUE
412
+ t_dv_setu32(VALUE self, VALUE index, VALUE value) {
413
+ DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
414
+ unsigned int idx0 = dv->offset + (unsigned int)idx;
415
+ unsigned int idx1 = dv->offset + (unsigned int)idx + 1;
416
+ unsigned int idx2 = dv->offset + (unsigned int)idx + 2;
417
+ unsigned int idx3 = dv->offset + (unsigned int)idx + 3;
418
+ CHECKBOUNDSBB(idx0);
419
+ CHECKBOUNDSBB(idx3);
420
+ long val = NUM2LONG(value);
421
+ ADJUSTBOUNDS(val, 0xFFFFFFFF);
422
+ unsigned long uval = (unsigned long)val;
423
+ if (CHECK_LITTLEENDIAN(dv)) {
424
+ bb->ptr[idx0] = (unsigned char)(uval & 0xFF);
425
+ bb->ptr[idx1] = (unsigned char)((uval >> 8) & 0xFF);
426
+ bb->ptr[idx2] = (unsigned char)((uval >> 16) & 0xFF);
427
+ bb->ptr[idx3] = (unsigned char)((uval >> 24) & 0xFF);
428
+ } else {
429
+ bb->ptr[idx0] = (unsigned char)((uval >> 24) & 0xFF);
430
+ bb->ptr[idx1] = (unsigned char)((uval >> 16) & 0xFF);
431
+ bb->ptr[idx2] = (unsigned char)((uval >> 8) & 0xFF);
432
+ bb->ptr[idx3] = (unsigned char)(uval & 0xFF);
433
+ }
434
+ return self;
435
+ }
436
+
437
+ void
438
+ Init_dataview() {
439
+ idEndianess = rb_intern("endianess");
440
+ idLittle = rb_intern("little");
441
+ idBig = rb_intern("big");
442
+
443
+ cDataView = rb_define_class("DataView", rb_cObject);
444
+ rb_define_alloc_func(cDataView, t_dv_allocator);
445
+ rb_include_module(cDataView, rb_mEnumerable);
446
+
447
+ rb_define_method(cDataView, "initialize", t_dv_initialize, -1);
448
+ rb_define_method(cDataView, "getBit", t_dv_getbit, 1);
449
+ rb_define_method(cDataView, "getU8", t_dv_getu8, 1);
450
+ rb_define_method(cDataView, "getU16", t_dv_getu16, 1);
451
+ rb_define_method(cDataView, "getU24", t_dv_getu24, 1);
452
+ rb_define_method(cDataView, "getU32", t_dv_getu32, 1);
453
+
454
+ rb_define_method(cDataView, "setU8", t_dv_setu8, 2);
455
+ rb_define_method(cDataView, "setU16", t_dv_setu16, 2);
456
+ rb_define_method(cDataView, "setU24", t_dv_setu24, 2);
457
+ rb_define_method(cDataView, "setU32", t_dv_setu32, 2);
458
+
459
+ rb_define_method(cDataView, "endianess", t_dv_endianess, 0);
460
+ rb_define_method(cDataView, "offset=", t_dv_setoffset, 1);
461
+ rb_define_method(cDataView, "offset", t_dv_offset, 0);
462
+ rb_define_method(cDataView, "size=", t_dv_setsize, 1);
463
+ rb_define_alias(cDataView, "length=", "size=");
464
+ rb_define_method(cDataView, "size", t_dv_size, 0);
465
+ rb_define_alias(cDataView, "length", "size");
466
+ rb_define_method(cDataView, "each", t_dv_each, 0);
467
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef LLC_DATAVIEW_H
2
+ #define LLC_DATAVIEW_H
3
+
4
+ #include <ruby.h>
5
+
6
+ struct LLC_DataView {
7
+ VALUE bb_obj;
8
+ unsigned int offset;
9
+ unsigned int size;
10
+ unsigned char flags;
11
+ };
12
+
13
+ #endif
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mkmf'
3
+
4
+ # preparation for compilation goes here
5
+
6
+ create_header
7
+ create_makefile 'arraybuffer_ext'
@@ -0,0 +1,3 @@
1
+ #ifndef EXTCONF_H
2
+ #define EXTCONF_H
3
+ #endif
@@ -0,0 +1 @@
1
+ require "arraybuffer_ext"
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arraybuffer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - André Diego Piske
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.9'
27
+ description:
28
+ email:
29
+ - andrepiske@gmail.com
30
+ executables: []
31
+ extensions:
32
+ - ext/arraybuffer/extconf.rb
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ext/arraybuffer/arraybuffer.c
36
+ - ext/arraybuffer/arraybuffer.h
37
+ - ext/arraybuffer/arraybuffer_ext.c
38
+ - ext/arraybuffer/dataview.c
39
+ - ext/arraybuffer/dataview.h
40
+ - ext/arraybuffer/extconf.rb
41
+ - extconf.h
42
+ - lib/arraybuffer.rb
43
+ homepage: https://github.com/andrepiske/rb-arraybuffer
44
+ licenses:
45
+ - MIT
46
+ metadata:
47
+ source_code_uri: https://github.com/andrepiske/rb-arraybuffer
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '2.1'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.1.2
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Low level byte operators and buffers
67
+ test_files: []