snow-data 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 425085a25eb678abb07c07ba25d1a52142d86822
4
+ data.tar.gz: b04d708b4f18e405354bd56f7175e4ddaec4291e
5
+ SHA512:
6
+ metadata.gz: f03aa50d5ad415403388c91d3560b0c3ca188ef8309797c3f3e6f342380c4880b37e224dd025870fa420ec8819b8d7d8a68e0e7aea13d63ab16b150b1228a846
7
+ data.tar.gz: 17975205c4c120f24ebd00ebe0feb6d47699847a063564a51e42f6a9b66a50d95a4b1ceb6414081bfe79620f6f9dd7ef235a37745db6616a84f738cb0caa1629
data/COPYING ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2013, Noel Raymond Cower <ncower@gmail.com>.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ The views and conclusions contained in the software and documentation are those
25
+ of the authors and should not be interpreted as representing official policies,
26
+ either expressed or implied, of the FreeBSD Project.
@@ -0,0 +1,135 @@
1
+ snow-data
2
+ =========
3
+
4
+ $ gem install snow-data [ -- [--warn-implicit-size] [--warn-no-bytesize] ]
5
+
6
+
7
+ Intro
8
+ -----
9
+
10
+ Snow-Data is a simple gem for dealing with memory and defining structs in a
11
+ C-like way. Incidentally, it's also hideously unsafe, so everything is tainted
12
+ by default. You'll thank me for this later, even if almost every operation does
13
+ bounds-checking where possible to ensure you're not being a horrible person.
14
+
15
+ For more information on usage, see the rdoc documentation for Snow::Memory
16
+ and Snow::CStruct, as it explains the important things. Like CStructs. And how
17
+ to talk to people. Ok, it can't help you with that.
18
+
19
+ _ALLONS-Y!_
20
+
21
+
22
+ Example
23
+ -------
24
+
25
+ For those wanting a quick-ish example of using snow-data, I'll include one here
26
+ showing you how you might define a few structs, including a Vec3, Vec2, Color,
27
+ and Vertex and working with those.
28
+
29
+ Bear in mind that, down the road, it will also be possible to assign snow-math
30
+ types to these as well (provided they use the same underlying types), though I
31
+ wouldn't use this for defining data types for anything other than transit to
32
+ another API that expects its data in a format like this.
33
+
34
+ How you use it, ultimately, is really up to you.
35
+
36
+ #!/usr/bin/env ruby -w
37
+
38
+ require 'snow-data'
39
+
40
+ # Defines a struct { float x, y, z; } and a struct { float x, y; }, essentially,
41
+ # all of whose members are 4-byte aligned (this is the default for floats, but
42
+ # it helps to illustrate that you can specify alignment).
43
+ Vec3 = Snow::CStruct[:Vec3, 'x: float :4; y: float :4; z: float :4']
44
+ Vec2 = Snow::CStruct[:Vec2, 'x: float :4; y: float :4']
45
+ # ui8 is shorthand for uint8_t -- you can write either, and the documentation
46
+ # for CStruct::new explains the short- and long-form names for each primitive
47
+ # type provided by Snow-Data. Further, CStructs defined with a name, as with
48
+ # Vec3, Vec2, and Color, have getters and setters defined in the Memory class
49
+ # and are usable as member types, as I'll show below.
50
+ Color = Snow::CStruct[:Color, 'r: ui8; g: ui8; b: ui8; a: ui8']
51
+
52
+ # Define a vertex type whose members are all also 4-byte aligned. The vertex
53
+ # itself has a position, a normal, two texcoords (e.g., diffuse and lightmap),
54
+ # and a color value. Because we've not given Vertex a name (no :Vertex argument
55
+ # to CStruct), it isn't usable as a type for struct members.
56
+ Vertex = Snow::CStruct[<<END_TYPE]
57
+ position: Vec3 : 4
58
+ normal: Vec3 : 4
59
+ texcoord: Vec2[2] : 4
60
+ color: Color : 4
61
+ END_TYPE
62
+
63
+ # So let's create a vertex.
64
+ a_vertex = Vertex.new { |v|
65
+ v.position = Vec3.new { |p| p.x = 1; p.y = 2; p.z = 3 }
66
+ v.normal = Vec3.new { |n| n.x = 0.707107; n.y = 0; n.z = 0.707107 }
67
+ # For array types, we must use set_* functions, as the name= shorthand for
68
+ # struct members only assigns to the first element of an array.
69
+ v.texcoord = Vec2.new { |t| t.x = 1.0; t.y = 1.0 }
70
+ # Though if you're masochistic you could also do this:
71
+ v.__send__(:texcoord=, Vec2.new { |t| t.x = 0.5; t.y = 0.5 }, 1)
72
+ v.color = Color.new { |c| c.r = 255; c.g = 127; c.b = 63; c.a = 220 }
73
+ }
74
+
75
+ puts <<VERTEX_DESCRIPTION
76
+ Our vertex has the following properties:
77
+ Position: #{a_vertex.position.to_h}
78
+ Normal: #{a_vertex.normal.to_h}
79
+ Texcoords: [
80
+ #{a_vertex.texcoord(0).to_h}
81
+ #{a_vertex.texcoord(1).to_h}
82
+ ]
83
+ Color: #{a_vertex.color.to_h}
84
+
85
+ VERTEX_DESCRIPTION
86
+
87
+ # For kicks, let's create an array.
88
+ some_vertices = Vertex[64]
89
+
90
+ # And set all vertices to the above vertex.
91
+ some_vertices.map! { a_vertex }
92
+
93
+ puts <<VERTEX_DESCRIPTION
94
+ Our vertex in the array at index 36 has the following properties:
95
+ Position: #{some_vertices[36].position.to_h}
96
+ Normal: #{some_vertices[36].normal.to_h}
97
+ Texcoords: [
98
+ #{some_vertices[36].texcoord(0).to_h}
99
+ #{some_vertices[36].texcoord(1).to_h}
100
+ ]
101
+ Color: #{some_vertices[36].color.to_h}
102
+ VERTEX_DESCRIPTION
103
+
104
+
105
+ License
106
+ -------
107
+
108
+ Snow-Data is licensed under a simplified BSD license, like most of my gems.
109
+
110
+ Copyright (c) 2013, Noel Raymond Cower <ncower@gmail.com>.
111
+ All rights reserved.
112
+
113
+ Redistribution and use in source and binary forms, with or without
114
+ modification, are permitted provided that the following conditions are met:
115
+
116
+ 1. Redistributions of source code must retain the above copyright notice, this
117
+ list of conditions and the following disclaimer.
118
+ 2. Redistributions in binary form must reproduce the above copyright notice,
119
+ this list of conditions and the following disclaimer in the documentation
120
+ and/or other materials provided with the distribution.
121
+
122
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
123
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
124
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
125
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
126
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
127
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
128
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
129
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
130
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
131
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
132
+
133
+ The views and conclusions contained in the software and documentation are those
134
+ of the authors and should not be interpreted as representing official policies,
135
+ either expressed or implied, of the FreeBSD Project.
@@ -0,0 +1,58 @@
1
+ #! /usr/bin/env ruby -w
2
+ # This file is part of ruby-snowmath.
3
+ # Copyright (c) 2013 Noel Raymond Cower. All rights reserved.
4
+ # See COPYING for license details.
5
+
6
+ require 'mkmf'
7
+
8
+ # Compile as C99
9
+ $CFLAGS += " -std=c99 -Wall -pedantic"
10
+
11
+ OptKVPair = Struct.new(:key, :value)
12
+
13
+ option_mappings = {
14
+ '-D' => OptKVPair[:build_debug, true],
15
+ '--debug' => OptKVPair[:build_debug, true],
16
+ '-ND' => OptKVPair[:build_debug, false],
17
+ '--release' => OptKVPair[:build_debug, false],
18
+ '--warn-implicit-size' => OptKVPair[:warn_implicit_size, true],
19
+ '-Ws' => OptKVPair[:warn_implicit_size, true],
20
+ '--warn-no-bytesize' => OptKVPair[:warn_no_bytesize, true],
21
+ '-Wbs' => OptKVPair[:warn_implicit_size, true],
22
+ '--debug-memory-copy' => OptKVPair[:debug_memory_copy, true],
23
+ '--debug-allocations' => OptKVPair[:debug_allocations, true]
24
+ }
25
+
26
+ options = {
27
+ :build_debug => false,
28
+ :warn_implicit_size => false,
29
+ :warn_no_bytesize => false,
30
+ :debug_memory_copy => false,
31
+ :debug_allocations => false
32
+ }
33
+
34
+ ARGV.each {
35
+ |arg|
36
+ pair = option_mappings[arg]
37
+ if pair
38
+ options[pair.key] = pair.value
39
+ else
40
+ $stderr.puts "Unrecognized install option: #{arg}"
41
+ end
42
+ }
43
+
44
+ if options[:build_debug]
45
+ $CFLAGS += " -g"
46
+ $stdout.puts "Building extension in debug mode"
47
+ else
48
+ # mfpmath is ignored on clang, FYI
49
+ $CFLAGS += " -O3 -fno-strict-aliasing"
50
+ $stdout.puts "Building extension in release mode"
51
+ end
52
+
53
+ $CFLAGS += ' -DSD_SD_WARN_ON_IMPLICIT_COPY_SIZE' if options[:warn_implicit_size]
54
+ $CFLAGS += ' -DSD_WARN_ON_NO_BYTESIZE_METHOD' if options[:warn_no_bytesize]
55
+ $CFLAGS += ' -DSD_VERBOSE_COPY_LOG' if options[:debug_memory_copy]
56
+ $CFLAGS += ' -DSD_VERBOSE_MALLOC_LOG' if options[:debug_allocations]
57
+
58
+ create_makefile('snow-data/snowdata_bindings', 'snow-data/')
@@ -0,0 +1,1867 @@
1
+ /*
2
+ This file is part of ruby-snowdata.
3
+ Copyright (c) 2013 Noel Raymond Cower. All rights reserved.
4
+ See COPYING for license details.
5
+ */
6
+
7
+ #include "ruby.h"
8
+ #include <stdint.h>
9
+ #include <stdio.h>
10
+
11
+ static ID kSD_IVAR_BYTESIZE;
12
+ static ID kSD_IVAR_ALIGNMENT;
13
+ static ID kSD_ID_BYTESIZE;
14
+ static ID kSD_ID_ADDRESS;
15
+
16
+ #define SD_INT8_TO_NUM(X) INT2FIX(X)
17
+ #define SD_INT16_TO_NUM(X) INT2FIX(X)
18
+ #define SD_INT32_TO_NUM(X) INT2FIX(X)
19
+ #define SD_NUM_TO_INT8(X) ((int8_t)INT2FIX(X))
20
+ #define SD_NUM_TO_INT16(X) ((int16_t)INT2FIX(X))
21
+ #define SD_NUM_TO_INT32(X) ((int32_t)INT2FIX(X))
22
+
23
+ #if INT64_MAX <= INT_MAX
24
+ #define SD_INT64_TO_NUM(X) INT2FIX(X)
25
+ #define SD_NUM_TO_INT64(X) ((int64_t)NUM2INT(X))
26
+ #elif INT64_MAX == LONG_MAX
27
+ #define SD_INT64_TO_NUM(X) LONG2NUM(X)
28
+ #define SD_NUM_TO_INT64(X) ((int64_t)NUM2LONG(X))
29
+ #elif INT64_MAX == LLONG_MAX
30
+ #define SD_INT64_TO_NUM(X) ULL2NUM(X)
31
+ #define SD_NUM_TO_INT64(X) ((int64_t)NUM2LL(X))
32
+ #else
33
+ #error int64_t is not sizeof int, long, or long long
34
+ #endif
35
+
36
+ #define SD_UINT8_TO_NUM(X) UINT2NUM(X)
37
+ #define SD_UINT16_TO_NUM(X) UINT2NUM(X)
38
+ #define SD_UINT32_TO_NUM(X) UINT2NUM(X)
39
+
40
+ #define SD_NUM_TO_UINT8(X) ((uint8_t)NUM2UINT(X))
41
+ #define SD_NUM_TO_UINT16(X) ((uint16_t)NUM2UINT(X))
42
+ #define SD_NUM_TO_UINT32(X) ((uint32_t)NUM2UINT(X))
43
+
44
+ #if UINT64_MAX <= UINT_MAX
45
+ #define SD_UINT64_TO_NUM(X) UINT2NUM(X)
46
+ #define SD_NUM_TO_UINT64(X) ((uint64_t)NUM2UINT(X))
47
+ #elif UINT64_MAX == ULONG_MAX
48
+ #define SD_UINT64_TO_NUM(X) ULONG2NUM(X)
49
+ #define SD_NUM_TO_UINT64(X) ((uint64_t)NUM2ULONG(X))
50
+ #elif UINT64_MAX == ULLONG_MAX
51
+ #define SD_UINT64_TO_NUM(X) ULL2NUM(X)
52
+ #define SD_NUM_TO_UINT64(X) ((uint64_t)NUM2ULL(X))
53
+ #else
54
+ #error uint64_t is not sizeof unsigned int, unsigned long, or unsigned long long
55
+ #endif
56
+
57
+ #define SD_SIZE_T_TO_NUM(X) SIZET2NUM(X)
58
+ #define SD_NUM_TO_SIZE_T(X) NUM2SIZET(X)
59
+
60
+ #if SIZEOF_PTRDIFF_T <= SIZEOF_INT
61
+ #define SD_PTRDIFF_T_TO_NUM(X) INT2FIX(X)
62
+ #define SD_NUM_TO_PTRDIFF_T(X) ((ptrdiff_t)NUM2INT(X))
63
+ #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
64
+ #define SD_PTRDIFF_T_TO_NUM(X) LONG2FIX(X)
65
+ #define SD_NUM_TO_PTRDIFF_T(X) ((ptrdiff_t)NUM2LONG(X))
66
+ #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
67
+ #define SD_PTRDIFF_T_TO_NUM(X) LL2NUM(X)
68
+ #define SD_NUM_TO_PTRDIFF_T(X) ((ptrdiff_t)NUM2LL(X))
69
+ #else
70
+ #error ptrdiff_t is not sizeof unsigned int, unsigned long, or unsigned long long
71
+ #endif
72
+
73
+ #if SIZEOF_INTPTR_T <= SIZEOF_INT
74
+ #define SD_INTPTR_T_TO_NUM(X) INT2FIX(X)
75
+ #define SD_NUM_TO_INTPTR_T(X) ((intptr_t)NUM2INT(X))
76
+ #elif SIZEOF_INTPTR_T == SIZEOF_LONG
77
+ #define SD_INTPTR_T_TO_NUM(X) LONG2FIX(X)
78
+ #define SD_NUM_TO_INTPTR_T(X) ((intptr_t)NUM2LONG(X))
79
+ #elif SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
80
+ #define SD_INTPTR_T_TO_NUM(X) LL2NUM(X)
81
+ #define SD_NUM_TO_INTPTR_T(X) ((intptr_t)NUM2LL(X))
82
+ #else
83
+ #error intptr_t is not sizeof unsigned int, unsigned long, or unsigned long long
84
+ #endif
85
+
86
+
87
+ #if SIZEOF_UINTPTR_T <= SIZEOF_INT
88
+ #define SD_UINTPTR_T_TO_NUM(X) INT2FIX(X)
89
+ #define SD_NUM_TO_UINTPTR_T(X) ((uintptr_t)NUM2INT(X))
90
+ #elif SIZEOF_UINTPTR_T == SIZEOF_LONG
91
+ #define SD_UINTPTR_T_TO_NUM(X) LONG2FIX(X)
92
+ #define SD_NUM_TO_UINTPTR_T(X) ((uintptr_t)NUM2LONG(X))
93
+ #elif SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG
94
+ #define SD_UINTPTR_T_TO_NUM(X) LL2NUM(X)
95
+ #define SD_NUM_TO_UINTPTR_T(X) ((uintptr_t)NUM2LL(X))
96
+ #else
97
+ #error uintptr_t is not sizeof unsigned int, unsigned long, or unsigned long long
98
+ #endif
99
+
100
+ #define SD_LONG_TO_NUM(X) LONG2FIX(X)
101
+ #define SD_LONG_LONG_TO_NUM(X) LL2NUM(X)
102
+ #define SD_UNSIGNED_LONG_TO_NUM(X) ULONG2NUM(X)
103
+ #define SD_UNSIGNED_LONG_LONG_TO_NUM(X) ULL2NUM(X)
104
+ #define SD_FLOAT_TO_NUM(X) rb_float_new((double)(X))
105
+ #define SD_DOUBLE_TO_NUM(X) rb_float_new(X)
106
+ #define SD_INT_TO_NUM(X) INT2FIX(X)
107
+ #define SD_UNSIGNED_INT_TO_NUM(X) UINT2NUM(X)
108
+ #define SD_SHORT_TO_NUM(X) INT2FIX(X)
109
+ #define SD_UNSIGNED_SHORT_TO_NUM(X) UINT2NUM(X)
110
+ #define SD_CHAR_TO_NUM(X) CHR2FIX(X)
111
+ #define SD_UNSIGNED_CHAR_TO_NUM(X) UINT2NUM(X)
112
+ #define SD_SIGNED_CHAR_TO_NUM(X) INT2FIX(X)
113
+
114
+ #define SD_NUM_TO_LONG(X) ((long)NUM2LONG(X))
115
+ #define SD_NUM_TO_LONG_LONG(X) ((long long)NUM2LL(X))
116
+ #define SD_NUM_TO_UNSIGNED_LONG(X) ((unsigned long)NUM2ULONG(X))
117
+ #define SD_NUM_TO_UNSIGNED_LONG_LONG(X) ((unsigned long long)NUM2ULL(X))
118
+ #define SD_NUM_TO_FLOAT(X) ((float)rb_num2dbl(X))
119
+ #define SD_NUM_TO_DOUBLE(X) ((double)rb_num2dbl(X))
120
+ #define SD_NUM_TO_INT(X) ((int)NUM2INT(X))
121
+ #define SD_NUM_TO_UNSIGNED_INT(X) ((unsigned int)NUM2UINT(X))
122
+ #define SD_NUM_TO_SHORT(X) ((short)NUM2INT(X))
123
+ #define SD_NUM_TO_UNSIGNED_SHORT(X) ((unsigned short)NUM2UINT(X))
124
+ #define SD_NUM_TO_CHAR(X) ((char)NUM2CHR(X))
125
+ #define SD_NUM_TO_UNSIGNED_CHAR(X) ((unsigned char)NUM2UINT(X))
126
+ #define SD_NUM_TO_SIGNED_CHAR(X) ((signed char)NUM2INT(X))
127
+
128
+ static void sd_check_null_block(VALUE self)
129
+ {
130
+ if (DATA_PTR(self) == NULL) {
131
+ rb_raise(rb_eRuntimeError, "Pointer is NULL");
132
+ }
133
+ }
134
+
135
+ static void sd_check_block_bounds(VALUE self, size_t offset, size_t size)
136
+ {
137
+ const size_t block_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE));
138
+ if (offset >= block_size) {
139
+ rb_raise(rb_eRangeError,
140
+ "Offset %zu is out of bounds for block with size %zu",
141
+ offset, block_size);
142
+ } else if (offset + size > block_size || offset + size < offset) {
143
+ rb_raise(rb_eRangeError,
144
+ "Offset(%zu) + size(%zu) is out of bounds for block with size %zu",
145
+ offset, size, block_size);
146
+ }
147
+ }
148
+
149
+ /*
150
+ Returns 1 if size is a power of two and nonzero, otherwise returns 0.
151
+ */
152
+ static int is_power_of_two(size_t size)
153
+ {
154
+ return ((size & (size - 1)) == 0) && (size != 0);
155
+ }
156
+
157
+ /*
158
+ Returns a size aligned to the given alignment. The alignment must be a power
159
+ of two.
160
+ */
161
+ static size_t align_size(size_t size, size_t alignment)
162
+ {
163
+ return (size + (alignment - 1)) & ~(alignment - 1);
164
+ }
165
+
166
+ /*
167
+ Given a pointer, returns it aligned to the given alignment. In most cases,
168
+ this results in no change.
169
+ */
170
+ static void *align_ptr(void *ptr, size_t alignment)
171
+ {
172
+ return (void *)(((intptr_t)ptr + (alignment - 1)) & ~(alignment - 1));
173
+ }
174
+
175
+ /*
176
+ Allocated a block of memory of at least size bytes aligned to the given byte
177
+ alignment.
178
+ */
179
+ static void *com_malloc(size_t size, size_t alignment)
180
+ {
181
+ const size_t aligned_size = align_size(size + sizeof(void *), alignment);
182
+ void *const ptr = xcalloc(aligned_size, 1);
183
+ void **const aligned_ptr = align_ptr((uint8_t *)ptr + sizeof(void *), alignment);
184
+ aligned_ptr[-1] = ptr;
185
+ #ifdef SD_VERBOSE_MALLOC_LOG
186
+ fprintf(stderr, "Allocated block %p with aligned size %zu (requested: %zu"
187
+ " aligned to %zu bytes), returning aligned pointer %p with usable size %td\n",
188
+ ptr, aligned_size, size, alignment, aligned_ptr,
189
+ (uint8_t *)(ptr + aligned_size) - (uint8_t *)aligned_ptr);
190
+ #endif
191
+ return aligned_ptr;
192
+ }
193
+
194
+ /*
195
+ Frees memory previously allocated by com_malloc. This _does not work_ if it
196
+ was allocated by any other means.
197
+ */
198
+ static void com_free(void *aligned_ptr)
199
+ {
200
+ #ifdef SD_VERBOSE_MALLOC_LOG
201
+ fprintf(stderr, "Deallocating aligned pointer %p with underlying pointer %p\n",
202
+ aligned_ptr,
203
+ ((void **)aligned_ptr)[-1]);
204
+ #endif
205
+ xfree(((void **)aligned_ptr)[-1]);
206
+ }
207
+
208
+ /*
209
+ call-seq:
210
+ get_int8(offset) => int8_t
211
+
212
+ Reads a int8_t from the offset into the memory block and returns it.
213
+ The offset is not bounds-checked and it is possible to read outside of bounds,
214
+ which is considered undefined behavior and may crash or do other horrible
215
+ things.
216
+ */
217
+ static VALUE sd_get_int8(VALUE self, VALUE sd_offset)
218
+ {
219
+ typedef int8_t conv_type_t;
220
+ const size_t offset = NUM2SIZET(sd_offset);
221
+ conv_type_t value;
222
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
223
+ sd_check_null_block(self);
224
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
225
+ return SD_INT8_TO_NUM(value);
226
+ }
227
+
228
+ /*
229
+ call-seq:
230
+ set_int8(offset, value) => value
231
+
232
+ Sets a int8_t at the offset to the value. Returns the assigned value.
233
+ */
234
+ static VALUE sd_set_int8(VALUE self, VALUE sd_offset, VALUE sd_value)
235
+ {
236
+ typedef int8_t conv_type_t;
237
+ const size_t offset = NUM2SIZET(sd_offset);
238
+ conv_type_t value;
239
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
240
+ sd_check_null_block(self);
241
+ rb_check_frozen(self);
242
+ value = (conv_type_t)SD_NUM_TO_INT8(sd_value);
243
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
244
+ return sd_value;
245
+ }
246
+
247
+ /*
248
+ call-seq:
249
+ get_int16(offset) => int16_t
250
+
251
+ Reads a int16_t from the offset into the memory block and returns it.
252
+ The offset is not bounds-checked and it is possible to read outside of bounds,
253
+ which is considered undefined behavior and may crash or do other horrible
254
+ things.
255
+ */
256
+ static VALUE sd_get_int16(VALUE self, VALUE sd_offset)
257
+ {
258
+ typedef int16_t conv_type_t;
259
+ const size_t offset = NUM2SIZET(sd_offset);
260
+ conv_type_t value;
261
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
262
+ sd_check_null_block(self);
263
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
264
+ return SD_INT16_TO_NUM(value);
265
+ }
266
+
267
+ /*
268
+ call-seq:
269
+ set_int16(offset, value) => value
270
+
271
+ Sets a int16_t at the offset to the value. Returns the assigned value.
272
+ */
273
+ static VALUE sd_set_int16(VALUE self, VALUE sd_offset, VALUE sd_value)
274
+ {
275
+ typedef int16_t conv_type_t;
276
+ const size_t offset = NUM2SIZET(sd_offset);
277
+ conv_type_t value;
278
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
279
+ sd_check_null_block(self);
280
+ rb_check_frozen(self);
281
+ value = (conv_type_t)SD_NUM_TO_INT16(sd_value);
282
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
283
+ return sd_value;
284
+ }
285
+
286
+ /*
287
+ call-seq:
288
+ get_int32(offset) => int32_t
289
+
290
+ Reads a int32_t from the offset into the memory block and returns it.
291
+ The offset is not bounds-checked and it is possible to read outside of bounds,
292
+ which is considered undefined behavior and may crash or do other horrible
293
+ things.
294
+ */
295
+ static VALUE sd_get_int32(VALUE self, VALUE sd_offset)
296
+ {
297
+ typedef int32_t conv_type_t;
298
+ const size_t offset = NUM2SIZET(sd_offset);
299
+ conv_type_t value;
300
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
301
+ sd_check_null_block(self);
302
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
303
+ return SD_INT32_TO_NUM(value);
304
+ }
305
+
306
+ /*
307
+ call-seq:
308
+ set_int32(offset, value) => value
309
+
310
+ Sets a int32_t at the offset to the value. Returns the assigned value.
311
+ */
312
+ static VALUE sd_set_int32(VALUE self, VALUE sd_offset, VALUE sd_value)
313
+ {
314
+ typedef int32_t conv_type_t;
315
+ const size_t offset = NUM2SIZET(sd_offset);
316
+ conv_type_t value;
317
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
318
+ sd_check_null_block(self);
319
+ rb_check_frozen(self);
320
+ value = (conv_type_t)SD_NUM_TO_INT32(sd_value);
321
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
322
+ return sd_value;
323
+ }
324
+
325
+ /*
326
+ call-seq:
327
+ get_int64(offset) => int64_t
328
+
329
+ Reads a int64_t from the offset into the memory block and returns it.
330
+ The offset is not bounds-checked and it is possible to read outside of bounds,
331
+ which is considered undefined behavior and may crash or do other horrible
332
+ things.
333
+ */
334
+ static VALUE sd_get_int64(VALUE self, VALUE sd_offset)
335
+ {
336
+ typedef int64_t conv_type_t;
337
+ const size_t offset = NUM2SIZET(sd_offset);
338
+ conv_type_t value;
339
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
340
+ sd_check_null_block(self);
341
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
342
+ return SD_INT64_TO_NUM(value);
343
+ }
344
+
345
+ /*
346
+ call-seq:
347
+ set_int64(offset, value) => value
348
+
349
+ Sets a int64_t at the offset to the value. Returns the assigned value.
350
+ */
351
+ static VALUE sd_set_int64(VALUE self, VALUE sd_offset, VALUE sd_value)
352
+ {
353
+ typedef int64_t conv_type_t;
354
+ const size_t offset = NUM2SIZET(sd_offset);
355
+ conv_type_t value;
356
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
357
+ sd_check_null_block(self);
358
+ rb_check_frozen(self);
359
+ value = (conv_type_t)SD_NUM_TO_INT64(sd_value);
360
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
361
+ return sd_value;
362
+ }
363
+
364
+ /*
365
+ call-seq:
366
+ get_uint8(offset) => uint8_t
367
+
368
+ Reads a uint8_t from the offset into the memory block and returns it.
369
+ The offset is not bounds-checked and it is possible to read outside of bounds,
370
+ which is considered undefined behavior and may crash or do other horrible
371
+ things.
372
+ */
373
+ static VALUE sd_get_uint8(VALUE self, VALUE sd_offset)
374
+ {
375
+ typedef uint8_t conv_type_t;
376
+ const size_t offset = NUM2SIZET(sd_offset);
377
+ conv_type_t value;
378
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
379
+ sd_check_null_block(self);
380
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
381
+ return SD_UINT8_TO_NUM(value);
382
+ }
383
+
384
+ /*
385
+ call-seq:
386
+ set_uint8(offset, value) => value
387
+
388
+ Sets a uint8_t at the offset to the value. Returns the assigned value.
389
+ */
390
+ static VALUE sd_set_uint8(VALUE self, VALUE sd_offset, VALUE sd_value)
391
+ {
392
+ typedef uint8_t conv_type_t;
393
+ const size_t offset = NUM2SIZET(sd_offset);
394
+ conv_type_t value;
395
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
396
+ sd_check_null_block(self);
397
+ rb_check_frozen(self);
398
+ value = (conv_type_t)SD_NUM_TO_UINT8(sd_value);
399
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
400
+ return sd_value;
401
+ }
402
+
403
+ /*
404
+ call-seq:
405
+ get_uint16(offset) => uint16_t
406
+
407
+ Reads a uint16_t from the offset into the memory block and returns it.
408
+ The offset is not bounds-checked and it is possible to read outside of bounds,
409
+ which is considered undefined behavior and may crash or do other horrible
410
+ things.
411
+ */
412
+ static VALUE sd_get_uint16(VALUE self, VALUE sd_offset)
413
+ {
414
+ typedef uint16_t conv_type_t;
415
+ const size_t offset = NUM2SIZET(sd_offset);
416
+ conv_type_t value;
417
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
418
+ sd_check_null_block(self);
419
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
420
+ return SD_UINT16_TO_NUM(value);
421
+ }
422
+
423
+ /*
424
+ call-seq:
425
+ set_uint16(offset, value) => value
426
+
427
+ Sets a uint16_t at the offset to the value. Returns the assigned value.
428
+ */
429
+ static VALUE sd_set_uint16(VALUE self, VALUE sd_offset, VALUE sd_value)
430
+ {
431
+ typedef uint16_t conv_type_t;
432
+ const size_t offset = NUM2SIZET(sd_offset);
433
+ conv_type_t value;
434
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
435
+ sd_check_null_block(self);
436
+ rb_check_frozen(self);
437
+ value = (conv_type_t)SD_NUM_TO_UINT16(sd_value);
438
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
439
+ return sd_value;
440
+ }
441
+
442
+ /*
443
+ call-seq:
444
+ get_uint32(offset) => uint32_t
445
+
446
+ Reads a uint32_t from the offset into the memory block and returns it.
447
+ The offset is not bounds-checked and it is possible to read outside of bounds,
448
+ which is considered undefined behavior and may crash or do other horrible
449
+ things.
450
+ */
451
+ static VALUE sd_get_uint32(VALUE self, VALUE sd_offset)
452
+ {
453
+ typedef uint32_t conv_type_t;
454
+ const size_t offset = NUM2SIZET(sd_offset);
455
+ conv_type_t value;
456
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
457
+ sd_check_null_block(self);
458
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
459
+ return SD_UINT32_TO_NUM(value);
460
+ }
461
+
462
+ /*
463
+ call-seq:
464
+ set_uint32(offset, value) => value
465
+
466
+ Sets a uint32_t at the offset to the value. Returns the assigned value.
467
+ */
468
+ static VALUE sd_set_uint32(VALUE self, VALUE sd_offset, VALUE sd_value)
469
+ {
470
+ typedef uint32_t conv_type_t;
471
+ const size_t offset = NUM2SIZET(sd_offset);
472
+ conv_type_t value;
473
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
474
+ sd_check_null_block(self);
475
+ rb_check_frozen(self);
476
+ value = (conv_type_t)SD_NUM_TO_UINT32(sd_value);
477
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
478
+ return sd_value;
479
+ }
480
+
481
+ /*
482
+ call-seq:
483
+ get_uint64(offset) => uint64_t
484
+
485
+ Reads a uint64_t from the offset into the memory block and returns it.
486
+ The offset is not bounds-checked and it is possible to read outside of bounds,
487
+ which is considered undefined behavior and may crash or do other horrible
488
+ things.
489
+ */
490
+ static VALUE sd_get_uint64(VALUE self, VALUE sd_offset)
491
+ {
492
+ typedef uint64_t conv_type_t;
493
+ const size_t offset = NUM2SIZET(sd_offset);
494
+ conv_type_t value;
495
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
496
+ sd_check_null_block(self);
497
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
498
+ return SD_UINT64_TO_NUM(value);
499
+ }
500
+
501
+ /*
502
+ call-seq:
503
+ set_uint64(offset, value) => value
504
+
505
+ Sets a uint64_t at the offset to the value. Returns the assigned value.
506
+ */
507
+ static VALUE sd_set_uint64(VALUE self, VALUE sd_offset, VALUE sd_value)
508
+ {
509
+ typedef uint64_t conv_type_t;
510
+ const size_t offset = NUM2SIZET(sd_offset);
511
+ conv_type_t value;
512
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
513
+ sd_check_null_block(self);
514
+ rb_check_frozen(self);
515
+ value = (conv_type_t)SD_NUM_TO_UINT64(sd_value);
516
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
517
+ return sd_value;
518
+ }
519
+
520
+ /*
521
+ call-seq:
522
+ get_size_t(offset) => size_t
523
+
524
+ Reads a size_t from the offset into the memory block and returns it.
525
+ The offset is not bounds-checked and it is possible to read outside of bounds,
526
+ which is considered undefined behavior and may crash or do other horrible
527
+ things.
528
+ */
529
+ static VALUE sd_get_size_t(VALUE self, VALUE sd_offset)
530
+ {
531
+ typedef size_t conv_type_t;
532
+ const size_t offset = NUM2SIZET(sd_offset);
533
+ conv_type_t value;
534
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
535
+ sd_check_null_block(self);
536
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
537
+ return SD_SIZE_T_TO_NUM(value);
538
+ }
539
+
540
+ /*
541
+ call-seq:
542
+ set_size_t(offset, value) => value
543
+
544
+ Sets a size_t at the offset to the value. Returns the assigned value.
545
+ */
546
+ static VALUE sd_set_size_t(VALUE self, VALUE sd_offset, VALUE sd_value)
547
+ {
548
+ typedef size_t conv_type_t;
549
+ const size_t offset = NUM2SIZET(sd_offset);
550
+ conv_type_t value;
551
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
552
+ sd_check_null_block(self);
553
+ rb_check_frozen(self);
554
+ value = (conv_type_t)SD_NUM_TO_SIZE_T(sd_value);
555
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
556
+ return sd_value;
557
+ }
558
+
559
+ /*
560
+ call-seq:
561
+ get_ptrdiff_t(offset) => ptrdiff_t
562
+
563
+ Reads a ptrdiff_t from the offset into the memory block and returns it.
564
+ The offset is not bounds-checked and it is possible to read outside of bounds,
565
+ which is considered undefined behavior and may crash or do other horrible
566
+ things.
567
+ */
568
+ static VALUE sd_get_ptrdiff_t(VALUE self, VALUE sd_offset)
569
+ {
570
+ typedef ptrdiff_t conv_type_t;
571
+ const size_t offset = NUM2SIZET(sd_offset);
572
+ conv_type_t value;
573
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
574
+ sd_check_null_block(self);
575
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
576
+ return SD_PTRDIFF_T_TO_NUM(value);
577
+ }
578
+
579
+ /*
580
+ call-seq:
581
+ set_ptrdiff_t(offset, value) => value
582
+
583
+ Sets a ptrdiff_t at the offset to the value. Returns the assigned value.
584
+ */
585
+ static VALUE sd_set_ptrdiff_t(VALUE self, VALUE sd_offset, VALUE sd_value)
586
+ {
587
+ typedef ptrdiff_t conv_type_t;
588
+ const size_t offset = NUM2SIZET(sd_offset);
589
+ conv_type_t value;
590
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
591
+ sd_check_null_block(self);
592
+ rb_check_frozen(self);
593
+ value = (conv_type_t)SD_NUM_TO_PTRDIFF_T(sd_value);
594
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
595
+ return sd_value;
596
+ }
597
+
598
+ /*
599
+ call-seq:
600
+ get_intptr_t(offset) => intptr_t
601
+
602
+ Reads a intptr_t from the offset into the memory block and returns it.
603
+ The offset is not bounds-checked and it is possible to read outside of bounds,
604
+ which is considered undefined behavior and may crash or do other horrible
605
+ things.
606
+ */
607
+ static VALUE sd_get_intptr_t(VALUE self, VALUE sd_offset)
608
+ {
609
+ typedef intptr_t conv_type_t;
610
+ const size_t offset = NUM2SIZET(sd_offset);
611
+ conv_type_t value;
612
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
613
+ sd_check_null_block(self);
614
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
615
+ return SD_INTPTR_T_TO_NUM(value);
616
+ }
617
+
618
+ /*
619
+ call-seq:
620
+ set_intptr_t(offset, value) => value
621
+
622
+ Sets a intptr_t at the offset to the value. Returns the assigned value.
623
+ */
624
+ static VALUE sd_set_intptr_t(VALUE self, VALUE sd_offset, VALUE sd_value)
625
+ {
626
+ typedef intptr_t conv_type_t;
627
+ const size_t offset = NUM2SIZET(sd_offset);
628
+ conv_type_t value;
629
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
630
+ sd_check_null_block(self);
631
+ rb_check_frozen(self);
632
+ value = (conv_type_t)SD_NUM_TO_INTPTR_T(sd_value);
633
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
634
+ return sd_value;
635
+ }
636
+
637
+ /*
638
+ call-seq:
639
+ get_uintptr_t(offset) => uintptr_t
640
+
641
+ Reads a uintptr_t from the offset into the memory block and returns it.
642
+ The offset is not bounds-checked and it is possible to read outside of bounds,
643
+ which is considered undefined behavior and may crash or do other horrible
644
+ things.
645
+ */
646
+ static VALUE sd_get_uintptr_t(VALUE self, VALUE sd_offset)
647
+ {
648
+ typedef uintptr_t conv_type_t;
649
+ const size_t offset = NUM2SIZET(sd_offset);
650
+ conv_type_t value;
651
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
652
+ sd_check_null_block(self);
653
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
654
+ return SD_UINTPTR_T_TO_NUM(value);
655
+ }
656
+
657
+ /*
658
+ call-seq:
659
+ set_uintptr_t(offset, value) => value
660
+
661
+ Sets a uintptr_t at the offset to the value. Returns the assigned value.
662
+ */
663
+ static VALUE sd_set_uintptr_t(VALUE self, VALUE sd_offset, VALUE sd_value)
664
+ {
665
+ typedef uintptr_t conv_type_t;
666
+ const size_t offset = NUM2SIZET(sd_offset);
667
+ conv_type_t value;
668
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
669
+ sd_check_null_block(self);
670
+ rb_check_frozen(self);
671
+ value = (conv_type_t)SD_NUM_TO_UINTPTR_T(sd_value);
672
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
673
+ return sd_value;
674
+ }
675
+
676
+ /*
677
+ call-seq:
678
+ get_long(offset) => long
679
+
680
+ Reads a long from the offset into the memory block and returns it.
681
+ The offset is not bounds-checked and it is possible to read outside of bounds,
682
+ which is considered undefined behavior and may crash or do other horrible
683
+ things.
684
+ */
685
+ static VALUE sd_get_long(VALUE self, VALUE sd_offset)
686
+ {
687
+ typedef long conv_type_t;
688
+ const size_t offset = NUM2SIZET(sd_offset);
689
+ conv_type_t value;
690
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
691
+ sd_check_null_block(self);
692
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
693
+ return SD_LONG_TO_NUM(value);
694
+ }
695
+
696
+ /*
697
+ call-seq:
698
+ set_long(offset, value) => value
699
+
700
+ Sets a long at the offset to the value. Returns the assigned value.
701
+ */
702
+ static VALUE sd_set_long(VALUE self, VALUE sd_offset, VALUE sd_value)
703
+ {
704
+ typedef long conv_type_t;
705
+ const size_t offset = NUM2SIZET(sd_offset);
706
+ conv_type_t value;
707
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
708
+ sd_check_null_block(self);
709
+ rb_check_frozen(self);
710
+ value = (conv_type_t)SD_NUM_TO_LONG(sd_value);
711
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
712
+ return sd_value;
713
+ }
714
+
715
+ /*
716
+ call-seq:
717
+ get_long_long(offset) => long long
718
+
719
+ Reads a long long from the offset into the memory block and returns it.
720
+ The offset is not bounds-checked and it is possible to read outside of bounds,
721
+ which is considered undefined behavior and may crash or do other horrible
722
+ things.
723
+ */
724
+ static VALUE sd_get_long_long(VALUE self, VALUE sd_offset)
725
+ {
726
+ typedef long long conv_type_t;
727
+ const size_t offset = NUM2SIZET(sd_offset);
728
+ conv_type_t value;
729
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
730
+ sd_check_null_block(self);
731
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
732
+ return SD_LONG_LONG_TO_NUM(value);
733
+ }
734
+
735
+ /*
736
+ call-seq:
737
+ set_long_long(offset, value) => value
738
+
739
+ Sets a long long at the offset to the value. Returns the assigned value.
740
+ */
741
+ static VALUE sd_set_long_long(VALUE self, VALUE sd_offset, VALUE sd_value)
742
+ {
743
+ typedef long long conv_type_t;
744
+ const size_t offset = NUM2SIZET(sd_offset);
745
+ conv_type_t value;
746
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
747
+ sd_check_null_block(self);
748
+ rb_check_frozen(self);
749
+ value = (conv_type_t)SD_NUM_TO_LONG_LONG(sd_value);
750
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
751
+ return sd_value;
752
+ }
753
+
754
+ /*
755
+ call-seq:
756
+ get_unsigned_long(offset) => unsigned long
757
+
758
+ Reads a unsigned long from the offset into the memory block and returns it.
759
+ The offset is not bounds-checked and it is possible to read outside of bounds,
760
+ which is considered undefined behavior and may crash or do other horrible
761
+ things.
762
+ */
763
+ static VALUE sd_get_unsigned_long(VALUE self, VALUE sd_offset)
764
+ {
765
+ typedef unsigned long conv_type_t;
766
+ const size_t offset = NUM2SIZET(sd_offset);
767
+ conv_type_t value;
768
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
769
+ sd_check_null_block(self);
770
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
771
+ return SD_UNSIGNED_LONG_TO_NUM(value);
772
+ }
773
+
774
+ /*
775
+ call-seq:
776
+ set_unsigned_long(offset, value) => value
777
+
778
+ Sets a unsigned long at the offset to the value. Returns the assigned value.
779
+ */
780
+ static VALUE sd_set_unsigned_long(VALUE self, VALUE sd_offset, VALUE sd_value)
781
+ {
782
+ typedef unsigned long conv_type_t;
783
+ const size_t offset = NUM2SIZET(sd_offset);
784
+ conv_type_t value;
785
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
786
+ sd_check_null_block(self);
787
+ rb_check_frozen(self);
788
+ value = (conv_type_t)SD_NUM_TO_UNSIGNED_LONG(sd_value);
789
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
790
+ return sd_value;
791
+ }
792
+
793
+ /*
794
+ call-seq:
795
+ get_unsigned_long_long(offset) => unsigned long long
796
+
797
+ Reads a unsigned long long from the offset into the memory block and returns it.
798
+ The offset is not bounds-checked and it is possible to read outside of bounds,
799
+ which is considered undefined behavior and may crash or do other horrible
800
+ things.
801
+ */
802
+ static VALUE sd_get_unsigned_long_long(VALUE self, VALUE sd_offset)
803
+ {
804
+ typedef unsigned long long conv_type_t;
805
+ const size_t offset = NUM2SIZET(sd_offset);
806
+ conv_type_t value;
807
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
808
+ sd_check_null_block(self);
809
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
810
+ return SD_UNSIGNED_LONG_LONG_TO_NUM(value);
811
+ }
812
+
813
+ /*
814
+ call-seq:
815
+ set_unsigned_long_long(offset, value) => value
816
+
817
+ Sets a unsigned long long at the offset to the value. Returns the assigned value.
818
+ */
819
+ static VALUE sd_set_unsigned_long_long(VALUE self, VALUE sd_offset, VALUE sd_value)
820
+ {
821
+ typedef unsigned long long conv_type_t;
822
+ const size_t offset = NUM2SIZET(sd_offset);
823
+ conv_type_t value;
824
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
825
+ sd_check_null_block(self);
826
+ rb_check_frozen(self);
827
+ value = (conv_type_t)SD_NUM_TO_UNSIGNED_LONG_LONG(sd_value);
828
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
829
+ return sd_value;
830
+ }
831
+
832
+ /*
833
+ call-seq:
834
+ get_float(offset) => float
835
+
836
+ Reads a float from the offset into the memory block and returns it.
837
+ The offset is not bounds-checked and it is possible to read outside of bounds,
838
+ which is considered undefined behavior and may crash or do other horrible
839
+ things.
840
+ */
841
+ static VALUE sd_get_float(VALUE self, VALUE sd_offset)
842
+ {
843
+ typedef float conv_type_t;
844
+ const size_t offset = NUM2SIZET(sd_offset);
845
+ conv_type_t value;
846
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
847
+ sd_check_null_block(self);
848
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
849
+ return SD_FLOAT_TO_NUM(value);
850
+ }
851
+
852
+ /*
853
+ call-seq:
854
+ set_float(offset, value) => value
855
+
856
+ Sets a float at the offset to the value. Returns the assigned value.
857
+ */
858
+ static VALUE sd_set_float(VALUE self, VALUE sd_offset, VALUE sd_value)
859
+ {
860
+ typedef float conv_type_t;
861
+ const size_t offset = NUM2SIZET(sd_offset);
862
+ conv_type_t value;
863
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
864
+ sd_check_null_block(self);
865
+ rb_check_frozen(self);
866
+ value = (conv_type_t)SD_NUM_TO_FLOAT(sd_value);
867
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
868
+ return sd_value;
869
+ }
870
+
871
+ /*
872
+ call-seq:
873
+ get_double(offset) => double
874
+
875
+ Reads a double from the offset into the memory block and returns it.
876
+ The offset is not bounds-checked and it is possible to read outside of bounds,
877
+ which is considered undefined behavior and may crash or do other horrible
878
+ things.
879
+ */
880
+ static VALUE sd_get_double(VALUE self, VALUE sd_offset)
881
+ {
882
+ typedef double conv_type_t;
883
+ const size_t offset = NUM2SIZET(sd_offset);
884
+ conv_type_t value;
885
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
886
+ sd_check_null_block(self);
887
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
888
+ return SD_DOUBLE_TO_NUM(value);
889
+ }
890
+
891
+ /*
892
+ call-seq:
893
+ set_double(offset, value) => value
894
+
895
+ Sets a double at the offset to the value. Returns the assigned value.
896
+ */
897
+ static VALUE sd_set_double(VALUE self, VALUE sd_offset, VALUE sd_value)
898
+ {
899
+ typedef double conv_type_t;
900
+ const size_t offset = NUM2SIZET(sd_offset);
901
+ conv_type_t value;
902
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
903
+ sd_check_null_block(self);
904
+ rb_check_frozen(self);
905
+ value = (conv_type_t)SD_NUM_TO_DOUBLE(sd_value);
906
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
907
+ return sd_value;
908
+ }
909
+
910
+ /*
911
+ call-seq:
912
+ get_int(offset) => int
913
+
914
+ Reads a int from the offset into the memory block and returns it.
915
+ The offset is not bounds-checked and it is possible to read outside of bounds,
916
+ which is considered undefined behavior and may crash or do other horrible
917
+ things.
918
+ */
919
+ static VALUE sd_get_int(VALUE self, VALUE sd_offset)
920
+ {
921
+ typedef int conv_type_t;
922
+ const size_t offset = NUM2SIZET(sd_offset);
923
+ conv_type_t value;
924
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
925
+ sd_check_null_block(self);
926
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
927
+ return SD_INT_TO_NUM(value);
928
+ }
929
+
930
+ /*
931
+ call-seq:
932
+ set_int(offset, value) => value
933
+
934
+ Sets a int at the offset to the value. Returns the assigned value.
935
+ */
936
+ static VALUE sd_set_int(VALUE self, VALUE sd_offset, VALUE sd_value)
937
+ {
938
+ typedef int conv_type_t;
939
+ const size_t offset = NUM2SIZET(sd_offset);
940
+ conv_type_t value;
941
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
942
+ sd_check_null_block(self);
943
+ rb_check_frozen(self);
944
+ value = (conv_type_t)SD_NUM_TO_INT(sd_value);
945
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
946
+ return sd_value;
947
+ }
948
+
949
+ /*
950
+ call-seq:
951
+ get_unsigned_int(offset) => unsigned int
952
+
953
+ Reads a unsigned int from the offset into the memory block and returns it.
954
+ The offset is not bounds-checked and it is possible to read outside of bounds,
955
+ which is considered undefined behavior and may crash or do other horrible
956
+ things.
957
+ */
958
+ static VALUE sd_get_unsigned_int(VALUE self, VALUE sd_offset)
959
+ {
960
+ typedef unsigned int conv_type_t;
961
+ const size_t offset = NUM2SIZET(sd_offset);
962
+ conv_type_t value;
963
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
964
+ sd_check_null_block(self);
965
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
966
+ return SD_UNSIGNED_INT_TO_NUM(value);
967
+ }
968
+
969
+ /*
970
+ call-seq:
971
+ set_unsigned_int(offset, value) => value
972
+
973
+ Sets a unsigned int at the offset to the value. Returns the assigned value.
974
+ */
975
+ static VALUE sd_set_unsigned_int(VALUE self, VALUE sd_offset, VALUE sd_value)
976
+ {
977
+ typedef unsigned int conv_type_t;
978
+ const size_t offset = NUM2SIZET(sd_offset);
979
+ conv_type_t value;
980
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
981
+ sd_check_null_block(self);
982
+ rb_check_frozen(self);
983
+ value = (conv_type_t)SD_NUM_TO_UNSIGNED_INT(sd_value);
984
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
985
+ return sd_value;
986
+ }
987
+
988
+ /*
989
+ call-seq:
990
+ get_short(offset) => short
991
+
992
+ Reads a short from the offset into the memory block and returns it.
993
+ The offset is not bounds-checked and it is possible to read outside of bounds,
994
+ which is considered undefined behavior and may crash or do other horrible
995
+ things.
996
+ */
997
+ static VALUE sd_get_short(VALUE self, VALUE sd_offset)
998
+ {
999
+ typedef short conv_type_t;
1000
+ const size_t offset = NUM2SIZET(sd_offset);
1001
+ conv_type_t value;
1002
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1003
+ sd_check_null_block(self);
1004
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
1005
+ return SD_SHORT_TO_NUM(value);
1006
+ }
1007
+
1008
+ /*
1009
+ call-seq:
1010
+ set_short(offset, value) => value
1011
+
1012
+ Sets a short at the offset to the value. Returns the assigned value.
1013
+ */
1014
+ static VALUE sd_set_short(VALUE self, VALUE sd_offset, VALUE sd_value)
1015
+ {
1016
+ typedef short conv_type_t;
1017
+ const size_t offset = NUM2SIZET(sd_offset);
1018
+ conv_type_t value;
1019
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1020
+ sd_check_null_block(self);
1021
+ rb_check_frozen(self);
1022
+ value = (conv_type_t)SD_NUM_TO_SHORT(sd_value);
1023
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
1024
+ return sd_value;
1025
+ }
1026
+
1027
+ /*
1028
+ call-seq:
1029
+ get_unsigned_short(offset) => unsigned short
1030
+
1031
+ Reads a unsigned short from the offset into the memory block and returns it.
1032
+ The offset is not bounds-checked and it is possible to read outside of bounds,
1033
+ which is considered undefined behavior and may crash or do other horrible
1034
+ things.
1035
+ */
1036
+ static VALUE sd_get_unsigned_short(VALUE self, VALUE sd_offset)
1037
+ {
1038
+ typedef unsigned short conv_type_t;
1039
+ const size_t offset = NUM2SIZET(sd_offset);
1040
+ conv_type_t value;
1041
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1042
+ sd_check_null_block(self);
1043
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
1044
+ return SD_UNSIGNED_SHORT_TO_NUM(value);
1045
+ }
1046
+
1047
+ /*
1048
+ call-seq:
1049
+ set_unsigned_short(offset, value) => value
1050
+
1051
+ Sets a unsigned short at the offset to the value. Returns the assigned value.
1052
+ */
1053
+ static VALUE sd_set_unsigned_short(VALUE self, VALUE sd_offset, VALUE sd_value)
1054
+ {
1055
+ typedef unsigned short conv_type_t;
1056
+ const size_t offset = NUM2SIZET(sd_offset);
1057
+ conv_type_t value;
1058
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1059
+ sd_check_null_block(self);
1060
+ rb_check_frozen(self);
1061
+ value = (conv_type_t)SD_NUM_TO_UNSIGNED_SHORT(sd_value);
1062
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
1063
+ return sd_value;
1064
+ }
1065
+
1066
+ /*
1067
+ call-seq:
1068
+ get_char(offset) => char
1069
+
1070
+ Reads a char from the offset into the memory block and returns it.
1071
+ The offset is not bounds-checked and it is possible to read outside of bounds,
1072
+ which is considered undefined behavior and may crash or do other horrible
1073
+ things.
1074
+ */
1075
+ static VALUE sd_get_char(VALUE self, VALUE sd_offset)
1076
+ {
1077
+ typedef char conv_type_t;
1078
+ const size_t offset = NUM2SIZET(sd_offset);
1079
+ conv_type_t value;
1080
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1081
+ sd_check_null_block(self);
1082
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
1083
+ return SD_CHAR_TO_NUM(value);
1084
+ }
1085
+
1086
+ /*
1087
+ call-seq:
1088
+ set_char(offset, value) => value
1089
+
1090
+ Sets a char at the offset to the value. Returns the assigned value.
1091
+ */
1092
+ static VALUE sd_set_char(VALUE self, VALUE sd_offset, VALUE sd_value)
1093
+ {
1094
+ typedef char conv_type_t;
1095
+ const size_t offset = NUM2SIZET(sd_offset);
1096
+ conv_type_t value;
1097
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1098
+ sd_check_null_block(self);
1099
+ rb_check_frozen(self);
1100
+ value = (conv_type_t)SD_NUM_TO_CHAR(sd_value);
1101
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
1102
+ return sd_value;
1103
+ }
1104
+
1105
+ /*
1106
+ call-seq:
1107
+ get_unsigned_char(offset) => unsigned char
1108
+
1109
+ Reads a unsigned char from the offset into the memory block and returns it.
1110
+ The offset is not bounds-checked and it is possible to read outside of bounds,
1111
+ which is considered undefined behavior and may crash or do other horrible
1112
+ things.
1113
+ */
1114
+ static VALUE sd_get_unsigned_char(VALUE self, VALUE sd_offset)
1115
+ {
1116
+ typedef unsigned char conv_type_t;
1117
+ const size_t offset = NUM2SIZET(sd_offset);
1118
+ conv_type_t value;
1119
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1120
+ sd_check_null_block(self);
1121
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
1122
+ return SD_UNSIGNED_CHAR_TO_NUM(value);
1123
+ }
1124
+
1125
+ /*
1126
+ call-seq:
1127
+ set_unsigned_char(offset, value) => value
1128
+
1129
+ Sets a unsigned char at the offset to the value. Returns the assigned value.
1130
+ */
1131
+ static VALUE sd_set_unsigned_char(VALUE self, VALUE sd_offset, VALUE sd_value)
1132
+ {
1133
+ typedef unsigned char conv_type_t;
1134
+ const size_t offset = NUM2SIZET(sd_offset);
1135
+ conv_type_t value;
1136
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1137
+ sd_check_null_block(self);
1138
+ rb_check_frozen(self);
1139
+ value = (conv_type_t)SD_NUM_TO_UNSIGNED_CHAR(sd_value);
1140
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
1141
+ return sd_value;
1142
+ }
1143
+
1144
+ /*
1145
+ call-seq:
1146
+ get_signed_char(offset) => signed char
1147
+
1148
+ Reads a signed char from the offset into the memory block and returns it.
1149
+ The offset is not bounds-checked and it is possible to read outside of bounds,
1150
+ which is considered undefined behavior and may crash or do other horrible
1151
+ things.
1152
+ */
1153
+ static VALUE sd_get_signed_char(VALUE self, VALUE sd_offset)
1154
+ {
1155
+ typedef signed char conv_type_t;
1156
+ const size_t offset = NUM2SIZET(sd_offset);
1157
+ conv_type_t value;
1158
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1159
+ sd_check_null_block(self);
1160
+ value = *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset);
1161
+ return SD_SIGNED_CHAR_TO_NUM(value);
1162
+ }
1163
+
1164
+ /*
1165
+ call-seq:
1166
+ set_signed_char(offset, value) => value
1167
+
1168
+ Sets a signed char at the offset to the value. Returns the assigned value.
1169
+ */
1170
+ static VALUE sd_set_signed_char(VALUE self, VALUE sd_offset, VALUE sd_value)
1171
+ {
1172
+ typedef signed char conv_type_t;
1173
+ const size_t offset = NUM2SIZET(sd_offset);
1174
+ conv_type_t value;
1175
+ sd_check_block_bounds(self, offset, sizeof(conv_type_t));
1176
+ sd_check_null_block(self);
1177
+ rb_check_frozen(self);
1178
+ value = (conv_type_t)SD_NUM_TO_SIGNED_CHAR(sd_value);
1179
+ *(conv_type_t *)(((uint8_t *)RDATA(self)->data) + offset) = value;
1180
+ return sd_value;
1181
+ }
1182
+
1183
+ /*
1184
+ call-seq:
1185
+ get_string(offset, length = nil) -> String
1186
+
1187
+ Copies a string out of the block and returns it. The length argument is used
1188
+ to specify how the string is copied.
1189
+
1190
+ If length is nil, the string is extracted from offset up to the first null
1191
+ character. If length is -1, it extracts all characters from offset onward in
1192
+ the string and returns it. Otherwise, for any other length, it tries to copy
1193
+ length characters from the block before the end of the block.
1194
+
1195
+ This method does not work on zero-length blocks.
1196
+ */
1197
+ static VALUE sd_get_string(int argc, VALUE *argv, VALUE self)
1198
+ {
1199
+ VALUE sd_offset;
1200
+ VALUE sd_length;
1201
+ size_t offset;
1202
+ size_t length = ~(size_t)0;
1203
+ size_t self_length = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE));
1204
+ const uint8_t *data = DATA_PTR(self);
1205
+
1206
+ sd_check_null_block(self);
1207
+
1208
+ rb_scan_args(argc, argv, "11", &sd_offset, &sd_length);
1209
+
1210
+ offset = NUM2SIZET(sd_offset);
1211
+
1212
+ if (offset >= self_length) {
1213
+ return rb_str_new("", 0);
1214
+ }
1215
+
1216
+ if (RTEST(sd_length)) {
1217
+ length = NUM2SIZET(sd_length);
1218
+
1219
+ if (length == ~(size_t)0
1220
+ || (offset + length) > self_length
1221
+ || (offset + length) < offset) {
1222
+ length = self_length - offset;
1223
+ }
1224
+ } else {
1225
+ for (length = offset; length < self_length && data[length]; ++length)
1226
+ ;
1227
+ length -= offset;
1228
+ }
1229
+
1230
+ return rb_str_new((const char *)(data + offset), length);
1231
+ }
1232
+
1233
+ static VALUE sd_set_string_nullterm(VALUE self, VALUE sd_offset, VALUE sd_value, int null_terminated)
1234
+ {
1235
+ uint8_t *data = DATA_PTR(self);
1236
+ const uint8_t *string_data = (const uint8_t *)StringValueCStr(sd_value);
1237
+ size_t offset = NUM2SIZET(sd_offset);
1238
+ /* Subtract 1 from the block length to account for a null character) */
1239
+ size_t length = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE)) - null_terminated;
1240
+ size_t str_length = RSTRING_LEN(sd_value);
1241
+
1242
+ if (offset >= length) {
1243
+ return sd_value;
1244
+ }
1245
+
1246
+ length -= offset;
1247
+ if (str_length < length) {
1248
+ length = str_length;
1249
+ }
1250
+
1251
+ if (length > 0) {
1252
+ memcpy(data + offset, string_data, length);
1253
+ }
1254
+
1255
+ if (null_terminated) {
1256
+ data[offset + length] = '\0';
1257
+ }
1258
+
1259
+ return sd_value;
1260
+ }
1261
+
1262
+ /*
1263
+ call-seq:
1264
+ set_string(offset, value, null_terminated = false) -> value
1265
+
1266
+ Copies the string value into the block at the offset supplied.
1267
+
1268
+ If null_terminated is true, it will always write a null-terminating character
1269
+ if it fits. This means that you need at least string.bytesize + 1 bytes
1270
+ available from the offset onwards to fully story a string, otherwise the
1271
+ string's contents will be truncated to fit the null-terminating character.
1272
+
1273
+ If null_terminated is false, no null character is written and only the string
1274
+ bytes are copied to the block. If the full string does not fit, it will be
1275
+ truncated.
1276
+ */
1277
+ static VALUE sd_set_string(int argc, VALUE *argv, VALUE self)
1278
+ {
1279
+ VALUE sd_offset, sd_value, sd_null_terminated;
1280
+
1281
+ sd_check_null_block(self);
1282
+ rb_check_frozen(self);
1283
+
1284
+ rb_scan_args(argc, argv, "21", &sd_offset, &sd_value, &sd_null_terminated);
1285
+
1286
+ return sd_set_string_nullterm(self, sd_offset, sd_value, !!RTEST(sd_null_terminated));
1287
+ }
1288
+
1289
+ /*
1290
+ call-seq:
1291
+ new(address, size, alignment = SIZEOF_VOID_POINTER) => Memory
1292
+
1293
+ Creates a new Memory object that wraps an existing pointer. Alignment is
1294
+ optional and defaults to the size of a pointer (Memory::SIZEOF_VOID_POINTER).
1295
+
1296
+ Size must be greater than zero. Zero-sized blocks are not permitted as they
1297
+ render most memory functionality useless and make it very difficult to ensure
1298
+ nothing bad is happening when you do bad things with snow-data. Because, let's
1299
+ be honest with ourselves for a moment, everyone using this gem? They're bad
1300
+ people. They're very bad people.
1301
+
1302
+ Note that Memory objects created with this method will not attempt to free
1303
+ the memory they wrap, as they did not allocate it and so do not own it. If
1304
+ an address held by a Memory object is invalid, the Memory object is also
1305
+ implicitly invalid as well, though there is no way for it to check this. You
1306
+ are responsible for freeing any memory not allocated through ::malloc and
1307
+ Memory subclasses.
1308
+
1309
+ It is an ArgumentError to provide a size of zero, nil, or false. It is also
1310
+ an ArgumentError to provide a NULL (zero) address.
1311
+
1312
+ If a subclass overrides ::new, it is also aliased as ::wrap and ::__wrap__.
1313
+ Subclasses may override ::wrap but must not override ::__wrap__.
1314
+ */
1315
+ static VALUE sd_memory_new(int argc, VALUE *argv, VALUE self)
1316
+ {
1317
+ VALUE sd_size;
1318
+ VALUE sd_address;
1319
+ VALUE sd_alignment;
1320
+ VALUE memory = Qnil;
1321
+ void *address;
1322
+ size_t size;
1323
+ size_t alignment;
1324
+
1325
+ rb_scan_args(argc, argv, "21", &sd_address, &sd_size, &sd_alignment);
1326
+
1327
+ address = (void *)SD_NUM_TO_INTPTR_T(sd_address);
1328
+ size = 0;
1329
+ alignment = SIZEOF_VOIDP;
1330
+
1331
+ if (address == NULL) {
1332
+ rb_raise(rb_eArgError, "Address is NULL (%p).", address);
1333
+ }
1334
+
1335
+ if (RTEST(sd_size)) {
1336
+ size = NUM2SIZET(sd_size);
1337
+ } else {
1338
+ rb_raise(rb_eArgError, "Block size is false or nil");
1339
+ }
1340
+
1341
+ if (!size) {
1342
+ rb_raise(rb_eArgError, "Block size must be 1 or greater");
1343
+ }
1344
+
1345
+ if (RTEST(sd_alignment)) {
1346
+ alignment = NUM2SIZET(sd_alignment);
1347
+ }
1348
+
1349
+ memory = Data_Wrap_Struct(self, 0, 0, address);
1350
+ rb_ivar_set(memory, kSD_IVAR_BYTESIZE, SIZET2NUM(size));
1351
+ rb_ivar_set(memory, kSD_IVAR_ALIGNMENT, SIZET2NUM(alignment));
1352
+ rb_obj_call_init(memory, 0, 0);
1353
+ rb_obj_taint(memory);
1354
+
1355
+ return memory;
1356
+ }
1357
+
1358
+ /*
1359
+ call-seq:
1360
+ malloc(size, alignment = nil) => Memory
1361
+
1362
+ Allocates a new block with the given size and alignment and returns it. If
1363
+ no alignment is specified, it defaults to Snow::Memory::SIZEOF_VOID_POINTER.
1364
+
1365
+ Raises a RangeError if either size is zero or alignment is not a power of two.
1366
+ */
1367
+ static VALUE sd_memory_malloc(int argc, VALUE *argv, VALUE self)
1368
+ {
1369
+ VALUE sd_size;
1370
+ VALUE sd_alignment;
1371
+ size_t alignment;
1372
+ size_t size;
1373
+ void *data;
1374
+ VALUE memory;
1375
+
1376
+ rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment);
1377
+
1378
+ /* Get size and alignment */
1379
+ size = NUM2SIZET(sd_size);
1380
+ alignment = RTEST(sd_alignment) ? NUM2SIZET(sd_alignment) : sizeof(void *);
1381
+ if (!is_power_of_two(alignment)) {
1382
+ rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not a"
1383
+ " power of two", alignment);
1384
+ } else if (size < 1) {
1385
+ rb_raise(rb_eRangeError, "Size of block must be 1 or more -- zero-byte"
1386
+ " blocks are not permitted");
1387
+ }
1388
+
1389
+ /* Allocate block */
1390
+ data = com_malloc(size, alignment);
1391
+ memory = Data_Wrap_Struct(self, 0, com_free, data);
1392
+
1393
+ rb_ivar_set(memory, kSD_IVAR_BYTESIZE, SIZET2NUM(size));
1394
+ rb_ivar_set(memory, kSD_IVAR_ALIGNMENT, SIZET2NUM(alignment));
1395
+ rb_obj_call_init(memory, 0, 0);
1396
+ rb_obj_taint(memory);
1397
+ return memory;
1398
+ }
1399
+
1400
+ /*
1401
+ call-seq:
1402
+ realloc!(size, alignment = nil) => self
1403
+
1404
+ Reallocates the memory backing this pointer with a new size and optionally a
1405
+ new alignment. If the new size is the same as the old size, the method returns
1406
+ early and nothing is reallocated.
1407
+
1408
+ If a new alignment is specified, the memory will be reallocated regardless of
1409
+ whether the new and old sizes are the same. If no alignment is specified, the
1410
+ memory's previous alignment is used.
1411
+
1412
+ If the block for this memory was previously freed or the block is not owner by
1413
+ this object, a new block is allocated and the memory takes ownership of it.
1414
+ It is fine to realloc! on a previously freed block.
1415
+
1416
+ Raises a RangeError if either size is zero or alignment is not a power of two.
1417
+ */
1418
+ static VALUE sd_memory_realloc(int argc, VALUE *argv, VALUE self)
1419
+ {
1420
+ struct RData *data;
1421
+ void *new_data;
1422
+ size_t size;
1423
+ size_t prev_size;
1424
+ size_t prev_align;
1425
+ size_t alignment;
1426
+ VALUE sd_size;
1427
+ VALUE sd_alignment;
1428
+
1429
+ /*
1430
+ Don't check for null/zero length here, as it is safe to reuse a memory via
1431
+ realloc!. It's less safe for structs and arrays, but you just have to do the
1432
+ sane thing in most cases. Granted, I'm a hypocrite for saying you need to
1433
+ do the sane thing after writing this gem.
1434
+ */
1435
+ rb_check_frozen(self);
1436
+
1437
+ rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment);
1438
+
1439
+ size = NUM2SIZET(sd_size);
1440
+ prev_align =
1441
+ alignment = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_ALIGNMENT));
1442
+ prev_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE));
1443
+
1444
+ if (RTEST(sd_alignment)) {
1445
+ alignment = NUM2SIZET(sd_alignment);
1446
+ }
1447
+
1448
+ if (prev_size == size && alignment == prev_align) {
1449
+ return self;
1450
+ } else if (!is_power_of_two(alignment)) {
1451
+ rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not a"
1452
+ " power of two", alignment);
1453
+ } else if (size < 1) {
1454
+ rb_raise(rb_eRangeError, "Size of block must be 1 or more -- zero-byte"
1455
+ " blocks are not permitted");
1456
+ }
1457
+
1458
+ data = RDATA(self);
1459
+ new_data = com_malloc(size, alignment);
1460
+
1461
+ if (data->data && prev_size > 0) {
1462
+ const size_t copy_sizes[2] = { prev_size, size };
1463
+ memcpy(new_data, data->data, copy_sizes[prev_size > size]);
1464
+ }
1465
+
1466
+ if (data->dfree) {
1467
+ data->dfree(data->data);
1468
+ } else if (data->data) {
1469
+ rb_warning("realloc called on unowned pointer %p -- allocating new block"
1470
+ " and memcpying contents (size: %zd bytes), but original block will"
1471
+ " not be freed.", data->data, prev_size);
1472
+ }
1473
+
1474
+ data->data = new_data;
1475
+ data->dfree = com_free;
1476
+
1477
+ rb_ivar_set(self, kSD_IVAR_BYTESIZE, SIZET2NUM(size));
1478
+ rb_ivar_set(self, kSD_IVAR_ALIGNMENT, SIZET2NUM(alignment));
1479
+ return self;
1480
+ }
1481
+
1482
+ /*
1483
+ call-seq:
1484
+ free!() => self
1485
+
1486
+ Frees any memory owned by the object. This is a convenience function for when
1487
+ you want to free the memory ahead of the object being collected by the GC.
1488
+ */
1489
+ static VALUE sd_memory_free(VALUE self)
1490
+ {
1491
+ struct RData *data = RDATA(self);
1492
+
1493
+ rb_check_frozen(self);
1494
+
1495
+ if (data->data && data->dfree) {
1496
+ data->dfree(data->data);
1497
+ data->dfree = 0;
1498
+ } else if (!data->data) {
1499
+ rb_raise(rb_eRuntimeError,
1500
+ "Double-free on %s",
1501
+ rb_obj_classname(self));
1502
+ }
1503
+
1504
+ data->data = 0;
1505
+ rb_ivar_set(self, kSD_IVAR_BYTESIZE, INT2FIX(0));
1506
+
1507
+ return self;
1508
+ }
1509
+
1510
+ /*
1511
+ call-seq:
1512
+ copy!(source, destination_offset = nil, source_offset = nil, byte_size = nil) => self
1513
+
1514
+ Copies byte_size bytes from an offset in the source data to an offset into
1515
+ the receiver (the destination).
1516
+
1517
+ If either offset is nil, they default to zero.
1518
+
1519
+ If the byte_size is nil, it defaults to the receiver's #bytesize.
1520
+
1521
+ If the source responds to #bytesize and the source's bytesize is smaller than
1522
+ the size given, the source's size is used instead of the specified or default
1523
+ size.
1524
+
1525
+ The source pointer does not have its bounds checked, as this isn't possible
1526
+ for all cases. Instead, you must ensure that your source offset and byte size
1527
+ are both within range of the source data.
1528
+
1529
+ For those curious, under the hood, this uses memmove, not memcpy. So, it is
1530
+ possible to copy overlapping regions of memory, but it isn't guaranteed to be
1531
+ as fast as a simple memcpy. Either way, if this is a concern for you, you
1532
+ probably shouldn't be using Ruby.
1533
+
1534
+ === Exceptions
1535
+
1536
+ - If attempting to copy into a region that is outside the bounds of the
1537
+ receiver will raise a RangeError.
1538
+ - If either the receiver or the source address is NULL, it will raise an
1539
+ ArgumentError.
1540
+ - If the source object is neither a Data object (or a subclass thereof) or a
1541
+ Numerical address, it raises a TypeError.
1542
+ */
1543
+ static VALUE sd_memory_copy(int argc, VALUE *argv, VALUE self)
1544
+ {
1545
+ VALUE sd_source;
1546
+ VALUE sd_destination_offset;
1547
+ VALUE sd_source_offset;
1548
+ VALUE sd_byte_size;
1549
+ struct RData *self_data;
1550
+ const uint8_t *source_pointer;
1551
+ uint8_t *destination_pointer;
1552
+ size_t source_offset;
1553
+ size_t destination_offset;
1554
+ size_t byte_size;
1555
+ size_t self_byte_size;
1556
+ int source_is_data = 0;
1557
+
1558
+ sd_check_null_block(self);
1559
+ rb_check_frozen(self);
1560
+
1561
+ rb_scan_args(argc, argv, "13",
1562
+ &sd_source,
1563
+ &sd_destination_offset,
1564
+ &sd_source_offset,
1565
+ &sd_byte_size);
1566
+
1567
+ /*
1568
+ By default, try to get an address from the object, if possible. Then use
1569
+ that address and don't extract it from the Data object or what have you.
1570
+ */
1571
+ if (rb_obj_respond_to(sd_source, kSD_ID_ADDRESS, 0)) {
1572
+ VALUE source_address = rb_funcall2(sd_source, kSD_ID_ADDRESS, 0, 0);
1573
+ if (RTEST(rb_obj_is_kind_of(source_address, rb_cNumeric))) {
1574
+ source_pointer = (uint8_t *)SD_NUM_TO_INTPTR_T(source_address);
1575
+ goto sd_memory_copy_skip_data_check;
1576
+ }
1577
+ }
1578
+
1579
+ if (RTEST(rb_obj_is_kind_of(sd_source, rb_cData))) {
1580
+ /* Otherwise extract a pointer from the object if it's a Data object */
1581
+ const struct RData *source_data = RDATA(sd_source);
1582
+ source_pointer = ((const uint8_t *)source_data->data);
1583
+ source_is_data = 1;
1584
+ } else if (RTEST(rb_obj_is_kind_of(sd_source, rb_cNumeric))) {
1585
+ /* Otherwise, if it's a Numeric, try to convert what is assumed to be an
1586
+ address to a pointer */
1587
+ source_pointer = (uint8_t *)SD_NUM_TO_INTPTR_T(sd_source);
1588
+ } else {
1589
+ rb_raise(rb_eTypeError,
1590
+ "Source object must be type of numeric (address) or Data- got %s",
1591
+ rb_obj_classname(sd_source));
1592
+ }
1593
+
1594
+ sd_memory_copy_skip_data_check: /* skip from address check */
1595
+ self_data = RDATA(self);
1596
+
1597
+ /*
1598
+ Check if the source pointer is NULL -- error if it is (the destination
1599
+ pointer is checked by sd_check_null_block above).
1600
+ */
1601
+ if (source_pointer == NULL) {
1602
+ rb_raise(rb_eArgError, "Source pointer is NULL");
1603
+ }
1604
+
1605
+ /* Grab data from ruby values and offset the source pointer. */
1606
+ source_offset = RTEST(sd_source_offset) ? NUM2SIZET(sd_source_offset) : 0;
1607
+ destination_offset = RTEST(sd_destination_offset) ? NUM2SIZET(sd_destination_offset) : 0;
1608
+ destination_pointer = (uint8_t *)self_data->data + destination_offset;
1609
+ self_byte_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE));
1610
+ source_pointer += source_offset;
1611
+
1612
+ if (self_byte_size == 0) {
1613
+ /*
1614
+ If self is a zero-length block, do not try to copy. It's just not sane to
1615
+ attempt it here since we can't do any bounds checking, even if the bounds
1616
+ might be arbitrarily specified (in which case I'd just be shooting myself
1617
+ in the foot if I did that and trying to circumvent the anti-foot-shot
1618
+ protections).
1619
+ */
1620
+ rb_raise(rb_eRuntimeError, "self.bytesize == 0 -- cannot safely copy to this block");
1621
+ } else if (!RTEST(sd_byte_size)) {
1622
+ /*
1623
+ If not copy size is specified, use self_byte_size and just try to cram as
1624
+ much in there as is feasible. Truncate self_byte_size as needed for the
1625
+ offset.
1626
+ */
1627
+ byte_size = self_byte_size - destination_offset;
1628
+ #ifdef SD_WARN_ON_IMPLICIT_COPY_SIZE
1629
+ if (!source_is_data) {
1630
+ rb_warning(
1631
+ "Copying %zu bytes from non-Data memory address %p without explicit size",
1632
+ byte_size,
1633
+ source_pointer);
1634
+ }
1635
+ #endif
1636
+ } else {
1637
+ /* User-specified size */
1638
+ byte_size = NUM2SIZET(sd_byte_size);
1639
+ }
1640
+
1641
+ /*
1642
+ If the source responds to bytesize, check if the copy is within bounds for
1643
+ the source. If it's out of bounds, raise a RangeError, otherwise optionally
1644
+ emit a warning that bounds checking doesn't work for this source.
1645
+ */
1646
+ if (rb_obj_respond_to(sd_source, kSD_ID_BYTESIZE, 0)) {
1647
+ size_t source_size = NUM2SIZET(rb_funcall2(sd_source, kSD_ID_BYTESIZE, 0, 0));
1648
+ if (source_offset > source_size
1649
+ || (source_offset + byte_size) > source_size
1650
+ || (source_offset + byte_size) < source_offset) {
1651
+ rb_raise(rb_eRangeError, "Attempt to copy out of source bounds");
1652
+ }
1653
+ }
1654
+ #ifdef SD_WARN_ON_NO_BYTESIZE_METHOD
1655
+ else if (source_is_data) {
1656
+ rb_warning(
1657
+ "Copying from Data object pointer %p that does not respond to #bytesize"
1658
+ " -- this operation is not bounds-checked.",
1659
+ source_pointer);
1660
+ }
1661
+ #endif
1662
+
1663
+ if ((destination_offset + byte_size) > self_byte_size
1664
+ || (destination_offset + byte_size) < destination_offset) {
1665
+ rb_raise(rb_eRangeError,
1666
+ "Offset %zu with byte size %zu is out of bounds of self",
1667
+ destination_offset,
1668
+ byte_size);
1669
+ }
1670
+
1671
+ #ifdef SD_VERBOSE_COPY_LOG
1672
+ /*
1673
+ Emit some debugging info just in case things go completely haywire and you
1674
+ really need to know what's going on.
1675
+ */
1676
+ fprintf(stderr,
1677
+ "# copy! ----------------------------------------\n"
1678
+ "# destination_pointer = %p" "\n"
1679
+ "# source_pointer = %p" "\n"
1680
+ "# destination_offset = %zu" "\n"
1681
+ "# source_offset = %zu" "\n"
1682
+ "# byte_size = %zu" "\n"
1683
+ "# self_byte_size = %zu" "\n"
1684
+ "# source.class = %s" "\n"
1685
+ "# self.class = %s" "\n"
1686
+ "# --------------------------------------- /copy!\n",
1687
+ destination_pointer - destination_offset,
1688
+ source_pointer - source_offset,
1689
+ destination_offset,
1690
+ source_offset,
1691
+ byte_size,
1692
+ self_byte_size,
1693
+ rb_obj_classname(sd_source),
1694
+ rb_obj_classname(self));
1695
+ #endif
1696
+
1697
+ /* And skip a copy if we can */
1698
+ if (byte_size == 0 || source_pointer == destination_pointer) {
1699
+ return self;
1700
+ }
1701
+
1702
+ memmove(destination_pointer, source_pointer, byte_size);
1703
+
1704
+ return self;
1705
+ }
1706
+
1707
+ /*
1708
+ call-seq:
1709
+ to_s(null_terminated = true) => String
1710
+
1711
+ Gets a string representation of the contents of this block. If null_terminated
1712
+ is true (or nil), the returned string will end before the first null
1713
+ character.
1714
+ */
1715
+ static VALUE sd_memory_to_s(int argc, VALUE *argv, VALUE self)
1716
+ {
1717
+ VALUE null_terminated;
1718
+ size_t byte_size = NUM2SIZET(rb_ivar_get(self, kSD_IVAR_BYTESIZE));
1719
+ const char *data = DATA_PTR(self);
1720
+
1721
+ sd_check_null_block(self);
1722
+
1723
+ rb_scan_args(argc, argv, "01", &null_terminated);
1724
+
1725
+ if (null_terminated == Qnil || RTEST(null_terminated)) {
1726
+ size_t string_length = 0;
1727
+ for (; string_length < byte_size && data[string_length]; ++string_length)
1728
+ ;
1729
+ byte_size = string_length;
1730
+ }
1731
+
1732
+ return rb_str_new(data, byte_size);
1733
+ }
1734
+
1735
+ /*
1736
+ call-seq:
1737
+ address => Integer
1738
+
1739
+ Gets the address of this memory block as an Integer.
1740
+ */
1741
+ static VALUE sd_memory_address(VALUE self)
1742
+ {
1743
+ return SD_UINTPTR_T_TO_NUM((uintptr_t)RDATA(self)->data);
1744
+ }
1745
+
1746
+ /*
1747
+ call-seq:
1748
+ align_size(size_or_offset, alignment = nil) => Integer
1749
+
1750
+ Aligns a given size or offset to a specific alignment. If no alignment is
1751
+ provided, it defaults to the size of a pointer on the architecture the
1752
+ extension was compiled for.
1753
+
1754
+ See Snow::Memory::SIZEOF_VOID_POINTER for the size of a pointer.
1755
+
1756
+ Raises a RangeError if the alignment is not a power of two. In this case, 1
1757
+ is considered a valid power of two.
1758
+ */
1759
+ static VALUE sd_align_size(int argc, VALUE *argv, VALUE self)
1760
+ {
1761
+ VALUE sd_alignment;
1762
+ VALUE sd_size;
1763
+ size_t alignment = sizeof(void *);
1764
+ rb_scan_args(argc, argv, "11", &sd_size, &sd_alignment);
1765
+ if (RTEST(sd_alignment)) {
1766
+ alignment = NUM2SIZET(sd_alignment);
1767
+ if (!is_power_of_two(alignment)) {
1768
+ rb_raise(rb_eRangeError, "Alignment must be a power of two -- %zu is not"
1769
+ " a power of two", alignment);
1770
+ }
1771
+ }
1772
+ return SIZET2NUM(align_size(NUM2SIZET(sd_size), alignment));
1773
+ }
1774
+
1775
+ void Init_snowdata_bindings(void)
1776
+ {
1777
+ VALUE sd_snow_module = rb_define_module("Snow");
1778
+ VALUE sd_memory_klass = rb_define_class_under(sd_snow_module, "Memory", rb_cData);
1779
+
1780
+ kSD_IVAR_BYTESIZE = rb_intern("@__bytesize__");
1781
+ kSD_IVAR_ALIGNMENT = rb_intern("@__alignment__");
1782
+ kSD_ID_BYTESIZE = rb_intern("bytesize");
1783
+ kSD_ID_ADDRESS = rb_intern("address");
1784
+
1785
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INT"), SIZET2NUM(SIZEOF_INT));
1786
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_SHORT"), SIZET2NUM(SIZEOF_SHORT));
1787
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_LONG"), SIZET2NUM(SIZEOF_LONG));
1788
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_LONG_LONG"), SIZET2NUM(SIZEOF_LONG_LONG));
1789
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_OFF_T"), SIZET2NUM(SIZEOF_OFF_T));
1790
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_VOIDP"), SIZET2NUM(SIZEOF_VOIDP));
1791
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_FLOAT"), SIZET2NUM(SIZEOF_FLOAT));
1792
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_DOUBLE"), SIZET2NUM(SIZEOF_DOUBLE));
1793
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_SIZE_T"), SIZET2NUM(SIZEOF_SIZE_T));
1794
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_PTRDIFF_T"), SIZET2NUM(SIZEOF_PTRDIFF_T));
1795
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INT8_T"), SIZET2NUM(SIZEOF_INT8_T));
1796
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_UINT8_T"), SIZET2NUM(SIZEOF_UINT8_T));
1797
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INT16_T"), SIZET2NUM(SIZEOF_INT16_T));
1798
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_UINT16_T"), SIZET2NUM(SIZEOF_UINT16_T));
1799
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INT32_T"), SIZET2NUM(SIZEOF_INT32_T));
1800
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_UINT32_T"), SIZET2NUM(SIZEOF_UINT32_T));
1801
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INT64_T"), SIZET2NUM(SIZEOF_INT64_T));
1802
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_UINT64_T"), SIZET2NUM(SIZEOF_UINT64_T));
1803
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_INTPTR_T"), SIZET2NUM(SIZEOF_INTPTR_T));
1804
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_UINTPTR_T"), SIZET2NUM(SIZEOF_UINTPTR_T));
1805
+ rb_const_set(sd_memory_klass, rb_intern("SIZEOF_VOID_POINTER"), SIZET2NUM(sizeof(void *)));
1806
+
1807
+ rb_define_singleton_method(sd_memory_klass, "new", sd_memory_new, -1);
1808
+ rb_define_singleton_method(sd_memory_klass, "malloc", sd_memory_malloc, -1);
1809
+ rb_define_singleton_method(sd_memory_klass, "align_size", sd_align_size, -1);
1810
+ rb_define_method(sd_memory_klass, "realloc!", sd_memory_realloc, -1);
1811
+ rb_define_method(sd_memory_klass, "copy!", sd_memory_copy, -1);
1812
+ rb_define_method(sd_memory_klass, "to_s", sd_memory_to_s, -1);
1813
+ rb_define_method(sd_memory_klass, "free!", sd_memory_free, 0);
1814
+ rb_define_method(sd_memory_klass, "address", sd_memory_address, 0);
1815
+ rb_define_method(sd_memory_klass, "get_int8_t", sd_get_int8, 1);
1816
+ rb_define_method(sd_memory_klass, "set_int8_t", sd_set_int8, 2);
1817
+ rb_define_method(sd_memory_klass, "get_int16_t", sd_get_int16, 1);
1818
+ rb_define_method(sd_memory_klass, "set_int16_t", sd_set_int16, 2);
1819
+ rb_define_method(sd_memory_klass, "get_int32_t", sd_get_int32, 1);
1820
+ rb_define_method(sd_memory_klass, "set_int32_t", sd_set_int32, 2);
1821
+ rb_define_method(sd_memory_klass, "get_int64_t", sd_get_int64, 1);
1822
+ rb_define_method(sd_memory_klass, "set_int64_t", sd_set_int64, 2);
1823
+ rb_define_method(sd_memory_klass, "get_uint8_t", sd_get_uint8, 1);
1824
+ rb_define_method(sd_memory_klass, "set_uint8_t", sd_set_uint8, 2);
1825
+ rb_define_method(sd_memory_klass, "get_uint16_t", sd_get_uint16, 1);
1826
+ rb_define_method(sd_memory_klass, "set_uint16_t", sd_set_uint16, 2);
1827
+ rb_define_method(sd_memory_klass, "get_uint32_t", sd_get_uint32, 1);
1828
+ rb_define_method(sd_memory_klass, "set_uint32_t", sd_set_uint32, 2);
1829
+ rb_define_method(sd_memory_klass, "get_uint64_t", sd_get_uint64, 1);
1830
+ rb_define_method(sd_memory_klass, "set_uint64_t", sd_set_uint64, 2);
1831
+ rb_define_method(sd_memory_klass, "get_size_t", sd_get_size_t, 1);
1832
+ rb_define_method(sd_memory_klass, "set_size_t", sd_set_size_t, 2);
1833
+ rb_define_method(sd_memory_klass, "get_ptrdiff_t", sd_get_ptrdiff_t, 1);
1834
+ rb_define_method(sd_memory_klass, "set_ptrdiff_t", sd_set_ptrdiff_t, 2);
1835
+ rb_define_method(sd_memory_klass, "get_intptr_t", sd_get_intptr_t, 1);
1836
+ rb_define_method(sd_memory_klass, "set_intptr_t", sd_set_intptr_t, 2);
1837
+ rb_define_method(sd_memory_klass, "get_uintptr_t", sd_get_uintptr_t, 1);
1838
+ rb_define_method(sd_memory_klass, "set_uintptr_t", sd_set_uintptr_t, 2);
1839
+ rb_define_method(sd_memory_klass, "get_long", sd_get_long, 1);
1840
+ rb_define_method(sd_memory_klass, "set_long", sd_set_long, 2);
1841
+ rb_define_method(sd_memory_klass, "get_long_long", sd_get_long_long, 1);
1842
+ rb_define_method(sd_memory_klass, "set_long_long", sd_set_long_long, 2);
1843
+ rb_define_method(sd_memory_klass, "get_unsigned_long", sd_get_unsigned_long, 1);
1844
+ rb_define_method(sd_memory_klass, "set_unsigned_long", sd_set_unsigned_long, 2);
1845
+ rb_define_method(sd_memory_klass, "get_unsigned_long_long", sd_get_unsigned_long_long, 1);
1846
+ rb_define_method(sd_memory_klass, "set_unsigned_long_long", sd_set_unsigned_long_long, 2);
1847
+ rb_define_method(sd_memory_klass, "get_float", sd_get_float, 1);
1848
+ rb_define_method(sd_memory_klass, "set_float", sd_set_float, 2);
1849
+ rb_define_method(sd_memory_klass, "get_double", sd_get_double, 1);
1850
+ rb_define_method(sd_memory_klass, "set_double", sd_set_double, 2);
1851
+ rb_define_method(sd_memory_klass, "get_int", sd_get_int, 1);
1852
+ rb_define_method(sd_memory_klass, "set_int", sd_set_int, 2);
1853
+ rb_define_method(sd_memory_klass, "get_unsigned_int", sd_get_unsigned_int, 1);
1854
+ rb_define_method(sd_memory_klass, "set_unsigned_int", sd_set_unsigned_int, 2);
1855
+ rb_define_method(sd_memory_klass, "get_short", sd_get_short, 1);
1856
+ rb_define_method(sd_memory_klass, "set_short", sd_set_short, 2);
1857
+ rb_define_method(sd_memory_klass, "get_unsigned_short", sd_get_unsigned_short, 1);
1858
+ rb_define_method(sd_memory_klass, "set_unsigned_short", sd_set_unsigned_short, 2);
1859
+ rb_define_method(sd_memory_klass, "get_char", sd_get_char, 1);
1860
+ rb_define_method(sd_memory_klass, "set_char", sd_set_char, 2);
1861
+ rb_define_method(sd_memory_klass, "get_unsigned_char", sd_get_unsigned_char, 1);
1862
+ rb_define_method(sd_memory_klass, "set_unsigned_char", sd_set_unsigned_char, 2);
1863
+ rb_define_method(sd_memory_klass, "get_signed_char", sd_get_signed_char, 1);
1864
+ rb_define_method(sd_memory_klass, "set_signed_char", sd_set_signed_char, 2);
1865
+ rb_define_method(sd_memory_klass, "get_string", sd_get_string, -1);
1866
+ rb_define_method(sd_memory_klass, "set_string", sd_set_string, -1);
1867
+ }