ruby-gdsii 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.txt +113 -0
- data/bin/rgds-debug +43 -0
- data/bin/rgds-dump +38 -0
- data/bin/rgds-join +98 -0
- data/bin/rgds-layers +53 -0
- data/bin/rgds-sremove +135 -0
- data/bin/rgds-ssplit +113 -0
- data/bin/rgds-stats +134 -0
- data/bin/rgds-structs +41 -0
- data/bin/rgds-tree +166 -0
- data/bin/rgds2rb +99 -0
- data/lib/gdsii.rb +137 -0
- data/lib/gdsii/aref.rb +243 -0
- data/lib/gdsii/bnf.rb +309 -0
- data/lib/gdsii/boundary.rb +53 -0
- data/lib/gdsii/box.rb +65 -0
- data/lib/gdsii/byte_order.rb +36 -0
- data/lib/gdsii/element.rb +172 -0
- data/lib/gdsii/group.rb +98 -0
- data/lib/gdsii/library.rb +518 -0
- data/lib/gdsii/mixins.rb +378 -0
- data/lib/gdsii/node.rb +65 -0
- data/lib/gdsii/path.rb +169 -0
- data/lib/gdsii/property.rb +108 -0
- data/lib/gdsii/record.rb +606 -0
- data/lib/gdsii/record/consts.rb +384 -0
- data/lib/gdsii/record/datatypes/ascii.rb +145 -0
- data/lib/gdsii/record/datatypes/bitarray.rb +101 -0
- data/lib/gdsii/record/datatypes/data.rb +111 -0
- data/lib/gdsii/record/datatypes/int2.rb +67 -0
- data/lib/gdsii/record/datatypes/int4.rb +65 -0
- data/lib/gdsii/record/datatypes/nodata.rb +60 -0
- data/lib/gdsii/record/datatypes/real4.rb +51 -0
- data/lib/gdsii/record/datatypes/real8.rb +120 -0
- data/lib/gdsii/sref.rb +61 -0
- data/lib/gdsii/strans.rb +133 -0
- data/lib/gdsii/structure.rb +352 -0
- data/lib/gdsii/text.rb +203 -0
- data/pkg/ruby-gdsii.gem +23 -0
- data/samples/hello.gds +0 -0
- data/samples/hello.out.rb +84 -0
- data/samples/hello.rb +94 -0
- data/test/baseline/dcp1.gds +0 -0
- data/test/baseline/h_write.gds +0 -0
- data/test/h_pthru.rb +22 -0
- data/test/h_write.rb +117 -0
- data/test/hs_pthru.rb +31 -0
- data/test/l_pthru.rb +23 -0
- data/test/test_gds_group.rb +379 -0
- data/test/test_gds_record.rb +99 -0
- metadata +118 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'gdsii/record/datatypes/data.rb'
|
2
|
+
|
3
|
+
module Gdsii
|
4
|
+
|
5
|
+
module RecData
|
6
|
+
|
7
|
+
#
|
8
|
+
# Class for BITARRAY data type
|
9
|
+
#
|
10
|
+
class BitArray < Data
|
11
|
+
|
12
|
+
# Value is an array of 16-bit integers which represent the bit array.
|
13
|
+
# To get a String of the bit array represented as an array of strings
|
14
|
+
# madeup of 16 1's and 0's consider using the #to_s_a or #to_s methods.
|
15
|
+
attr_reader :value
|
16
|
+
|
17
|
+
# Construct an Gdsii::RecData::BitArray data object. The value is an
|
18
|
+
# array of 16-bit integers representing the bit array. Examples:
|
19
|
+
#
|
20
|
+
# record = Gdsii::RecData::BitArray.new([1234])
|
21
|
+
# record.value.inspect #=> [1234]
|
22
|
+
#
|
23
|
+
# Or alternatively to initialize with an array of strings madeup of 16
|
24
|
+
# 1's and 0's, use Gdsii::RecData::BitArray.s_a_to_i_a:
|
25
|
+
#
|
26
|
+
# arr = Gdsii::RecData::BitArray.s_a_to_i_a(["0000010011010010"])
|
27
|
+
# record = Gdsii::RecData::BitArray.new(arr)
|
28
|
+
# record.value.inspect #=> [1234]
|
29
|
+
#
|
30
|
+
def initialize(value)
|
31
|
+
super(GDT_BITARRAY, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set the value for this object; verify that the value items are of
|
35
|
+
# type Fixnum (or at least can be coerced using "to_i").
|
36
|
+
def value=(value)
|
37
|
+
@value = Data.coerce_value(value, Integer, :to_i)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the size of the record *data* in bytes. Each array element
|
41
|
+
# consumes 2 bytes.
|
42
|
+
def byte_size()
|
43
|
+
@value.length * 2
|
44
|
+
end
|
45
|
+
|
46
|
+
# Reads a BITARRAY record from the given file and for the length of bytes
|
47
|
+
# given and returns a new Gdsii::RecData::BitArray object.
|
48
|
+
def BitArray.read(file, byte_count)
|
49
|
+
raw = file.read(byte_count)
|
50
|
+
data = raw.unpack("n")
|
51
|
+
BitArray.new(data)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Writes the integer values representing the bit array in this
|
55
|
+
# Gdsii::RecData::BitArray object to the given file as a GDSII BITARRAY
|
56
|
+
# record.
|
57
|
+
def write(file)
|
58
|
+
file.write @value.pack("n")
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Returns an array containing string representations for each of the
|
63
|
+
# 16-bit integers in the value. Example:
|
64
|
+
#
|
65
|
+
# record = Gdsii::RecData::BitArray.new([1234, 9876])
|
66
|
+
# record.to_s_a.inspect #=> ["0000010011010010", "0010011010010100"]
|
67
|
+
#
|
68
|
+
def to_s_a()
|
69
|
+
@value.map {|string| [string].pack("n").unpack("B16")[0]}
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Returns a string containing string representations for each of the
|
74
|
+
# 16-bit integers in the value joined by spaces. Example:
|
75
|
+
#
|
76
|
+
# record = Gdsii::RecData::BitArray.new([1234, 9876])
|
77
|
+
# record.to_s.inspect #=> "0000010011010010 0010011010010100"
|
78
|
+
#
|
79
|
+
def to_s()
|
80
|
+
to_s_a.join(' ')
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Converts an array of strings at 16 characters in length using 1's and
|
85
|
+
# 0's to an array of respective integer values.
|
86
|
+
#
|
87
|
+
# arr = Gdsii::RecData::BitArray.s_a_to_i_a(["0000010011010010"])
|
88
|
+
# arr.inspect #=> [1234]
|
89
|
+
#
|
90
|
+
# Also see #new for an example used in object construction.
|
91
|
+
#
|
92
|
+
def BitArray.s_a_to_i_a(value)
|
93
|
+
string_arr = Data.coerce_value(value, String, :to_s)
|
94
|
+
string_arr.map {|string| [string].pack("B16").unpack("n")[0]}
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
module Gdsii
|
3
|
+
|
4
|
+
module RecData
|
5
|
+
|
6
|
+
#
|
7
|
+
# Generic class to represent various record data types. This class is
|
8
|
+
# intended to be inherited and not called directly.
|
9
|
+
#
|
10
|
+
class Data
|
11
|
+
|
12
|
+
# Data type integer represented by one of the Gdsii::GDT_ constants.
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
# Pointer to the parent record object
|
16
|
+
attr_reader :record
|
17
|
+
|
18
|
+
#
|
19
|
+
# Create a generic record data object. Intended to be called internally
|
20
|
+
# by Gdsii::RecType classes - not intended to be called directly.
|
21
|
+
#
|
22
|
+
def initialize(type, value, record=nil)
|
23
|
+
if Data.valid_type?(type)
|
24
|
+
@type = type
|
25
|
+
else
|
26
|
+
raise TypeError,
|
27
|
+
"Invalid data type specified: #{type}"
|
28
|
+
end
|
29
|
+
@record = record
|
30
|
+
self.value = value
|
31
|
+
end
|
32
|
+
|
33
|
+
# Quick access to the data value array. Equivalent to self.value[index].
|
34
|
+
def [](index); @value[index]; end
|
35
|
+
|
36
|
+
# Check that the given data type (as an integer) is valid as defined by
|
37
|
+
# the Gdsii::DATATYPE_INFO array.
|
38
|
+
def Data.valid_type?(type)
|
39
|
+
(0...DATATYPE_INFO.length).member?(type)
|
40
|
+
end
|
41
|
+
|
42
|
+
########################################################################
|
43
|
+
# DATA TYPE SHORTCUTS
|
44
|
+
########################################################################
|
45
|
+
|
46
|
+
# Returns true if this record is an ASCII data type, false if not
|
47
|
+
def is_ascii?(); @type == GDT_ASCII; end
|
48
|
+
|
49
|
+
# Returns true if this record is an INT2 data type, false if not
|
50
|
+
def is_int2?(); @type == GDT_INT2; end
|
51
|
+
|
52
|
+
# Returns true if this record is an INT4 data type, false if not
|
53
|
+
def is_int4?(); @type == GDT_INT4; end
|
54
|
+
|
55
|
+
# Returns true if this record is a REAL8 data type, false if not
|
56
|
+
def is_real8?(); @type == GDT_REAL8; end
|
57
|
+
|
58
|
+
# Returns true if this record is a BITARRAY data type, false if not
|
59
|
+
def is_bitarray?(); @type == GDT_BITARRAY; end
|
60
|
+
|
61
|
+
# Returns true if this record is a NO_DATA data type, false if not
|
62
|
+
def is_no_data?(); @type == GDT_NO_DATA; end
|
63
|
+
|
64
|
+
# Returns true if this record is a REAL4 data type, false if not
|
65
|
+
def is_real4?(); @type == GDT_REAL4; end
|
66
|
+
|
67
|
+
|
68
|
+
########################################################################
|
69
|
+
# PROTECTED METHODS (private to this class)
|
70
|
+
########################################################################
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Check the class for the given datum (single data element, NOT an array)
|
75
|
+
# and raises an exception if the datum does not match the given class.
|
76
|
+
def Data.ensure_class(datum, klass)
|
77
|
+
unless datum.kind_of?(klass)
|
78
|
+
raise TypeError,
|
79
|
+
"#{self.class.to_s} value must be descended from #{klass}; given: '#{datum.class}'"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Ensures that the given value is descended from the Array class. If
|
84
|
+
# not, then an InvalidValue exception is raised.
|
85
|
+
def Data.ensure_array(value)
|
86
|
+
unless value.kind_of?(Array)
|
87
|
+
raise TypeError,
|
88
|
+
"All data must be descended from Array class; given: #{value.class}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Generic method for setting a value. The classes that inherit from
|
93
|
+
# this class use this to coerce and validate their value.
|
94
|
+
def Data.coerce_value(value, klass, coerce_method)
|
95
|
+
Data.ensure_array value
|
96
|
+
value.each_with_index do |datum, i|
|
97
|
+
# Make sure that it matches the class; if not, try to coerce
|
98
|
+
unless datum.kind_of?(klass)
|
99
|
+
if datum.respond_to?(coerce_method) then
|
100
|
+
the_method = datum.method(coerce_method)
|
101
|
+
value[i] = the_method.call
|
102
|
+
end
|
103
|
+
Data.ensure_class(value[i], klass)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
value
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'gdsii/record/datatypes/data.rb'
|
2
|
+
require 'gdsii/byte_order.rb'
|
3
|
+
|
4
|
+
module Gdsii
|
5
|
+
|
6
|
+
module RecData
|
7
|
+
|
8
|
+
#
|
9
|
+
# Store a GDSII INT2 data type
|
10
|
+
#
|
11
|
+
class Int2 < Data
|
12
|
+
|
13
|
+
# Value is an array of integers.
|
14
|
+
attr_reader :value
|
15
|
+
|
16
|
+
# Construct an Gdsii::RecData::Int2 data object. The value is an array
|
17
|
+
# of integers (Fixnum).
|
18
|
+
def initialize(value)
|
19
|
+
super(GDT_INT2, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set the value for this object; verify that the value items are of
|
23
|
+
# type Fixnum (or at least can be coerced using "to_i").
|
24
|
+
def value=(value)
|
25
|
+
@value = Data.coerce_value(value, Fixnum, :to_i)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the size of the record *data* in bytes. Each array element
|
29
|
+
# consumes 2 bytes (hence INT2).
|
30
|
+
def byte_size()
|
31
|
+
@value.length * 2
|
32
|
+
end
|
33
|
+
|
34
|
+
# Reads an INT2 record from the given file and for the length of bytes
|
35
|
+
# given and returns a new Gdsii::RecData::Int2 object.
|
36
|
+
def Int2.read(file, byte_count)
|
37
|
+
data = []
|
38
|
+
while (byte_count > 0)
|
39
|
+
raw = file.read(2)
|
40
|
+
raw.reverse! if (ByteOrder::little_endian?)
|
41
|
+
data.push raw.unpack('s')[0]
|
42
|
+
byte_count -= 2
|
43
|
+
end
|
44
|
+
Int2.new(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Writes the integer values in this Gdsii::RecData::Int2 object to the
|
48
|
+
# given file as a GDSII INT2 record.
|
49
|
+
def write(file)
|
50
|
+
value.each do |item|
|
51
|
+
# always write int2 as network order (as per GDSII spec)
|
52
|
+
file.write [item].pack('n')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Converts the array of integer values to a string (values are joined by
|
57
|
+
# spaces).
|
58
|
+
def to_s()
|
59
|
+
value.map {|v| v.to_s}.join(' ')
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'gdsii/record/datatypes/data.rb'
|
2
|
+
require 'gdsii/byte_order.rb'
|
3
|
+
|
4
|
+
module Gdsii
|
5
|
+
|
6
|
+
module RecData
|
7
|
+
|
8
|
+
#
|
9
|
+
# Class for INT4 data type
|
10
|
+
#
|
11
|
+
class Int4 < Data
|
12
|
+
|
13
|
+
# Value is an array of integers.
|
14
|
+
attr_reader :value
|
15
|
+
|
16
|
+
# Construct an Gdsii::RecData::Int4 data object. The value is an array
|
17
|
+
# of integers (Fixnum).
|
18
|
+
def initialize(value)
|
19
|
+
super(GDT_INT4, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set the value for this object; verify that the value items are of
|
23
|
+
# type Fixnum (or at least can be coerced using "to_i").
|
24
|
+
def value=(value)
|
25
|
+
@value = Data.coerce_value(value, Fixnum, :to_i)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the size of the record *data* in bytes. Each array element
|
29
|
+
# consumes 4 bytes (hence INT4).
|
30
|
+
def byte_size()
|
31
|
+
@value.length * 4
|
32
|
+
end
|
33
|
+
|
34
|
+
# Reads an INT4 record from the given file and for the length of bytes
|
35
|
+
# given and returns a new Gdsii::RecData::Int4 object.
|
36
|
+
def Int4.read(file, byte_count)
|
37
|
+
data = []
|
38
|
+
while (byte_count > 0)
|
39
|
+
raw = file.read(4)
|
40
|
+
raw.reverse! if (ByteOrder::little_endian?)
|
41
|
+
data.push raw.unpack('i')[0]
|
42
|
+
byte_count -= 4
|
43
|
+
end
|
44
|
+
Int4.new(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Writes the integer values in this Gdsii::RecData::Int2 object to the
|
48
|
+
# given file as a GDSII INT4 record.
|
49
|
+
def write(file)
|
50
|
+
value.each do |item|
|
51
|
+
# always write int4 in network order (as per GDSII spec)
|
52
|
+
file.write [item].pack('N')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Converts the array of integer values to a string (values are joined by
|
57
|
+
# spaces).
|
58
|
+
def to_s()
|
59
|
+
value.map {|v| v.to_s}.join(' ')
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'gdsii/record/datatypes/data.rb'
|
2
|
+
|
3
|
+
module Gdsii
|
4
|
+
|
5
|
+
module RecData
|
6
|
+
|
7
|
+
#
|
8
|
+
# Store a GDSII NODATA data type. This data type has no value.
|
9
|
+
#
|
10
|
+
class NoData < Data
|
11
|
+
|
12
|
+
# Value will always be an empty array for a Gdsii::RecData::NoData object
|
13
|
+
attr_reader :value
|
14
|
+
|
15
|
+
# Construct an NoData data object. No value is given because there
|
16
|
+
# isn't a value for Gdsii::RecData::NoData.
|
17
|
+
def initialize()
|
18
|
+
super(GDT_NO_DATA, [])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Throws an exception unless an empty arra is passed because there is
|
22
|
+
# no data associated with a Gdsii::RecData::NoData object.
|
23
|
+
def value=(value=[])
|
24
|
+
Data.ensure_array value
|
25
|
+
unless value.empty?
|
26
|
+
raise ArgumentError,
|
27
|
+
"GDT_NO_DATA must have an empty array; given length: #{value.length}"
|
28
|
+
end
|
29
|
+
@value = value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the size of the record *data* in bytes. Since a
|
33
|
+
# Gdsii::RecData::NoData object has no data, 0 is always returned.
|
34
|
+
def byte_size(); 0; end
|
35
|
+
|
36
|
+
# Reads a NO_DATA record from the given file object and returns a
|
37
|
+
# new Gdsii::RecData::NoData object.
|
38
|
+
def NoData.read(file, byte_count=0)
|
39
|
+
# validate byte count
|
40
|
+
if byte_count > 0 then
|
41
|
+
raise ArgumentError,
|
42
|
+
"GDT_NO_DATA expects 0 bytes of record length; requested: #{byte_count}"
|
43
|
+
end
|
44
|
+
NoData.new()
|
45
|
+
end
|
46
|
+
|
47
|
+
# Performs no operation since there is no data in a Gdsii::RecType::NoData
|
48
|
+
# object to write to a file. However this method is necessary so that
|
49
|
+
# it can respond to methods common to other Gdsii::RecType::Data
|
50
|
+
# descended classes.
|
51
|
+
def write(file); end
|
52
|
+
|
53
|
+
# Returns an empty string (which represents no data).
|
54
|
+
def to_s(); ''; end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'gdsii/record/datatypes/data.rb'
|
2
|
+
|
3
|
+
module Gdsii
|
4
|
+
|
5
|
+
module RecData
|
6
|
+
|
7
|
+
#
|
8
|
+
# Class for REAL4 data type (UNSUPPORTED - will raise an exception)
|
9
|
+
#
|
10
|
+
class Real4 < Data
|
11
|
+
|
12
|
+
# Value is an array of floating point numbers
|
13
|
+
attr_reader :value
|
14
|
+
|
15
|
+
# Will raise an exception immediately as REAL4 is not supported in the
|
16
|
+
# GDSII specification.
|
17
|
+
def initialize(value)
|
18
|
+
raise "GDT_REAL4 is unsupported"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Raises an TypeError exception as REAL4 is not supported
|
22
|
+
def value=(value)
|
23
|
+
raise "GDT_REAL4 is unsupported"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the size of the record *data* in bytes. Each array element
|
27
|
+
# consumes 4 bytes (hence REAL4).
|
28
|
+
def byte_size()
|
29
|
+
@value.length * 4
|
30
|
+
end
|
31
|
+
|
32
|
+
# just create the Gdsii::RecData::Real4 object and raise the exception
|
33
|
+
def Real4.read(file, byte_count)
|
34
|
+
Real4.new([0])
|
35
|
+
end
|
36
|
+
|
37
|
+
# Raises an exception since REAL4 is unsupported
|
38
|
+
def write(file)
|
39
|
+
raise "GDT_REAL4 is unsupported"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Converts the array of floating point values to a string (values are
|
43
|
+
# joined by spaces).
|
44
|
+
def to_s()
|
45
|
+
value.map {|v| v.to_s}.join(' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|