arraybuffer 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []