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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19ea4341e8a445c5f0f7fb037201da95de458b1c598b19dfcdede555a7ada4af
4
- data.tar.gz: 55c21ac531706d232aeb9997c214ea99124e5c5d72ca94266abcf91b47431408
3
+ metadata.gz: 517c77a2de7cbcd60febb5217cd77f8b249848c7947519a50f9a63fb291713a4
4
+ data.tar.gz: 56cfdbea1a7222001ebd918d7e8e10674837b51621d490de97d104b059ee8301
5
5
  SHA512:
6
- metadata.gz: 761a077323636bb899b3c764f1b6225e0af328468d70a82a8d2cad42e70c585eeda68c6bbb8bf23c2ba3b80f495fc93402ef9b7e92cea77936d1e22a7a8b48fc
7
- data.tar.gz: c1f26cdd5a15d3cb1068be495f8b1aee915b29a647fec7fc146420f0b39bf67a186a64b7b7fd52d58e744a380c3a5426ec0a906f0d71ac87313dca883093883a
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->ptr)
42
- xfree(bb->ptr);
43
- bb->ptr = xmalloc(s);
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
- 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);
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 a copy of the buffer. It's encoding is always
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 rb_tainted_str_new(
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
  }
@@ -6,6 +6,7 @@
6
6
  struct LLC_ArrayBuffer {
7
7
  unsigned char *ptr;
8
8
  unsigned int size;
9
+ VALUE backing_str;
9
10
  };
10
11
 
11
12
  #endif
@@ -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
  }
@@ -3,5 +3,9 @@ require 'mkmf'
3
3
 
4
4
  # preparation for compilation goes here
5
5
 
6
+ if have_header("ruby/memory_view.h")
7
+ have_type("rb_memory_view_t", ["ruby/memory_view.h"])
8
+ end
9
+
6
10
  create_header
7
11
  create_makefile 'arraybuffer_ext'
data/extconf.h CHANGED
@@ -1,3 +1,5 @@
1
1
  #ifndef EXTCONF_H
2
2
  #define EXTCONF_H
3
+ #define HAVE_RUBY_MEMORY_VIEW_H 1
4
+ #define HAVE_TYPE_RB_MEMORY_VIEW_T 1
3
5
  #endif
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.3
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: 2020-03-17 00:00:00.000000000 Z
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
- description:
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.1.2
64
- signing_key:
78
+ rubygems_version: 3.3.11
79
+ signing_key:
65
80
  specification_version: 4
66
- summary: Low level byte operators and buffers
81
+ summary: An array buffer (a.k.a. byte array) implementation forRuby, implemented natively.
67
82
  test_files: []