Module: Gdsii::Read
- Included in:
- Group
- Defined in:
- lib/gdsii/mixins.rb
Overview
This module will be extended into all classes descended of Group (i.e. the high-level GDSII access classes). The extension brings a “read” class method (i.e. singleton) into these classes which enables a GDSII file to be read into these data structures using the BNF specification.
Instance Method Summary collapse
-
#read(file, parent_records = nil, parent_bnf_item = nil, yield_at = nil) {|group| ... } ⇒ Object
Accepts a file handle and reads data from that file handle into an object descended of Group.
Instance Method Details
#read(file, parent_records = nil, parent_bnf_item = nil, yield_at = nil) {|group| ... } ⇒ Object
Accepts a file handle and reads data from that file handle into an object descended of Group. The parent_records and parent_bnf_item arguments are for internal use only.
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/gdsii/mixins.rb', line 288 def read(file, parent_records=nil, parent_bnf_item=nil, yield_at=nil) # Set BNF index at 0, get the BNF items, create an empty grouping object i = 0 bnf_items = bnf_spec.bnf_items group = self.new # puts "#{self}" # Loop through the BNF spec for this grouping... while i < bnf_items.length do bnf_item = bnf_items[i] # see what kind of a BNF item this is - a Class or a record type (Fixnum) if bnf_item.key.class == Class # return if stop_at_class is set to true (used internally for # Library#read_header and Cell#read_header). yield group if yield_at == :before_group # Determine the class to use klass = bnf_item.key # Read from the class if bnf_item.multiple? if (rec = klass.read(file, group.records, bnf_item)) # if a record was returned, then add it group.records.add(bnf_item.key, rec) else # if nil was returned, then we're done with the record; next i += 1 end else # If the record is singular, then get it from the class and # increment the counter rec = klass.read(file, group.records, bnf_item) group.records.set(bnf_item.key, rec) i += 1 end else # ELSE, a record type is expected (Fixnum) rec = Record.read(file) # puts " --> expect #{Gdsii::grt_name(bnf_item.key)}; rec == #{rec.name}" if rec.type == bnf_item.key # This record matches the grouping BNF item that was expected, so # store the data if bnf_item.multiple? group.records.add(bnf_item.key, rec) else group.records.set(bnf_item.key, rec) i += 1 end else # Record does not match expected record as per BNF. Check that we # have data already set in this record or that the record is # optional. if group.records.has_data?(bnf_item.key) or bnf_item.optional? # Already has data - just move to the next record and reset file # pointer i += 1 file.seek(-rec.byte_size, IO::SEEK_CUR) elsif (parent_bnf_item and parent_bnf_item.key.class == Class and (parent_records.has_data?(parent_bnf_item.key) or parent_bnf_item.optional?)) # OK, in this case, we are descended into a Class and did not # match the BNF expected. Furthermore, the parent calling this # grouping either already got the data needed or this was an # optional class in the first place. In either case, we're OK # and just need to get out - which is what we do by returning # nil. file.seek(-rec.byte_size, IO::SEEK_CUR) return nil else # Does not match the expected BNF... fail raise "Unexpected record while reading GDSII file starting at file position #{file.pos-rec.byte_size}\n" + "This record is in the wrong place according to the GDSII specification (from BNF)\n" + "Expected record was #{Gdsii::grt_name(bnf_item.key)}; instead, received:\n" + "Record type = #{Gdsii::grt_name(rec.type)}\n" + "Data type = #{Gdsii::gdt_name(rec.data.type)}\n" + "Record length = #{rec.byte_size}\n" end end end end # Return this record grouping yield group if yield_at == :group group end |