jfreeze-ruby-gdsii 1.0.1

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.
Files changed (54) hide show
  1. data/CHANGELOG.txt +6 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.txt +113 -0
  4. data/Rakefile +30 -0
  5. data/bin/rgds-debug +43 -0
  6. data/bin/rgds-dump +38 -0
  7. data/bin/rgds-join +98 -0
  8. data/bin/rgds-layers +53 -0
  9. data/bin/rgds-sremove +136 -0
  10. data/bin/rgds-ssplit +113 -0
  11. data/bin/rgds-stats +134 -0
  12. data/bin/rgds-structs +41 -0
  13. data/bin/rgds-tree +167 -0
  14. data/bin/rgds2rb +99 -0
  15. data/lib/gdsii.rb +137 -0
  16. data/lib/gdsii/aref.rb +243 -0
  17. data/lib/gdsii/bnf.rb +309 -0
  18. data/lib/gdsii/boundary.rb +53 -0
  19. data/lib/gdsii/box.rb +65 -0
  20. data/lib/gdsii/byte_order.rb +36 -0
  21. data/lib/gdsii/element.rb +172 -0
  22. data/lib/gdsii/group.rb +98 -0
  23. data/lib/gdsii/library.rb +518 -0
  24. data/lib/gdsii/mixins.rb +378 -0
  25. data/lib/gdsii/node.rb +65 -0
  26. data/lib/gdsii/path.rb +169 -0
  27. data/lib/gdsii/property.rb +108 -0
  28. data/lib/gdsii/record.rb +606 -0
  29. data/lib/gdsii/record/consts.rb +384 -0
  30. data/lib/gdsii/record/datatypes/ascii.rb +145 -0
  31. data/lib/gdsii/record/datatypes/bitarray.rb +101 -0
  32. data/lib/gdsii/record/datatypes/data.rb +111 -0
  33. data/lib/gdsii/record/datatypes/int2.rb +67 -0
  34. data/lib/gdsii/record/datatypes/int4.rb +65 -0
  35. data/lib/gdsii/record/datatypes/nodata.rb +60 -0
  36. data/lib/gdsii/record/datatypes/real4.rb +51 -0
  37. data/lib/gdsii/record/datatypes/real8.rb +120 -0
  38. data/lib/gdsii/sref.rb +61 -0
  39. data/lib/gdsii/strans.rb +133 -0
  40. data/lib/gdsii/structure.rb +352 -0
  41. data/lib/gdsii/text.rb +203 -0
  42. data/pkg/ruby-gdsii.gem +46 -0
  43. data/samples/hello.gds +0 -0
  44. data/samples/hello.out.rb +84 -0
  45. data/samples/hello.rb +94 -0
  46. data/test/baseline/dcp1.gds +0 -0
  47. data/test/baseline/h_write.gds +0 -0
  48. data/test/h_pthru.rb +22 -0
  49. data/test/h_write.rb +117 -0
  50. data/test/hs_pthru.rb +31 -0
  51. data/test/l_pthru.rb +23 -0
  52. data/test/test_gds_group.rb +379 -0
  53. data/test/test_gds_record.rb +99 -0
  54. metadata +117 -0
data/lib/gdsii/bnf.rb ADDED
@@ -0,0 +1,309 @@
1
+ require 'gdsii/record/consts'
2
+
3
+ module Gdsii
4
+
5
+ #
6
+ # Class to hold BNF items which are to be listed in the BnfSpec class. The
7
+ # BnfItem objects are used to indicate the unique BNF key and also whether
8
+ # or not it is optional and whether or not it is multiple.
9
+ #
10
+ class BnfItem
11
+
12
+ attr_reader :key, :optional, :multiple
13
+
14
+ #
15
+ # Create a new BNF item of a given key and specify if it is optional
16
+ # and if there are multiple values. The key is either one of the
17
+ # Gdsii::GRT_* constants or is a class descended from Gdsii::Group.
18
+ # Examples:
19
+ #
20
+ # BnfItem.new(Property,true,true),
21
+ # BnfItem.new(GRT_ENDEL)
22
+ #
23
+ def initialize(key, optional=false, multiple=false)
24
+ @key = key
25
+ @optional = optional
26
+ @multiple = multiple
27
+ end
28
+
29
+ #
30
+ # True if this BNF item is optional; false if not (opposite of #required?)
31
+ #
32
+ def optional?() @optional; end
33
+
34
+ #
35
+ # True if this BNF item has multiple values; false if not
36
+ #
37
+ def multiple?() @multiple; end
38
+
39
+ #
40
+ # Dump the name for this BNF item
41
+ #
42
+ def to_s(); Gdsii::grt_name(@key); end
43
+
44
+ #
45
+ # (hide from RDoc) - Add details to inspect
46
+ #
47
+ def inspect() # :nodoc:
48
+ "#<#{self.class}:0x#{sprintf("%x", self.object_id*2)} == #{self.to_s}>"
49
+ end
50
+
51
+ end
52
+
53
+ ############################################################################
54
+
55
+ #
56
+ # This class represents the order of a GDSII record grouping using a specific
57
+ # record order in Backus-Naur Form (BNF). It consists of a number of BnfItem
58
+ # objects where the order of the items is important in determining the order
59
+ # in which the GDSII file format should be read or written from/to a file.
60
+ #
61
+ class BnfSpec
62
+
63
+ include Enumerable
64
+
65
+ attr_reader :bnf_items
66
+
67
+ #
68
+ # Creates a Backus-Naur Form (BNF) grouping consisting of BnfItem objects.
69
+ #
70
+ # spec = BnfSpec.new(
71
+ # BnfItem.new(GRT_PROPATTR),
72
+ # BnfItem.new(GRT_PROPVALUE)
73
+ # )
74
+ #
75
+ def initialize(*bnf_items)
76
+ @bnf_items = bnf_items
77
+ end
78
+
79
+ #
80
+ # Loops through each BnfItem in this BnfSpec yielding the BnfItem along
81
+ # the way.
82
+ #
83
+ # spec.each {|bnf_item| ...}
84
+ #
85
+ def each()
86
+ @bnf_items.each {|bnf_item| yield bnf_item}
87
+ end
88
+ alias :each_item :each
89
+
90
+ #
91
+ # Finds a BnfItem of a given key in this Bnf object or nil if one is not
92
+ # found.
93
+ #
94
+ # spec = ...
95
+ # spec.find_item(GRT_PROPATTR) #=> BnfItem ...
96
+ # spec.find_item(GRT_HEADER) #=> nil
97
+ #
98
+ def find_item(key)
99
+ @bnf_items.find {|bnf_item| bnf_item.key == key}
100
+ end
101
+
102
+ #
103
+ # Shortcut for #find_item but will raise an exception if the item key
104
+ # is not part of this BNF.
105
+ #
106
+ # spec = ...
107
+ # spec.find_item(GRT_PROPATTR) #=> BnfItem ...
108
+ # spec.find_item(GRT_HEADER) #=> raise IndexError ...
109
+ #
110
+ def [](key)
111
+ if (found = find_item(key))
112
+ found
113
+ else
114
+ raise IndexError, "Cannot find BnfItem of key #{Gdsii::grt_name(key)} in BNF"
115
+ end
116
+ end
117
+
118
+ #
119
+ # Format for inspection
120
+ #
121
+ def inspect() # :nodoc:
122
+ "#<#{self.class}:0x#{sprintf("%x", self.object_id*2)}:@bnf_items.map {|i| i.to_s}.inspect>"
123
+ end
124
+
125
+ end
126
+
127
+ ############################################################################
128
+
129
+ #
130
+ # Used to store records for a record grouping (i.e. classes descending
131
+ # from Group). Only records that are in the BnfSpec may be added.
132
+ #
133
+ class BnfRecords
134
+
135
+ #
136
+ # Create a new BnfRecords object. The parent class is stored so that
137
+ # entries may be compared against the BnfSpec.
138
+ #
139
+ def initialize(parent_class)
140
+ @parent_class = parent_class
141
+ @bnf_records = {}
142
+ end
143
+
144
+ #
145
+ # Returns the BnfSpec of the parent class.
146
+ #
147
+ def bnf_spec()
148
+ @parent_class.bnf_spec
149
+ end
150
+
151
+ #
152
+ # Returns the BNF record keys that exist in this grouping of BNF records.
153
+ #
154
+ def bnf_keys()
155
+ @bnf_records.keys
156
+ end
157
+
158
+ #
159
+ # Retrieves the Record for a given BNF item key. If the record is
160
+ # multiple according to the BNF description, then an array of
161
+ # Record objects is returned. Used internally by various grouping accessor
162
+ # methods.
163
+ #
164
+ def get(key)
165
+ bnf_item = bnf_spec[key]
166
+ if bnf_item.multiple?
167
+ @bnf_records[key] = [] unless @bnf_records.has_key? key
168
+ @bnf_records[key]
169
+ else
170
+ if key.class == Class and @bnf_records[key].nil?
171
+ @bnf_records[key] = key.new
172
+ end
173
+ @bnf_records[key]
174
+ end
175
+ end
176
+
177
+ alias :[] :get
178
+
179
+ #
180
+ # Retrieves the Record *data* (i.e value) for a given BNF item key. If
181
+ # the record is multiple according to the BNF description, then an array
182
+ # of Record data is returned. Used internally by various grouping accessor
183
+ # methods.
184
+ #
185
+ def get_data(key)
186
+ if bnf_spec[key].multiple?
187
+ get(key).map {|record| record.data_value}
188
+ else
189
+ ((record = get(key)).nil?) ? nil : record.data_value
190
+ end
191
+ end
192
+
193
+ #
194
+ # Sets the record data for a given BNF item key. The value may be the
195
+ # of the class to be added or can be a raw value which is automatically
196
+ # coerced into the proper class for the given key. Used internally by
197
+ # various grouping accessor methods. Returns the object being set.
198
+ #
199
+ def set(key, value)
200
+ if key.class == Class
201
+ @bnf_records[key] = value
202
+ elsif value.nil?
203
+ @bnf_records[key] = value
204
+ else
205
+ value = coerce_record_value(key, value)
206
+ value = [value] if bnf_spec[key].multiple? and value.class != Array
207
+ @bnf_records[key] = value
208
+ end
209
+ end
210
+
211
+ alias :[]= :set
212
+
213
+ #
214
+ # Adds the record or record value to the bnf_records hash (applicable only
215
+ # for records with multiple entries). Returns the updated list of values.
216
+ # Used internally by various grouping accessor methods. Returns the object
217
+ # being set.
218
+ #
219
+ def add(key, value)
220
+ if bnf_spec[key].multiple?
221
+ value = coerce_record_value(key, value)
222
+ get(key).push value
223
+ else
224
+ raise TypeError, "BNF for key #{key} is singular in class #{parent_class}; use #set instead"
225
+ end
226
+ end
227
+
228
+ #
229
+ # Accepts a code block which should return true or false. If the return
230
+ # value is true, then the value meeting the criteria is removed. This
231
+ # is used internally by various grouping accessor methods. Note, this is
232
+ # only applicable for records with multiple values.
233
+ #
234
+ # object.reject!(Property) {|property|
235
+ # property.attr == 1
236
+ # }
237
+ #
238
+ def reject!(key)
239
+ if bnf_spec[key].multiple?
240
+ @bnf_records[key].reject! {|value| yield value}
241
+ else
242
+ raise TypeError, "BNF for key #{key} is singular in class #{parent_class}; use #set to nil"
243
+ end
244
+ end
245
+
246
+ #
247
+ # Deletes the given key from the bnf_records hash.
248
+ #
249
+ def delete_key(key)
250
+ @bnf_records.delete(key)
251
+ end
252
+
253
+ #
254
+ # True if the record item is not nil (if the BnfItem is singular) or an
255
+ # empty array (if the BnfItem is multiple).
256
+ #
257
+ def has_data?(key)
258
+ bnf_item = bnf_spec[key]
259
+ if (bnf_item.multiple? and get(key).empty?) or
260
+ (not bnf_item.multiple? and get(key).nil?)
261
+ false
262
+ else
263
+ true
264
+ end
265
+ end
266
+
267
+ #
268
+ # Write the BNF records to file. Ensures that the required records exist
269
+ # according to the BnfSpec (otherwise an error is raised). A file object
270
+ # is expected.
271
+ #
272
+ def write(file, alt_bnf=nil)
273
+ # Loop through each BNF item
274
+ bnf = alt_bnf ? alt_bnf : bnf_spec
275
+ bnf.each_item do |bnf_item|
276
+ if has_data?(bnf_item.key)
277
+ if bnf_item.multiple?
278
+ get(bnf_item.key).each {|record| record.write(file)}
279
+ else
280
+ get(bnf_item.key).write(file)
281
+ end
282
+ elsif not bnf_item.optional?
283
+ raise "Required data in BNF are not set: #{bnf_item}"
284
+ end
285
+ end
286
+ end
287
+
288
+ ##########################################################################
289
+ # PRIVATE METHODS
290
+ ##########################################################################
291
+
292
+ private
293
+
294
+ #
295
+ # Used by #add and #set to convert a raw value into the proper class
296
+ # given the key (if needed). This method is not used outside of this
297
+ # class.
298
+ #
299
+ def coerce_record_value(key, value)
300
+ if value.kind_of?(Record) or value.kind_of?(Group)
301
+ value
302
+ else
303
+ Record.new(key, value)
304
+ end
305
+ end
306
+
307
+ end
308
+ end
309
+
@@ -0,0 +1,53 @@
1
+ require 'gdsii/element'
2
+ require 'gdsii/mixins'
3
+
4
+ module Gdsii
5
+
6
+ #
7
+ # Represents a GDSII Boundary element (i.e. a rectangle or polygon). Most
8
+ # methods are from Element or from the various included Access module
9
+ # methods.
10
+ #
11
+ class Boundary < Element
12
+
13
+ # Include various record accessors
14
+ include Access::Layer
15
+ include Access::Datatype
16
+ include Access::XY
17
+ include Access::ELFlags
18
+ include Access::Plex
19
+
20
+ #
21
+ # Boundary BNF description:
22
+ #
23
+ # <boundary> ::= BOUNDARY [ELFLAGS] [PLEX] LAYER DATATYPE XY
24
+ #
25
+ self.bnf_spec = BnfSpec.new(
26
+ BnfItem.new(GRT_BOUNDARY),
27
+ BnfItem.new(GRT_ELFLAGS, true),
28
+ BnfItem.new(GRT_PLEX, true),
29
+ BnfItem.new(GRT_LAYER),
30
+ BnfItem.new(GRT_DATATYPE),
31
+ BnfItem.new(GRT_XY),
32
+ BnfItem.new(Properties,true),
33
+ BnfItem.new(GRT_ENDEL)
34
+ )
35
+
36
+ #
37
+ # Boundary object constructor. Layer and datatype are given as Fixnum
38
+ # and the coordinate points are given as an array of Fixnum alternating
39
+ # x and y values (coordinate pair range is 4-200). Example:
40
+ #
41
+ # rectangle = Gdsii::Boundary.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
42
+ #
43
+ def initialize(layer=nil, datatype=nil, xy=nil)
44
+ super()
45
+ @records[GRT_BOUNDARY] = Record.new(GRT_BOUNDARY)
46
+ self.layer = layer unless layer.nil?
47
+ self.datatype = datatype unless datatype.nil?
48
+ self.xy = xy unless xy.nil?
49
+ yield self if block_given?
50
+ end
51
+
52
+ end
53
+ end
data/lib/gdsii/box.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'gdsii/group'
2
+ require 'gdsii/element'
3
+
4
+ module Gdsii
5
+
6
+ #
7
+ # Represents a GDSII box element. Most methods are from Element or from the
8
+ # various included Access module methods.
9
+ #
10
+ class Box < Element
11
+
12
+ # Include various record accessors
13
+ include Access::Layer
14
+ include Access::XY
15
+ include Access::ELFlags
16
+ include Access::Plex
17
+
18
+ #
19
+ # Box BNF description:
20
+ #
21
+ # <box> ::= BOX [ELFLAGS] [PLEX] LAYER BOXTYPE XY
22
+ #
23
+ self.bnf_spec = BnfSpec.new(
24
+ BnfItem.new(GRT_BOX),
25
+ BnfItem.new(GRT_ELFLAGS, true),
26
+ BnfItem.new(GRT_PLEX, true),
27
+ BnfItem.new(GRT_LAYER),
28
+ BnfItem.new(GRT_BOXTYPE),
29
+ BnfItem.new(GRT_XY),
30
+ BnfItem.new(Properties, true),
31
+ BnfItem.new(GRT_ENDEL)
32
+ )
33
+
34
+ #
35
+ # Create a box record grouping given a layer, boxtype, and xy coordinates.
36
+ # The box object is to have exactly 5 coordinate pairs.
37
+ #
38
+ # box = Gdsii::Box.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
39
+ #
40
+ def initialize(layer=nil, boxtype=nil, xy=nil)
41
+ super()
42
+ @records[GRT_BOX] = Record.new(GRT_BOX)
43
+ self.layer = layer unless layer.nil?
44
+ self.boxtype = boxtype unless boxtype.nil?
45
+ self.xy = xy unless xy.nil?
46
+ yield self if block_given?
47
+ end
48
+
49
+ #
50
+ # Get the boxtype record (returns Record).
51
+ #
52
+ def boxtype_record() @records.get(GRT_BOXTYPE); end
53
+
54
+ #
55
+ # Get the boxtype number (returns Fixnum).
56
+ #
57
+ def boxtype() @records.get_data(GRT_BOXTYPE); end
58
+
59
+ #
60
+ # Set the boxtype number.
61
+ #
62
+ def boxtype=(val) @records.set(GRT_BOXTYPE, val); end
63
+
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # ByteOrder is lifted from ruby-talk 107439, cited by Michael Neumann
3
+ #
4
+ module ByteOrder
5
+
6
+ Native = :Native
7
+ Big = BigEndian = Network = :BigEndian
8
+ Little = LittleEndian = :LittleEndian
9
+
10
+ # examines the locale byte order on the running machine
11
+ def byte_order
12
+ if [0x12345678].pack("L") == "\x12\x34\x56\x78"
13
+ BigEndian
14
+ else
15
+ LittleEndian
16
+ end
17
+ end
18
+ alias byteorder byte_order
19
+ module_function :byte_order, :byteorder
20
+
21
+ def little_endian?
22
+ byte_order == LittleEndian
23
+ end
24
+
25
+ def big_endian?
26
+ byte_order == BigEndian
27
+ end
28
+
29
+ alias little? little_endian?
30
+ alias big? big_endian?
31
+ alias network? big_endian?
32
+
33
+ module_function :little_endian?, :little?
34
+ module_function :big_endian?, :big?, :network?
35
+
36
+ end