ruby-fizzbuzz 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,64 +1,48 @@
1
- # -*- encoding: utf-8 -*-
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 -g -Wall -Wextra -pedantic'
7
+ $CFLAGS << ' -std=c99 -Wall -Wextra -pedantic'
28
8
 
29
- unless RbConfig::CONFIG['host_os'][/darwin/]
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 << " %s" % ENV['LDFLAGS'] if ENV['LDFLAGS']
18
+ $LDFLAGS << format(' %s', ENV['LDFLAGS']) if ENV['LDFLAGS']
34
19
 
35
20
  %w(CFLAGS CXXFLAGS CPPFLAGS).each do |variable|
36
- $CFLAGS << " %s" % ENV[variable] if ENV[variable]
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
- You appear to be missing Ruby development libraries and/or header
43
- files. You can install missing compile-time dependencies in one of
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
- - Debian / Ubuntu
30
+ - Debian / Ubuntu
47
31
 
48
- apt-get install ruby-dev
32
+ apt-get install ruby-dev
49
33
 
50
- - Red Hat / CentOS / Fedora
34
+ - Red Hat / CentOS / Fedora
51
35
 
52
- yum install ruby-devel
36
+ yum install ruby-devel or dnf install ruby-devel
53
37
 
54
38
 
55
- Alternatively, you can use either of the following Ruby version
56
- managers in order to install Ruby locally (for your user only)
57
- and/or system-wide:
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
@@ -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
- fizzbuzz_direction_t direction);
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
- const char *message);
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) #=> #<FizzBuzz:0xb6fd3b38 @stop=100, @start=1>
63
- * fb = FizzBuzz.new(-100,-1) #=> #<FizzBuzz:0xb72d5700 @stop=-1, @start=-100>
64
- * fb = FizzBuzz.new(-15, 15) #=> #<FizzBuzz:0xb6fd0460 @stop=15, @start=-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 an _Fixnum_ or _Bignum_ type.
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
- * fizzfuzz.start -> integer
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) #=> #<FizzBuzz:0xf726b48c @stop=100, @start=1>
102
- * fb.start #=> 1
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
- * fizzfuzz.start= (integer) -> integer
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) #=> #<FizzBuzz:0xf726f03c @stop=100, @start=1>
121
- * fb.start #=> 1
122
- * fb.start = 15 #=> 15
123
- * fb.start #=> 15
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
- * an _Fixnum_ or _Bignum_ type.
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
- * fizzfuzz.stop -> integer
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) #=> #<FizzBuzz:0xf7272bec @stop=100, @start=1>
148
- * fb.stop #=> 100
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
- * fizzfuzz.stop= (integer) -> integer
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) #=> #<FizzBuzz:0xf727679c @stop=100, @start=1>
167
- * fb.stop #=> 100
168
- * fb.stop = 15 #=> 15
169
- * fb.stop #=> 15
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
- * an _Fixnum_ or _Bignum_ type.
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) #=> #<FizzBuzz:0xf727fd60 @stop=15, @start=1>
195
- * fb.to_a #=> [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
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 -> an Enumerator
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) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
218
- * fb.each #=> #<Enumerator: #<FizzBuzz:0x007fc5139e5540 @start=1, @stop=15>: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) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
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 -> an Enumerator
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) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
265
- * fb.each #=> #<Enumerator: #<FizzBuzz:0x007fc513a0de00 @start=1, @stop=15>:reverse_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) #=> #<FizzBuzz:0xb7308664 @stop=15, @start=1>
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
- * an _Fixnum_ or _Bignum_ type.
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
- * an _Fixnum_ or _Bignum_ type.
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) #=> false
362
- * FizzBuzz.is_fizzbuzz?(5) #=> false
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
- * an _Fixnum_ or _Bignum_ type.
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
- * an _Fixnum_ or _Bignum_ type.
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
- int8_t score;
389
+ int score;
415
390
 
416
- if (ZERO_P(value)) {
417
- return value;
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
- "Score value out of bounds, must be between 0 and 3 inclusive");
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, fizzbuzz_direction_t direction)
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 = rb_ivar_get(object, id_at_stop);
414
+ VALUE stop = rb_ivar_get(object, id_at_stop);
443
415
 
444
- if (WANT_ARRAY(type)) {
445
- array = rb_ary_new();
446
- }
447
- else {
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
- if (LOOP_FORWARD(direction)) {
452
- for (i = start; LESS_EQUAL(i, stop); i = INCREASE(i)) {
453
- value = fizzbuzz_evaluate(i);
454
- WANT_ARRAY(type) ? rb_ary_push(array, value) : rb_yield(value);
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 = (struct fizzbuzz_exception *)value;
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
- assert(e != NULL && "Must be a valid pointer to `fizzbuzz_exception_t' type");
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
- rb_jump_tag(exception);
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, const char *message)
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 = rb_intern("@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 : */