snow-data 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|