CooCoo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/CooCoo.gemspec +47 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +88 -0
- data/README.md +123 -0
- data/Rakefile +81 -0
- data/bin/cuda-dev-info +25 -0
- data/bin/cuda-free +28 -0
- data/bin/cuda-free-trend +7 -0
- data/bin/ffi-gen +267 -0
- data/bin/spec_runner_html.sh +42 -0
- data/bin/trainer +198 -0
- data/bin/trend-cost +13 -0
- data/examples/char-rnn.rb +405 -0
- data/examples/cifar/cifar.rb +94 -0
- data/examples/img-similarity.rb +201 -0
- data/examples/math_ops.rb +57 -0
- data/examples/mnist.rb +365 -0
- data/examples/mnist_classifier.rb +293 -0
- data/examples/mnist_dream.rb +214 -0
- data/examples/seeds.rb +268 -0
- data/examples/seeds_dataset.txt +210 -0
- data/examples/t10k-images-idx3-ubyte +0 -0
- data/examples/t10k-labels-idx1-ubyte +0 -0
- data/examples/train-images-idx3-ubyte +0 -0
- data/examples/train-labels-idx1-ubyte +0 -0
- data/ext/buffer/Rakefile +50 -0
- data/ext/buffer/buffer.pre.cu +727 -0
- data/ext/buffer/matrix.pre.cu +49 -0
- data/lib/CooCoo.rb +1 -0
- data/lib/coo-coo.rb +18 -0
- data/lib/coo-coo/activation_functions.rb +344 -0
- data/lib/coo-coo/consts.rb +5 -0
- data/lib/coo-coo/convolution.rb +298 -0
- data/lib/coo-coo/core_ext.rb +75 -0
- data/lib/coo-coo/cost_functions.rb +91 -0
- data/lib/coo-coo/cuda.rb +116 -0
- data/lib/coo-coo/cuda/device_buffer.rb +240 -0
- data/lib/coo-coo/cuda/device_buffer/ffi.rb +109 -0
- data/lib/coo-coo/cuda/error.rb +51 -0
- data/lib/coo-coo/cuda/host_buffer.rb +117 -0
- data/lib/coo-coo/cuda/runtime.rb +157 -0
- data/lib/coo-coo/cuda/vector.rb +315 -0
- data/lib/coo-coo/data_sources.rb +2 -0
- data/lib/coo-coo/data_sources/xournal.rb +25 -0
- data/lib/coo-coo/data_sources/xournal/bitmap_stream.rb +197 -0
- data/lib/coo-coo/data_sources/xournal/document.rb +377 -0
- data/lib/coo-coo/data_sources/xournal/loader.rb +144 -0
- data/lib/coo-coo/data_sources/xournal/renderer.rb +101 -0
- data/lib/coo-coo/data_sources/xournal/saver.rb +99 -0
- data/lib/coo-coo/data_sources/xournal/training_document.rb +78 -0
- data/lib/coo-coo/data_sources/xournal/training_document/constants.rb +15 -0
- data/lib/coo-coo/data_sources/xournal/training_document/document_maker.rb +89 -0
- data/lib/coo-coo/data_sources/xournal/training_document/document_reader.rb +105 -0
- data/lib/coo-coo/data_sources/xournal/training_document/example.rb +37 -0
- data/lib/coo-coo/data_sources/xournal/training_document/sets.rb +76 -0
- data/lib/coo-coo/debug.rb +8 -0
- data/lib/coo-coo/dot.rb +129 -0
- data/lib/coo-coo/drawing.rb +4 -0
- data/lib/coo-coo/drawing/cairo_canvas.rb +100 -0
- data/lib/coo-coo/drawing/canvas.rb +68 -0
- data/lib/coo-coo/drawing/chunky_canvas.rb +101 -0
- data/lib/coo-coo/drawing/sixel.rb +214 -0
- data/lib/coo-coo/enum.rb +17 -0
- data/lib/coo-coo/from_name.rb +58 -0
- data/lib/coo-coo/fully_connected_layer.rb +205 -0
- data/lib/coo-coo/generation_script.rb +38 -0
- data/lib/coo-coo/grapher.rb +140 -0
- data/lib/coo-coo/image.rb +286 -0
- data/lib/coo-coo/layer.rb +67 -0
- data/lib/coo-coo/layer_factory.rb +26 -0
- data/lib/coo-coo/linear_layer.rb +59 -0
- data/lib/coo-coo/math.rb +607 -0
- data/lib/coo-coo/math/abstract_vector.rb +121 -0
- data/lib/coo-coo/math/functions.rb +39 -0
- data/lib/coo-coo/math/interpolation.rb +7 -0
- data/lib/coo-coo/network.rb +264 -0
- data/lib/coo-coo/neuron.rb +112 -0
- data/lib/coo-coo/neuron_layer.rb +168 -0
- data/lib/coo-coo/option_parser.rb +18 -0
- data/lib/coo-coo/platform.rb +17 -0
- data/lib/coo-coo/progress_bar.rb +11 -0
- data/lib/coo-coo/recurrence/backend.rb +99 -0
- data/lib/coo-coo/recurrence/frontend.rb +101 -0
- data/lib/coo-coo/sequence.rb +187 -0
- data/lib/coo-coo/shell.rb +2 -0
- data/lib/coo-coo/temporal_network.rb +291 -0
- data/lib/coo-coo/trainer.rb +21 -0
- data/lib/coo-coo/trainer/base.rb +67 -0
- data/lib/coo-coo/trainer/batch.rb +82 -0
- data/lib/coo-coo/trainer/batch_stats.rb +27 -0
- data/lib/coo-coo/trainer/momentum_stochastic.rb +59 -0
- data/lib/coo-coo/trainer/stochastic.rb +47 -0
- data/lib/coo-coo/transformer.rb +272 -0
- data/lib/coo-coo/vector_layer.rb +194 -0
- data/lib/coo-coo/version.rb +3 -0
- data/lib/coo-coo/weight_deltas.rb +23 -0
- data/prototypes/convolution.rb +116 -0
- data/prototypes/linear_drop.rb +51 -0
- data/prototypes/recurrent_layers.rb +79 -0
- data/www/images/screamer.png +0 -0
- data/www/images/screamer.xcf +0 -0
- data/www/index.html +82 -0
- metadata +373 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
require 'coo-coo/math'
|
3
|
+
|
4
|
+
module CooCoo
|
5
|
+
module Drawing
|
6
|
+
class Canvas
|
7
|
+
attr_accessor :fill_color, :stroke_color
|
8
|
+
|
9
|
+
def fill_color=(c)
|
10
|
+
@fill_color = ChunkyPNG::Color.parse(c)
|
11
|
+
end
|
12
|
+
|
13
|
+
def stroke_color=(c)
|
14
|
+
@stroke_color = ChunkyPNG::Color.parse(c)
|
15
|
+
end
|
16
|
+
|
17
|
+
def flush
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def line(x1, y1, x2, y2)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def stroke(points)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def rect(x, y, w, h)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def circle(x, y, r)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def blit(img, x, y)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def text(txt, x, y, font, size, style = nil)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def color_components(c)
|
47
|
+
[ ChunkyPNG::Color.r(c),
|
48
|
+
ChunkyPNG::Color.g(c),
|
49
|
+
ChunkyPNG::Color.b(c)
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_grayscale(c)
|
54
|
+
ChunkyPNG::Color.r(ChunkyPNG::Color.to_grayscale(c))
|
55
|
+
end
|
56
|
+
|
57
|
+
def chunky_to_vector(img, grayscale)
|
58
|
+
f = if grayscale
|
59
|
+
method(:to_grayscale)
|
60
|
+
else
|
61
|
+
method(:color_components)
|
62
|
+
end
|
63
|
+
|
64
|
+
Vector[img.pixels.collect(&f).flatten]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
require 'coo-coo/math'
|
3
|
+
|
4
|
+
module CooCoo
|
5
|
+
module Drawing
|
6
|
+
class ChunkyCanvas < Canvas
|
7
|
+
attr_reader :image
|
8
|
+
|
9
|
+
def initialize(img_or_width, height = nil)
|
10
|
+
if height
|
11
|
+
img = ChunkyPNG::Image.new(img_or_width, height)
|
12
|
+
else
|
13
|
+
img = img_or_width
|
14
|
+
end
|
15
|
+
|
16
|
+
@image = img
|
17
|
+
end
|
18
|
+
|
19
|
+
def line(x1, y1, x2, y2)
|
20
|
+
@image.line(x1, y1, x2, y2, stroke_color)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def stroke(points)
|
25
|
+
last_x = points[0][0]
|
26
|
+
last_y = points[0][1]
|
27
|
+
last_w = points[0][2] || 1.0
|
28
|
+
last_color = points[0][3]
|
29
|
+
|
30
|
+
points.each.drop(1).each do |(x, y, w, color)|
|
31
|
+
w ||= 1.0
|
32
|
+
|
33
|
+
if color
|
34
|
+
self.stroke_color = color
|
35
|
+
self.fill_color = color
|
36
|
+
end
|
37
|
+
|
38
|
+
if w <= 1.0
|
39
|
+
line(last_x.to_i, last_y.to_i, x.to_i, y.to_i)
|
40
|
+
else
|
41
|
+
step_x = (x / w).abs.round
|
42
|
+
step_y = (y / w).abs.round
|
43
|
+
steps = Math.max(step_x, step_y)
|
44
|
+
steps = 4.0 if steps < 4.0
|
45
|
+
|
46
|
+
(steps + 1).to_i.times do |n|
|
47
|
+
t = n / steps.to_f
|
48
|
+
if color
|
49
|
+
self.stroke_color = lerp_color(last_color, color, t)
|
50
|
+
self.fill_color = lerp_color(last_color, color, t)
|
51
|
+
end
|
52
|
+
|
53
|
+
circle(Math.lerp(last_x, x, t).to_i,
|
54
|
+
Math.lerp(last_y, y, t).to_i,
|
55
|
+
(Math.lerp(last_w, w, t)/2.0).ceil.to_i)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
last_x = x
|
60
|
+
last_y = y
|
61
|
+
last_w = w
|
62
|
+
last_color = color
|
63
|
+
end
|
64
|
+
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def lerp_color(a, b, t)
|
69
|
+
ChunkyPNG::Color.interpolate_quick(a, b, (t * 256).to_i)
|
70
|
+
end
|
71
|
+
|
72
|
+
def rect(x, y, w, h)
|
73
|
+
@image.rect(x, y, w, h, stroke_color, fill_color)
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def circle(x, y, r)
|
78
|
+
@image.circle(x, y, r, stroke_color, fill_color)
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def blit(other, x, y, w, h)
|
83
|
+
img = ChunkyPNG::Image.from_blob(other)
|
84
|
+
if w != img.width || h != img.height
|
85
|
+
img.resample_bilinear!(w.to_i, h.to_i)
|
86
|
+
end
|
87
|
+
@image.compose!(img, x.to_i, y.to_i)
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
def text(txt, x, y, font, font_size, font_style = nil)
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_vector(grayscale = false)
|
96
|
+
chunky_to_vector(@image, grayscale)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module CooCoo
|
4
|
+
module Drawing
|
5
|
+
module Sixel
|
6
|
+
def self.from_array(a, width, height = nil)
|
7
|
+
s = Stringer.new
|
8
|
+
s.begin_sixel + s.from_array(a, width, height) + s.newline + s.finish_sixel
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.with_sixel(io = $stdout, &block)
|
12
|
+
Streamer.new(io) do |s|
|
13
|
+
block.call(s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.to_string(&block)
|
18
|
+
stream = StringIO.new
|
19
|
+
Streamer.new(stream, &block)
|
20
|
+
stream.string
|
21
|
+
end
|
22
|
+
|
23
|
+
class Streamer
|
24
|
+
def initialize(io = $stdout, stringer = Stringer.new, &block)
|
25
|
+
@io = io
|
26
|
+
@stringer = stringer
|
27
|
+
with_sixel(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(mid, *args, &block)
|
31
|
+
@io.write(@stringer.send(mid, *args, &block))
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_sixel(&block)
|
35
|
+
begin_sixel
|
36
|
+
block.call(self)
|
37
|
+
ensure
|
38
|
+
finish_sixel
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Stringer
|
43
|
+
RGB = Struct.new(:r, :g, :b)
|
44
|
+
HSL = Struct.new(:h, :s, :l)
|
45
|
+
|
46
|
+
def initialize(options = Hash.new)
|
47
|
+
@max_colors = options.fetch(:max_colors, 256)
|
48
|
+
@colors = Array.new(@max_colors)
|
49
|
+
@background = options.fetch(:background, 0)
|
50
|
+
end
|
51
|
+
|
52
|
+
def from_array(a, width, height = nil)
|
53
|
+
height ||= (a.size / width.to_f).ceil
|
54
|
+
max_color = a.max.ceil
|
55
|
+
|
56
|
+
(height / 6.0).ceil.times.collect do |y|
|
57
|
+
(max_color + 1).times.collect do |c|
|
58
|
+
#next if c == 0
|
59
|
+
in_color(c) + width.times.collect do |x|
|
60
|
+
sixel_line(c, *6.times.collect { |i|
|
61
|
+
a[(y*6+i) * width + x] rescue @background
|
62
|
+
})
|
63
|
+
end.join
|
64
|
+
end.join(cr)
|
65
|
+
end.join(newline)
|
66
|
+
end
|
67
|
+
|
68
|
+
def sixel_line(c, *pixels)
|
69
|
+
line = 6.times.inject(0) { |acc, i|
|
70
|
+
if pixels[i].to_i == c
|
71
|
+
(acc | (1 << i))
|
72
|
+
else
|
73
|
+
acc
|
74
|
+
end
|
75
|
+
}
|
76
|
+
[ 63 + line ].pack('c')
|
77
|
+
end
|
78
|
+
|
79
|
+
def move_to(x, y)
|
80
|
+
finish_sixel + "\e[#{y.to_i};#{x.to_i}H" + begin_sixel
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_color(c, r, g, b)
|
84
|
+
@colors[c] = RGB.new(r, g, b)
|
85
|
+
emit_color(c)
|
86
|
+
end
|
87
|
+
|
88
|
+
def set_color_hsl(c, h, s, l)
|
89
|
+
@colors[c] = HSL.new(h, s, l)
|
90
|
+
emit_color(c)
|
91
|
+
end
|
92
|
+
|
93
|
+
def emit_color(n, c = nil)
|
94
|
+
case c
|
95
|
+
when RGB then "\##{n.to_i};2;#{c.r.to_i};#{c.g.to_i};#{c.b.to_i}"
|
96
|
+
when HSL then "\##{n.to_i};1;#{c.h.to_i};#{c.s.to_i};#{c.l.to_i}"
|
97
|
+
else @colors[n] && emit_color(n, @colors[n])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def emit_all_colors
|
102
|
+
@colors.each.with_index.collect do |c, i|
|
103
|
+
emit_color(i, c) if c
|
104
|
+
end.join
|
105
|
+
end
|
106
|
+
|
107
|
+
def in_color(c)
|
108
|
+
"\##{c}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def start_sixel
|
112
|
+
"\ePq"
|
113
|
+
end
|
114
|
+
|
115
|
+
def begin_sixel
|
116
|
+
start_sixel + emit_all_colors
|
117
|
+
end
|
118
|
+
|
119
|
+
def finish_sixel
|
120
|
+
"\e\\"
|
121
|
+
end
|
122
|
+
|
123
|
+
def cr
|
124
|
+
"$"
|
125
|
+
end
|
126
|
+
|
127
|
+
def lf
|
128
|
+
"-\n"
|
129
|
+
end
|
130
|
+
|
131
|
+
def newline
|
132
|
+
cr + lf
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if __FILE__ == $0
|
140
|
+
require 'coo-coo/math'
|
141
|
+
|
142
|
+
HI = <<-EOT
|
143
|
+
\ePq
|
144
|
+
\#0;2;0;0;0\#1;2;100;0;0\#2;2;0;100;0
|
145
|
+
\#1~~@@vv@@~~@@~~$
|
146
|
+
\#2??}}GG}}??}}??-
|
147
|
+
\#1!14@
|
148
|
+
\e\\
|
149
|
+
EOT
|
150
|
+
|
151
|
+
arr = 100.times.collect { |y|
|
152
|
+
100.times.collect { |x|
|
153
|
+
8 + (8 * (Math.cos(y / 100.0 * 6.28) * Math.sin(x / 100.0 * 6.28))).to_i
|
154
|
+
}
|
155
|
+
}.flatten
|
156
|
+
line = 100.times.collect { |y| 40.times.collect { |i| (i < 2 || i > 37) ? 15 : 0 } }.flatten
|
157
|
+
stringer = CooCoo::Drawing::Sixel::Stringer.new
|
158
|
+
|
159
|
+
puts(HI)
|
160
|
+
|
161
|
+
puts
|
162
|
+
puts("In sixel")
|
163
|
+
puts(stringer.begin_sixel)
|
164
|
+
puts("\#0;2;100;0;0\#1;2;0;100;0\#2;2;0;0;100")
|
165
|
+
16.times {
|
166
|
+
$stdout.write(stringer.sixel_line(1, 1, 1, 0, 0, 1, 1))
|
167
|
+
}
|
168
|
+
puts
|
169
|
+
puts(stringer.sixel_line(1, 0, 0, 1, 1, 0, 0))
|
170
|
+
puts(stringer.sixel_line(1, 0, 0, 1, 1, 0, 0))
|
171
|
+
puts(stringer.sixel_line(2, 1, 1, 2, 2, 1, 1))
|
172
|
+
puts(stringer.sixel_line(2, 1, 1, 2, 2, 1, 1))
|
173
|
+
puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
|
174
|
+
puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
|
175
|
+
puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
|
176
|
+
puts(stringer.finish_sixel)
|
177
|
+
|
178
|
+
puts("And the big one:")
|
179
|
+
puts
|
180
|
+
puts(stringer.begin_sixel)
|
181
|
+
#puts("\#0;2;100;0;0\#1;2;0;100;0\#2;2;0;0;100\#3;2;100,100,100")
|
182
|
+
16.times { |i| puts(stringer.set_color(i, i * 100 / 16.0, i * 100 / 16.0, i * 100 / 16.0)) }
|
183
|
+
# puts(stringer.set_color(0, 100, 0, 0) +
|
184
|
+
# stringer.set_color(1, 0, 100, 0) +
|
185
|
+
# stringer.set_color(2, 0, 0, 100) +
|
186
|
+
# stringer.set_color(3, 100, 100, 100))
|
187
|
+
puts(stringer.from_array(arr, 100, 100))
|
188
|
+
puts(stringer.cr)
|
189
|
+
puts(stringer.from_array(arr.collect { |a| arr.max - a }, 100, 100))
|
190
|
+
puts(stringer.newline)
|
191
|
+
puts(stringer.newline)
|
192
|
+
puts(stringer.from_array(line, 40, 100))
|
193
|
+
puts(stringer.finish_sixel)
|
194
|
+
|
195
|
+
v = CooCoo::Vector.new(28 * 28, 2)
|
196
|
+
CooCoo::Drawing::Sixel.with_sixel do |s|
|
197
|
+
s.set_color(0, 0, 0, 0)
|
198
|
+
s.set_color(1, 100, 0, 0)
|
199
|
+
s.set_color(2, 100, 100, 100)
|
200
|
+
s.set_color(3, 100, 0, 100)
|
201
|
+
s.set_color(3, 50, 50, 50)
|
202
|
+
s.from_array(CooCoo::Vector[64.times] / 16, 64, 1)
|
203
|
+
s.from_array(CooCoo::Vector[64.times] / 16, 1, 64)
|
204
|
+
s.from_array(CooCoo::Vector[64.times] / 16, 8, 8)
|
205
|
+
s.newline
|
206
|
+
s.from_array(v, 28)
|
207
|
+
s.newline
|
208
|
+
s.from_array(CooCoo::Vector.new(28 * 28, 3), 28)
|
209
|
+
s.newline
|
210
|
+
s.from_array(CooCoo::Vector.rand(28 * 28, 4), 28)
|
211
|
+
end
|
212
|
+
|
213
|
+
puts("Good bye.")
|
214
|
+
end
|
data/lib/coo-coo/enum.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'coo-coo/core_ext'
|
2
|
+
|
3
|
+
class Enumerator
|
4
|
+
define_once(:zero) do
|
5
|
+
Array.new(size, self.first.zero)
|
6
|
+
end
|
7
|
+
|
8
|
+
define_once(:sum) do
|
9
|
+
inject(0) do |acc, e|
|
10
|
+
acc += e
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
define_once(:average) do
|
15
|
+
sum / (size || count)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module CooCoo
|
2
|
+
# Adds class methods to register classes that can be instantiated
|
3
|
+
# using strings.
|
4
|
+
#
|
5
|
+
# To get an instance, use {#from_name}.
|
6
|
+
#
|
7
|
+
# To add classes to the registry, call {#register}, preferably
|
8
|
+
# inside the class definition.
|
9
|
+
module FromName
|
10
|
+
# Adds a class to the registry using the given name.
|
11
|
+
# @param klass [Class] the class to instantiate
|
12
|
+
# @param name [String] name to use when calling #from_name
|
13
|
+
# @return [self]
|
14
|
+
def register(klass, name = nil)
|
15
|
+
@klasses ||= Hash.new
|
16
|
+
@klasses[(name || klass.name).split('::').last] = klass
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Array] of names of all the registered classes.
|
21
|
+
def named_classes
|
22
|
+
@klasses.keys.sort
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Enumerator] of all the registered classes.
|
26
|
+
def each(&block)
|
27
|
+
@klasses.each(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns an instance of the class registered with the given name.
|
31
|
+
# @param name [String] Registered name of the class with optional arguments in parenthesis.
|
32
|
+
# @param args Additional arguments to pass to the constructor. Overrides any given in the string.
|
33
|
+
# @return An instance of the registered class.
|
34
|
+
def from_name(name, *args)
|
35
|
+
name, params = parse_name(name)
|
36
|
+
klass = @klasses.fetch(name)
|
37
|
+
params = args unless args == nil || args.empty?
|
38
|
+
|
39
|
+
if params && klass.respond_to?(:new)
|
40
|
+
klass.new(*params)
|
41
|
+
elsif klass.respond_to?(:instance)
|
42
|
+
klass.instance
|
43
|
+
else
|
44
|
+
klass
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def parse_name(name)
|
50
|
+
m = name.match(/(\w+)\((.*)\)/)
|
51
|
+
if m
|
52
|
+
return m[1], m[2].split(',').collect(&:chomp)
|
53
|
+
else
|
54
|
+
return name, nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|