Skip to content

HTTPS clone URL

Subversion checkout URL

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