supplement 1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
+
|