snow-data 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +25 -35
- data/lib/snow-data/c_struct.rb +85 -14
- data/lib/snow-data/c_struct/builder.rb +94 -0
- data/lib/snow-data/c_struct/struct_base.rb +1 -1
- data/lib/snow-data/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40d3b634a2fe9ad1783ff57bd03dbdb9e01d28a4
|
4
|
+
data.tar.gz: 0087c9dd8a0f26fbc239b518d66243ee4b391f48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e8e6ec2a0160b4ba35170e73d4db301bb99a6af90a769f72ee75e8e1aef4d6ccb0708f4f84546330721ae134487261e8c8ac4dd2897cf9b56f8f229ed257c53
|
7
|
+
data.tar.gz: a46085a0735417717a5af9a952027e1e711b292b0b76406dd2522e038ca21473bcd38e15562503747ae4c3f09430d5a418d7ea286c839bcf00e91af41dd7c6f3
|
data/README.md
CHANGED
@@ -53,36 +53,35 @@ How you use it, ultimately, is really up to you.
|
|
53
53
|
# itself has a position, a normal, two texcoords (e.g., diffuse and lightmap),
|
54
54
|
# and a color value. Because we've not given Vertex a name (no :Vertex argument
|
55
55
|
# to CStruct), it isn't usable as a type for struct members.
|
56
|
-
Vertex = Snow::CStruct
|
57
|
-
position
|
58
|
-
normal:
|
59
|
-
texcoord
|
60
|
-
color:
|
61
|
-
|
56
|
+
Vertex = Snow::CStruct.new {
|
57
|
+
vec3 :position, align: 4
|
58
|
+
vec3 :normal, align: 4
|
59
|
+
vec2 :texcoord, [2], align: 4
|
60
|
+
color :color, align: 4
|
61
|
+
}
|
62
|
+
|
63
|
+
def stringify_vertex(vertex)
|
64
|
+
<<-VERTEX_DESCRIPTION
|
65
|
+
Position: #{vertex.position.to_h}
|
66
|
+
Normal: #{vertex.normal.to_h}
|
67
|
+
Texcoords: [#{vertex.texcoord(0).to_h}, #{vertex.texcoord(1).to_h}]
|
68
|
+
Color: #{vertex.color.to_h}
|
69
|
+
VERTEX_DESCRIPTION
|
70
|
+
end
|
62
71
|
|
63
72
|
# So let's create a vertex.
|
64
73
|
a_vertex = Vertex.new { |v|
|
65
|
-
v.position
|
66
|
-
v.normal
|
74
|
+
v.position = Vec3.new { |p| p.x = 1; p.y = 2; p.z = 3 }
|
75
|
+
v.normal = Vec3.new { |n| n.x = 0.707107; n.y = 0; n.z = 0.707107 }
|
67
76
|
# For array types, we must use set_* functions, as the name= shorthand for
|
68
77
|
# struct members only assigns to the first element of an array.
|
69
|
-
v.texcoord
|
70
|
-
#
|
71
|
-
v
|
72
|
-
v.color
|
78
|
+
v.texcoord = Vec2.new { |t| t.x = 1.0; t.y = 1.0 }
|
79
|
+
# This also works:
|
80
|
+
v[:texcoord, 1] = Vec2.new { |t| t.x = 0.5; t.y = 0.5 }
|
81
|
+
v.color = Color.new { |c| c.r = 255; c.g = 127; c.b = 63; c.a = 220 }
|
73
82
|
}
|
74
83
|
|
75
|
-
puts
|
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
|
84
|
+
puts "Our vertex:\n#{stringify_vertex a_vertex}"
|
86
85
|
|
87
86
|
# For kicks, let's create an array.
|
88
87
|
some_vertices = Vertex[64]
|
@@ -90,16 +89,7 @@ How you use it, ultimately, is really up to you.
|
|
90
89
|
# And set all vertices to the above vertex.
|
91
90
|
some_vertices.map! { a_vertex }
|
92
91
|
|
93
|
-
puts
|
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
|
92
|
+
puts "Our vertex at index 36:\n#{stringify_vertex some_vertices[36]}"
|
103
93
|
|
104
94
|
|
105
95
|
License
|
@@ -114,10 +104,10 @@ Snow-Data is licensed under a simplified BSD license, like most of my gems.
|
|
114
104
|
modification, are permitted provided that the following conditions are met:
|
115
105
|
|
116
106
|
1. Redistributions of source code must retain the above copyright notice, this
|
117
|
-
list of conditions and the following disclaimer.
|
107
|
+
list of conditions and the following disclaimer.
|
118
108
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
119
109
|
this list of conditions and the following disclaimer in the documentation
|
120
|
-
and/or other materials provided with the distribution.
|
110
|
+
and/or other materials provided with the distribution.
|
121
111
|
|
122
112
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
123
113
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
data/lib/snow-data/c_struct.rb
CHANGED
@@ -6,6 +6,7 @@ require 'snow-data/snowdata_bindings'
|
|
6
6
|
require 'snow-data/memory'
|
7
7
|
require 'snow-data/c_struct/struct_base'
|
8
8
|
require 'snow-data/c_struct/array_base'
|
9
|
+
require 'snow-data/c_struct/builder'
|
9
10
|
|
10
11
|
module Snow
|
11
12
|
|
@@ -16,6 +17,8 @@ class CStruct
|
|
16
17
|
# Info for a struct member. Defines a member's name, type, size, length,
|
17
18
|
# alignment, and offset.
|
18
19
|
#
|
20
|
+
# The type member of this may not be an alias of another type.
|
21
|
+
#
|
19
22
|
StructMemberInfo = Struct.new(:name, :type, :size, :length, :alignment, :offset)
|
20
23
|
|
21
24
|
|
@@ -174,7 +177,7 @@ class CStruct
|
|
174
177
|
|
175
178
|
# Used for getters/setters on Memory objects. Simply maps short type names to
|
176
179
|
# their long-form type names.
|
177
|
-
|
180
|
+
TYPE_ALIASES = {
|
178
181
|
# char
|
179
182
|
:c => :char,
|
180
183
|
:sc => :signed_char,
|
@@ -207,6 +210,37 @@ class CStruct
|
|
207
210
|
}
|
208
211
|
|
209
212
|
|
213
|
+
#
|
214
|
+
# Gets the actual type for a given type. Only useful for deducing the target
|
215
|
+
# type for a type alias.
|
216
|
+
#
|
217
|
+
def self.real_type_of(type)
|
218
|
+
while TYPE_ALIASES.include?(type)
|
219
|
+
type = TYPE_ALIASES[type]
|
220
|
+
end
|
221
|
+
type
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
#
|
226
|
+
# Aliases the type for old_name to new_name. Raises
|
227
|
+
#
|
228
|
+
def self.alias_type(new_name, old_name)
|
229
|
+
return self if new_name == old_name
|
230
|
+
old_name = real_type_of(old_name)
|
231
|
+
|
232
|
+
if ! SIZES.include?(old_name)
|
233
|
+
raise ArgumentError, "There is no type named #{old_name} to alias"
|
234
|
+
elsif TYPE_ALIASES.include?(new_name) || SIZES.include?(new_name)
|
235
|
+
raise ArgumentError, "Type <#{new_name}> is already defined in CStruct"
|
236
|
+
end
|
237
|
+
|
238
|
+
TYPE_ALIASES[new_name] = old_name
|
239
|
+
Builder.flush_type_methods!
|
240
|
+
self
|
241
|
+
end
|
242
|
+
|
243
|
+
|
210
244
|
#
|
211
245
|
# call-seq:
|
212
246
|
# add_type(name, klass) => klass
|
@@ -215,13 +249,22 @@ class CStruct
|
|
215
249
|
# can be used as a member type by using the name provided to #add_type in
|
216
250
|
# struct encodings.
|
217
251
|
#
|
218
|
-
def self.add_type(name, klass)
|
219
|
-
|
252
|
+
def self.add_type(name = nil, klass)
|
253
|
+
raise "Class must be a subclass of #{Memory}" unless Memory > klass
|
254
|
+
|
255
|
+
if ! name
|
256
|
+
name = klass.name
|
257
|
+
if (last_sro = name.rindex('::'))
|
258
|
+
name = name[last_sro + 2, name.length]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
name = name.to_sym
|
220
263
|
|
221
|
-
raise "
|
264
|
+
raise "Type for #{name} is already defined" if SIZES.include?(name)
|
222
265
|
|
223
266
|
ALIGNMENTS[name] = klass::ALIGNMENT
|
224
|
-
SIZES[name]
|
267
|
+
SIZES[name] = klass::SIZE
|
225
268
|
|
226
269
|
getter = :"get_#{name}"
|
227
270
|
setter = :"set_#{name}"
|
@@ -246,6 +289,8 @@ class CStruct
|
|
246
289
|
|
247
290
|
end # class_exec
|
248
291
|
|
292
|
+
Builder.flush_type_methods!
|
293
|
+
|
249
294
|
klass
|
250
295
|
end
|
251
296
|
|
@@ -254,6 +299,8 @@ class CStruct
|
|
254
299
|
# call-seq:
|
255
300
|
# new(name, encoding) => Class
|
256
301
|
# new(encoding) => Class
|
302
|
+
# new(name) { ... } => Class
|
303
|
+
# new { ... } => Class
|
257
304
|
#
|
258
305
|
# Creates a new C-struct class and returns it. Optionally, if a name is
|
259
306
|
# provided, it is also added as a class under the CStruct class.
|
@@ -275,6 +322,10 @@ class CStruct
|
|
275
322
|
# call ::add_type(name, klass). This will not register it as a constant under
|
276
323
|
# CStruct.
|
277
324
|
#
|
325
|
+
# If a block is given, a CStruct::Builder is allocated and the block is
|
326
|
+
# instance_exec'd for that builder. Encoding strings may not be passed if you
|
327
|
+
# opt to use a builder block in place of an encoding string.
|
328
|
+
#
|
278
329
|
#
|
279
330
|
# ### Encodings
|
280
331
|
#
|
@@ -355,10 +406,30 @@ class CStruct
|
|
355
406
|
# `fetch(index)` and `store(index, value)` methods, both aliased to `[]` and
|
356
407
|
# `[]=` respectively.
|
357
408
|
#
|
358
|
-
def self.new(
|
409
|
+
def self.new(*args, &block)
|
410
|
+
klass_name = nil
|
411
|
+
encoding = nil
|
412
|
+
|
413
|
+
case
|
414
|
+
when args.length == 0 && block_given?
|
415
|
+
; #nop
|
416
|
+
when args.length == 1 && block_given?
|
417
|
+
klass_name = args[0]
|
418
|
+
when args.length == 1
|
419
|
+
encoding = args[0]
|
420
|
+
when args.length == 2 && !block_given?
|
421
|
+
klass_name, encoding = *args
|
422
|
+
else
|
423
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..2)"
|
424
|
+
end
|
425
|
+
|
359
426
|
klass_name = klass_name.intern if klass_name
|
360
427
|
|
361
|
-
members =
|
428
|
+
members = if block_given?
|
429
|
+
Builder.new(&block).member_info
|
430
|
+
else
|
431
|
+
decode_member_info(encoding)
|
432
|
+
end
|
362
433
|
|
363
434
|
raise "No valid members found in encoding" if members.empty?
|
364
435
|
|
@@ -385,8 +456,7 @@ class CStruct
|
|
385
456
|
encoding.scan(ENCODING_REGEX).map do
|
386
457
|
|match|
|
387
458
|
name = match[0].intern
|
388
|
-
type = match[1].intern
|
389
|
-
type = LONG_NAMES[type] if LONG_NAMES.include?(type)
|
459
|
+
type = real_type_of(match[1].intern)
|
390
460
|
length = (match[3] || 1).to_i
|
391
461
|
align = (match[5] || ALIGNMENTS[type] || 1).to_i
|
392
462
|
size = SIZES[type] * length
|
@@ -428,9 +498,9 @@ class CStruct
|
|
428
498
|
members.freeze
|
429
499
|
|
430
500
|
# Get the alignment, size, aligned size, and encoding of the struct.
|
431
|
-
alignment
|
432
|
-
|
433
|
-
aligned_size = Memory.align_size(
|
501
|
+
alignment = members.map { |member| member.alignment }.max { |lhs, rhs| lhs <=> rhs }
|
502
|
+
type_size = members.last.size + members.last.offset
|
503
|
+
aligned_size = Memory.align_size(type_size, alignment)
|
434
504
|
# Oddly enough, it would be easier to pass the encoding string into this
|
435
505
|
# function, but then it would ruin the nice little thing I have going where
|
436
506
|
# this function isn't dependent on parsing encodings, so we reproduce the
|
@@ -443,7 +513,7 @@ class CStruct
|
|
443
513
|
# and other methods.
|
444
514
|
const_set(:ENCODING, encoding)
|
445
515
|
const_set(:MEMBERS, members)
|
446
|
-
const_set(:SIZE,
|
516
|
+
const_set(:SIZE, type_size)
|
447
517
|
const_set(:ALIGNED_SIZE, aligned_size)
|
448
518
|
const_set(:ALIGNMENT, alignment)
|
449
519
|
|
@@ -492,7 +562,8 @@ class CStruct
|
|
492
562
|
|
493
563
|
class <<self ; alias_method :[], :new ; end
|
494
564
|
|
495
|
-
|
565
|
+
Builder.flush_type_methods!
|
496
566
|
|
567
|
+
end # class CStruct
|
497
568
|
|
498
569
|
end # module Snow
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Snow ; end
|
4
|
+
class Snow::CStruct ; end
|
5
|
+
|
6
|
+
class Snow::CStruct::Builder
|
7
|
+
|
8
|
+
@@defined_types = Set.new
|
9
|
+
|
10
|
+
#
|
11
|
+
# call-seq:
|
12
|
+
# new => Builder
|
13
|
+
# new { ... } => Builder
|
14
|
+
#
|
15
|
+
# In either form, a new Builder is allocated and returned. If a block is
|
16
|
+
# given, then it will be instance_exec'd, allowing you to easily call any
|
17
|
+
# declaration methods on the builder instance.
|
18
|
+
#
|
19
|
+
def initialize(&block)
|
20
|
+
@members = []
|
21
|
+
@last_offset = 0
|
22
|
+
instance_exec(&block) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# call-seq:
|
27
|
+
# member_info => [StructMemberInfo]
|
28
|
+
#
|
29
|
+
# Returns the StructMemberInfo array for the builder. You should copy this if
|
30
|
+
# you need to modify it, and the same goes for its elements.
|
31
|
+
#
|
32
|
+
def member_info
|
33
|
+
@members
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# call-seq:
|
38
|
+
# flush_type_methods! => self
|
39
|
+
#
|
40
|
+
# Defines methods for declaring members of any recognized CStruct type,
|
41
|
+
# including aliases.
|
42
|
+
#
|
43
|
+
def self.flush_type_methods!
|
44
|
+
::Snow::CStruct::SIZES.each do |type_name, type_size|
|
45
|
+
next if @@defined_types.include?(type_name)
|
46
|
+
|
47
|
+
method_name = type_name.to_s
|
48
|
+
first_char = method_name[0]
|
49
|
+
case
|
50
|
+
when first_char >= ?A && first_char <= ?Z
|
51
|
+
method_name[0] = first_char.downcase
|
52
|
+
when first_char >= ?0 && first_char <= ?9
|
53
|
+
method_name[0] = "_#{first_char}"
|
54
|
+
end
|
55
|
+
method_name = method_name.to_sym
|
56
|
+
|
57
|
+
__send__(:define_method, method_name) do | name, lengths = 1, align: nil |
|
58
|
+
name = name.to_sym
|
59
|
+
|
60
|
+
length = case lengths
|
61
|
+
when Integer, Fixnum then lengths
|
62
|
+
when Array then lengths.reduce(:*)
|
63
|
+
else lengths.to_i
|
64
|
+
end
|
65
|
+
raise "Invalid length for member #{name}: must be >= 1" if length < 1
|
66
|
+
|
67
|
+
size = length * type_size
|
68
|
+
|
69
|
+
align = (align || ::Snow::CStruct::ALIGNMENTS[type_name]).to_i
|
70
|
+
raise "Nil alignment for type #{type_name}" if align.nil?
|
71
|
+
|
72
|
+
last_offset = instance_variable_get(:@last_offset)
|
73
|
+
offset = ::Snow::Memory.align_size(last_offset, align)
|
74
|
+
last_offset = offset + size
|
75
|
+
|
76
|
+
member_info = ::Snow::CStruct::StructMemberInfo[
|
77
|
+
name, type_name, size, length, align, offset]
|
78
|
+
|
79
|
+
instance_variable_set(:@last_offset, last_offset)
|
80
|
+
instance_variable_get(:@members).push(member_info.freeze)
|
81
|
+
end # define_method(type_name)
|
82
|
+
|
83
|
+
@@defined_types.add(type_name)
|
84
|
+
|
85
|
+
end # SIZES.each
|
86
|
+
|
87
|
+
::Snow::CStruct::TYPE_ALIASES.each { |short, long|
|
88
|
+
__send__(:alias_method, short, long)
|
89
|
+
}
|
90
|
+
|
91
|
+
self
|
92
|
+
end # flush_type_methods!
|
93
|
+
|
94
|
+
end
|
@@ -96,7 +96,7 @@ module Snow::CStruct::StructBase
|
|
96
96
|
id_text = __id__.to_s(16).rjust(14, ?0)
|
97
97
|
addr_text = self.address.to_s(16).rjust(14, ?0)
|
98
98
|
|
99
|
-
member_text = if ! null? && CStruct.long_inspect
|
99
|
+
member_text = if ! null? && ::Snow::CStruct.long_inspect
|
100
100
|
# Get member text
|
101
101
|
all_members_text = (self.class::MEMBERS.map do |member|
|
102
102
|
name = member.name
|
data/lib/snow-data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snow-data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noel Raymond Cower
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07-
|
11
|
+
date: 2013-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
Snow-Data is a gem for allocating memory and working with existing blocks of
|
@@ -25,6 +25,7 @@ extra_rdoc_files:
|
|
25
25
|
- COPYING
|
26
26
|
files:
|
27
27
|
- lib/snow-data/c_struct/array_base.rb
|
28
|
+
- lib/snow-data/c_struct/builder.rb
|
28
29
|
- lib/snow-data/c_struct/struct_base.rb
|
29
30
|
- lib/snow-data/c_struct.rb
|
30
31
|
- lib/snow-data/memory.rb
|