Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 710 lines (610 sloc) 16.428 kB
817a62d 2000-05-01
matz authored
1 /**********************************************************************
99d0354 Initial revision
matz authored
2
3 range.c -
4
5 $Author$
6 $Date$
7 created at: Thu Aug 19 17:46:47 JST 1993
8
42bc5d2 Updated Copyrights of Matz to 2003.
michal authored
9 Copyright (C) 1993-2003 Yukihiro Matsumoto
99d0354 Initial revision
matz authored
10
817a62d 2000-05-01
matz authored
11 **********************************************************************/
99d0354 Initial revision
matz authored
12
13 #include "ruby.h"
14
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
15 VALUE rb_cRange;
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
16 static ID id_cmp, id_succ, id_beg, id_end, id_excl;
07bb9f2 1.4.0
matz authored
17
5c51be8 matz
matz authored
18 #define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
8f257d9 range.c: small-cleanup [ruby-core:276]
michal authored
19 #define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
99d0354 Initial revision
matz authored
20
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
21 static VALUE
d85c44a * struct.c (rb_struct_eql): should compare values with "eql?".
matz authored
22 range_failed()
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
23 {
d85c44a * struct.c (rb_struct_eql): should compare values with "eql?".
matz authored
24 rb_raise(rb_eArgError, "bad value for range");
25 return Qnil; /* dummy */
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
26 }
27
28 static VALUE
d85c44a * struct.c (rb_struct_eql): should compare values with "eql?".
matz authored
29 range_check(args)
30 VALUE *args;
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
31 {
0bfdf4f @nobu * eval.c (rb_rescue2): reduce PUSH_TAG() as well as NODE_RESCUE.
nobu authored
32 return rb_funcall(args[0], id_cmp, 1, args[1]);
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
33 }
99d0354 Initial revision
matz authored
34
5928d4c 2000-02-29
matz authored
35 static void
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
36 range_init(range, beg, end, exclude_end)
37 VALUE range, beg, end;
07bb9f2 1.4.0
matz authored
38 int exclude_end;
99d0354 Initial revision
matz authored
39 {
07bb9f2 1.4.0
matz authored
40 VALUE args[2];
99d0354 Initial revision
matz authored
41
8f257d9 range.c: small-cleanup [ruby-core:276]
michal authored
42 args[0] = beg;
43 args[1] = end;
44
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
45 if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
0bfdf4f @nobu * eval.c (rb_rescue2): reduce PUSH_TAG() as well as NODE_RESCUE.
nobu authored
46 VALUE v;
47
48 v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
49 if (NIL_P(v)) range_failed();
99d0354 Initial revision
matz authored
50 }
51
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
52 SET_EXCL(range, exclude_end);
53 rb_ivar_set(range, id_beg, beg);
54 rb_ivar_set(range, id_end, end);
99d0354 Initial revision
matz authored
55 }
56
57 VALUE
07bb9f2 1.4.0
matz authored
58 rb_range_new(beg, end, exclude_end)
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
59 VALUE beg, end;
07bb9f2 1.4.0
matz authored
60 int exclude_end;
61 {
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
62 VALUE range = rb_obj_alloc(rb_cRange);
5928d4c 2000-02-29
matz authored
63
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
64 range_init(range, beg, end, exclude_end);
65 return range;
07bb9f2 1.4.0
matz authored
66 }
67
8983f9e Michael Granger added RDoc for range.c
dave authored
68 /*
69 * call-seq:
70 * Range.new(start, end, exclusive=false) => range
71 *
72 * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
73 * parameter is omitted or is <code>false</code>, the <i>range</i> will include
74 * the end object; otherwise, it will be excluded.
75 */
76
07bb9f2 1.4.0
matz authored
77 static VALUE
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
78 range_initialize(argc, argv, range)
07bb9f2 1.4.0
matz authored
79 int argc;
80 VALUE *argv;
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
81 VALUE range;
07bb9f2 1.4.0
matz authored
82 {
bb85be1 * array.c (rb_ary_sort_bang): returns self, even if its length is
matz authored
83 VALUE beg, end, flags;
07bb9f2 1.4.0
matz authored
84
bb85be1 * array.c (rb_ary_sort_bang): returns self, even if its length is
matz authored
85 rb_scan_args(argc, argv, "21", &beg, &end, &flags);
5928d4c 2000-02-29
matz authored
86 /* Ranges are immutable, so that they should be initialized only once. */
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
87 if (rb_ivar_defined(range, id_beg)) {
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
88 rb_name_error(rb_intern("initialize"), "`initialize' called twice");
5928d4c 2000-02-29
matz authored
89 }
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
90 range_init(range, beg, end, RTEST(flags));
5928d4c 2000-02-29
matz authored
91 return Qnil;
07bb9f2 1.4.0
matz authored
92 }
93
8983f9e Michael Granger added RDoc for range.c
dave authored
94
95 /*
96 * call-seq:
97 * rng.exclude_end? => true or false
98 *
99 * Returns <code>true</code> if <i>rng</i> excludes its end value.
100 */
101
07bb9f2 1.4.0
matz authored
102 static VALUE
103 range_exclude_end_p(range)
104 VALUE range;
99d0354 Initial revision
matz authored
105 {
8f257d9 range.c: small-cleanup [ruby-core:276]
michal authored
106 return EXCL(range) ? Qtrue : Qfalse;
99d0354 Initial revision
matz authored
107 }
108
8983f9e Michael Granger added RDoc for range.c
dave authored
109
110 /*
111 * call-seq:
112 * rng == obj => true or false
113 *
114 * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
115 * beginning and end items (by comparing them with <code>==</code>), and has
116 * the same #exclude_end? setting as <i>rng</t>.
117 *
118 * (0..2) == (0..2) #=> true
119 * (0..2) == Range.new(0,2) #=> true
120 * (0..2) == (0...2) #=> false
121 *
122 */
123
99d0354 Initial revision
matz authored
124 static VALUE
5c51be8 matz
matz authored
125 range_eq(range, obj)
126 VALUE range, obj;
127 {
2ba87ec thread_critical bug reported by Dave - matz
matz authored
128 if (range == obj) return Qtrue;
4112162 * variable.c (rb_copy_generic_ivar): remove old generic instance
matz authored
129 if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
130 return Qfalse;
5c51be8 matz
matz authored
131
132 if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
133 return Qfalse;
134 if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
135 return Qfalse;
136
137 if (EXCL(range) != EXCL(obj)) return Qfalse;
138
139 return Qtrue;
140 }
141
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
142 static int
6432869 * string.c (rb_str_new2): NULL pointer check added.
matz authored
143 r_lt(a, b)
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
144 VALUE a, b;
145 {
146 VALUE r = rb_funcall(a, id_cmp, 1, b);
147
db2c62f * numeric.c (num_step): use DBL_EPSILON.
matz authored
148 if (NIL_P(r)) return Qfalse;
293fdb4 * ext/pty/pty.c (pty_finalize_syswait): join (using Thread#value)
matz authored
149 if (rb_cmpint(r, a, b) < 0) return Qtrue;
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
150 return Qfalse;
151 }
152
153 static int
6432869 * string.c (rb_str_new2): NULL pointer check added.
matz authored
154 r_le(a, b)
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
155 VALUE a, b;
156 {
75bc427 * range.c (range_each_func): terminates loop if generating value
matz authored
157 int c;
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
158 VALUE r = rb_funcall(a, id_cmp, 1, b);
159
db2c62f * numeric.c (num_step): use DBL_EPSILON.
matz authored
160 if (NIL_P(r)) return Qfalse;
75bc427 * range.c (range_each_func): terminates loop if generating value
matz authored
161 c = rb_cmpint(r, a, b);
162 if (c == 0) return INT2FIX(0);
163 if (c < 0) return Qtrue;
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
164 return Qfalse;
165 }
166
db2c62f * numeric.c (num_step): use DBL_EPSILON.
matz authored
167
8983f9e Michael Granger added RDoc for range.c
dave authored
168 /*
169 * call-seq:
170 * rng.eql?(obj) => true or false
171 *
172 * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
173 * beginning and end items (by comparing them with #eql?), and has the same
174 * #exclude_end? setting as <i>rng</i>.
175 *
176 * (0..2) == (0..2) #=> true
177 * (0..2) == Range.new(0,2) #=> true
178 * (0..2) == (0...2) #=> false
179 *
180 */
181
5c51be8 matz
matz authored
182 static VALUE
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
183 range_eql(range, obj)
184 VALUE range, obj;
185 {
186 if (range == obj) return Qtrue;
4112162 * variable.c (rb_copy_generic_ivar): remove old generic instance
matz authored
187 if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
188 return Qfalse;
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
189
190 if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
191 return Qfalse;
192 if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
193 return Qfalse;
194
195 if (EXCL(range) != EXCL(obj)) return Qfalse;
196
197 return Qtrue;
198 }
199
23f64f4 Add RDoc for kernel functions, and tidy up
dave authored
200 /*
201 * call-seq:
202 * rng.hash => fixnum
203 *
204 * Generate a hash value such that two ranges with the same start and
205 * end points, and the same value for the "exclude end" flag, generate
206 * the same hash value.
207 */
208
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
209 static VALUE
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
210 range_hash(range)
211 VALUE range;
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
212 {
213 long hash = EXCL(range);
214 VALUE v;
215
216 v = rb_hash(rb_ivar_get(range, id_beg));
217 hash ^= v << 1;
218 v = rb_hash(rb_ivar_get(range, id_end));
219 hash ^= v << 9;
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
220 hash ^= EXCL(range) << 24;
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
221
8f257d9 range.c: small-cleanup [ruby-core:276]
michal authored
222 return LONG2FIX(hash);
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
223 }
224
225 static VALUE
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
226 str_step(args)
299d4e6 * range.c (range_step): new method.
matz authored
227 VALUE *args;
228 {
229 return rb_str_upto(args[0], args[1], EXCL(args[2]));
230 }
231
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
232 static void
233 range_each_func(range, func, v, e, arg)
234 VALUE range;
2281c5b * io.c (read_all): block string buffer modification during
matz authored
235 void (*func) _((VALUE, void*));
8f257d9 range.c: small-cleanup [ruby-core:276]
michal authored
236 VALUE v, e;
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
237 void *arg;
238 {
75bc427 * range.c (range_each_func): terminates loop if generating value
matz authored
239 int c;
240
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
241 if (EXCL(range)) {
242 while (r_lt(v, e)) {
2281c5b * io.c (read_all): block string buffer modification during
matz authored
243 (*func)(v, arg);
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
244 v = rb_funcall(v, id_succ, 0, 0);
245 }
246 }
247 else {
75bc427 * range.c (range_each_func): terminates loop if generating value
matz authored
248 while (RTEST(c = r_le(v, e))) {
2281c5b * io.c (read_all): block string buffer modification during
matz authored
249 (*func)(v, arg);
75bc427 * range.c (range_each_func): terminates loop if generating value
matz authored
250 if (c == INT2FIX(0)) break;
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
251 v = rb_funcall(v, id_succ, 0, 0);
252 }
253 }
254 }
255
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
256 static VALUE
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
257 step_i(i, arg)
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
258 VALUE i;
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
259 VALUE arg;
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
260 {
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
261 VALUE *iter = (VALUE *)arg;
262
263 if (FIXNUM_P(iter[0])) {
264 iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
265 }
266 else {
97e4373 @mame * range.c (step_i): rb_funcall receives VALUE as an argument.
mame authored
267 iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
268 }
269 if (iter[0] == INT2FIX(0)) {
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
270 rb_yield(i);
271 iter[0] = iter[1];
272 }
2281c5b * io.c (read_all): block string buffer modification during
matz authored
273 return Qnil;
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
274 }
275
1dd6798 @shyouhei merge revision(s) 21298:
shyouhei authored
276 extern int ruby_float_step _((VALUE from, VALUE to, VALUE step, int excl));
277
8983f9e Michael Granger added RDoc for range.c
dave authored
278 /*
279 * call-seq:
280 * rng.step(n=1) {| obj | block } => rng
281 *
282 * Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
f814cc7 @knu Merge from ruby_1_8.
knu authored
283 * the range contains numbers, <i>n</i> is added for each iteration. Otherwise
8983f9e Michael Granger added RDoc for range.c
dave authored
284 * <code>step</code> invokes <code>succ</code> to iterate through range
285 * elements. The following code uses class <code>Xs</code>, which is defined
286 * in the class-level documentation.
287 *
288 * range = Xs.new(1)..Xs.new(10)
289 * range.step(2) {|x| puts x}
290 * range.step(3) {|x| puts x}
291 *
292 * <em>produces:</em>
293 *
294 * 1 x
295 * 3 xxx
296 * 5 xxxxx
297 * 7 xxxxxxx
298 * 9 xxxxxxxxx
299 * 1 x
300 * 4 xxxx
301 * 7 xxxxxxx
302 * 10 xxxxxxxxxx
303 */
304
305
299d4e6 * range.c (range_step): new method.
matz authored
306 static VALUE
307 range_step(argc, argv, range)
308 int argc;
309 VALUE *argv;
310 VALUE range;
311 {
aa2c73f @knu Merge -r16241:16456 from ruby_1_8.
knu authored
312 VALUE b, e, step, tmp;
299d4e6 * range.c (range_step): new method.
matz authored
313
64063ca @knu * range.c (range_each, range_step): Return an enumerator if no
knu authored
314 RETURN_ENUMERATOR(range, argc, argv);
315
299d4e6 * range.c (range_step): new method.
matz authored
316 b = rb_ivar_get(range, id_beg);
317 e = rb_ivar_get(range, id_end);
aa2c73f @knu Merge -r16241:16456 from ruby_1_8.
knu authored
318 if (argc == 0) {
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
319 step = INT2FIX(1);
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
320 }
321 else {
aa2c73f @knu Merge -r16241:16456 from ruby_1_8.
knu authored
322 rb_scan_args(argc, argv, "01", &step);
f814cc7 @knu Merge from ruby_1_8.
knu authored
323 if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
324 step = rb_to_int(step);
aa2c73f @knu Merge -r16241:16456 from ruby_1_8.
knu authored
325 }
f814cc7 @knu Merge from ruby_1_8.
knu authored
326 if (rb_funcall(step, '<', 1, INT2FIX(0))) {
327 rb_raise(rb_eArgError, "step can't be negative");
328 }
329 else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
330 rb_raise(rb_eArgError, "step can't be 0");
aa2c73f @knu Merge -r16241:16456 from ruby_1_8.
knu authored
331 }
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
332 }
f814cc7 @knu Merge from ruby_1_8.
knu authored
333
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
334 if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
335 long end = FIX2LONG(e);
f814cc7 @knu Merge from ruby_1_8.
knu authored
336 long i, unit = FIX2LONG(step);
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
337
f814cc7 @knu Merge from ruby_1_8.
knu authored
338 if (!EXCL(range))
339 end += 1;
db9561e * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
matz authored
340 i = FIX2LONG(b);
341 while (i < end) {
fa79abb *.c: Int vs Long cleanup
michal authored
342 rb_yield(LONG2NUM(i));
db9561e * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
matz authored
343 if (i + unit < i) break;
344 i += unit;
299d4e6 * range.c (range_step): new method.
matz authored
345 }
f814cc7 @knu Merge from ruby_1_8.
knu authored
346
347 }
1dd6798 @shyouhei merge revision(s) 21298:
shyouhei authored
348 else if (ruby_float_step(b, e, step, EXCL(range))) {
349 /* done */
350 }
f814cc7 @knu Merge from ruby_1_8.
knu authored
351 else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
352 !NIL_P(rb_check_to_integer(b, "to_int")) ||
353 !NIL_P(rb_check_to_integer(e, "to_int"))) {
354 ID op = EXCL(range) ? '<' : rb_intern("<=");
355
356 while (RTEST(rb_funcall(b, op, 1, e))) {
357 rb_yield(b);
358 b = rb_funcall(b, '+', 1, step);
359 }
299d4e6 * range.c (range_step): new method.
matz authored
360 }
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
361 else {
f814cc7 @knu Merge from ruby_1_8.
knu authored
362 tmp = rb_check_string_type(b);
299d4e6 * range.c (range_step): new method.
matz authored
363
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
364 if (!NIL_P(tmp)) {
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
365 VALUE args[5], iter[2];
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
366
367 b = tmp;
f814cc7 @knu Merge from ruby_1_8.
knu authored
368 args[0] = e;
369 args[1] = EXCL(range) ? Qtrue : Qfalse;
370 iter[0] = INT2FIX(1);
371 iter[1] = step;
372 rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
373 }
f34cd5c * range.c (range_step): should not round step into integer if
matz authored
374 else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
375 !NIL_P(rb_check_to_integer(b, "to_int")) ||
376 !NIL_P(rb_check_to_integer(e, "to_int"))) {
377 ID c = EXCL(range) ? '<' : rb_intern("<=");
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
378
379 while (RTEST(rb_funcall(b, c, 1, e))) {
380 rb_yield(b);
381 b = rb_funcall(b, '+', 1, step);
382 }
299d4e6 * range.c (range_step): new method.
matz authored
383 }
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
384 else {
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
385 VALUE args[2];
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
386
387 if (!rb_respond_to(b, id_succ)) {
8db23b3 * exception error messages updated. [ruby-core:04497]
matz authored
388 rb_raise(rb_eTypeError, "can't iterate from %s",
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
389 rb_obj_classname(b));
390 }
6020b90 @nobu * range.c (step_i, range_step): support non-fixnum steps.
nobu authored
391 args[0] = INT2FIX(1);
392 args[1] = step;
51e0483 * parse.y (value_expr0): class and module statements should not be
matz authored
393 range_each_func(range, step_i, b, e, args);
394 }
299d4e6 * range.c (range_step): new method.
matz authored
395 }
396 return range;
397 }
398
2281c5b * io.c (read_all): block string buffer modification during
matz authored
399 static void
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
400 each_i(v, arg)
401 VALUE v;
402 void *arg;
403 {
e3ba92e * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
matz authored
404 rb_yield(v);
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
405 }
406
8983f9e Michael Granger added RDoc for range.c
dave authored
407 /*
408 * call-seq:
409 * rng.each {| i | block } => rng
410 *
411 * Iterates over the elements <i>rng</i>, passing each in turn to the
23f64f4 Add RDoc for kernel functions, and tidy up
dave authored
412 * block. You can only iterate if the start object of the range
413 * supports the +succ+ method (which means that you can't iterate over
414 * ranges of +Float+ objects).
8983f9e Michael Granger added RDoc for range.c
dave authored
415 *
416 * (10..15).each do |n|
417 * print n, ' '
418 * end
419 *
420 * <em>produces:</em>
421 *
422 * 10 11 12 13 14 15
423 */
424
299d4e6 * range.c (range_step): new method.
matz authored
425 static VALUE
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
426 range_each(range)
427 VALUE range;
428 {
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
429 VALUE beg, end;
430
64063ca @knu * range.c (range_each, range_step): Return an enumerator if no
knu authored
431 RETURN_ENUMERATOR(range, 0, 0);
432
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
433 beg = rb_ivar_get(range, id_beg);
434 end = rb_ivar_get(range, id_end);
435
436 if (!rb_respond_to(beg, id_succ)) {
8db23b3 * exception error messages updated. [ruby-core:04497]
matz authored
437 rb_raise(rb_eTypeError, "can't iterate from %s",
a0cf2fd * variable.c (rb_obj_classname): new function.
matz authored
438 rb_obj_classname(beg));
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
439 }
e1025c5 * range.c (range_each): treat fixnums specially to boost.
matz authored
440 if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
441 long lim = FIX2LONG(end);
442 long i;
443
444 if (!EXCL(range)) lim += 1;
445 for (i=FIX2LONG(beg); i<lim; i++) {
446 rb_yield(LONG2NUM(i));
447 }
448 }
449 else if (TYPE(beg) == T_STRING) {
2a54445 @nobu * range.c (range_each): followed step_i change.
nobu authored
450 VALUE args[5], iter[2];
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
451
452 args[0] = beg; args[1] = end; args[2] = range;
2a54445 @nobu * range.c (range_each): followed step_i change.
nobu authored
453 iter[0] = INT2FIX(1); iter[1] = INT2FIX(1);
0f45784 @unak * range.c (range_step, range_each): need cast.
unak authored
454 rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i,
455 (VALUE)iter);
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
456 }
457 else {
549225b -Wall cleanups (removed unused vars, no 'code has no effect' warnings)
michal authored
458 range_each_func(range, each_i, beg, end, NULL);
0390fc5 * range.c (range_step): iteration done using "+" if elements are
matz authored
459 }
460 return range;
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
461 }
462
8983f9e Michael Granger added RDoc for range.c
dave authored
463 /*
464 * call-seq:
465 * rng.first => obj
466 * rng.begin => obj
467 *
468 * Returns the first object in <i>rng</i>.
469 */
470
b6b8afa * numeric.c (num_step): better iteration condition for float
matz authored
471 static VALUE
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
472 range_first(range)
473 VALUE range;
99d0354 Initial revision
matz authored
474 {
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
475 return rb_ivar_get(range, id_beg);
99d0354 Initial revision
matz authored
476 }
477
8983f9e Michael Granger added RDoc for range.c
dave authored
478
479 /*
480 * call-seq:
481 * rng.end => obj
482 * rng.last => obj
483 *
484 * Returns the object that defines the end of <i>rng</i>.
485 *
486 * (1..10).end #=> 10
487 * (1...10).end #=> 10
488 */
489
490
99d0354 Initial revision
matz authored
491 static VALUE
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
492 range_last(range)
493 VALUE range;
99d0354 Initial revision
matz authored
494 {
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
495 return rb_ivar_get(range, id_end);
99d0354 Initial revision
matz authored
496 }
497
498 VALUE
07bb9f2 1.4.0
matz authored
499 rb_range_beg_len(range, begp, lenp, len, err)
99d0354 Initial revision
matz authored
500 VALUE range;
07bb9f2 1.4.0
matz authored
501 long *begp, *lenp;
502 long len;
503 int err;
99d0354 Initial revision
matz authored
504 {
07bb9f2 1.4.0
matz authored
505 long beg, end, b, e;
99d0354 Initial revision
matz authored
506
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
507 if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
99d0354 Initial revision
matz authored
508
07bb9f2 1.4.0
matz authored
509 beg = b = NUM2LONG(rb_ivar_get(range, id_beg));
510 end = e = NUM2LONG(rb_ivar_get(range, id_end));
511
512 if (beg < 0) {
513 beg += len;
514 if (beg < 0) goto out_of_range;
515 }
516 if (err == 0 || err == 2) {
517 if (beg > len) goto out_of_range;
42f0ec9 * range.c (rb_range_beg_len): returns Qnil only when "beg" points
matz authored
518 if (end > len) end = len;
07bb9f2 1.4.0
matz authored
519 }
67688bf * parse.y (new_yield): distinguish "yield 1,2" and "yield [1,2]".
matz authored
520 if (end < 0) end += len;
3717865 * array.c (push_values_at): Array#values_at should work with
matz authored
521 if (!EXCL(range)) end++; /* include end point */
07bb9f2 1.4.0
matz authored
522 len = end - beg;
42f0ec9 * range.c (rb_range_beg_len): returns Qnil only when "beg" points
matz authored
523 if (len < 0) len = 0;
07bb9f2 1.4.0
matz authored
524
525 *begp = beg;
526 *lenp = len;
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
527 return Qtrue;
07bb9f2 1.4.0
matz authored
528
529 out_of_range:
530 if (err) {
2231bb6 * array.c: fixed format string for 'long' args (%d -> %ld).
michal authored
531 rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
f4d7f48 * class.c (rb_include_module): detect cyclic module inclusion.
matz authored
532 b, EXCL(range)? "." : "", e);
07bb9f2 1.4.0
matz authored
533 }
534 return Qnil;
99d0354 Initial revision
matz authored
535 }
536
23f64f4 Add RDoc for kernel functions, and tidy up
dave authored
537 /*
538 * call-seq:
539 * rng.to_s => string
540 *
541 * Convert this range object to a printable form.
542 */
543
99d0354 Initial revision
matz authored
544 static VALUE
545 range_to_s(range)
546 VALUE range;
547 {
548 VALUE str, str2;
549
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
550 str = rb_obj_as_string(rb_ivar_get(range, id_beg));
551 str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
620b13d 2000-04-10
matz authored
552 str = rb_str_dup(str);
07bb9f2 1.4.0
matz authored
553 rb_str_cat(str, "...", EXCL(range)?3:2);
620b13d 2000-04-10
matz authored
554 rb_str_append(str, str2);
555 OBJ_INFECT(str, str2);
99d0354 Initial revision
matz authored
556
557 return str;
558 }
559
23f64f4 Add RDoc for kernel functions, and tidy up
dave authored
560 /*
561 * call-seq:
562 * rng.inspect => string
563 *
564 * Convert this range object to a printable form (using
565 * <code>inspect</code> to convert the start and end
566 * objects).
567 */
568
569
99d0354 Initial revision
matz authored
570 static VALUE
571 range_inspect(range)
572 VALUE range;
573 {
574 VALUE str, str2;
575
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
576 str = rb_inspect(rb_ivar_get(range, id_beg));
577 str2 = rb_inspect(rb_ivar_get(range, id_end));
620b13d 2000-04-10
matz authored
578 str = rb_str_dup(str);
07bb9f2 1.4.0
matz authored
579 rb_str_cat(str, "...", EXCL(range)?3:2);
620b13d 2000-04-10
matz authored
580 rb_str_append(str, str2);
581 OBJ_INFECT(str, str2);
99d0354 Initial revision
matz authored
582
583 return str;
584 }
585
8983f9e Michael Granger added RDoc for range.c
dave authored
586 /*
587 * call-seq:
2281c5b * io.c (read_all): block string buffer modification during
matz authored
588 * rng === obj => true or false
589 * rng.member?(val) => true or false
590 * rng.include?(val) => true or false
8983f9e Michael Granger added RDoc for range.c
dave authored
591 *
592 * Returns <code>true</code> if <i>obj</i> is an element of
593 * <i>rng</i>, <code>false</code> otherwise. Conveniently,
594 * <code>===</code> is the comparison operator used by
595 * <code>case</code> statements.
596 *
597 * case 79
598 * when 1..50 then print "low\n"
599 * when 51..75 then print "medium\n"
600 * when 76..100 then print "high\n"
601 * end
602 *
603 * <em>produces:</em>
604 *
605 * high
606 */
607
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
608 static VALUE
609 range_include(range, val)
610 VALUE range, val;
611 {
612 VALUE beg, end;
613
614 beg = rb_ivar_get(range, id_beg);
615 end = rb_ivar_get(range, id_end);
db2c62f * numeric.c (num_step): use DBL_EPSILON.
matz authored
616 if (r_le(beg, val)) {
617 if (EXCL(range)) {
618 if (r_lt(val, end)) return Qtrue;
619 }
620 else {
621 if (r_le(val, end)) return Qtrue;
622 }
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
623 }
624 return Qfalse;
625 }
626
8983f9e Michael Granger added RDoc for range.c
dave authored
627
628 /* A <code>Range</code> represents an interval---a set of values with a
629 * start and an end. Ranges may be constructed using the
630 * <em>s</em><code>..</code><em>e</em> and
631 * <em>s</em><code>...</code><em>e</em> literals, or with
632 * <code>Range::new</code>. Ranges constructed using <code>..</code>
633 * run from the start to the end inclusively. Those created using
634 * <code>...</code> exclude the end value. When used as an iterator,
635 * ranges return each value in the sequence.
636 *
637 * (-1..-5).to_a #=> []
638 * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
639 * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
640 * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
641 *
642 * Ranges can be constructed using objects of any type, as long as the
643 * objects can be compared using their <code><=></code> operator and
644 * they support the <code>succ</code> method to return the next object
645 * in sequence.
646 *
647 * class Xs # represent a string of 'x's
648 * include Comparable
649 * attr :length
650 * def initialize(n)
651 * @length = n
652 * end
653 * def succ
654 * Xs.new(@length + 1)
655 * end
656 * def <=>(other)
657 * @length <=> other.length
658 * end
659 * def to_s
660 * sprintf "%2d #{inspect}", @length
661 * end
662 * def inspect
663 * 'x' * @length
664 * end
665 * end
666 *
667 * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
668 * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
669 * r.member?(Xs.new(5)) #=> true
670 *
671 * In the previous code example, class <code>Xs</code> includes the
672 * <code>Comparable</code> module. This is because
673 * <code>Enumerable#member?</code> checks for equality using
674 * <code>==</code>. Including <code>Comparable</code> ensures that the
675 * <code>==</code> method is defined in terms of the <code><=></code>
676 * method implemented in <code>Xs</code>.
677 *
678 */
679
99d0354 Initial revision
matz authored
680 void
681 Init_Range()
682 {
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
683 rb_cRange = rb_define_class("Range", rb_cObject);
684 rb_include_module(rb_cRange, rb_mEnumerable);
5928d4c 2000-02-29
matz authored
685 rb_define_method(rb_cRange, "initialize", range_initialize, -1);
5c51be8 matz
matz authored
686 rb_define_method(rb_cRange, "==", range_eq, 1);
eca0b53 * parse.y (yylex): obsolete '?<whitespace>'; use '?\s', '?\n',
matz authored
687 rb_define_method(rb_cRange, "===", range_include, 1);
7b1e0f2 * file.c (path_check_1): forgot to initialize 'p'.
matz authored
688 rb_define_method(rb_cRange, "eql?", range_eql, 1);
689 rb_define_method(rb_cRange, "hash", range_hash, 0);
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
690 rb_define_method(rb_cRange, "each", range_each, 0);
299d4e6 * range.c (range_step): new method.
matz authored
691 rb_define_method(rb_cRange, "step", range_step, -1);
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
692 rb_define_method(rb_cRange, "first", range_first, 0);
693 rb_define_method(rb_cRange, "last", range_last, 0);
694 rb_define_method(rb_cRange, "begin", range_first, 0);
695 rb_define_method(rb_cRange, "end", range_last, 0);
696 rb_define_method(rb_cRange, "to_s", range_to_s, 0);
697 rb_define_method(rb_cRange, "inspect", range_inspect, 0);
698
07bb9f2 1.4.0
matz authored
699 rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
700
2281c5b * io.c (read_all): block string buffer modification during
matz authored
701 rb_define_method(rb_cRange, "member?", range_include, 1);
90b8654 * eval.c (rb_eval): ruby_frame->last_func may be null, if it's
matz authored
702 rb_define_method(rb_cRange, "include?", range_include, 1);
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
703
704 id_cmp = rb_intern("<=>");
b53fdf2 * ruby.c (proc_options): unexpected SecurityError happens when -T4.
matz authored
705 id_succ = rb_intern("succ");
a2af08d This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
706 id_beg = rb_intern("begin");
707 id_end = rb_intern("end");
5c51be8 matz
matz authored
708 id_excl = rb_intern("excl");
99d0354 Initial revision
matz authored
709 }
Something went wrong with that request. Please try again.