arraybuffer 0.0.3 → 0.0.6

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