supplement 1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE +34 -0
- data/README +50 -0
- data/examples/teatimer +87 -0
- data/lib/Rakefile +32 -0
- data/lib/mkrf_conf +41 -0
- data/lib/supplement.c +1657 -0
- data/lib/supplement.h +83 -0
- data/lib/supplement/date.rb +53 -0
- data/lib/supplement/filesys.c +395 -0
- data/lib/supplement/filesys.h +35 -0
- data/lib/supplement/itimer.c +126 -0
- data/lib/supplement/itimer.h +17 -0
- data/lib/supplement/terminal.c +144 -0
- data/lib/supplement/terminal.h +21 -0
- data/lib/sync.c +34 -0
- data/lib/sync.h +13 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MWJlMThjNWM2NDk3ZmFiMWQ3Y2ZkYWIwZjg2YzhlYjgxYWZjOTE5Mw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MGZhYmI5YjQxMWQ0MjNiN2Y0YzVhZjcxY2VmZTkwZWU0YzQ2ZDg4Nw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
Y2M2MTcyZGEyMGMxZjFiZTdjNDM5NzM3OWFjNjRiMzQ4Y2I3MmUxZmNjZTQ4
|
10
|
+
MTkyNTNlOTk5NTlkNzhlZmExODE3NmEzZTMxYjBkMzU3ZDY3NTNlMjcxMTQ4
|
11
|
+
N2ViZWM2YWFjNjMzNTkwNjhhOWRhZDlhNWE1Njg3NmMyMDYxMzA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDhjNzViMTYzNTljZGNkNzQwYTAyMTI2YWIzYzNlODA3ZWRjZmI0MThlOTUx
|
14
|
+
OWUyMmRkYjQwYjcyNWZlNWZkYWFlZTFkMzY4MjFlOTcwYmQxNTQzNjY1ZmU3
|
15
|
+
NDgwNTljMGU4NzNlYzgxMjk4N2Y4MWZjZTEwMGY1NTM2M2VhZDk=
|
data/LICENSE
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
_ _
|
2
|
+
___ _ _ _ __ _ __ | | ___ _ __ ___ ___ _ __ | |_
|
3
|
+
/ __| | | | '_ \| '_ \| |/ _ \ '_ ` _ \ / _ \ '_ \| __|
|
4
|
+
\__ \ |_| | |_) | |_) | | __/ | | | | | __/ | | | |_
|
5
|
+
|___/\__,_| .__/| .__/|_|\___|_| |_| |_|\___|_| |_|\__|
|
6
|
+
|_| |_|
|
7
|
+
|
8
|
+
Copyright (c) 2009-2013, Bertram Scharpf <software@bertram-scharpf.de>.
|
9
|
+
All rights reserved.
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
12
|
+
modification, are permitted provided that the following conditions are
|
13
|
+
met:
|
14
|
+
|
15
|
+
* Redistributions of source code must retain the above copyright
|
16
|
+
notice, this list of conditions and the following disclaimer.
|
17
|
+
|
18
|
+
* Redistributions in binary form must reproduce the above copyright
|
19
|
+
notice, this list of conditions and the following disclaimer in
|
20
|
+
the documentation and/or other materials provided with the
|
21
|
+
distribution.
|
22
|
+
|
23
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
24
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
25
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
26
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
27
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
28
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
33
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
data/README
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= supplement 1.6 -- Useful Ruby enhancements
|
2
|
+
|
3
|
+
Some simple Ruby extensions.
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
These are methods on standard classes that didn't manage to become part of
|
8
|
+
the Ruby interpreter. (Although, some are part of Ruby 1.9/1.8.7 but not
|
9
|
+
1.8.6).
|
10
|
+
|
11
|
+
They are all very small, most of them have less than 15 lines of code.
|
12
|
+
So they would not be a weight in the Ruby interpreter but it is very
|
13
|
+
difficult to convince a majority that they belong there.
|
14
|
+
|
15
|
+
The methods won't be useful for everybody but some programmers may like
|
16
|
+
to make them part of their programming style.
|
17
|
+
|
18
|
+
If you like to get taunted, then go to the Ruby mailing list and propose
|
19
|
+
one of them to be included into the Ruby standard.
|
20
|
+
|
21
|
+
== Intention
|
22
|
+
|
23
|
+
In my own code I use quite often a method <code>String#notempty?</code>
|
24
|
+
that does almost the same as <code>Numeric#nonzero?</code>. Every
|
25
|
+
attempt proposing it for the Ruby standard implementation has failed;
|
26
|
+
the discussion evolves the same every time.
|
27
|
+
|
28
|
+
Now here it is where I can just point to.
|
29
|
+
|
30
|
+
== Contents (uncomplete)
|
31
|
+
|
32
|
+
* String#notempty?
|
33
|
+
* String#clear
|
34
|
+
* String#head
|
35
|
+
* String#tail
|
36
|
+
* String#rest
|
37
|
+
* String#start_with?
|
38
|
+
* String#end_with?
|
39
|
+
* Array#notempty?
|
40
|
+
* Hash#notempty?
|
41
|
+
* Struct.[]
|
42
|
+
* Interval timer
|
43
|
+
* File system stats
|
44
|
+
* File#flockb using a block
|
45
|
+
|
46
|
+
== Warning
|
47
|
+
|
48
|
+
The RDoc in this project doesn't work properly. If in doubt, refer to the
|
49
|
+
source code.
|
50
|
+
|
data/examples/teatimer
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# teatimer -- Countdown timer
|
5
|
+
#
|
6
|
+
|
7
|
+
# This is an example application for the itimer library.
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# $ teatimer 3m play bell.wav
|
11
|
+
# # Count down 3 minutes and the exec the player.
|
12
|
+
#
|
13
|
+
|
14
|
+
require "supplement/itimer"
|
15
|
+
|
16
|
+
|
17
|
+
class TeaTimer
|
18
|
+
|
19
|
+
M = 60
|
20
|
+
H = 60 * M
|
21
|
+
|
22
|
+
class <<self
|
23
|
+
|
24
|
+
def from_str time
|
25
|
+
seconds = case time
|
26
|
+
when /m\z/ then Integer( $`) * M
|
27
|
+
when /h\z/ then Integer( $`) * H
|
28
|
+
else divide_colons time
|
29
|
+
end
|
30
|
+
new seconds
|
31
|
+
end
|
32
|
+
|
33
|
+
def run time
|
34
|
+
t = from_str time
|
35
|
+
t.run
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def divide_colons time
|
41
|
+
a = time.split ":", -1
|
42
|
+
a.map! { |x| Integer( x) }
|
43
|
+
a.reverse!
|
44
|
+
r = a.shift
|
45
|
+
if a.first then r += M * a.shift end
|
46
|
+
if a.first then r += H * a.shift end
|
47
|
+
a.empty? or raise "Illegal time spec: #{time}."
|
48
|
+
r
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize seconds
|
54
|
+
@seconds = seconds
|
55
|
+
end
|
56
|
+
|
57
|
+
class Done < Exception ; end
|
58
|
+
|
59
|
+
def run
|
60
|
+
trap "SIGALRM" do
|
61
|
+
@seconds -= 1
|
62
|
+
print_rest
|
63
|
+
raise Done if @seconds.zero?
|
64
|
+
end
|
65
|
+
Process.setitimer 1
|
66
|
+
print_rest
|
67
|
+
sleep
|
68
|
+
rescue Done
|
69
|
+
puts
|
70
|
+
ensure
|
71
|
+
trap "SIGALRM", "DEFAULT"
|
72
|
+
Process.setitimer nil
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def print_rest
|
78
|
+
$stdout.print " \r%02d:%02d:%02d" %
|
79
|
+
[ @seconds / H, @seconds % H / M, @seconds % M]
|
80
|
+
$stdout.flush
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
TeaTimer.run $*.first =~ /\A\d+/ ? $*.shift : "3m"
|
86
|
+
exec *$* if $*.any?
|
87
|
+
|
data/lib/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Rakefile -- build some libraries
|
3
|
+
#
|
4
|
+
|
5
|
+
require "autorake"
|
6
|
+
|
7
|
+
c = compiler "-O2", "-fPIC"
|
8
|
+
l = linker "-shared"
|
9
|
+
|
10
|
+
rule ".o" => ".c" do |t|
|
11
|
+
c.cc t.name, t.source
|
12
|
+
end
|
13
|
+
|
14
|
+
DLs = {
|
15
|
+
"supplement.so" => %w(supplement.o sync.o),
|
16
|
+
"supplement/filesys.so" => %w(supplement/filesys.o),
|
17
|
+
"supplement/itimer.so" => %w(supplement/itimer.o),
|
18
|
+
"supplement/terminal.so" => %w(supplement/terminal.o),
|
19
|
+
}
|
20
|
+
|
21
|
+
DLs.each { |k,v|
|
22
|
+
task k => v do |t|
|
23
|
+
l.cc t.name, t.prerequisites
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
task :default => DLs.keys
|
28
|
+
|
29
|
+
task :clean do
|
30
|
+
FileList[ "**/*.o", "**/*.so"].each { |f| rm_f f }
|
31
|
+
end
|
32
|
+
|
data/lib/mkrf_conf
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# mkrf_conf -- configure Supplement
|
5
|
+
#
|
6
|
+
|
7
|
+
require "autorake/mkconfig"
|
8
|
+
|
9
|
+
Autorake.configure {
|
10
|
+
|
11
|
+
extending_ruby
|
12
|
+
|
13
|
+
if RUBY_VERSION < "1.9.2" then
|
14
|
+
enable :array_select_bang
|
15
|
+
if RUBY_VERSION < "1.9" then
|
16
|
+
enable :string_ord
|
17
|
+
enable :string_clear
|
18
|
+
if RUBY_VERSION < "1.8.7" then
|
19
|
+
enable :array_index_with_block
|
20
|
+
enable :kernel_tap
|
21
|
+
enable :string_start_with
|
22
|
+
enable :thread_exclusive
|
23
|
+
end
|
24
|
+
have_header "rubysig.h"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if RUBY_VERSION < "1.9" then
|
29
|
+
have_header "ruby.h"
|
30
|
+
have_header "st.h"
|
31
|
+
have_header "rubyio.h"
|
32
|
+
have_header "re.h"
|
33
|
+
else
|
34
|
+
have_header "ruby/ruby.h"
|
35
|
+
have_header "ruby/st.h"
|
36
|
+
have_header "ruby/io.h"
|
37
|
+
have_header "ruby/re.h"
|
38
|
+
end
|
39
|
+
|
40
|
+
}
|
41
|
+
|
data/lib/supplement.c
ADDED
@@ -0,0 +1,1657 @@
|
|
1
|
+
/*
|
2
|
+
* supplement.c -- Simple Ruby Extensions
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "supplement.h"
|
6
|
+
|
7
|
+
#include "sync.h"
|
8
|
+
|
9
|
+
#if HAVE_HEADER_ST_H
|
10
|
+
#include <st.h>
|
11
|
+
#elif HAVE_HEADER_RUBY_ST_H
|
12
|
+
#include <ruby/st.h>
|
13
|
+
#endif
|
14
|
+
#if HAVE_HEADER_RUBYIO_H
|
15
|
+
#include <rubyio.h>
|
16
|
+
#elif HAVE_HEADER_RUBY_IO_H
|
17
|
+
#include <ruby/io.h>
|
18
|
+
#endif
|
19
|
+
#if HAVE_HEADER_RE_H
|
20
|
+
#include <re.h>
|
21
|
+
#elif HAVE_HEADER_RUBY_RE_H
|
22
|
+
#include <ruby/re.h>
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#ifdef FEATURE_THREAD_EXCLUSIVE
|
26
|
+
#ifdef HAVE_HEADER_RUBYSIG_H
|
27
|
+
#include <rubysig.h>
|
28
|
+
#endif
|
29
|
+
#endif
|
30
|
+
|
31
|
+
|
32
|
+
#include <sys/stat.h>
|
33
|
+
#include <sys/file.h>
|
34
|
+
#include <math.h>
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
#ifdef HAVE_HEADER_RUBY_H
|
39
|
+
/* Oh what a bug! */
|
40
|
+
#define R_MATCH( obj) RMATCH( obj)
|
41
|
+
#else
|
42
|
+
#endif
|
43
|
+
|
44
|
+
|
45
|
+
struct supplement_flock {
|
46
|
+
struct supplement_flock *prev;
|
47
|
+
VALUE file;
|
48
|
+
int op;
|
49
|
+
int last_op;
|
50
|
+
};
|
51
|
+
|
52
|
+
static struct supplement_flock *flocks_root = NULL;
|
53
|
+
|
54
|
+
|
55
|
+
static VALUE supplement_index_blk( VALUE);
|
56
|
+
static VALUE supplement_rindex_blk( VALUE);
|
57
|
+
#ifdef FEATURE_ARRAY_INDEX_WITH_BLOCK
|
58
|
+
static VALUE supplement_index_val( VALUE, VALUE);
|
59
|
+
static VALUE supplement_rindex_val( VALUE, VALUE);
|
60
|
+
#endif
|
61
|
+
#ifdef FEATURE_ARRAY_SELECT_BANG
|
62
|
+
static VALUE supplement_reject( VALUE);
|
63
|
+
static VALUE supplement_invert_yield( VALUE);
|
64
|
+
#endif
|
65
|
+
static VALUE supplement_each_line( VALUE);
|
66
|
+
static void supplement_init_flock( struct supplement_flock *, VALUE, VALUE);
|
67
|
+
static VALUE supplement_do_unflock( VALUE);
|
68
|
+
static VALUE supplement_do_unumask( VALUE);
|
69
|
+
static VALUE supplement_chdir( VALUE);
|
70
|
+
#ifdef FEATURE_THREAD_EXCLUSIVE
|
71
|
+
static VALUE bsruby_set_thread_critical( VALUE);
|
72
|
+
#endif
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
static ID id_delete_at;
|
77
|
+
static ID id_cmp;
|
78
|
+
static ID id_eqq;
|
79
|
+
#ifdef FEATURE_ARRAY_SELECT_BANG
|
80
|
+
static ID id_reject_bang;
|
81
|
+
#endif
|
82
|
+
static ID id_chdir;
|
83
|
+
static ID id_path;
|
84
|
+
static ID id_mkdir;
|
85
|
+
static ID id_index;
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Document-class: Object
|
91
|
+
*/
|
92
|
+
|
93
|
+
/*
|
94
|
+
* call-seq:
|
95
|
+
* new_string -> str
|
96
|
+
*
|
97
|
+
* Returns another string that may be modified without touching the original
|
98
|
+
* object. This means +dup+ for a string and +to_s+ for any other object.
|
99
|
+
*
|
100
|
+
* If a block is given, that may modify a created string (built from a
|
101
|
+
* non-string object). For a dup'ed string object the block will not be
|
102
|
+
* called.
|
103
|
+
*/
|
104
|
+
|
105
|
+
VALUE
|
106
|
+
rb_obj_new_string( VALUE obj)
|
107
|
+
{
|
108
|
+
VALUE r;
|
109
|
+
|
110
|
+
r = rb_obj_as_string( obj);
|
111
|
+
if (rb_block_given_p())
|
112
|
+
rb_yield( r);
|
113
|
+
return r;
|
114
|
+
}
|
115
|
+
|
116
|
+
|
117
|
+
/*
|
118
|
+
* call-seq:
|
119
|
+
* nil_if val -> nil or self
|
120
|
+
*
|
121
|
+
* Returns +nil+ when the string matches +val+. +val+ is compared using
|
122
|
+
* the <code>===</code> operator, just like in the case statement.
|
123
|
+
*
|
124
|
+
* "hello".nil_if "NONE" #=> "hello"
|
125
|
+
* "NONE".nil_if "NONE" #=> nil
|
126
|
+
* "NONE".nil_if /^none$/i #=> nil
|
127
|
+
*
|
128
|
+
* 20.nil_if 10 #=> 20
|
129
|
+
* 10.nil_if 10 #=> nil
|
130
|
+
* 1.0.nil_if Float #=> nil
|
131
|
+
*
|
132
|
+
*/
|
133
|
+
|
134
|
+
VALUE
|
135
|
+
rb_obj_nil_if( VALUE obj, VALUE val)
|
136
|
+
{
|
137
|
+
if (!id_eqq)
|
138
|
+
id_eqq = rb_intern( "===");
|
139
|
+
return RTEST( rb_funcall( val, id_eqq, 1, obj)) ? Qnil : obj;
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
/*
|
144
|
+
* Document-module: Kernel
|
145
|
+
*/
|
146
|
+
|
147
|
+
#ifdef FEATURE_KERNEL_TAP
|
148
|
+
|
149
|
+
/*
|
150
|
+
* call-seq:
|
151
|
+
* tap { |x| ... } -> obj
|
152
|
+
*
|
153
|
+
* Yields <code>x</code> to the block, and then returns <code>x</code>.
|
154
|
+
* The primary purpose of this method is to "tap into" a method chain,
|
155
|
+
* in order to perform operations on intermediate results within the chain.
|
156
|
+
*
|
157
|
+
* (1..10) .tap { |x| puts "original: #{x.inspect}" }
|
158
|
+
* .to_a .tap { |x| puts "array: #{x.inspect}" }
|
159
|
+
* .select { |x| x%2==0 } .tap { |x| puts "evens: #{x.inspect}" }
|
160
|
+
* .map { |x| x*x } .tap { |x| puts "squares: #{x.inspect}" }
|
161
|
+
*
|
162
|
+
*/
|
163
|
+
|
164
|
+
VALUE
|
165
|
+
rb_krn_tap( VALUE obj)
|
166
|
+
{
|
167
|
+
rb_yield( obj);
|
168
|
+
return obj;
|
169
|
+
}
|
170
|
+
|
171
|
+
#endif
|
172
|
+
|
173
|
+
/*
|
174
|
+
* call-seq:
|
175
|
+
* tap! { |x| ... } -> obj
|
176
|
+
*
|
177
|
+
* Yields +x+ to the block, and then returns +x+ if and only
|
178
|
+
* if +x+ is not +nil+.
|
179
|
+
*
|
180
|
+
*/
|
181
|
+
|
182
|
+
VALUE
|
183
|
+
rb_krn_tap_bang( VALUE obj)
|
184
|
+
{
|
185
|
+
if (!NIL_P( obj))
|
186
|
+
rb_yield( obj);
|
187
|
+
return obj;
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
/*
|
192
|
+
* Document-class: NilClass
|
193
|
+
*/
|
194
|
+
|
195
|
+
/*
|
196
|
+
* call-seq:
|
197
|
+
* notempty? -> nil
|
198
|
+
*
|
199
|
+
* This spares testing for +nil+ when checking strings.
|
200
|
+
*/
|
201
|
+
|
202
|
+
VALUE
|
203
|
+
rb_nil_notempty_p( VALUE str)
|
204
|
+
{
|
205
|
+
return Qnil;
|
206
|
+
}
|
207
|
+
|
208
|
+
/*
|
209
|
+
* Document-method: nonzero?
|
210
|
+
*
|
211
|
+
* call-seq:
|
212
|
+
* nonzero? -> nil
|
213
|
+
*
|
214
|
+
* This spares testing for +nil+ when checking numbers.
|
215
|
+
*/
|
216
|
+
|
217
|
+
/*
|
218
|
+
* Document-method: each_line
|
219
|
+
*
|
220
|
+
* call-seq:
|
221
|
+
* each_line { |l| ... } -> nil
|
222
|
+
*
|
223
|
+
* This spares testing for +nil+ when checking strings.
|
224
|
+
*/
|
225
|
+
|
226
|
+
VALUE
|
227
|
+
rb_nil_each_line( VALUE str)
|
228
|
+
{
|
229
|
+
RETURN_ENUMERATOR( str, 0, 0);
|
230
|
+
return Qnil;
|
231
|
+
}
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
/*
|
236
|
+
* Document-class: String
|
237
|
+
*/
|
238
|
+
|
239
|
+
|
240
|
+
/*
|
241
|
+
* call-seq:
|
242
|
+
* new_string -> str
|
243
|
+
*
|
244
|
+
* Returns another string that may be modified without touching the original
|
245
|
+
* object. This means +dup+ for a string and +to_s+ for any other object.
|
246
|
+
*
|
247
|
+
*/
|
248
|
+
|
249
|
+
VALUE
|
250
|
+
rb_str_new_string( VALUE obj)
|
251
|
+
{
|
252
|
+
return rb_str_dup( obj);
|
253
|
+
}
|
254
|
+
|
255
|
+
|
256
|
+
/*
|
257
|
+
* call-seq:
|
258
|
+
* notempty? -> nil or self
|
259
|
+
*
|
260
|
+
* Returns <code>self</code> if and only if <code>str</code> is not
|
261
|
+
* empty, <code>nil</code> otherwise.
|
262
|
+
*
|
263
|
+
* "hello".notempty? #=> "hello"
|
264
|
+
* "".notempty? #=> nil
|
265
|
+
*/
|
266
|
+
|
267
|
+
VALUE
|
268
|
+
rb_str_notempty_p( VALUE str)
|
269
|
+
{
|
270
|
+
#if 0
|
271
|
+
/* Ruby Coding style */
|
272
|
+
if (RSTRING_LEN( str) == 0)
|
273
|
+
return Qnil;
|
274
|
+
return str;
|
275
|
+
#else
|
276
|
+
return RSTRING_LEN( str) ? str : Qnil;
|
277
|
+
#endif
|
278
|
+
}
|
279
|
+
|
280
|
+
|
281
|
+
/*
|
282
|
+
* call-seq:
|
283
|
+
* eat( n = nil) -> str
|
284
|
+
*
|
285
|
+
* Returns first <code>n</code> characters of <code>self</code> or
|
286
|
+
* whole string if <code>n</code> is <code>nil</code>. The returned
|
287
|
+
* substring will be deleted from <code>self</code>. If <code>n</code>
|
288
|
+
* is negative, characters will be eaten from the right.
|
289
|
+
*
|
290
|
+
* a = "upcase"
|
291
|
+
* a.eat 2 #=> "up"
|
292
|
+
* a #=> "case"
|
293
|
+
*/
|
294
|
+
|
295
|
+
VALUE
|
296
|
+
rb_str_eat( int argc, VALUE *argv, VALUE str)
|
297
|
+
{
|
298
|
+
VALUE val;
|
299
|
+
int n;
|
300
|
+
int l;
|
301
|
+
int r;
|
302
|
+
|
303
|
+
#ifdef HAVE_HEADER_RUBY_H
|
304
|
+
n = l = RSTRING_LEN( str);
|
305
|
+
#else
|
306
|
+
n = l = rb_str_strlen( str);
|
307
|
+
#endif
|
308
|
+
if (rb_scan_args( argc, argv, "01", &val) == 1) {
|
309
|
+
if (!NIL_P( val)) {
|
310
|
+
int v = NUM2INT( val);
|
311
|
+
if (v >= 0) {
|
312
|
+
if (n >= v) n = v;
|
313
|
+
} else {
|
314
|
+
n = -n;
|
315
|
+
if (n <= v) n = v;
|
316
|
+
}
|
317
|
+
}
|
318
|
+
}
|
319
|
+
rb_str_modify( str);
|
320
|
+
#ifdef HAVE_HEADER_RUBY_H
|
321
|
+
if (n > 0) {
|
322
|
+
r = l - n;
|
323
|
+
val = rb_str_new5( str, RSTRING_PTR( str), n);
|
324
|
+
memmove( RSTRING_PTR( str), RSTRING_PTR( str) + n, r);
|
325
|
+
} else {
|
326
|
+
r = l + n;
|
327
|
+
val = rb_str_new5( str, RSTRING_PTR( str) + r, -n);
|
328
|
+
}
|
329
|
+
RSTRING_LEN( str) = r;
|
330
|
+
OBJ_INFECT( val, str);
|
331
|
+
#else
|
332
|
+
if (n > 0) {
|
333
|
+
r = 0;
|
334
|
+
} else if (n < 0) {
|
335
|
+
r = l + n;
|
336
|
+
n = -n;
|
337
|
+
} else
|
338
|
+
return Qnil;
|
339
|
+
val = rb_str_substr( str, r, n);
|
340
|
+
if (!NIL_P(val))
|
341
|
+
rb_str_update( str, r, n, rb_str_new( NULL, 0));
|
342
|
+
#endif
|
343
|
+
return val;
|
344
|
+
}
|
345
|
+
|
346
|
+
|
347
|
+
/*
|
348
|
+
* call-seq:
|
349
|
+
* cut!( length) -> str
|
350
|
+
*
|
351
|
+
* Cut string to <code>length</code>. If nothing was removed,
|
352
|
+
* <code>nil</code> is returned.
|
353
|
+
*
|
354
|
+
* a = "hello"
|
355
|
+
* a.cut! 4 #=> "hell"
|
356
|
+
* a #=> "hell"
|
357
|
+
* a.cut! 4 #=> nil
|
358
|
+
*/
|
359
|
+
|
360
|
+
VALUE
|
361
|
+
rb_str_cut_bang( VALUE str, VALUE len)
|
362
|
+
{
|
363
|
+
int l;
|
364
|
+
#ifdef HAVE_HEADER_RUBY_H
|
365
|
+
#else
|
366
|
+
int n;
|
367
|
+
#endif
|
368
|
+
|
369
|
+
rb_str_modify( str);
|
370
|
+
l = NUM2INT( len);
|
371
|
+
if (l < 0)
|
372
|
+
l = 0;
|
373
|
+
#ifdef HAVE_HEADER_RUBY_H
|
374
|
+
if (l < RSTRING_LEN( str)) {
|
375
|
+
RSTRING_LEN( str) = l;
|
376
|
+
return str;
|
377
|
+
}
|
378
|
+
#else
|
379
|
+
n = rb_str_strlen( str);
|
380
|
+
if (l < n) {
|
381
|
+
rb_str_update( str, l, n - l, rb_str_new( NULL, 0));
|
382
|
+
return str;
|
383
|
+
}
|
384
|
+
#endif
|
385
|
+
return Qnil;
|
386
|
+
}
|
387
|
+
|
388
|
+
|
389
|
+
#ifdef FEATURE_STRING_CLEAR
|
390
|
+
|
391
|
+
/*
|
392
|
+
* call-seq:
|
393
|
+
* clear -> self
|
394
|
+
*
|
395
|
+
* Set to empty string. Equivalent to <code>str.replace ""</code>.
|
396
|
+
*
|
397
|
+
* a = "hello" #=> "hello"
|
398
|
+
* a.clear #=> ""
|
399
|
+
* a.empty? #=> true
|
400
|
+
*/
|
401
|
+
|
402
|
+
VALUE
|
403
|
+
rb_str_clear( VALUE str)
|
404
|
+
{
|
405
|
+
rb_str_modify( str);
|
406
|
+
rb_str_resize( str, 0);
|
407
|
+
return str;
|
408
|
+
}
|
409
|
+
|
410
|
+
#endif
|
411
|
+
|
412
|
+
|
413
|
+
/*
|
414
|
+
* call-seq:
|
415
|
+
* head( n = 1) -> str
|
416
|
+
*
|
417
|
+
* Returns first <code>n</code> bytes in <code>str</code>.
|
418
|
+
*
|
419
|
+
* "hello".head( 2) #=> "he"
|
420
|
+
*/
|
421
|
+
|
422
|
+
VALUE
|
423
|
+
rb_str_head( int argc, VALUE *argv, VALUE str)
|
424
|
+
{
|
425
|
+
VALUE n;
|
426
|
+
VALUE str2;
|
427
|
+
long len;
|
428
|
+
|
429
|
+
len = rb_scan_args( argc, argv, "01", &n) == 1 ? NUM2LONG( n) : 1;
|
430
|
+
return rb_str_substr( str, 0, len);
|
431
|
+
}
|
432
|
+
|
433
|
+
|
434
|
+
/*
|
435
|
+
* call-seq:
|
436
|
+
* rest( n = 1) -> str
|
437
|
+
*
|
438
|
+
* Return rest after <code>n</code> bytes in <code>str</code>.
|
439
|
+
*
|
440
|
+
* "hello".rest( 2) #=> "llo"
|
441
|
+
*/
|
442
|
+
|
443
|
+
VALUE
|
444
|
+
rb_str_rest( int argc, VALUE *argv, VALUE str)
|
445
|
+
{
|
446
|
+
VALUE n;
|
447
|
+
long l, beg, len;
|
448
|
+
|
449
|
+
beg = rb_scan_args( argc, argv, "01", &n) == 1 ? NUM2LONG( n) : 1;
|
450
|
+
if (beg < 0)
|
451
|
+
beg = 0;
|
452
|
+
#ifdef HAVE_HEADER_RUBY_H
|
453
|
+
l = RSTRING_LEN( str);
|
454
|
+
#else
|
455
|
+
l = rb_str_strlen( str);
|
456
|
+
#endif
|
457
|
+
return rb_str_substr( str, beg, l - beg);
|
458
|
+
}
|
459
|
+
|
460
|
+
|
461
|
+
/*
|
462
|
+
* call-seq:
|
463
|
+
* tail( n = 1) -> str
|
464
|
+
*
|
465
|
+
* Returns last <code>n</code> bytes in <code>str</code>.
|
466
|
+
*
|
467
|
+
* "hello".tail( 2) #=> "lo"
|
468
|
+
*/
|
469
|
+
|
470
|
+
VALUE
|
471
|
+
rb_str_tail( int argc, VALUE *argv, VALUE str)
|
472
|
+
{
|
473
|
+
VALUE n;
|
474
|
+
long l, beg, len;
|
475
|
+
|
476
|
+
len = rb_scan_args( argc, argv, "01", &n) == 1 ? NUM2LONG( n) : 1;
|
477
|
+
#ifdef HAVE_HEADER_RUBY_H
|
478
|
+
l = RSTRING_LEN( str);
|
479
|
+
#else
|
480
|
+
l = rb_str_strlen( str);
|
481
|
+
#endif
|
482
|
+
beg = l - len;
|
483
|
+
if (beg < 0)
|
484
|
+
beg = 0, len = l;
|
485
|
+
return rb_str_substr( str, beg, len);
|
486
|
+
}
|
487
|
+
|
488
|
+
|
489
|
+
#ifdef FEATURE_STRING_START_WITH
|
490
|
+
|
491
|
+
/*
|
492
|
+
* call-seq:
|
493
|
+
* start_with?( oth) -> true or false
|
494
|
+
*
|
495
|
+
* Checks whether the head is <code>oth</code>.
|
496
|
+
*
|
497
|
+
* "sys-apps".start_with?( "sys-") #=> true
|
498
|
+
*/
|
499
|
+
|
500
|
+
VALUE
|
501
|
+
rb_str_start_with_p( VALUE str, VALUE oth)
|
502
|
+
{
|
503
|
+
return NIL_P( rb_str_starts_with_p( str, oth)) ? Qfalse : Qtrue;
|
504
|
+
}
|
505
|
+
|
506
|
+
|
507
|
+
/*
|
508
|
+
* call-seq:
|
509
|
+
* end_with?( oth) -> true or false
|
510
|
+
*
|
511
|
+
* Checks whether the tail is <code>oth</code>.
|
512
|
+
*
|
513
|
+
* "sys-apps".end_with?( "-apps") #=> true
|
514
|
+
*/
|
515
|
+
|
516
|
+
VALUE
|
517
|
+
rb_str_end_with_p( VALUE str, VALUE oth)
|
518
|
+
{
|
519
|
+
return NIL_P( rb_str_ends_with_p( str, oth)) ? Qfalse : Qtrue;
|
520
|
+
}
|
521
|
+
|
522
|
+
#endif
|
523
|
+
|
524
|
+
/*
|
525
|
+
* call-seq:
|
526
|
+
* starts_with?( oth) -> nil or int
|
527
|
+
*
|
528
|
+
* Checks whether the head is <code>oth</code>. Returns length of
|
529
|
+
* <code>oth</code> when matching.
|
530
|
+
*
|
531
|
+
* "sys-apps".starts_with?( "sys-") #=> 4
|
532
|
+
*
|
533
|
+
* Caution! The Ruby 1.9.3 method #start_with? (notice the missing s)
|
534
|
+
* just returns +true+ or +false+.
|
535
|
+
*/
|
536
|
+
|
537
|
+
VALUE
|
538
|
+
rb_str_starts_with_p( VALUE str, VALUE oth)
|
539
|
+
{
|
540
|
+
long i;
|
541
|
+
char *s, *o;
|
542
|
+
VALUE ost;
|
543
|
+
|
544
|
+
#ifdef HAVE_HEADER_RUBY_H
|
545
|
+
#else
|
546
|
+
if (!rb_str_comparable( str, oth))
|
547
|
+
return Qnil;
|
548
|
+
#endif
|
549
|
+
ost = rb_string_value( &oth);
|
550
|
+
i = RSTRING_LEN( ost);
|
551
|
+
if (i > RSTRING_LEN( str))
|
552
|
+
return Qnil;
|
553
|
+
s = RSTRING_PTR( str);
|
554
|
+
o = RSTRING_PTR( ost);
|
555
|
+
for (; i; i--, s++, o++) {
|
556
|
+
if (*s != *o)
|
557
|
+
return Qnil;
|
558
|
+
}
|
559
|
+
#ifdef HAVE_HEADER_RUBY_H
|
560
|
+
return INT2FIX( RSTRING_LEN( ost));
|
561
|
+
#else
|
562
|
+
return INT2FIX( rb_str_strlen( ost));
|
563
|
+
#endif
|
564
|
+
}
|
565
|
+
|
566
|
+
|
567
|
+
/*
|
568
|
+
* call-seq:
|
569
|
+
* ends_with?( oth) -> nil or int
|
570
|
+
*
|
571
|
+
* Checks whether the tail is <code>oth</code>. Returns the position
|
572
|
+
* where <code>oth</code> starts when matching.
|
573
|
+
*
|
574
|
+
* "sys-apps".ends_with?( "-apps") #=> 3
|
575
|
+
*
|
576
|
+
* Caution! The Ruby 1.9.3 method #start_with? (notice the missing s)
|
577
|
+
* just returns +true+ or +false+.
|
578
|
+
*/
|
579
|
+
|
580
|
+
VALUE
|
581
|
+
rb_str_ends_with_p( VALUE str, VALUE oth)
|
582
|
+
{
|
583
|
+
long i;
|
584
|
+
char *s, *o;
|
585
|
+
VALUE ost;
|
586
|
+
|
587
|
+
#ifdef HAVE_HEADER_RUBY_H
|
588
|
+
#else
|
589
|
+
if (!rb_str_comparable( str, oth))
|
590
|
+
return Qnil;
|
591
|
+
#endif
|
592
|
+
ost = rb_string_value( &oth);
|
593
|
+
i = RSTRING_LEN( ost);
|
594
|
+
if (i > RSTRING_LEN( str))
|
595
|
+
return Qnil;
|
596
|
+
s = RSTRING_END( str);
|
597
|
+
o = RSTRING_END( ost);
|
598
|
+
for (; i; i--)
|
599
|
+
if (*--s != *--o)
|
600
|
+
return Qnil;
|
601
|
+
#ifdef HAVE_HEADER_RUBY_H
|
602
|
+
return INT2FIX( RSTRING_LEN( str) - RSTRING_LEN( ost));
|
603
|
+
#else
|
604
|
+
return INT2FIX( rb_str_strlen( str) - rb_str_strlen( ost));
|
605
|
+
#endif
|
606
|
+
}
|
607
|
+
|
608
|
+
#ifdef FEATURE_STRING_ORD
|
609
|
+
|
610
|
+
/*
|
611
|
+
* call-seq:
|
612
|
+
* ord() -> nil or int
|
613
|
+
*
|
614
|
+
* Returns the ASCII value of the first character, if any.
|
615
|
+
*
|
616
|
+
* Caution! For UTF-8 characters, this will return the first byte's value.
|
617
|
+
* This will do no harm in Ruby 1.8 but the standard Ruby 1.9 +String#ord+
|
618
|
+
* returns the first codepoint. Please do not overwrite that method.
|
619
|
+
*/
|
620
|
+
|
621
|
+
VALUE rb_str_ord( VALUE str)
|
622
|
+
{
|
623
|
+
return RSTRING_LEN( str) > 0 ? INT2FIX( RSTRING_PTR( str)[ 0]) : Qnil;
|
624
|
+
}
|
625
|
+
|
626
|
+
#endif
|
627
|
+
|
628
|
+
/*
|
629
|
+
* call-seq:
|
630
|
+
* axe( n = 80) -> str
|
631
|
+
*
|
632
|
+
* Cut off everthing beyond then <code>n</code>th character. Replace the
|
633
|
+
* last bytes by ellipses.
|
634
|
+
*
|
635
|
+
* a = "Redistribution and use in source and binary forms, with or without"
|
636
|
+
* a.axe( 16) #=> "Redistributio..."
|
637
|
+
*/
|
638
|
+
|
639
|
+
VALUE
|
640
|
+
rb_str_axe( int argc, VALUE *argv, VALUE str)
|
641
|
+
{
|
642
|
+
VALUE n;
|
643
|
+
VALUE ret;
|
644
|
+
long newlen, oldlen;
|
645
|
+
|
646
|
+
if (rb_scan_args( argc, argv, "01", &n) == 1 && !NIL_P( n))
|
647
|
+
newlen = NUM2LONG( n);
|
648
|
+
else
|
649
|
+
newlen = 80;
|
650
|
+
if (newlen < 0)
|
651
|
+
return Qnil;
|
652
|
+
|
653
|
+
#ifdef HAVE_HEADER_RUBY_H
|
654
|
+
oldlen = RSTRING_LEN( str);
|
655
|
+
#else
|
656
|
+
oldlen = rb_str_strlen( str);
|
657
|
+
#endif
|
658
|
+
if (newlen < oldlen) {
|
659
|
+
VALUE ell;
|
660
|
+
long e;
|
661
|
+
|
662
|
+
ell = rb_str_new2( "...");
|
663
|
+
#ifdef HAVE_HEADER_RUBY_H
|
664
|
+
e = RSTRING_LEN( ell);
|
665
|
+
#else
|
666
|
+
e = rb_str_strlen( ell);
|
667
|
+
#endif
|
668
|
+
if (newlen > e) {
|
669
|
+
ret = rb_str_substr( str, 0, newlen - e);
|
670
|
+
rb_str_append( ret, ell);
|
671
|
+
} else
|
672
|
+
ret = rb_str_substr( str, 0, newlen);
|
673
|
+
OBJ_INFECT( ret, str);
|
674
|
+
} else
|
675
|
+
ret = str;
|
676
|
+
return ret;
|
677
|
+
}
|
678
|
+
|
679
|
+
|
680
|
+
/*
|
681
|
+
* Document-class: Numeric
|
682
|
+
*/
|
683
|
+
|
684
|
+
/*
|
685
|
+
* call-seq:
|
686
|
+
* pos? -> true or false
|
687
|
+
*
|
688
|
+
* Check whether +num+ is positive.
|
689
|
+
*
|
690
|
+
*/
|
691
|
+
|
692
|
+
VALUE
|
693
|
+
rb_num_pos_p( VALUE num)
|
694
|
+
{
|
695
|
+
VALUE r = Qfalse;
|
696
|
+
|
697
|
+
switch (TYPE( num)) {
|
698
|
+
case T_FIXNUM:
|
699
|
+
if (NUM2LONG( num) > 0)
|
700
|
+
r = Qtrue;
|
701
|
+
break;
|
702
|
+
|
703
|
+
case T_BIGNUM:
|
704
|
+
if (RBIGNUM_SIGN( num)) /* 0 is not a Bignum. */
|
705
|
+
r = Qtrue;
|
706
|
+
break;
|
707
|
+
|
708
|
+
case T_FLOAT:
|
709
|
+
if (RFLOAT_VALUE( num) > 0.0)
|
710
|
+
r = Qtrue;
|
711
|
+
break;
|
712
|
+
|
713
|
+
default:
|
714
|
+
return rb_num_neg_p( rb_funcall( INT2FIX( 0), id_cmp, 1, num));
|
715
|
+
break;
|
716
|
+
}
|
717
|
+
return r;
|
718
|
+
}
|
719
|
+
|
720
|
+
/*
|
721
|
+
* call-seq:
|
722
|
+
* neg? -> true or false
|
723
|
+
*
|
724
|
+
* Check whether +num+ is negative.
|
725
|
+
*
|
726
|
+
*/
|
727
|
+
|
728
|
+
VALUE
|
729
|
+
rb_num_neg_p( VALUE num)
|
730
|
+
{
|
731
|
+
VALUE r = Qfalse;
|
732
|
+
|
733
|
+
switch (TYPE( num)) {
|
734
|
+
case T_FIXNUM:
|
735
|
+
if (NUM2LONG( num) < 0)
|
736
|
+
r = Qtrue;
|
737
|
+
break;
|
738
|
+
|
739
|
+
case T_BIGNUM:
|
740
|
+
if (!RBIGNUM_SIGN( num)) /* 0 is not a Bignum. */
|
741
|
+
r = Qtrue;
|
742
|
+
break;
|
743
|
+
|
744
|
+
case T_FLOAT:
|
745
|
+
if (RFLOAT_VALUE( num) < 0.0)
|
746
|
+
r = Qtrue;
|
747
|
+
break;
|
748
|
+
|
749
|
+
default:
|
750
|
+
return rb_num_neg_p( rb_funcall( num, id_cmp, 1, INT2FIX( 0)));
|
751
|
+
break;
|
752
|
+
}
|
753
|
+
return r;
|
754
|
+
}
|
755
|
+
|
756
|
+
/*
|
757
|
+
* call-seq:
|
758
|
+
* grammatical sing, plu -> str
|
759
|
+
*
|
760
|
+
* Singular or plural
|
761
|
+
*
|
762
|
+
* 1.grammatical "line", "lines" #=> "line"
|
763
|
+
* 6.grammatical "child", "children" #=> "children"
|
764
|
+
*/
|
765
|
+
|
766
|
+
VALUE
|
767
|
+
rb_num_grammatical( VALUE num, VALUE sing, VALUE plu)
|
768
|
+
{
|
769
|
+
long l;
|
770
|
+
double d;
|
771
|
+
|
772
|
+
switch (TYPE( num)) {
|
773
|
+
case T_FIXNUM:
|
774
|
+
l = NUM2LONG( num);
|
775
|
+
if (l == 1l || l == -1l)
|
776
|
+
return sing;
|
777
|
+
break;
|
778
|
+
|
779
|
+
case T_BIGNUM:
|
780
|
+
/* 1 is not a Bignum */
|
781
|
+
break;
|
782
|
+
|
783
|
+
case T_FLOAT:
|
784
|
+
d = RFLOAT_VALUE( num);
|
785
|
+
if (d == 1.0 || d == -1.0)
|
786
|
+
return sing;
|
787
|
+
break;
|
788
|
+
|
789
|
+
default:
|
790
|
+
l = NUM2LONG( rb_funcall( num, id_cmp, 1, INT2FIX( 1)));
|
791
|
+
if (l == 0)
|
792
|
+
return sing;
|
793
|
+
l = NUM2LONG( rb_funcall( num, id_cmp, 1, INT2FIX(-1)));
|
794
|
+
if (l == 0)
|
795
|
+
return sing;
|
796
|
+
break;
|
797
|
+
}
|
798
|
+
return plu;
|
799
|
+
}
|
800
|
+
|
801
|
+
|
802
|
+
/*
|
803
|
+
* call-seq:
|
804
|
+
* num.sqrt -> num
|
805
|
+
*
|
806
|
+
* Square root.
|
807
|
+
*
|
808
|
+
* 144.sqrt #=> 12.0
|
809
|
+
*/
|
810
|
+
|
811
|
+
VALUE
|
812
|
+
rb_num_sqrt( VALUE num)
|
813
|
+
{
|
814
|
+
return rb_float_new( sqrt( RFLOAT_VALUE( rb_Float( num))));
|
815
|
+
}
|
816
|
+
|
817
|
+
/*
|
818
|
+
* call-seq:
|
819
|
+
* num.cbrt -> num
|
820
|
+
*
|
821
|
+
* Cube root.
|
822
|
+
*
|
823
|
+
* 27.cbrt #=> 3.0
|
824
|
+
*/
|
825
|
+
|
826
|
+
VALUE
|
827
|
+
rb_num_cbrt( VALUE num)
|
828
|
+
{
|
829
|
+
double n;
|
830
|
+
int neg;
|
831
|
+
int i;
|
832
|
+
|
833
|
+
n = RFLOAT_VALUE( rb_Float( num));
|
834
|
+
if ((neg = n < 0))
|
835
|
+
n = -n;
|
836
|
+
n = sqrt( sqrt( n));
|
837
|
+
i = 2;
|
838
|
+
for (;;) {
|
839
|
+
double w = n;
|
840
|
+
int j;
|
841
|
+
|
842
|
+
for (j=i;j;--j) w = sqrt( w);
|
843
|
+
i *= 2;
|
844
|
+
w *= n;
|
845
|
+
if (n == w) break;
|
846
|
+
n = w;
|
847
|
+
}
|
848
|
+
return rb_float_new( neg ? -n : n);
|
849
|
+
}
|
850
|
+
|
851
|
+
|
852
|
+
/*
|
853
|
+
* Document-class: Array
|
854
|
+
*/
|
855
|
+
|
856
|
+
/*
|
857
|
+
* call-seq:
|
858
|
+
* notempty? -> nil or self
|
859
|
+
*
|
860
|
+
* Returns <code>self</code> if and only if <code>ary</code> is not
|
861
|
+
* empty, <code>nil</code> otherwise.
|
862
|
+
*
|
863
|
+
* %w(a b).notempty? #=> [ "a", "b"]
|
864
|
+
* [].notempty? #=> nil
|
865
|
+
*/
|
866
|
+
|
867
|
+
VALUE
|
868
|
+
rb_ary_notempty_p( VALUE ary)
|
869
|
+
{
|
870
|
+
return RARRAY_LEN( ary) == 0 ? Qnil : ary;
|
871
|
+
}
|
872
|
+
|
873
|
+
|
874
|
+
/*
|
875
|
+
* call-seq:
|
876
|
+
* indexes() -> ary
|
877
|
+
* keys() -> ary
|
878
|
+
*
|
879
|
+
* Returns the indexes from <code>0</code> to
|
880
|
+
* <code>array.length()</code> as an array.
|
881
|
+
*
|
882
|
+
* [ "a", "h", "q"].indexes #=> [ 0, 1, 2]
|
883
|
+
*/
|
884
|
+
|
885
|
+
VALUE
|
886
|
+
rb_ary_indexes( VALUE ary)
|
887
|
+
{
|
888
|
+
VALUE ret;
|
889
|
+
int i, j;
|
890
|
+
|
891
|
+
j = RARRAY_LEN( ary);
|
892
|
+
ret = rb_ary_new2( j);
|
893
|
+
for (i = 0; j; ++i, --j) {
|
894
|
+
rb_ary_push( ret, INT2FIX( i));
|
895
|
+
}
|
896
|
+
return ret;
|
897
|
+
}
|
898
|
+
|
899
|
+
|
900
|
+
/*
|
901
|
+
* call-seq:
|
902
|
+
* pick { |elem| ... } -> obj or nil
|
903
|
+
*
|
904
|
+
* Deletes the element where the <em>block</em> first returns
|
905
|
+
* <code>true</code>. Or <code>nil</code> if nothing is found.
|
906
|
+
*
|
907
|
+
* a = %w(ant bat cat dog)
|
908
|
+
* a.pick { |e| e =~ /^c/ } #=> "cat"
|
909
|
+
* a #=> ["ant", "bat", "dog"]
|
910
|
+
* a.pick { |e| e =~ /^x/ } #=> nil
|
911
|
+
*/
|
912
|
+
|
913
|
+
VALUE
|
914
|
+
rb_ary_pick( VALUE ary)
|
915
|
+
{
|
916
|
+
VALUE pos;
|
917
|
+
|
918
|
+
pos = supplement_index_blk( ary);
|
919
|
+
if (!NIL_P( pos))
|
920
|
+
return rb_funcall( ary, id_delete_at, 1, pos);
|
921
|
+
return Qnil;
|
922
|
+
}
|
923
|
+
|
924
|
+
VALUE
|
925
|
+
supplement_index_blk( VALUE ary)
|
926
|
+
{
|
927
|
+
long i, j;
|
928
|
+
|
929
|
+
for (i = 0, j = RARRAY_LEN( ary); j > 0; i++, j--) {
|
930
|
+
if (RTEST( rb_yield( RARRAY_PTR( ary)[ i])))
|
931
|
+
return LONG2NUM( i);
|
932
|
+
}
|
933
|
+
return Qnil;
|
934
|
+
}
|
935
|
+
|
936
|
+
/*
|
937
|
+
* call-seq:
|
938
|
+
* rpick { |elem| ... } -> obj or nil
|
939
|
+
*
|
940
|
+
* Deletes the element where the <em>block</em> first returns
|
941
|
+
* <code>true</code>. Or <code>nil</code> if nothing is found. Search
|
942
|
+
* from right to left.
|
943
|
+
*
|
944
|
+
* a = %w(ant cow bat cat dog)
|
945
|
+
* a.rpick { |e| e =~ /^c/ } #=> "cat"
|
946
|
+
* a #=> ["ant", "cow", "bat", "dog"]
|
947
|
+
* a.rpick { |e| e =~ /^x/ } #=> nil
|
948
|
+
*/
|
949
|
+
|
950
|
+
VALUE
|
951
|
+
rb_ary_rpick( VALUE ary)
|
952
|
+
{
|
953
|
+
VALUE pos;
|
954
|
+
|
955
|
+
pos = supplement_rindex_blk( ary);
|
956
|
+
if (!NIL_P( pos))
|
957
|
+
return rb_funcall( ary, id_delete_at, 1, pos);
|
958
|
+
return Qnil;
|
959
|
+
}
|
960
|
+
|
961
|
+
VALUE
|
962
|
+
supplement_rindex_blk( VALUE ary)
|
963
|
+
{
|
964
|
+
long i;
|
965
|
+
|
966
|
+
for (i = RARRAY_LEN( ary); i;) {
|
967
|
+
--i;
|
968
|
+
if (rb_yield( RARRAY_PTR( ary)[ i]))
|
969
|
+
return LONG2NUM( i);
|
970
|
+
}
|
971
|
+
return Qnil;
|
972
|
+
}
|
973
|
+
|
974
|
+
|
975
|
+
#ifdef FEATURE_ARRAY_INDEX_WITH_BLOCK
|
976
|
+
|
977
|
+
/*
|
978
|
+
* call-seq:
|
979
|
+
* index( obj) -> int or nil
|
980
|
+
* index() { |elem| ... } -> int or nil
|
981
|
+
*
|
982
|
+
* Returns the index of the first object in <code>self</code> such that
|
983
|
+
* is <code>==</code> to <code>obj</code> or the <em>block</em> returns
|
984
|
+
* <code>true</code>. If no match is found, <code>nil</code> is
|
985
|
+
* returned.
|
986
|
+
*
|
987
|
+
* a = %w(a b c d e)
|
988
|
+
* a.index("b") #=> 1
|
989
|
+
* a.index("z") #=> nil
|
990
|
+
* a.index { |e| e >= "b" } #=> 1
|
991
|
+
* a.index { |e| e >= "q" } #=> nil
|
992
|
+
*/
|
993
|
+
|
994
|
+
VALUE
|
995
|
+
rb_ary_index( int argc, VALUE *argv, VALUE ary)
|
996
|
+
{
|
997
|
+
VALUE val;
|
998
|
+
|
999
|
+
if (rb_scan_args( argc, argv, "01", &val) == 1) {
|
1000
|
+
if (rb_block_given_p())
|
1001
|
+
rb_warning( "given block not used");
|
1002
|
+
return supplement_index_val( ary, val);
|
1003
|
+
} else
|
1004
|
+
return supplement_index_blk( ary);
|
1005
|
+
return Qnil;
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
VALUE
|
1009
|
+
supplement_index_val( VALUE ary, VALUE val)
|
1010
|
+
{
|
1011
|
+
long i;
|
1012
|
+
|
1013
|
+
for (i = 0; i < RARRAY_LEN( ary); i++)
|
1014
|
+
if (rb_equal( RARRAY_PTR( ary)[ i], val))
|
1015
|
+
return LONG2NUM( i);
|
1016
|
+
return Qnil;
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
|
1020
|
+
/*
|
1021
|
+
* call-seq:
|
1022
|
+
* rindex( obj) -> int or nil
|
1023
|
+
* rindex() { |elem| ... } -> int or nil
|
1024
|
+
*
|
1025
|
+
* Returns the index of the first object in <code>self</code> such that
|
1026
|
+
* is <code>==</code> to <code>obj</code> or the <em>block</em> returns
|
1027
|
+
* <code>true</code>. If no match is found, <code>nil</code> is
|
1028
|
+
* returned. Search from right to left.
|
1029
|
+
*
|
1030
|
+
* a = %w(a b c d e)
|
1031
|
+
* a.rindex("b") #=> 1
|
1032
|
+
* a.rindex("z") #=> nil
|
1033
|
+
* a.rindex { |e| e >= "b" } #=> 4
|
1034
|
+
* a.rindex { |e| e >= "q" } #=> nil
|
1035
|
+
*/
|
1036
|
+
|
1037
|
+
VALUE
|
1038
|
+
rb_ary_rindex( int argc, VALUE *argv, VALUE ary)
|
1039
|
+
{
|
1040
|
+
VALUE val;
|
1041
|
+
|
1042
|
+
if (rb_scan_args( argc, argv, "01", &val) == 1) {
|
1043
|
+
if (rb_block_given_p())
|
1044
|
+
rb_warning( "given block not used");
|
1045
|
+
return supplement_rindex_val( ary, val);
|
1046
|
+
} else
|
1047
|
+
return supplement_rindex_blk( ary);
|
1048
|
+
return Qnil;
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
VALUE
|
1052
|
+
supplement_rindex_val( VALUE ary, VALUE val)
|
1053
|
+
{
|
1054
|
+
long i;
|
1055
|
+
|
1056
|
+
for (i = RARRAY_LEN( ary); i;)
|
1057
|
+
if (rb_equal( RARRAY_PTR( ary)[ --i], val))
|
1058
|
+
return LONG2NUM( i);
|
1059
|
+
return Qnil;
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
#endif
|
1063
|
+
|
1064
|
+
#ifdef FEATURE_ARRAY_SELECT_BANG
|
1065
|
+
|
1066
|
+
/*
|
1067
|
+
* Document-method: select!
|
1068
|
+
*
|
1069
|
+
* call-seq:
|
1070
|
+
* select! { |x| ... } -> ary
|
1071
|
+
*
|
1072
|
+
* Remove all items for that the block returns +nil+ or +false+.
|
1073
|
+
*
|
1074
|
+
*/
|
1075
|
+
|
1076
|
+
VALUE
|
1077
|
+
rb_ary_select_bang( VALUE self)
|
1078
|
+
{
|
1079
|
+
return rb_iterate( &supplement_reject, self,
|
1080
|
+
&supplement_invert_yield, Qnil);
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
VALUE
|
1084
|
+
supplement_reject( VALUE obj)
|
1085
|
+
{
|
1086
|
+
if (!id_reject_bang)
|
1087
|
+
id_reject_bang = rb_intern( "reject!");
|
1088
|
+
return rb_funcall( obj, id_reject_bang, 0);
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
VALUE
|
1092
|
+
supplement_invert_yield( VALUE elem)
|
1093
|
+
{
|
1094
|
+
return NIL_P( rb_yield( elem)) ? Qtrue : Qfalse;
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
#endif
|
1098
|
+
|
1099
|
+
|
1100
|
+
|
1101
|
+
/*
|
1102
|
+
* Document-class: Hash
|
1103
|
+
*/
|
1104
|
+
|
1105
|
+
/*
|
1106
|
+
* call-seq:
|
1107
|
+
* notempty? -> nil or self
|
1108
|
+
*
|
1109
|
+
* Returns <code>self</code> if and only if <code>hash</code> is not
|
1110
|
+
* empty, <code>nil</code> otherwise.
|
1111
|
+
*
|
1112
|
+
* { :a => "A"}.notempty? #=> { :a => "A"}
|
1113
|
+
* {}.notempty? #=> nil
|
1114
|
+
*/
|
1115
|
+
|
1116
|
+
VALUE
|
1117
|
+
rb_hash_notempty_p( VALUE hash)
|
1118
|
+
{
|
1119
|
+
return RHASH_SIZE( hash) == 0 ? Qnil : hash;
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
|
1123
|
+
/*
|
1124
|
+
* Document-class: File
|
1125
|
+
*/
|
1126
|
+
|
1127
|
+
/*
|
1128
|
+
* call-seq:
|
1129
|
+
* size -> integer
|
1130
|
+
*
|
1131
|
+
* Returns <code>file</code>'s size. A shortcut for
|
1132
|
+
* <code>file.stat.size</code>. This constitutes consistency with
|
1133
|
+
* <code>StringIO</code>.
|
1134
|
+
*
|
1135
|
+
* file.size #=> 16384
|
1136
|
+
*/
|
1137
|
+
|
1138
|
+
VALUE
|
1139
|
+
rb_file_size( VALUE obj)
|
1140
|
+
{
|
1141
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1142
|
+
OpenFile *fptr;
|
1143
|
+
#else
|
1144
|
+
rb_io_t *fptr;
|
1145
|
+
#endif
|
1146
|
+
struct stat st;
|
1147
|
+
|
1148
|
+
GetOpenFile( obj, fptr);
|
1149
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1150
|
+
if (fstat( fileno( fptr->f), &st) == -1) {
|
1151
|
+
rb_sys_fail( fptr->path);
|
1152
|
+
}
|
1153
|
+
#else
|
1154
|
+
if (fstat( fptr->fd, &st) == -1) {
|
1155
|
+
rb_sys_fail_str( fptr->pathv);
|
1156
|
+
}
|
1157
|
+
#endif
|
1158
|
+
return INT2FIX( st.st_size);
|
1159
|
+
}
|
1160
|
+
|
1161
|
+
|
1162
|
+
/*
|
1163
|
+
* call-seq:
|
1164
|
+
* flockb( excl = nil, nb = nil) { || ... } -> nil
|
1165
|
+
*
|
1166
|
+
* Lock file using the <code>flock()</code> system call.
|
1167
|
+
* When the <code>nb</code> flag is <code>true</code>, the method
|
1168
|
+
* won't block but rather raise an exception. Catch
|
1169
|
+
* <code>SystemCallError</code>. The calls may be nested in any order.
|
1170
|
+
*
|
1171
|
+
* File.open "/var/mail/joe", "a" do |f|
|
1172
|
+
* f.flockb true do
|
1173
|
+
* f.write another_message
|
1174
|
+
* end
|
1175
|
+
* end
|
1176
|
+
*/
|
1177
|
+
|
1178
|
+
VALUE
|
1179
|
+
rb_file_flockb( int argc, VALUE *argv, VALUE file)
|
1180
|
+
{
|
1181
|
+
VALUE excl, nb;
|
1182
|
+
struct supplement_flock cur_flock;
|
1183
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1184
|
+
OpenFile *fptr;
|
1185
|
+
#else
|
1186
|
+
rb_io_t *fptr;
|
1187
|
+
#endif
|
1188
|
+
int op;
|
1189
|
+
|
1190
|
+
rb_scan_args( argc, argv, "02", &excl, &nb);
|
1191
|
+
supplement_init_flock( &cur_flock, file, excl);
|
1192
|
+
|
1193
|
+
op = cur_flock.op | LOCK_NB;
|
1194
|
+
GetOpenFile( file, fptr);
|
1195
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1196
|
+
while (flock( fileno( fptr->f), op) < 0) {
|
1197
|
+
#else
|
1198
|
+
while (flock( fptr->fd, op) < 0) {
|
1199
|
+
#endif
|
1200
|
+
switch (errno) {
|
1201
|
+
case EAGAIN:
|
1202
|
+
case EACCES:
|
1203
|
+
#if defined( EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
1204
|
+
case EWOULDBLOCK:
|
1205
|
+
#endif
|
1206
|
+
if (!RTEST( nb)) {
|
1207
|
+
rb_thread_polling(); /* busy wait */
|
1208
|
+
rb_io_check_closed( fptr);
|
1209
|
+
continue;
|
1210
|
+
}
|
1211
|
+
/* fall through */
|
1212
|
+
default:
|
1213
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1214
|
+
rb_sys_fail( fptr->path);
|
1215
|
+
#else
|
1216
|
+
rb_sys_fail_str( fptr->pathv);
|
1217
|
+
#endif
|
1218
|
+
}
|
1219
|
+
}
|
1220
|
+
cur_flock.prev = flocks_root;
|
1221
|
+
flocks_root = &cur_flock;
|
1222
|
+
return rb_ensure( rb_yield, Qnil, supplement_do_unflock, Qnil);
|
1223
|
+
}
|
1224
|
+
|
1225
|
+
void
|
1226
|
+
supplement_init_flock( struct supplement_flock *s, VALUE file, VALUE excl)
|
1227
|
+
{
|
1228
|
+
struct supplement_flock *i;
|
1229
|
+
|
1230
|
+
s->file = file;
|
1231
|
+
|
1232
|
+
s->last_op = LOCK_UN;
|
1233
|
+
for (i = flocks_root; i != NULL; i = i->prev) {
|
1234
|
+
if (i->file == file) {
|
1235
|
+
s->last_op = i->op;
|
1236
|
+
break;
|
1237
|
+
}
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
switch (s->last_op) {
|
1241
|
+
case LOCK_UN:
|
1242
|
+
case LOCK_SH:
|
1243
|
+
s->op = RTEST( excl) ? LOCK_EX : LOCK_SH;
|
1244
|
+
break;
|
1245
|
+
case LOCK_EX:
|
1246
|
+
s->op = LOCK_EX;
|
1247
|
+
break;
|
1248
|
+
default:
|
1249
|
+
s->op = LOCK_UN; /* should never be reached. */
|
1250
|
+
break;
|
1251
|
+
}
|
1252
|
+
}
|
1253
|
+
|
1254
|
+
VALUE
|
1255
|
+
supplement_do_unflock( VALUE v)
|
1256
|
+
{
|
1257
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1258
|
+
OpenFile *fptr;
|
1259
|
+
#else
|
1260
|
+
rb_io_t *fptr;
|
1261
|
+
#endif
|
1262
|
+
int fd;
|
1263
|
+
|
1264
|
+
GetOpenFile( flocks_root->file, fptr);
|
1265
|
+
#ifdef HAVE_HEADER_RUBY_H
|
1266
|
+
flock( fileno( fptr->f), flocks_root->last_op);
|
1267
|
+
#else
|
1268
|
+
flock( fptr->fd, flocks_root->last_op);
|
1269
|
+
#endif
|
1270
|
+
flocks_root = flocks_root->prev;
|
1271
|
+
|
1272
|
+
return Qnil;
|
1273
|
+
}
|
1274
|
+
|
1275
|
+
|
1276
|
+
/*
|
1277
|
+
* call-seq:
|
1278
|
+
* umask() -> int
|
1279
|
+
* umask( int) -> int
|
1280
|
+
* umask( int) { ... } -> obj
|
1281
|
+
*
|
1282
|
+
* Returns the current umask value for this process. If the optional
|
1283
|
+
* argument is given, set the umask to that value and return the
|
1284
|
+
* previous value. If a block is given, the umask value will be
|
1285
|
+
* reset and the blocks value is returned.
|
1286
|
+
*
|
1287
|
+
* Umask values are <em>subtracted</em> from the default permissions,
|
1288
|
+
* so a umask of <code>0222</code> would make a file read-only for
|
1289
|
+
* everyone.
|
1290
|
+
*
|
1291
|
+
* File.umask( 0006) #=> 18
|
1292
|
+
* File.umask #=> 6
|
1293
|
+
*/
|
1294
|
+
|
1295
|
+
VALUE
|
1296
|
+
rb_file_s_umask( int argc, VALUE *argv)
|
1297
|
+
{
|
1298
|
+
int omask = 0;
|
1299
|
+
|
1300
|
+
rb_secure( 2);
|
1301
|
+
switch (argc) {
|
1302
|
+
case 0:
|
1303
|
+
omask = umask( 0777);
|
1304
|
+
umask( omask);
|
1305
|
+
break;
|
1306
|
+
case 1:
|
1307
|
+
omask = umask( NUM2INT( argv[ 0]));
|
1308
|
+
if (rb_block_given_p())
|
1309
|
+
return rb_ensure( rb_yield, Qnil,
|
1310
|
+
supplement_do_unumask, INT2FIX( omask));
|
1311
|
+
break;
|
1312
|
+
default:
|
1313
|
+
rb_raise( rb_eArgError,
|
1314
|
+
"wrong number of arguments (%d for 0..1)", argc);
|
1315
|
+
}
|
1316
|
+
return INT2FIX( omask);
|
1317
|
+
}
|
1318
|
+
|
1319
|
+
VALUE
|
1320
|
+
supplement_do_unumask( VALUE v)
|
1321
|
+
{
|
1322
|
+
umask( NUM2INT( v));
|
1323
|
+
return Qnil;
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
|
1327
|
+
/*
|
1328
|
+
* Document-class: Dir
|
1329
|
+
*/
|
1330
|
+
|
1331
|
+
/*
|
1332
|
+
* call-seq:
|
1333
|
+
* current() -> dir
|
1334
|
+
*
|
1335
|
+
* Current directory as a Dir object.
|
1336
|
+
*
|
1337
|
+
*/
|
1338
|
+
|
1339
|
+
VALUE
|
1340
|
+
rb_dir_s_current( VALUE dir)
|
1341
|
+
{
|
1342
|
+
return rb_funcall( dir, rb_intern( "new"), 1, rb_str_new( ".", 1));
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
|
1346
|
+
/*
|
1347
|
+
* call-seq:
|
1348
|
+
* mkdir!( path, modes = nil) -> str or nil
|
1349
|
+
*
|
1350
|
+
* Make a directory and all subdirectories if needed.
|
1351
|
+
*
|
1352
|
+
* If you specifiy modes, be sure that you have the permission to create
|
1353
|
+
* subdirectories.
|
1354
|
+
*
|
1355
|
+
* Returns the path demanded if the directory was created and +nil+ if
|
1356
|
+
* it existed before.
|
1357
|
+
*
|
1358
|
+
*/
|
1359
|
+
|
1360
|
+
VALUE
|
1361
|
+
rb_dir_s_mkdir_bang( int argc, VALUE *argv)
|
1362
|
+
{
|
1363
|
+
VALUE path, modes;
|
1364
|
+
|
1365
|
+
rb_scan_args( argc, argv, "11", &path, &modes);
|
1366
|
+
if (!rb_file_directory_p( rb_cFile, path)) {
|
1367
|
+
VALUE parent[2];
|
1368
|
+
|
1369
|
+
parent[ 0] = rb_file_dirname( path);
|
1370
|
+
parent[ 1] = modes;
|
1371
|
+
rb_dir_s_mkdir_bang( 2, parent);
|
1372
|
+
if (!id_mkdir)
|
1373
|
+
id_mkdir = rb_intern( "mkdir");
|
1374
|
+
if (NIL_P(modes))
|
1375
|
+
rb_funcall( rb_cDir, id_mkdir, 1, path);
|
1376
|
+
else
|
1377
|
+
rb_funcall( rb_cDir, id_mkdir, 2, path, modes);
|
1378
|
+
return path;
|
1379
|
+
}
|
1380
|
+
return Qnil;
|
1381
|
+
}
|
1382
|
+
|
1383
|
+
|
1384
|
+
/*
|
1385
|
+
* call-seq:
|
1386
|
+
* entries!() -> dir
|
1387
|
+
*
|
1388
|
+
* Entries without <code>"."</code> and <code>".."</code>.
|
1389
|
+
*
|
1390
|
+
*/
|
1391
|
+
|
1392
|
+
VALUE
|
1393
|
+
rb_dir_entries_bang( VALUE self)
|
1394
|
+
{
|
1395
|
+
VALUE e;
|
1396
|
+
|
1397
|
+
e = rb_funcall( self, rb_intern( "entries"), 0);
|
1398
|
+
rb_ary_delete( e, rb_str_new( ".", 1));
|
1399
|
+
rb_ary_delete( e, rb_str_new( "..", 2));
|
1400
|
+
return e;
|
1401
|
+
}
|
1402
|
+
|
1403
|
+
|
1404
|
+
/*
|
1405
|
+
* call-seq:
|
1406
|
+
* chdir() -> nil
|
1407
|
+
* chdir() { |path| ... } -> obj
|
1408
|
+
*
|
1409
|
+
* As you probably expect, change the working directory like in
|
1410
|
+
* <code>Dir.chdir</code>.
|
1411
|
+
*
|
1412
|
+
*/
|
1413
|
+
|
1414
|
+
VALUE
|
1415
|
+
rb_dir_chdir( VALUE dir)
|
1416
|
+
{
|
1417
|
+
VALUE path;
|
1418
|
+
|
1419
|
+
if (!id_chdir) {
|
1420
|
+
id_chdir = rb_intern( "chdir");
|
1421
|
+
id_path = rb_intern( "path");
|
1422
|
+
}
|
1423
|
+
path = rb_funcall( dir, id_path, 0);
|
1424
|
+
if (rb_block_given_p())
|
1425
|
+
return rb_iterate( &supplement_chdir, path, &rb_yield, Qnil);
|
1426
|
+
else {
|
1427
|
+
supplement_chdir( path);
|
1428
|
+
return Qnil;
|
1429
|
+
}
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
VALUE
|
1433
|
+
supplement_chdir( VALUE path)
|
1434
|
+
{
|
1435
|
+
return rb_funcall( rb_cDir, id_chdir, 1, path);
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
|
1439
|
+
/*
|
1440
|
+
* Document-class: Match
|
1441
|
+
*/
|
1442
|
+
|
1443
|
+
/*
|
1444
|
+
* call-seq:
|
1445
|
+
* begin( n = nil) -> integer
|
1446
|
+
*
|
1447
|
+
* Returns the offset of the start of the <code>n</code>th element of
|
1448
|
+
* the match array in the string. In case <code>n</code> is
|
1449
|
+
* <code>nil</code> the 0th match (whole) is assumed.
|
1450
|
+
*
|
1451
|
+
* m = /(.)(.)(\d+)(\d)/.match("THX1138.")
|
1452
|
+
* m.begin( 0) #=> 1
|
1453
|
+
* m.begin #=> 1
|
1454
|
+
* m.begin( 2) #=> 2
|
1455
|
+
*/
|
1456
|
+
|
1457
|
+
VALUE
|
1458
|
+
rb_match_begin( int argc, VALUE *argv, VALUE match)
|
1459
|
+
{
|
1460
|
+
VALUE val;
|
1461
|
+
int i;
|
1462
|
+
|
1463
|
+
if (rb_scan_args( argc, argv, "01", &val) == 1) {
|
1464
|
+
i = NIL_P( val) ? 0 : NUM2INT( val);
|
1465
|
+
} else
|
1466
|
+
i = 0;
|
1467
|
+
|
1468
|
+
if (i < 0 || RMATCH_REGS( match)->num_regs <= i)
|
1469
|
+
rb_raise( rb_eIndexError, "index %d out of matches", i);
|
1470
|
+
|
1471
|
+
if (RMATCH_REGS( match)->beg[i] < 0)
|
1472
|
+
return Qnil;
|
1473
|
+
|
1474
|
+
return INT2FIX( RMATCH_REGS( match)->beg[i]);
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
|
1478
|
+
/*
|
1479
|
+
* call-seq:
|
1480
|
+
* end( n = nil) -> integer
|
1481
|
+
*
|
1482
|
+
* Returns the offset of the character immediately following the end of
|
1483
|
+
* the <code>n</code>th element of the match array in the string. In
|
1484
|
+
* case <code>n</code> is <code>nil</code> the 0th match (whole) is
|
1485
|
+
* assumed.
|
1486
|
+
*
|
1487
|
+
* m = /(.)(.)(\d+)(\d)/.match("THX1138.")
|
1488
|
+
* m.end( 0) #=> 7
|
1489
|
+
* m.end #=> 7
|
1490
|
+
* m.end( 2) #=> 3
|
1491
|
+
*/
|
1492
|
+
|
1493
|
+
VALUE
|
1494
|
+
rb_match_end( int argc, VALUE *argv, VALUE match)
|
1495
|
+
{
|
1496
|
+
VALUE val;
|
1497
|
+
int i;
|
1498
|
+
|
1499
|
+
if (rb_scan_args( argc, argv, "01", &val) == 1) {
|
1500
|
+
i = NIL_P( val) ? 0 : NUM2INT( val);
|
1501
|
+
} else
|
1502
|
+
i = 0;
|
1503
|
+
|
1504
|
+
if (i < 0 || RMATCH_REGS( match)->num_regs <= i)
|
1505
|
+
rb_raise( rb_eIndexError, "index %d out of matches", i);
|
1506
|
+
|
1507
|
+
if (RMATCH_REGS( match)->beg[i] < 0)
|
1508
|
+
return Qnil;
|
1509
|
+
|
1510
|
+
return INT2FIX( RMATCH_REGS( match)->end[i]);
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
|
1514
|
+
#ifdef FEATURE_THREAD_EXCLUSIVE
|
1515
|
+
|
1516
|
+
/*
|
1517
|
+
* Document-class: Thread
|
1518
|
+
*/
|
1519
|
+
|
1520
|
+
/*
|
1521
|
+
* call-seq:
|
1522
|
+
* Thread.exclusive { ... } -> obj
|
1523
|
+
*
|
1524
|
+
* Sets the global ``thread critical'' condition temporarily. Return
|
1525
|
+
* value is the object returned by the <em>block</em>.
|
1526
|
+
*/
|
1527
|
+
|
1528
|
+
VALUE
|
1529
|
+
rb_thread_exclusive( void)
|
1530
|
+
{
|
1531
|
+
VALUE old_tc = rb_thread_critical;
|
1532
|
+
|
1533
|
+
rb_thread_critical = Qtrue;
|
1534
|
+
return rb_ensure( rb_yield, Qnil, bsruby_set_thread_critical, old_tc);
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
VALUE
|
1538
|
+
bsruby_set_thread_critical( VALUE c)
|
1539
|
+
{
|
1540
|
+
rb_thread_critical = c;
|
1541
|
+
return Qnil;
|
1542
|
+
}
|
1543
|
+
|
1544
|
+
#endif
|
1545
|
+
|
1546
|
+
|
1547
|
+
|
1548
|
+
/*
|
1549
|
+
* Document-class: Struct
|
1550
|
+
*/
|
1551
|
+
|
1552
|
+
/*
|
1553
|
+
* Document-method: []
|
1554
|
+
*
|
1555
|
+
* call-seq:
|
1556
|
+
* Struct[ ...] -> cls
|
1557
|
+
*
|
1558
|
+
* Alias for Struct.new; This applies to Struct subclass generation
|
1559
|
+
* as well as to the subclasses instance creation.
|
1560
|
+
*
|
1561
|
+
* S = Struct[ :a, :b] #=> S
|
1562
|
+
* s = S[ 'A', 'B'] #=> #<struct S a="A", b="B">
|
1563
|
+
*
|
1564
|
+
*/
|
1565
|
+
|
1566
|
+
|
1567
|
+
void Init_supplement( void)
|
1568
|
+
{
|
1569
|
+
rb_define_alias( rb_cObject, "cls", "class");
|
1570
|
+
rb_define_method( rb_cObject, "new_string", rb_obj_new_string, 0);
|
1571
|
+
rb_define_method( rb_cObject, "nil_if", rb_obj_nil_if, 1);
|
1572
|
+
#ifdef FEATURE_KERNEL_TAP
|
1573
|
+
rb_define_method( rb_mKernel, "tap", rb_krn_tap, 0);
|
1574
|
+
#endif
|
1575
|
+
rb_define_method( rb_mKernel, "tap!", rb_krn_tap_bang, 0);
|
1576
|
+
|
1577
|
+
rb_define_method( rb_cNilClass, "notempty?", rb_nil_notempty_p, 0);
|
1578
|
+
rb_define_method( rb_cNilClass, "nonzero?", rb_nil_notempty_p, 0);
|
1579
|
+
rb_define_method( rb_cNilClass, "each_line", rb_nil_each_line, 0);
|
1580
|
+
|
1581
|
+
rb_define_method( rb_cString, "new_string", rb_str_new_string, 0);
|
1582
|
+
rb_define_method( rb_cString, "notempty?", rb_str_notempty_p, 0);
|
1583
|
+
rb_define_method( rb_cString, "eat", rb_str_eat, -1);
|
1584
|
+
rb_define_method( rb_cString, "cut!", rb_str_cut_bang, 1);
|
1585
|
+
#ifdef FEATURE_STRING_CLEAR
|
1586
|
+
rb_define_method( rb_cString, "clear", rb_str_clear, 0);
|
1587
|
+
#endif
|
1588
|
+
rb_define_method( rb_cString, "head", rb_str_head, -1);
|
1589
|
+
rb_define_method( rb_cString, "rest", rb_str_rest, -1);
|
1590
|
+
rb_define_method( rb_cString, "tail", rb_str_tail, -1);
|
1591
|
+
#ifdef FEATURE_STRING_START_WITH
|
1592
|
+
rb_define_method( rb_cString, "start_with?", rb_str_start_with_p, 1);
|
1593
|
+
rb_define_method( rb_cString, "end_with?", rb_str_end_with_p, 1);
|
1594
|
+
#endif
|
1595
|
+
rb_define_method( rb_cString, "starts_with?", rb_str_starts_with_p, 1);
|
1596
|
+
rb_define_method( rb_cString, "ends_with?", rb_str_ends_with_p, 1);
|
1597
|
+
rb_define_alias( rb_cString, "starts_with", "start_with?");
|
1598
|
+
rb_define_alias( rb_cString, "ends_with", "end_with?");
|
1599
|
+
#ifdef FEATURE_STRING_ORD
|
1600
|
+
rb_define_method( rb_cString, "ord", rb_str_ord, 0);
|
1601
|
+
#endif
|
1602
|
+
rb_define_method( rb_cString, "axe", rb_str_axe, -1);
|
1603
|
+
|
1604
|
+
rb_define_method( rb_cNumeric, "pos?", rb_num_pos_p, 0);
|
1605
|
+
rb_define_method( rb_cNumeric, "neg?", rb_num_neg_p, 0);
|
1606
|
+
rb_define_method( rb_cNumeric, "grammatical", rb_num_grammatical, 2);
|
1607
|
+
rb_define_method( rb_cNumeric, "sqrt", rb_num_sqrt, 0);
|
1608
|
+
rb_define_method( rb_cNumeric, "cbrt", rb_num_cbrt, 0);
|
1609
|
+
|
1610
|
+
rb_define_method( rb_cArray, "notempty?", rb_ary_notempty_p, 0);
|
1611
|
+
rb_define_method( rb_cArray, "indexes", rb_ary_indexes, 0);
|
1612
|
+
rb_define_alias( rb_cArray, "keys", "indexes");
|
1613
|
+
rb_define_method( rb_cArray, "pick", rb_ary_pick, 0);
|
1614
|
+
rb_define_method( rb_cArray, "rpick", rb_ary_rpick, 0);
|
1615
|
+
#ifdef FEATURE_ARRAY_INDEX_WITH_BLOCK
|
1616
|
+
rb_define_method( rb_cArray, "index", rb_ary_index, -1);
|
1617
|
+
rb_define_method( rb_cArray, "rindex", rb_ary_rindex, -1);
|
1618
|
+
#endif
|
1619
|
+
#ifdef FEATURE_ARRAY_SELECT_BANG
|
1620
|
+
rb_define_method( rb_cArray, "select!", rb_ary_select_bang, 0);
|
1621
|
+
#endif
|
1622
|
+
|
1623
|
+
rb_define_method( rb_cHash, "notempty?", rb_hash_notempty_p, 0);
|
1624
|
+
|
1625
|
+
rb_define_method( rb_cFile, "size", rb_file_size, 0);
|
1626
|
+
rb_define_method( rb_cFile, "flockb", rb_file_flockb, -1);
|
1627
|
+
rb_define_singleton_method( rb_cFile, "umask", rb_file_s_umask, -1);
|
1628
|
+
|
1629
|
+
rb_define_singleton_method( rb_cDir, "current", rb_dir_s_current, 0);
|
1630
|
+
rb_define_singleton_method( rb_cDir, "mkdir!", rb_dir_s_mkdir_bang, -1);
|
1631
|
+
rb_define_method( rb_cDir, "entries!", rb_dir_entries_bang, 0);
|
1632
|
+
rb_define_method( rb_cDir, "chdir", rb_dir_chdir, 0);
|
1633
|
+
|
1634
|
+
rb_define_method( rb_cMatch, "begin", rb_match_begin, -1);
|
1635
|
+
rb_define_method( rb_cMatch, "end", rb_match_end, -1);
|
1636
|
+
|
1637
|
+
#ifdef FEATURE_THREAD_EXCLUSIVE
|
1638
|
+
rb_define_singleton_method( rb_cThread, "exclusive",
|
1639
|
+
rb_thread_exclusive, 0);
|
1640
|
+
#endif
|
1641
|
+
|
1642
|
+
rb_define_alias( rb_singleton_class( rb_cStruct), "[]", "new");
|
1643
|
+
|
1644
|
+
id_delete_at = rb_intern( "delete_at");
|
1645
|
+
id_cmp = rb_intern( "<=>");
|
1646
|
+
id_eqq = 0;
|
1647
|
+
#ifdef FEATURE_ARRAY_SELECT_BANG
|
1648
|
+
id_reject_bang = 0;
|
1649
|
+
#endif
|
1650
|
+
id_chdir = 0;
|
1651
|
+
id_path = 0;
|
1652
|
+
id_mkdir = 0;
|
1653
|
+
id_index = 0;
|
1654
|
+
|
1655
|
+
Init_supplement_sync();
|
1656
|
+
}
|
1657
|
+
|