ruby-gdsii 1.0.0
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.
- 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
|