arraybuffer 0.0.3 → 0.0.6
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.
- checksums.yaml +4 -4
- data/ext/arraybuffer/arraybuffer.c +78 -36
- data/ext/arraybuffer/arraybuffer.h +1 -0
- data/ext/arraybuffer/dataview.c +110 -0
- data/ext/arraybuffer/extconf.rb +4 -0
- data/extconf.h +2 -0
- data/lib/arraybuffer_ext.bundle +0 -0
- metadata +23 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 517c77a2de7cbcd60febb5217cd77f8b249848c7947519a50f9a63fb291713a4
|
4
|
+
data.tar.gz: 56cfdbea1a7222001ebd918d7e8e10674837b51621d490de97d104b059ee8301
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bae4c20202057631b3f554adecee91ade37f2d7f12de3cb88dc03405c321be5f79fac4931f6642af74d73e38dd2cab35857cc826eb2e45d6f9275ad3621c3213
|
7
|
+
data.tar.gz: a6955800866b293dfd7fbcd55b56b936876124081044e14024fe9f21b2ccbec0193a77c435f11ab0b5133fa2ba86de267f0f024a1cb00e22f93ad664c87cc746
|
@@ -1,6 +1,11 @@
|
|
1
1
|
#include "arraybuffer.h"
|
2
2
|
#include "extconf.h"
|
3
3
|
#include <string.h>
|
4
|
+
#include <ruby/version.h>
|
5
|
+
|
6
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
7
|
+
#include <ruby/memory_view.h>
|
8
|
+
#endif
|
4
9
|
|
5
10
|
extern VALUE cArrayBuffer;
|
6
11
|
|
@@ -12,15 +17,43 @@ extern VALUE cArrayBuffer;
|
|
12
17
|
rb_raise(rb_eArgError, "Index out of bounds: %d", (idx)); \
|
13
18
|
}
|
14
19
|
|
20
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
21
|
+
static bool
|
22
|
+
r_bb_mv_get(VALUE self, rb_memory_view_t *view, int flags) {
|
23
|
+
DECLAREBB(self);
|
24
|
+
if (!bb->size)
|
25
|
+
return 0;
|
26
|
+
rb_memory_view_init_as_byte_array(view, self, bb->ptr, (const ssize_t)bb->size, 0);
|
27
|
+
return 1;
|
28
|
+
}
|
29
|
+
|
30
|
+
// static bool
|
31
|
+
// r_bb_mv_release(VALUE self, rb_memory_view_t *view) {
|
32
|
+
// return 1;
|
33
|
+
// }
|
34
|
+
|
35
|
+
static bool
|
36
|
+
r_bb_mv_available_p(VALUE self) {
|
37
|
+
DECLAREBB(self);
|
38
|
+
return bb->size > 0 ? 1 : 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
static rb_memory_view_entry_t cArrayBufferMemoryView = {
|
42
|
+
r_bb_mv_get,
|
43
|
+
NULL, // r_bb_mv_release,
|
44
|
+
r_bb_mv_available_p
|
45
|
+
};
|
46
|
+
#endif
|
47
|
+
|
15
48
|
static void
|
16
49
|
t_bb_gc_mark(struct LLC_ArrayBuffer *bb) {
|
50
|
+
if (bb->backing_str) {
|
51
|
+
rb_gc_mark(bb->backing_str);
|
52
|
+
}
|
17
53
|
}
|
18
54
|
|
19
55
|
static void
|
20
56
|
t_bb_free(struct LLC_ArrayBuffer *bb) {
|
21
|
-
if (bb->ptr)
|
22
|
-
xfree(bb->ptr);
|
23
|
-
|
24
57
|
xfree(bb);
|
25
58
|
}
|
26
59
|
|
@@ -29,18 +62,46 @@ t_bb_allocator(VALUE klass) {
|
|
29
62
|
struct LLC_ArrayBuffer *bb = (struct LLC_ArrayBuffer*)xmalloc(sizeof(struct LLC_ArrayBuffer));
|
30
63
|
bb->ptr = NULL;
|
31
64
|
bb->size = 0;
|
65
|
+
bb->backing_str = NULL;
|
32
66
|
|
33
67
|
return Data_Wrap_Struct(klass, t_bb_gc_mark, t_bb_free, bb);
|
34
68
|
}
|
35
69
|
|
70
|
+
#if (RUBY_API_VERSION_CODE >= 30100)
|
71
|
+
// Ruby 3.1 and later
|
72
|
+
|
73
|
+
#define BB_BACKING_PTR(bb) \
|
74
|
+
(FL_TEST((bb)->backing_str, RSTRING_NOEMBED) ? RSTRING((bb)->backing_str)->as.heap.ptr : &RSTRING(bb->backing_str)->as.embed.ary)
|
75
|
+
#else
|
76
|
+
// Before ruby 3.1
|
77
|
+
|
78
|
+
#define BB_BACKING_PTR(bb) \
|
79
|
+
(FL_TEST((bb)->backing_str, RSTRING_NOEMBED) ? RSTRING((bb)->backing_str)->as.heap.ptr : &RSTRING(bb->backing_str)->as.ary)
|
80
|
+
#endif
|
81
|
+
|
82
|
+
static void
|
83
|
+
t_bb_reassign_ptr(struct LLC_ArrayBuffer *bb) {
|
84
|
+
if (!bb->backing_str) {
|
85
|
+
bb->ptr = NULL;
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
rb_str_set_len(bb->backing_str, bb->size);
|
90
|
+
bb->ptr = BB_BACKING_PTR(bb);
|
91
|
+
bb->ptr[bb->size] = 0;
|
92
|
+
}
|
93
|
+
|
36
94
|
static VALUE
|
37
95
|
t_bb_initialize(VALUE self, VALUE size) {
|
38
96
|
DECLAREBB(self);
|
39
97
|
unsigned int s = NUM2UINT(size);
|
40
98
|
bb->size = s;
|
41
|
-
if (bb->
|
42
|
-
|
43
|
-
|
99
|
+
if (bb->backing_str)
|
100
|
+
rb_gc_mark(bb->backing_str);
|
101
|
+
|
102
|
+
bb->backing_str = rb_str_buf_new(s);
|
103
|
+
|
104
|
+
t_bb_reassign_ptr(bb);
|
44
105
|
memset(bb->ptr, 0, (size_t)s);
|
45
106
|
return self;
|
46
107
|
}
|
@@ -96,31 +157,9 @@ t_bb_realloc(VALUE self, VALUE _new_size) {
|
|
96
157
|
if (new_size == bb->size)
|
97
158
|
return self;
|
98
159
|
|
99
|
-
|
100
|
-
|
101
|
-
|
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);
|
160
|
+
rb_str_resize(bb->backing_str, new_size);
|
161
|
+
bb->size = new_size;
|
162
|
+
t_bb_reassign_ptr(bb);
|
124
163
|
|
125
164
|
return self;
|
126
165
|
}
|
@@ -128,8 +167,8 @@ t_bb_realloc(VALUE self, VALUE _new_size) {
|
|
128
167
|
/*
|
129
168
|
* Returns a ASCII-8BIT string with the contents of the buffer
|
130
169
|
*
|
131
|
-
* The returned string is
|
132
|
-
* ASCII-8BIT.
|
170
|
+
* The returned string is the backing string of the buffer.
|
171
|
+
* It's encoding is always ASCII-8BIT.
|
133
172
|
* If the buffer has size zero, an empty string is returned.
|
134
173
|
*
|
135
174
|
* @return [String]
|
@@ -137,9 +176,7 @@ t_bb_realloc(VALUE self, VALUE _new_size) {
|
|
137
176
|
static VALUE
|
138
177
|
t_bb_bytes(VALUE self) {
|
139
178
|
DECLAREBB(self);
|
140
|
-
return
|
141
|
-
(const char*)bb->ptr,
|
142
|
-
bb->size);
|
179
|
+
return bb->backing_str;
|
143
180
|
}
|
144
181
|
|
145
182
|
void
|
@@ -156,4 +193,9 @@ Init_arraybuffer() {
|
|
156
193
|
rb_define_method(cArrayBuffer, "each", t_bb_each, 0);
|
157
194
|
rb_define_method(cArrayBuffer, "realloc", t_bb_realloc, 1);
|
158
195
|
rb_define_method(cArrayBuffer, "bytes", t_bb_bytes, 0);
|
196
|
+
rb_define_method(cArrayBuffer, "to_s", t_bb_bytes, 0);
|
197
|
+
|
198
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
199
|
+
rb_memory_view_register(cArrayBuffer, &cArrayBufferMemoryView);
|
200
|
+
#endif
|
159
201
|
}
|
data/ext/arraybuffer/dataview.c
CHANGED
@@ -6,6 +6,10 @@
|
|
6
6
|
#include <string.h>
|
7
7
|
#endif
|
8
8
|
|
9
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
10
|
+
#include <ruby/memory_view.h>
|
11
|
+
#endif
|
12
|
+
|
9
13
|
extern VALUE cArrayBuffer;
|
10
14
|
extern VALUE cDataView;
|
11
15
|
|
@@ -42,6 +46,39 @@ t_dv_allocator(VALUE klass) {
|
|
42
46
|
return Data_Wrap_Struct(klass, t_dv_gc_mark, t_dv_free, dv);
|
43
47
|
}
|
44
48
|
|
49
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
50
|
+
static bool
|
51
|
+
r_dv_mv_get(VALUE self, rb_memory_view_t *view, int flags) {
|
52
|
+
DECLAREDV(self);
|
53
|
+
if (!dv->size)
|
54
|
+
return 0;
|
55
|
+
|
56
|
+
DECLAREBB(dv->bb_obj);
|
57
|
+
|
58
|
+
char *ptr = (char*)bb->ptr + (size_t)dv->offset;
|
59
|
+
|
60
|
+
rb_memory_view_init_as_byte_array(view, self, ptr, (const ssize_t)dv->size, 0);
|
61
|
+
return 1;
|
62
|
+
}
|
63
|
+
|
64
|
+
// static bool
|
65
|
+
// r_dv_mv_release(VALUE self, rb_memory_view_t *view) {
|
66
|
+
// return 1;
|
67
|
+
// }
|
68
|
+
|
69
|
+
static bool
|
70
|
+
r_dv_mv_available_p(VALUE self) {
|
71
|
+
DECLAREDV(self);
|
72
|
+
return dv->size > 0 ? 1 : 0;
|
73
|
+
}
|
74
|
+
|
75
|
+
static rb_memory_view_entry_t cDataViewMemoryView = {
|
76
|
+
r_dv_mv_get,
|
77
|
+
NULL, // r_dv_mv_release,
|
78
|
+
r_dv_mv_available_p
|
79
|
+
};
|
80
|
+
#endif
|
81
|
+
|
45
82
|
/*
|
46
83
|
* call-seq:
|
47
84
|
* initialize(buffer, offset, size, endianess:)
|
@@ -434,6 +471,71 @@ t_dv_setu32(VALUE self, VALUE index, VALUE value) {
|
|
434
471
|
return self;
|
435
472
|
}
|
436
473
|
|
474
|
+
static VALUE
|
475
|
+
t_dv_setbytes(VALUE self, VALUE index, VALUE bytes) {
|
476
|
+
DECLAREDV(self); DECLARENCHECKIDX(index); DECLAREBB(dv->bb_obj);
|
477
|
+
unsigned int idx0 = dv->offset + (unsigned int)idx;
|
478
|
+
CHECKBOUNDSBB(idx0);
|
479
|
+
|
480
|
+
if (RB_TYPE_P(bytes, T_ARRAY)) {
|
481
|
+
const unsigned int length = (unsigned int)rb_array_len(bytes);
|
482
|
+
const VALUE* items = rb_array_const_ptr(bytes);
|
483
|
+
CHECKBOUNDSBB(idx0 + length);
|
484
|
+
|
485
|
+
for (unsigned int i = 0; i < length; i++) {
|
486
|
+
if (!RB_FIXNUM_P(items[i]))
|
487
|
+
rb_raise(rb_eRuntimeError, "array contains non fixnum value at index %d", i);
|
488
|
+
int num = NUM2INT(items[i]);
|
489
|
+
ADJUSTBOUNDS(num, 0xFF);
|
490
|
+
bb->ptr[idx0 + i] = (unsigned char)num;
|
491
|
+
}
|
492
|
+
} else if (RB_TYPE_P(bytes, T_STRING)) {
|
493
|
+
const char *str_ptr = RSTRING_PTR(bytes);
|
494
|
+
const unsigned int length = (unsigned int)RSTRING_LEN(bytes);
|
495
|
+
CHECKBOUNDSBB(idx0 + length);
|
496
|
+
|
497
|
+
for (unsigned int i = 0; i < length; i++) {
|
498
|
+
bb->ptr[idx0 + i] = (unsigned char)str_ptr[i];
|
499
|
+
}
|
500
|
+
} else if (RB_TYPE_P(bytes, T_DATA) &&
|
501
|
+
(CLASS_OF(bytes) == cArrayBuffer || CLASS_OF(bytes) == cDataView)) {
|
502
|
+
unsigned int length;
|
503
|
+
const char *src_bytes;
|
504
|
+
if (CLASS_OF(bytes) == cArrayBuffer) {
|
505
|
+
struct LLC_ArrayBuffer *src_bb = (struct LLC_ArrayBuffer*)rb_data_object_get(bytes);
|
506
|
+
length = src_bb->size;
|
507
|
+
src_bytes = (const char*)src_bb->ptr;
|
508
|
+
} else {
|
509
|
+
struct LLC_DataView *src_dv = (struct LLC_DataView*)rb_data_object_get(bytes);
|
510
|
+
struct LLC_ArrayBuffer *src_bb = (struct LLC_ArrayBuffer*)rb_data_object_get(src_dv->bb_obj);
|
511
|
+
length = src_dv->size;
|
512
|
+
src_bytes = (const char*)(src_bb->ptr + (size_t)src_dv->offset);
|
513
|
+
if (src_dv->offset >= src_bb->size)
|
514
|
+
rb_raise(rb_eRuntimeError, "offset exceeds the underlying source buffer size");
|
515
|
+
if (src_dv->offset + length >= src_bb->size)
|
516
|
+
rb_raise(rb_eRuntimeError, "offset + size exceeds the underlying source buffer size");
|
517
|
+
}
|
518
|
+
|
519
|
+
CHECKBOUNDSBB(idx0 + length);
|
520
|
+
memcpy((void*)(bb->ptr + (size_t)idx0), src_bytes, (size_t)length);
|
521
|
+
} else {
|
522
|
+
rb_raise(rb_eArgError, "Invalid type: %+"PRIsVALUE, CLASS_OF(bytes));
|
523
|
+
}
|
524
|
+
|
525
|
+
return self;
|
526
|
+
}
|
527
|
+
|
528
|
+
VALUE
|
529
|
+
t_dv_to_s(VALUE self) {
|
530
|
+
DECLAREDV(self);
|
531
|
+
DECLAREBB(dv->bb_obj);
|
532
|
+
|
533
|
+
const char *ptr = (const char*)bb->ptr + (size_t)dv->offset;
|
534
|
+
size_t len = (size_t)dv->size;
|
535
|
+
|
536
|
+
return rb_str_new(ptr, len);
|
537
|
+
}
|
538
|
+
|
437
539
|
void
|
438
540
|
Init_dataview() {
|
439
541
|
idEndianess = rb_intern("endianess");
|
@@ -456,6 +558,8 @@ Init_dataview() {
|
|
456
558
|
rb_define_method(cDataView, "setU24", t_dv_setu24, 2);
|
457
559
|
rb_define_method(cDataView, "setU32", t_dv_setu32, 2);
|
458
560
|
|
561
|
+
rb_define_method(cDataView, "setBytes", t_dv_setbytes, 2);
|
562
|
+
|
459
563
|
rb_define_method(cDataView, "endianess", t_dv_endianess, 0);
|
460
564
|
rb_define_method(cDataView, "offset=", t_dv_setoffset, 1);
|
461
565
|
rb_define_method(cDataView, "offset", t_dv_offset, 0);
|
@@ -464,4 +568,10 @@ Init_dataview() {
|
|
464
568
|
rb_define_method(cDataView, "size", t_dv_size, 0);
|
465
569
|
rb_define_alias(cDataView, "length", "size");
|
466
570
|
rb_define_method(cDataView, "each", t_dv_each, 0);
|
571
|
+
|
572
|
+
rb_define_method(cDataView, "to_s", t_dv_to_s, 0);
|
573
|
+
|
574
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
575
|
+
rb_memory_view_register(cDataView, &cDataViewMemoryView);
|
576
|
+
#endif
|
467
577
|
}
|
data/ext/arraybuffer/extconf.rb
CHANGED
data/extconf.h
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arraybuffer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- André Diego Piske
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,7 +24,21 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.9'
|
27
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.2'
|
41
|
+
description:
|
28
42
|
email:
|
29
43
|
- andrepiske@gmail.com
|
30
44
|
executables: []
|
@@ -40,12 +54,13 @@ files:
|
|
40
54
|
- ext/arraybuffer/extconf.rb
|
41
55
|
- extconf.h
|
42
56
|
- lib/arraybuffer.rb
|
57
|
+
- lib/arraybuffer_ext.bundle
|
43
58
|
homepage: https://github.com/andrepiske/rb-arraybuffer
|
44
59
|
licenses:
|
45
60
|
- MIT
|
46
61
|
metadata:
|
47
62
|
source_code_uri: https://github.com/andrepiske/rb-arraybuffer
|
48
|
-
post_install_message:
|
63
|
+
post_install_message:
|
49
64
|
rdoc_options: []
|
50
65
|
require_paths:
|
51
66
|
- lib
|
@@ -60,8 +75,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
75
|
- !ruby/object:Gem::Version
|
61
76
|
version: '0'
|
62
77
|
requirements: []
|
63
|
-
rubygems_version: 3.
|
64
|
-
signing_key:
|
78
|
+
rubygems_version: 3.3.11
|
79
|
+
signing_key:
|
65
80
|
specification_version: 4
|
66
|
-
summary:
|
81
|
+
summary: An array buffer (a.k.a. byte array) implementation forRuby, implemented natively.
|
67
82
|
test_files: []
|