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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de5502dc1786af224a1344f0221110e87bae22a0
4
- data.tar.gz: 207bffe6bbe3d1bf6f6ff3bef67615b12ef3767d
3
+ metadata.gz: 40d3b634a2fe9ad1783ff57bd03dbdb9e01d28a4
4
+ data.tar.gz: 0087c9dd8a0f26fbc239b518d66243ee4b391f48
5
5
  SHA512:
6
- metadata.gz: c38b07ce23e8fc20c451c5d529d535e9bbe826a5e41f149d5903c29a53ac7d01024d0becda54c7e75e4c24e07f1b216fe4a87a45098394b121eb3de309bd860f
7
- data.tar.gz: a71c448abd01932b31ec66d5bb197469b6b6521404fa270f20a45ae150eb51d798011e1fe56daea4d1421d684cf145c333582ecd6aa1d1db523f1bca01a5b5b6
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[<<END_TYPE]
57
- position: Vec3 : 4
58
- normal: Vec3 : 4
59
- texcoord: Vec2[2] : 4
60
- color: Color : 4
61
- END_TYPE
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 = 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 }
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 = 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 }
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 <<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
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 <<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
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
@@ -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
- LONG_NAMES = {
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
- name = name.intern
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 "No type name provided" if !name
264
+ raise "Type for #{name} is already defined" if SIZES.include?(name)
222
265
 
223
266
  ALIGNMENTS[name] = klass::ALIGNMENT
224
- SIZES[name] = klass::SIZE
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(klass_name = nil, encoding)
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 = decode_member_info(encoding)
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 = members.map { |member| member.alignment }.max { |lhs, rhs| lhs <=> rhs }
432
- size = members.last.size + members.last.offset
433
- aligned_size = Memory.align_size(size, alignment)
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, 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
- end # class CStruct
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
@@ -7,6 +7,6 @@ module Snow
7
7
  #
8
8
  # The snow-data version string.
9
9
  #
10
- SNOW_DATA_VERSION = '1.1.0'.freeze
10
+ SNOW_DATA_VERSION = '1.2.0'.freeze
11
11
 
12
12
  end
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.1.0
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-18 00:00:00.000000000 Z
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