summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--enum.c102
-rw-r--r--lib/cgi/session.rb4
-rw-r--r--lib/date.rb8
-rw-r--r--lib/thread.rb9
-rw-r--r--lib/timeout.rb1
-rw-r--r--parse.y9
7 files changed, 113 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 910d7988b9..8e6b439295 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed Jul 14 23:49:30 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enum.c (enum_min_by): new method Enum#min_by. added Enum#max_by
+ as well.
+
Wed Jul 14 18:05:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_asn1.c (ossl_asn1cons_to_der): fix type of
diff --git a/enum.c b/enum.c
index 08a1fde747..212e0f3b54 100644
--- a/enum.c
+++ b/enum.c
@@ -677,20 +677,6 @@ enum_min(obj)
return result;
}
-/*
- * call-seq:
- * enum.max => obj
- * enum.max {| a,b | block } => obj
- *
- * Returns the object in <i>enum</i> with the maximum value. The
- * first form assumes all objects implement <code>Comparable</code>;
- * the second uses the block to return <em>a <=> b</em>.
- *
- * a = %w(albatross dog horse)
- * a.max #=> "horse"
- * a.max {|a,b| a.length <=> b.length } #=> "albatross"
- */
-
static VALUE
max_i(i, memo)
VALUE i;
@@ -757,6 +743,92 @@ enum_max(obj)
}
static VALUE
+min_by_i(i, memo)
+ VALUE i;
+ NODE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (NIL_P(memo->u1.value)) {
+ memo->u1.value = v;
+ memo->u2.value = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
+ memo->u1.value = v;
+ memo->u2.value = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.min_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the minimum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.min_by {|x| x.length } #=> "dog"
+ */
+
+static VALUE
+enum_min_by(obj)
+ VALUE obj;
+{
+ VALUE result;
+ NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+
+ rb_iterate(rb_each, obj, min_by_i, (VALUE)memo);
+ result = memo->u2.value;
+ rb_gc_force_recycle((VALUE)memo);
+ return result;
+}
+
+static VALUE
+max_by_i(i, memo)
+ VALUE i;
+ NODE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (NIL_P(memo->u1.value)) {
+ memo->u1.value = v;
+ memo->u2.value = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
+ memo->u1.value = v;
+ memo->u2.value = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.max_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the maximum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.max_by {|x| x.length } #=> "albatross"
+ */
+
+static VALUE
+enum_max_by(obj)
+ VALUE obj;
+{
+ VALUE result;
+ NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+
+ rb_iterate(rb_each, obj, max_by_i, (VALUE)memo);
+ result = memo->u2.value;
+ rb_gc_force_recycle((VALUE)memo);
+ return result;
+}
+
+static VALUE
member_i(item, memo)
VALUE item;
NODE *memo;
@@ -933,6 +1005,8 @@ Init_Enumerable()
rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
rb_define_method(rb_mEnumerable,"min", enum_min, 0);
rb_define_method(rb_mEnumerable,"max", enum_max, 0);
+ rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
+ rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index cd6ce95f4d..a44de7cb81 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -365,7 +365,6 @@ class CGI
raise ArgumentError, "session_id `%s' is invalid" % id
end
@path = dir+"/"+prefix+id
- @path.untaint
unless File::exist? @path
@hash = {}
end
@@ -413,7 +412,8 @@ class CGI
# Close and delete the session's FileStore file.
def delete
- File::unlink @path
+ File::unlink @path
+ rescue Errno::ENOENT
end
end
diff --git a/lib/date.rb b/lib/date.rb
index b50e987852..b8c15a420a 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -711,7 +711,13 @@ class Date
alias_method :__#{id.to_i}__, :#{id.to_s}
private :__#{id.to_i}__
def #{id.to_s}(*args, &block)
- (@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0]
+ if @__#{id.to_i}__
+ @__#{id.to_i}__
+ elsif ! self.frozen?
+ @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block)
+ else
+ __#{id.to_i}__(*args, &block)
+ end
end
end;
end
diff --git a/lib/thread.rb b/lib/thread.rb
index 8b27356c48..a069c4680a 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -69,7 +69,7 @@ class Mutex
# Returns +true+ if this lock is currently held by some thread.
#
def locked?
- @locked
+ @locked && true
end
#
@@ -80,7 +80,7 @@ class Mutex
result = false
Thread.critical = true
unless @locked
- @locked = true
+ @locked = Thread.current
result = true
end
Thread.critical = false
@@ -92,10 +92,13 @@ class Mutex
#
def lock
while (Thread.critical = true; @locked)
+ if @locked == Thread.current
+ raise ThreadError, "deadlock; recursive locking"
+ end
@waiting.push Thread.current
Thread.stop
end
- @locked = true
+ @locked = Thread.current
Thread.critical = false
self
end
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 0ba5293d1d..7e3ee81ed0 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -35,6 +35,7 @@ module Timeout
def timeout(sec, exception=Error)
return yield if sec == nil or sec.zero?
+ raise ThreadError, "timeout within critical session" if Thread.critical
begin
x = Thread.current
y = Thread.start {
diff --git a/parse.y b/parse.y
index 6a68ef2ca2..121251ce1d 100644
--- a/parse.y
+++ b/parse.y
@@ -5391,11 +5391,10 @@ static NODE*
cond0(node)
NODE *node;
{
- enum node_type type = nd_type(node);
-
+ if (node == 0) return 0;
assign_in_cond(node);
- switch (type) {
+ switch (nd_type(node)) {
case NODE_DSTR:
case NODE_EVSTR:
case NODE_STR:
@@ -5419,8 +5418,8 @@ cond0(node)
case NODE_DOT3:
node->nd_beg = range_op(node->nd_beg);
node->nd_end = range_op(node->nd_end);
- if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
- else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
+ if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
+ else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
node->nd_cnt = local_append(internal_id());
if (!e_option_supplied()) {
int b = literal_node(node->nd_beg);