snow-data 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }