ruby-fizzbuzz 0.7.0 → 0.8.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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +5 -0
- data.tar.gz.sig +0 -0
- data/AUTHORS +1 -1
- data/CHANGELOG.md +175 -0
- data/COPYRIGHT +1 -1
- data/README.md +46 -0
- data/VERSION +1 -1
- data/bin/fizzbuzz +33 -61
- data/ext/fizzbuzz/common.h +39 -29
- data/ext/fizzbuzz/extconf.rb +24 -43
- data/ext/fizzbuzz/fizzbuzz.c +100 -117
- data/ext/fizzbuzz/fizzbuzz.h +60 -118
- data/kwilczynski-public.pem +25 -0
- data/lib/fizzbuzz.rb +106 -40
- data/lib/fizzbuzz/core/array.rb +9 -36
- data/lib/fizzbuzz/core/bignum.rb +9 -38
- data/lib/fizzbuzz/core/integer.rb +9 -38
- data/lib/fizzbuzz/core/range.rb +2 -31
- data/lib/fizzbuzz/version.rb +2 -29
- metadata +51 -24
- metadata.gz.sig +0 -0
- data/CHANGES +0 -84
- data/CHANGES.rdoc +0 -84
- data/README +0 -5
- data/README.rdoc +0 -12
- data/Rakefile +0 -97
- data/TODO +0 -16
- data/benchmark/benchmark_fizzbuzz.rb +0 -107
- data/ruby-fizzbuzz.gemspec +0 -65
- data/test/test_fizzbuzz.rb +0 -639
data/ext/fizzbuzz/extconf.rb
CHANGED
@@ -1,64 +1,48 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# :enddoc:
|
4
|
-
|
5
|
-
#
|
6
|
-
# extconf.rb
|
7
|
-
#
|
8
|
-
# Copyright 2012-2014 Krzysztof Wilczynski
|
9
|
-
#
|
10
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
11
|
-
# you may not use this file except in compliance with the License.
|
12
|
-
# You may obtain a copy of the License at
|
13
|
-
#
|
14
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
15
|
-
#
|
16
|
-
# Unless required by applicable law or agreed to in writing, software
|
17
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
18
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19
|
-
# See the License for the specific language governing permissions and
|
20
|
-
# limitations under the License.
|
21
|
-
#
|
1
|
+
# frozen_string_literal: true
|
22
2
|
|
23
3
|
require 'mkmf'
|
24
4
|
|
25
5
|
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
26
6
|
|
27
|
-
$CFLAGS << ' -std=c99 -
|
7
|
+
$CFLAGS << ' -std=c99 -Wall -Wextra -pedantic'
|
28
8
|
|
29
|
-
|
9
|
+
if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
|
10
|
+
$CFLAGS << ' -O3' unless $CFLAGS =~ /-O\d/
|
11
|
+
$CFLAGS << ' -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline'
|
12
|
+
end
|
13
|
+
|
14
|
+
unless RbConfig::CONFIG['host_os'] =~ /darwin/
|
30
15
|
$LDFLAGS << ' -Wl,--as-needed'
|
31
16
|
end
|
32
17
|
|
33
|
-
$LDFLAGS <<
|
18
|
+
$LDFLAGS << format(' %s', ENV['LDFLAGS']) if ENV['LDFLAGS']
|
34
19
|
|
35
20
|
%w(CFLAGS CXXFLAGS CPPFLAGS).each do |variable|
|
36
|
-
|
21
|
+
$CFLAGS << format(' %s', ENV[variable]) if ENV[variable]
|
37
22
|
end
|
38
23
|
|
39
24
|
unless have_header('ruby.h')
|
40
|
-
abort <<-EOS
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
the following ways:
|
25
|
+
abort "\n" + (<<-EOS).gsub(/^[ ]{,3}/, '') + "\n"
|
26
|
+
You appear to be missing Ruby development libraries and/or header
|
27
|
+
files. You can install missing compile-time dependencies in one of
|
28
|
+
the following ways:
|
45
29
|
|
46
|
-
|
30
|
+
- Debian / Ubuntu
|
47
31
|
|
48
|
-
|
32
|
+
apt-get install ruby-dev
|
49
33
|
|
50
|
-
|
34
|
+
- Red Hat / CentOS / Fedora
|
51
35
|
|
52
|
-
|
36
|
+
yum install ruby-devel or dnf install ruby-devel
|
53
37
|
|
54
38
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
- Ruby Version Manager (for RVM, see http://rvm.io/)
|
60
|
-
- Ruby Environment (for rbenv, see http://github.com/sstephenson/rbenv)
|
39
|
+
Alternatively, you can use either of the following Ruby version
|
40
|
+
managers in order to install Ruby locally (for your user only)
|
41
|
+
and/or system-wide:
|
61
42
|
|
43
|
+
- Ruby Version Manager (for RVM, see http://rvm.io/)
|
44
|
+
- Ruby Environment (for rbenv, see http://github.com/sstephenson/rbenv)
|
45
|
+
- Change Ruby (for chruby, see https://github.com/postmodern/chruby)
|
62
46
|
EOS
|
63
47
|
end
|
64
48
|
|
@@ -66,6 +50,3 @@ dir_config('fizzbuzz')
|
|
66
50
|
|
67
51
|
create_header
|
68
52
|
create_makefile('fizzbuzz/fizzbuzz')
|
69
|
-
|
70
|
-
# vim: set ts=2 sw=2 sts=2 et :
|
71
|
-
# encoding: utf-8
|
data/ext/fizzbuzz/fizzbuzz.c
CHANGED
@@ -1,23 +1,3 @@
|
|
1
|
-
/* :stopdoc: */
|
2
|
-
|
3
|
-
/*
|
4
|
-
* fizzbuzz.c
|
5
|
-
*
|
6
|
-
* Copyright 2012-2014 Krzysztof Wilczynski
|
7
|
-
*
|
8
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
-
* you may not use this file except in compliance with the License.
|
10
|
-
* You may obtain a copy of the License at
|
11
|
-
*
|
12
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
13
|
-
*
|
14
|
-
* Unless required by applicable law or agreed to in writing, software
|
15
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
-
* See the License for the specific language governing permissions and
|
18
|
-
* limitations under the License.
|
19
|
-
*/
|
20
|
-
|
21
1
|
#if defined(__cplusplus)
|
22
2
|
extern "C" {
|
23
3
|
#endif
|
@@ -36,16 +16,14 @@ void Init_fizzbuzz(void);
|
|
36
16
|
|
37
17
|
static VALUE fizzbuzz_evaluate(VALUE value);
|
38
18
|
static VALUE fizzbuzz_values(VALUE object, fizzbuzz_return_t type,
|
39
|
-
|
19
|
+
fizzbuzz_direction_t direction);
|
40
20
|
|
41
21
|
static VALUE fizzbuzz_exception_wrapper(VALUE value);
|
42
22
|
static VALUE fizzbuzz_exception(void *data);
|
43
23
|
|
44
24
|
static VALUE fizzbuzz_type_error(VALUE klass, const char *message);
|
45
25
|
static VALUE fizzbuzz_range_error(VALUE klass, VALUE start, VALUE stop,
|
46
|
-
|
47
|
-
|
48
|
-
/* :startdoc: */
|
26
|
+
const char *message);
|
49
27
|
|
50
28
|
/*
|
51
29
|
* call-seq:
|
@@ -59,16 +37,17 @@ static VALUE fizzbuzz_range_error(VALUE klass, VALUE start, VALUE stop,
|
|
59
37
|
*
|
60
38
|
* Example:
|
61
39
|
*
|
62
|
-
* fb = FizzBuzz.new(1, 100)
|
63
|
-
* fb = FizzBuzz.new(-100
|
64
|
-
* fb = FizzBuzz.new(-15, 15)
|
40
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xb6fd3b38 @stop=100, @start=1>
|
41
|
+
* fb = FizzBuzz.new(-100, -1) #=> #<FizzBuzz:0xb72d5700 @stop=-1, @start=-100>
|
42
|
+
* fb = FizzBuzz.new(-15, 15) #=> #<FizzBuzz:0xb6fd0460 @stop=15, @start=-15>
|
65
43
|
*
|
66
44
|
* The given value of +stop+ must always be greater than or equal to the
|
67
45
|
* given value of +start+, otherwise raises an <i>FizzBuzz::RangeError</i>
|
68
46
|
* exception.
|
69
47
|
*
|
70
48
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value of either
|
71
|
-
* +start+ or +stop+ is not
|
49
|
+
* +start+ or +stop+ is not a _Fixnum_ or _Bignum_ type, or an _Integer_ type
|
50
|
+
* starting from Ruby version 2.4 onwards.
|
72
51
|
*
|
73
52
|
* See also: FizzBuzz::fizzbuzz and FizzBuzz::[]
|
74
53
|
*/
|
@@ -92,14 +71,14 @@ rb_fb_initialize(int argc, VALUE *argv, VALUE object)
|
|
92
71
|
|
93
72
|
/*
|
94
73
|
* call-seq:
|
95
|
-
*
|
74
|
+
* fizzbuzz.start -> integer
|
96
75
|
*
|
97
76
|
* Returns the current value for +start+.
|
98
77
|
*
|
99
78
|
* Example:
|
100
79
|
*
|
101
|
-
* fb = FizzBuzz.new(1, 100)
|
102
|
-
* fb.start
|
80
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf726b48c @stop=100, @start=1>
|
81
|
+
* fb.start #=> 1
|
103
82
|
*/
|
104
83
|
VALUE
|
105
84
|
rb_fb_get_start(VALUE object)
|
@@ -109,7 +88,7 @@ rb_fb_get_start(VALUE object)
|
|
109
88
|
|
110
89
|
/*
|
111
90
|
* call-seq:
|
112
|
-
*
|
91
|
+
* fizzbuzz.start=( integer ) -> integer
|
113
92
|
*
|
114
93
|
* Sets the current value of +start+ if given new value is lower or equal
|
115
94
|
* to the current value of +stop+, or raises an <i>FizzBuzz::RangeError</i>
|
@@ -117,13 +96,14 @@ rb_fb_get_start(VALUE object)
|
|
117
96
|
*
|
118
97
|
* Examples:
|
119
98
|
*
|
120
|
-
* fb = FizzBuzz.new(1, 100)
|
121
|
-
* fb.start
|
122
|
-
* fb.start = 15
|
123
|
-
* fb.start
|
99
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf726f03c @stop=100, @start=1>
|
100
|
+
* fb.start #=> 1
|
101
|
+
* fb.start = 15 #=> 15
|
102
|
+
* fb.start #=> 15
|
124
103
|
*
|
125
104
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
126
|
-
*
|
105
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
106
|
+
* version 2.4 onwards.
|
127
107
|
*/
|
128
108
|
VALUE
|
129
109
|
rb_fb_set_start(VALUE object, VALUE value)
|
@@ -138,14 +118,14 @@ rb_fb_set_start(VALUE object, VALUE value)
|
|
138
118
|
|
139
119
|
/*
|
140
120
|
* call-seq:
|
141
|
-
*
|
121
|
+
* fizzbuzz.stop -> integer
|
142
122
|
*
|
143
123
|
* Returns the current value for +stop+.
|
144
124
|
*
|
145
125
|
* Example:
|
146
126
|
*
|
147
|
-
* fb = FizzBuzz.new(1, 100)
|
148
|
-
* fb.stop
|
127
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf7272bec @stop=100, @start=1>
|
128
|
+
* fb.stop #=> 100
|
149
129
|
*/
|
150
130
|
VALUE
|
151
131
|
rb_fb_get_stop(VALUE object)
|
@@ -155,7 +135,7 @@ rb_fb_get_stop(VALUE object)
|
|
155
135
|
|
156
136
|
/*
|
157
137
|
* call-seq:
|
158
|
-
*
|
138
|
+
* fizzbuzz.stop=( integer ) -> integer
|
159
139
|
*
|
160
140
|
* Sets the current value of +stop+ if given new value is greater or equal
|
161
141
|
* to the current value of +start+, or raises an <i>FizzBuzz::RangeError</i>
|
@@ -163,13 +143,14 @@ rb_fb_get_stop(VALUE object)
|
|
163
143
|
*
|
164
144
|
* Example:
|
165
145
|
*
|
166
|
-
* fb = FizzBuzz.new(1, 100)
|
167
|
-
* fb.stop
|
168
|
-
* fb.stop = 15
|
169
|
-
* fb.stop
|
146
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf727679c @stop=100, @start=1>
|
147
|
+
* fb.stop #=> 100
|
148
|
+
* fb.stop = 15 #=> 15
|
149
|
+
* fb.stop #=> 15
|
170
150
|
*
|
171
151
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
172
|
-
*
|
152
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
153
|
+
* version 2.4 onwards.
|
173
154
|
*/
|
174
155
|
VALUE
|
175
156
|
rb_fb_set_stop(VALUE object, VALUE value)
|
@@ -191,8 +172,8 @@ rb_fb_set_stop(VALUE object, VALUE value)
|
|
191
172
|
*
|
192
173
|
* Example:
|
193
174
|
*
|
194
|
-
* fb = FizzBuzz.new(1, 15)
|
195
|
-
* fb.to_a
|
175
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf727fd60 @stop=15, @start=1>
|
176
|
+
* fb.to_a #=> [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
|
196
177
|
*
|
197
178
|
* See also: FizzBuzz::fizzbuzz
|
198
179
|
*/
|
@@ -205,7 +186,7 @@ rb_fb_array(VALUE object)
|
|
205
186
|
/*
|
206
187
|
* call-seq:
|
207
188
|
* fizzbuzz.each {|value| block } -> self
|
208
|
-
* fizzbuzz.each
|
189
|
+
* fizzbuzz.each -> an Enumerator
|
209
190
|
*
|
210
191
|
* Calls the block _once_ for each subsequent value for a given range
|
211
192
|
* from +start+ to +stop+, passing the value as a parameter to the block.
|
@@ -214,12 +195,12 @@ rb_fb_array(VALUE object)
|
|
214
195
|
*
|
215
196
|
* Example:
|
216
197
|
*
|
217
|
-
* fb = FizzBuzz.new(1, 15)
|
218
|
-
* fb.each
|
198
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
|
199
|
+
* fb.each #=> #<Enumerator: #<FizzBuzz:0x007fc513 @start=1, @stop=15>:each>
|
219
200
|
*
|
220
201
|
* Example:
|
221
202
|
*
|
222
|
-
* fb = FizzBuzz.new(1, 15)
|
203
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
|
223
204
|
* fb.each {|value| puts "Got #{value}" }
|
224
205
|
*
|
225
206
|
* Produces:
|
@@ -251,7 +232,7 @@ rb_fb_enumerator(VALUE object)
|
|
251
232
|
/*
|
252
233
|
* call-seq:
|
253
234
|
* fizzbuzz.reverse_each {|value| block } -> self
|
254
|
-
* fizzbuzz.reverse_each
|
235
|
+
* fizzbuzz.reverse_each -> an Enumerator
|
255
236
|
*
|
256
237
|
* Calls the block _once_ for each subsequent value for a given range
|
257
238
|
* from +start+ to +stop+ in an <i>reverse order</i>, passing the value
|
@@ -261,12 +242,12 @@ rb_fb_enumerator(VALUE object)
|
|
261
242
|
*
|
262
243
|
* Example:
|
263
244
|
*
|
264
|
-
* fb = FizzBuzz.new(1, 15)
|
265
|
-
* fb.each
|
245
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
|
246
|
+
* fb.each #=> #<Enumerator: #<FizzBuzz:0x007fc513 @start=1, @stop=15>:reverse_each>
|
266
247
|
*
|
267
248
|
* Example:
|
268
249
|
*
|
269
|
-
* fb = FizzBuzz.new(1, 15)
|
250
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xb7308664 @stop=15, @start=1>
|
270
251
|
* fb.reverse_each {|value| puts "Got #{value}" }
|
271
252
|
*
|
272
253
|
* Produces:
|
@@ -309,16 +290,15 @@ rb_fb_reverse_enumerator(VALUE object)
|
|
309
290
|
* FizzBuzz.is_fizz?(15) #=> false
|
310
291
|
*
|
311
292
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
312
|
-
*
|
293
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
294
|
+
* version 2.4 onwards.
|
313
295
|
*
|
314
296
|
* See also: FizzBuzz::[]
|
315
297
|
*/
|
316
298
|
VALUE
|
317
|
-
rb_fb_is_fizz(VALUE object, VALUE value)
|
299
|
+
rb_fb_is_fizz(RB_UNUSED_VAR(VALUE object), VALUE value)
|
318
300
|
{
|
319
|
-
UNUSED(object);
|
320
301
|
CHECK_TYPE(value, error(E_INVALID_TYPE));
|
321
|
-
|
322
302
|
return CBOOL2RVAL(IS_FIZZ(value));
|
323
303
|
}
|
324
304
|
|
@@ -336,16 +316,15 @@ rb_fb_is_fizz(VALUE object, VALUE value)
|
|
336
316
|
* FizzBuzz.is_buzz?(15) #=> false
|
337
317
|
*
|
338
318
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
339
|
-
*
|
319
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
320
|
+
* version 2.4 onwards.
|
340
321
|
*
|
341
322
|
* See also: FizzBuzz::[]
|
342
323
|
*/
|
343
324
|
VALUE
|
344
|
-
rb_fb_is_buzz(VALUE object, VALUE value)
|
325
|
+
rb_fb_is_buzz(RB_UNUSED_VAR(VALUE object), VALUE value)
|
345
326
|
{
|
346
|
-
UNUSED(object);
|
347
327
|
CHECK_TYPE(value, error(E_INVALID_TYPE));
|
348
|
-
|
349
328
|
return CBOOL2RVAL(IS_BUZZ(value));
|
350
329
|
}
|
351
330
|
|
@@ -358,21 +337,20 @@ rb_fb_is_buzz(VALUE object, VALUE value)
|
|
358
337
|
*
|
359
338
|
* Example:
|
360
339
|
*
|
361
|
-
* FizzBuzz.is_fizzbuzz?(3)
|
362
|
-
* FizzBuzz.is_fizzbuzz?(5)
|
340
|
+
* FizzBuzz.is_fizzbuzz?(3) #=> false
|
341
|
+
* FizzBuzz.is_fizzbuzz?(5) #=> false
|
363
342
|
* FizzBuzz.is_fizzbuzz?(15) #=> true
|
364
343
|
*
|
365
344
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
366
|
-
*
|
345
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
346
|
+
* version 2.4 onwards.
|
367
347
|
*
|
368
348
|
* See also: FizzBuzz::[]
|
369
349
|
*/
|
370
350
|
VALUE
|
371
|
-
rb_fb_is_fizzbuzz(VALUE object, VALUE value)
|
351
|
+
rb_fb_is_fizzbuzz(RB_UNUSED_VAR(VALUE object), VALUE value)
|
372
352
|
{
|
373
|
-
UNUSED(object);
|
374
353
|
CHECK_TYPE(value, error(E_INVALID_TYPE));
|
375
|
-
|
376
354
|
return CBOOL2RVAL(IS_FIZZBUZZ(value));
|
377
355
|
}
|
378
356
|
|
@@ -393,82 +371,71 @@ rb_fb_is_fizzbuzz(VALUE object, VALUE value)
|
|
393
371
|
* FizzBuzz[15] #=> "FizzBuzz"
|
394
372
|
*
|
395
373
|
* Will raise a <i>FizzBuzz::TypeError</i> exception if given value is not
|
396
|
-
*
|
374
|
+
* a _Fixnum_ or _Bignum_ type, or an _Integer_ type starting from Ruby
|
375
|
+
* version 2.4 onwards.
|
397
376
|
*
|
398
377
|
* See also: FizzBuzz::is_fizz?, FizzBuzz::is_buzz? and FizzBuzz::is_fizzbuzz?
|
399
378
|
*/
|
400
379
|
VALUE
|
401
|
-
rb_fb_square(VALUE object, VALUE value)
|
380
|
+
rb_fb_square(RB_UNUSED_VAR(VALUE object), VALUE value)
|
402
381
|
{
|
403
|
-
UNUSED(object);
|
404
382
|
CHECK_TYPE(value, error(E_INVALID_TYPE));
|
405
|
-
|
406
383
|
return fizzbuzz_evaluate(value);
|
407
384
|
}
|
408
385
|
|
409
|
-
/* :enddoc: */
|
410
|
-
|
411
386
|
static VALUE
|
412
387
|
fizzbuzz_evaluate(VALUE value)
|
413
388
|
{
|
414
|
-
|
389
|
+
int score;
|
415
390
|
|
416
|
-
if (ZERO_P(value))
|
417
|
-
|
418
|
-
}
|
391
|
+
if (ZERO_P(value))
|
392
|
+
return value;
|
419
393
|
|
420
394
|
score = SCORE_VALUE(value);
|
395
|
+
|
421
396
|
assert((score >= 0 && score <= 3) && \
|
422
|
-
|
397
|
+
"Score value out of bounds, must be between 0 and 3 inclusive");
|
423
398
|
|
424
|
-
|
425
|
-
* The CSTR2RVAL macro uses rb_str_new2(const char *) which is
|
426
|
-
* rather slow due to all the heavy lifting done internally by
|
427
|
-
* str_new0(VALUE, const char *, long, int) to allocate space
|
428
|
-
* for the new String object, etc.
|
429
|
-
*/
|
430
|
-
return score < 1 ? value : CSTR2RVAL(word(score));
|
399
|
+
return score < 1 ? value : word(score);
|
431
400
|
}
|
432
401
|
|
433
402
|
static VALUE
|
434
|
-
fizzbuzz_values(VALUE object, fizzbuzz_return_t type,
|
403
|
+
fizzbuzz_values(VALUE object, fizzbuzz_return_t type,
|
404
|
+
fizzbuzz_direction_t direction)
|
435
405
|
{
|
406
|
+
int forward = LOOP_FORWARD(direction);
|
407
|
+
|
436
408
|
VALUE i = Qnil;
|
437
409
|
|
438
410
|
VALUE array = Qnil;
|
439
411
|
VALUE value = Qnil;
|
440
412
|
|
441
413
|
VALUE start = rb_ivar_get(object, id_at_start);
|
442
|
-
VALUE stop
|
414
|
+
VALUE stop = rb_ivar_get(object, id_at_stop);
|
443
415
|
|
444
|
-
if (WANT_ARRAY(type))
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
RETURN_ENUMERATOR(object, 0, 0);
|
449
|
-
}
|
416
|
+
if (WANT_ARRAY(type))
|
417
|
+
array = rb_ary_new();
|
418
|
+
else
|
419
|
+
RETURN_ENUMERATOR(object, 0, 0);
|
450
420
|
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
else {
|
458
|
-
for (i = stop; GREATER_EQUAL(i, start); i = DECREASE(i)) {
|
459
|
-
value = fizzbuzz_evaluate(i);
|
460
|
-
WANT_ARRAY(type) ? rb_ary_push(array, value) : rb_yield(value);
|
461
|
-
}
|
421
|
+
i = forward ? start : stop;
|
422
|
+
|
423
|
+
while (RB_LIKELY(forward ? LESS_EQUAL(i, stop) : GREATER_EQUAL(i, start))) {
|
424
|
+
value = fizzbuzz_evaluate(i);
|
425
|
+
WANT_ARRAY(type) ? rb_ary_push(array, value) : rb_yield(value);
|
426
|
+
i = forward ? INCREASE(i) : DECREASE(i);
|
462
427
|
}
|
463
428
|
|
429
|
+
RB_GC_GUARD(array);
|
430
|
+
RB_GC_GUARD(value);
|
431
|
+
|
464
432
|
return WANT_ARRAY(type) ? array : object;
|
465
433
|
}
|
466
434
|
|
467
435
|
static VALUE
|
468
436
|
fizzbuzz_exception_wrapper(VALUE value)
|
469
437
|
{
|
470
|
-
fizzbuzz_exception_t *e = (
|
471
|
-
|
438
|
+
fizzbuzz_exception_t *e = (fizzbuzz_exception_t *)value;
|
472
439
|
return rb_exc_new2(e->klass, e->message);
|
473
440
|
}
|
474
441
|
|
@@ -479,13 +446,14 @@ fizzbuzz_exception(void *data)
|
|
479
446
|
VALUE object = Qnil;
|
480
447
|
|
481
448
|
fizzbuzz_exception_t *e = data;
|
482
|
-
|
449
|
+
|
450
|
+
assert(e != NULL && \
|
451
|
+
"Must be a valid pointer to `fizzbuzz_exception_t' type");
|
483
452
|
|
484
453
|
object = rb_protect(fizzbuzz_exception_wrapper, (VALUE)e, &exception);
|
485
454
|
|
486
|
-
if (exception)
|
487
|
-
|
488
|
-
}
|
455
|
+
if (exception)
|
456
|
+
rb_jump_tag(exception);
|
489
457
|
|
490
458
|
rb_iv_set(object, "@start", e->start);
|
491
459
|
rb_iv_set(object, "@stop", e->stop);
|
@@ -507,7 +475,8 @@ fizzbuzz_type_error(VALUE klass, const char *message)
|
|
507
475
|
}
|
508
476
|
|
509
477
|
static VALUE
|
510
|
-
fizzbuzz_range_error(VALUE klass, VALUE start, VALUE stop,
|
478
|
+
fizzbuzz_range_error(VALUE klass, VALUE start, VALUE stop,
|
479
|
+
const char *message)
|
511
480
|
{
|
512
481
|
fizzbuzz_exception_t e;
|
513
482
|
|
@@ -523,11 +492,27 @@ void
|
|
523
492
|
Init_fizzbuzz(void)
|
524
493
|
{
|
525
494
|
id_at_start = rb_intern("@start");
|
526
|
-
id_at_stop
|
495
|
+
id_at_stop = rb_intern("@stop");
|
527
496
|
|
528
497
|
rb_cFizzBuzz = rb_define_class("FizzBuzz", rb_cObject);
|
529
498
|
rb_include_module(rb_cFizzBuzz, rb_mEnumerable);
|
530
499
|
|
500
|
+
/*
|
501
|
+
* The CSTR2RVAL macro uses rb_str_new2(const char *) which is
|
502
|
+
* rather slow due to all the heavy lifting done internally by
|
503
|
+
* str_new0(VALUE, const char *, long, int) to allocate space
|
504
|
+
* for the new String object, etc.
|
505
|
+
*/
|
506
|
+
rb_define_const(rb_cFizzBuzz, "WORD_FIZZ", CSTR2RVAL("Fizz"));
|
507
|
+
rb_define_const(rb_cFizzBuzz, "WORD_BUZZ", CSTR2RVAL("Buzz"));
|
508
|
+
rb_define_const(rb_cFizzBuzz, "WORD_FIZZBUZZ", CSTR2RVAL("FizzBuzz"));
|
509
|
+
|
510
|
+
if (NIL_P(words[0])) {
|
511
|
+
words[0] = rb_str_freeze(rb_const_get(rb_cFizzBuzz, rb_intern("WORD_FIZZ")));
|
512
|
+
words[1] = rb_str_freeze(rb_const_get(rb_cFizzBuzz, rb_intern("WORD_BUZZ")));
|
513
|
+
words[2] = rb_str_freeze(rb_const_get(rb_cFizzBuzz, rb_intern("WORD_FIZZBUZZ")));
|
514
|
+
}
|
515
|
+
|
531
516
|
/*
|
532
517
|
* Raised when _FizzBuzz_ encounters an error.
|
533
518
|
*/
|
@@ -577,5 +562,3 @@ Init_fizzbuzz(void)
|
|
577
562
|
#if defined(__cplusplus)
|
578
563
|
}
|
579
564
|
#endif
|
580
|
-
|
581
|
-
/* vim: set ts=8 sw=4 sts=2 et : */
|