Skip to content

Commit

Permalink
Showing 34 changed files with 1,587 additions and 174 deletions.
69 changes: 69 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/cast/ToSNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.cast;

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyTypesGen;
import org.jruby.truffle.nodes.core.KernelNodes;
import org.jruby.truffle.nodes.core.KernelNodesFactory;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(type = RubyNode.class)
public abstract class ToSNode extends RubyNode {

@Child protected DispatchHeadNode callToSNode;
@Child protected KernelNodes.ClassNode classNode;
@Child protected KernelNodes.ToSNode toSNode;

public ToSNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
callToSNode = new DispatchHeadNode(context, true);
classNode = KernelNodesFactory.ClassNodeFactory.create(context, sourceSection, new RubyNode[]{null});
toSNode = KernelNodesFactory.ToSNodeFactory.create(context, sourceSection, new RubyNode[]{null});
}

public ToSNode(ToSNode prev) {
super(prev);
callToSNode = prev.callToSNode;
classNode = prev.classNode;
toSNode = prev.toSNode;
}

@Override
public abstract RubyString executeString(VirtualFrame frame);

@Specialization
public RubyString toS(RubyString string) {
return string;
}

@Specialization(guards = "!isRubyString", rewriteOn = UnexpectedResultException.class)
public RubyString toS(VirtualFrame frame, Object object) throws UnexpectedResultException {
return RubyTypesGen.RUBYTYPES.expectRubyString(callToSNode.call(frame, object, "to_s", null));
}

@Specialization(guards = "!isRubyString")
public RubyString toSFallback(VirtualFrame frame, Object object) {
final Object value = callToSNode.call(frame, object, "to_s", null);

if (value instanceof RubyString) {
return (RubyString) value;
} else {
return toSNode.toS(classNode.executeGetClass(frame, object));
}
}
}
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.nodes.cast.ToSNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.core.RubyBasicObject;
@@ -25,13 +26,11 @@
*/
public final class InterpolatedStringNode extends RubyNode {

@Children protected final RubyNode[] children;
@Child protected DispatchHeadNode toS;
@Children protected final ToSNode[] children;

public InterpolatedStringNode(RubyContext context, SourceSection sourceSection, RubyNode[] children) {
public InterpolatedStringNode(RubyContext context, SourceSection sourceSection, ToSNode[] children) {
super(context, sourceSection);
this.children = children;
toS = new DispatchHeadNode(context, true);
}

@ExplodeLoop
@@ -40,16 +39,7 @@ public Object execute(VirtualFrame frame) {
final RubyString[] strings = new RubyString[children.length];

for (int n = 0; n < children.length; n++) {
Object result = toS.call(frame, children[n].execute(frame), "to_s", null);

if (result instanceof RubyString) {
strings[n] = (RubyString) result;
} else if (result instanceof RubyBasicObject) {
strings[n] = KernelNodesFactory.ToSNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}).toS((RubyBasicObject) result);
} else {
RubyBasicObject boxed = getContext().getCoreLibrary().getLogicalClass(result);
strings[n] = KernelNodesFactory.ToSNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}).toS(boxed);
}
strings[n] = children[n].executeString(frame);
}

return concat(strings);
Original file line number Diff line number Diff line change
@@ -362,6 +362,8 @@ public ClassNode(ClassNode prev) {
super(prev);
}

public abstract RubyClass executeGetClass(VirtualFrame frame, Object value);

@Specialization
public RubyClass getClass(boolean value) {
notDesignedForCompilation();
Original file line number Diff line number Diff line change
@@ -702,13 +702,13 @@ public RubyNode visitDSymbolNode(org.jruby.ast.DSymbolNode node) {
}

private RubyNode translateInterpolatedString(SourceSection sourceSection, List<org.jruby.ast.Node> childNodes) {
final List<RubyNode> children = new ArrayList<>();
final List<ToSNode> children = new ArrayList<>();

for (org.jruby.ast.Node child : childNodes) {
children.add(child.accept(this));
children.add(ToSNodeFactory.create(context, sourceSection, child.accept(this)));
}

return new InterpolatedStringNode(context, sourceSection, children.toArray(new RubyNode[children.size()]));
return new InterpolatedStringNode(context, sourceSection, children.toArray(new ToSNode[children.size()]));
}

@Override
2 changes: 1 addition & 1 deletion default.build.properties
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ version.ruby=2.2.0
version.ruby.major=2.2
version.ruby.minor=0
version.ruby.patchlevel=0
version.ruby.revision=48175
version.ruby.revision=48765

version.ruby1_9.major=1.9
version.ruby1_9=1.9.3
10 changes: 9 additions & 1 deletion lib/ruby/stdlib/csv.rb
Original file line number Diff line number Diff line change
@@ -1470,7 +1470,15 @@ def self.table(path, options = Hash.new)
# if the data cannot be transcoded,
# leaving the header unchanged.
# <b><tt>:skip_blanks</tt></b>:: When set to a +true+ value, CSV will
# skip over any rows with no content.
# skip over any empty rows. Note that
# this setting will not skip rows that
# contain column separators, even if
# the rows contain no actual data. If
# you want to skip rows that contain
# separators but no content, consider
# using <tt>:skip_lines</tt>, or
# inspecting fields.compact.empty? on
# each row.
# <b><tt>:force_quotes</tt></b>:: When set to a +true+ value, CSV will
# quote all CSV fields it creates.
# <b><tt>:skip_lines</tt></b>:: When set to an object responding to
24 changes: 21 additions & 3 deletions lib/ruby/stdlib/digest.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require 'digest.so'

module Digest
# A mutex for Digest().
REQUIRE_MUTEX = Mutex.new

def self.const_missing(name) # :nodoc:
case name
when :SHA256, :SHA384, :SHA512
@@ -76,15 +79,30 @@ def base64digest!
# call-seq:
# Digest(name) -> digest_subclass
#
# Returns a Digest subclass by +name+.
# Returns a Digest subclass by +name+ in a thread-safe manner even
# when on-demand loading is involved.
#
# require 'digest'
#
# Digest("MD5")
# # => Digest::MD5
#
# Digest("Foo")
# Digest(:SHA256)
# # => Digest::SHA256
#
# Digest(:Foo)
# # => LoadError: library not found for class Digest::Foo -- digest/foo
def Digest(name)
Digest.const_get(name)
const = name.to_sym
Digest::REQUIRE_MUTEX.synchronize {
# Ignore autoload's because it is void when we have #const_missing
Digest.const_missing(const)
}
rescue LoadError
# Constants do not necessarily rely on digest/*.
if Digest.const_defined?(const)
Digest.const_get(const)
else
raise
end
end
115 changes: 104 additions & 11 deletions lib/ruby/stdlib/matrix.rb
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ module ExceptionForMatrix # :nodoc:
# * #minor(*param)
# * #first_minor(row, column)
# * #cofactor(row, column)
# * #adjugate
# * #laplace_expansion(row_or_column: num)
# * #cofactor_expansion(row_or_column: num)
#
@@ -444,7 +445,7 @@ def collect(&block) # :yield: e

#
# Yields all elements of the matrix, starting with those of the first row,
# or returns an Enumerator is no block given.
# or returns an Enumerator if no block given.
# Elements can be restricted by passing an argument:
# * :all (default): yields all elements
# * :diagonal: yields only elements on the diagonal
@@ -689,6 +690,20 @@ def cofactor(row, column)
det_of_minor * (-1) ** (row + column)
end

#
# Returns the adjugate of the matrix.
#
# Matrix[ [7,6],[3,9] ].adjugate
# => 9 -6
# -3 7
#
def adjugate
Matrix.Raise ErrDimensionMismatch unless square?
Matrix.build(row_count, column_count) do |row, column|
cofactor(column, row)
end
end

#
# Returns the Laplace expansion along given row or column.
#
@@ -1676,6 +1691,11 @@ def ** (other)
# * #each2(v)
# * #collect2(v)
#
# Properties of vectors:
# * #angle_with(v)
# * Vector.independent?(*vs)
# * #independent?(*vs)
#
# Vector arithmetic:
# * #*(x) "is matrix or number"
# * #+(v)
@@ -1684,8 +1704,8 @@ def ** (other)
# * #-@
#
# Vector functions:
# * #inner_product(v)
# * #cross_product(v)
# * #inner_product(v), dot(v)
# * #cross_product(v), cross(v)
# * #collect
# * #magnitude
# * #map
@@ -1816,6 +1836,41 @@ def collect2(v) # :yield: e1, e2
end
end

#--
# PROPERTIES -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#++

#
# Returns +true+ iff all of vectors are linearly independent.
#
# Vector.independent?(Vector[1,0], Vector[0,1])
# => true
#
# Vector.independent?(Vector[1,2], Vector[2,4])
# => false
#
def Vector.independent?(*vs)
vs.each do |v|
raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector)
Vector.Raise ErrDimensionMismatch unless v.size == vs.first.size
end
return false if vs.count > vs.first.size
Matrix[*vs].rank.eql?(vs.count)
end

#
# Returns +true+ iff all of vectors are linearly independent.
#
# Vector[1,0].independent?(Vector[0,1])
# => true
#
# Vector[1,2].independent?(Vector[2,4])
# => false
#
def independent?(*vs)
self.class.independent?(self, *vs)
end

#--
# COMPARING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#++
@@ -1834,14 +1889,14 @@ def eql?(other)
end

#
# Return a copy of the vector.
# Returns a copy of the vector.
#
def clone
self.class.elements(@elements)
end

#
# Return a hash-code for the vector.
# Returns a hash-code for the vector.
#
def hash
@elements.hash
@@ -1944,17 +1999,41 @@ def inner_product(v)
}
p
end
alias_method :dot, :inner_product

#
# Returns the cross product of this vector with the other.
# Returns the cross product of this vector with the others.
# Vector[1, 0, 0].cross_product Vector[0, 1, 0] => Vector[0, 0, 1]
#
def cross_product(v)
Vector.Raise ErrDimensionMismatch unless size == v.size && v.size == 3
Vector[ v[2]*@elements[1] - v[1]*@elements[2],
v[0]*@elements[2] - v[2]*@elements[0],
v[1]*@elements[0] - v[0]*@elements[1] ]
# It is generalized to other dimensions to return a vector perpendicular
# to the arguments.
# Vector[1, 2].cross_product # => Vector[-2, 1]
# Vector[1, 0, 0, 0].cross_product(
# Vector[0, 1, 0, 0],
# Vector[0, 0, 1, 0]
# ) #=> Vector[0, 0, 0, 1]
#
def cross_product(*vs)
raise ErrOperationNotDefined, "cross product is not defined on vectors of dimension #{size}" unless size >= 2
raise ArgumentError, "wrong number of arguments (#{vs.size} for #{size - 2})" unless vs.size == size - 2
vs.each do |v|
raise TypeError, "expected Vector, got #{v.class}" unless v.is_a? Vector
Vector.Raise ErrDimensionMismatch unless v.size == size
end
case size
when 2
Vector[-@elements[1], @elements[0]]
when 3
v = vs[0]
Vector[ v[2]*@elements[1] - v[1]*@elements[2],
v[0]*@elements[2] - v[2]*@elements[0],
v[1]*@elements[0] - v[0]*@elements[1] ]
else
rows = self, *vs, Array.new(size) {|i| Vector.basis(size: size, index: i) }
Matrix.rows(rows).laplace_expansion(row: size - 1)
end
end
alias_method :cross, :cross_product

#
# Like Array#collect.
@@ -1999,6 +2078,20 @@ def normalize
self / n
end

#
# Returns an angle with another vector. Result is within the [0...Math::PI].
# Vector[1,0].angle_with(Vector[0,1])
# # => Math::PI / 2
#
def angle_with(v)
raise TypeError, "Expected a Vector, got a #{v.class}" unless v.is_a?(Vector)
Vector.Raise ErrDimensionMismatch if size != v.size
prod = magnitude * v.magnitude
raise ZeroVectorError, "Can't get angle of zero vector" if prod == 0

Math.acos( inner_product(v) / prod )
end

#--
# CONVERTING
#++
5 changes: 4 additions & 1 deletion lib/ruby/stdlib/net/http.rb
Original file line number Diff line number Diff line change
@@ -918,7 +918,10 @@ def connect
@socket.write(buf)
HTTPResponse.read_new(@socket).value
end
s.session = @ssl_session if @ssl_session
if @ssl_session and
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
s.session = @ssl_session if @ssl_session
end
# Server Name Indication (SNI) RFC 3546
s.hostname = @address if s.respond_to? :hostname=
Timeout.timeout(@open_timeout, Net::OpenTimeout) { s.connect }
66 changes: 52 additions & 14 deletions lib/ruby/stdlib/net/imap.rb
Original file line number Diff line number Diff line change
@@ -788,8 +788,10 @@ def uid_search(keys, charset = nil)
# +attr+ is a list of attributes to fetch; see the documentation
# for Net::IMAP::FetchData for a list of valid attributes.
#
# The return value is an array of Net::IMAP::FetchData. For
# example:
# The return value is an array of Net::IMAP::FetchData or nil
# (instead of an empty array) if there is no matching message.
#
# For example:
#
# p imap.fetch(6..8, "UID")
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
@@ -1254,9 +1256,7 @@ def validate_data(data)
when nil
when String
when Integer
if data < 0 || data >= 4294967296
raise DataFormatError, num.to_s
end
NumValidator.ensure_number(data)
when Array
data.each do |i|
validate_data(i)
@@ -1570,7 +1570,7 @@ def validate_internal(data)
case data
when "*"
when Integer
ensure_nz_number(data)
NumValidator.ensure_nz_number(data)
when Range
when Array
data.each do |i|
@@ -1584,11 +1584,42 @@ def validate_internal(data)
raise DataFormatError, data.inspect
end
end
end

# Common validators of number and nz_number types
module NumValidator # :nodoc
class << self
# Check is passed argument valid 'number' in RFC 3501 terminology
def valid_number?(num)
# [RFC 3501]
# number = 1*DIGIT
# ; Unsigned 32-bit integer
# ; (0 <= n < 4,294,967,296)
num >= 0 && num < 4294967296
end

# Check is passed argument valid 'nz_number' in RFC 3501 terminology
def valid_nz_number?(num)
# [RFC 3501]
# nz-number = digit-nz *DIGIT
# ; Non-zero unsigned 32-bit integer
# ; (0 < n < 4,294,967,296)
num != 0 && valid_number?(num)
end

def ensure_nz_number(num)
if num < -1 || num == 0 || num >= 4294967296
msg = "nz_number must be non-zero unsigned 32-bit integer: " +
num.inspect
# Ensure argument is 'number' or raise DataFormatError
def ensure_number(num)
return if valid_number?(num)

msg = "number must be unsigned 32-bit integer: #{num}"
raise DataFormatError, msg
end

# Ensure argument is 'nz_number' or raise DataFormatError
def ensure_nz_number(num)
return if valid_nz_number?(num)

msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}"
raise DataFormatError, msg
end
end
@@ -2098,9 +2129,9 @@ def parse(str)

BEG_REGEXP = /\G(?:\
(?# 1: SPACE )( +)|\
(?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\
(?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+])|\
(?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*#{'"'}\\\[\]+]+)|\
(?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\
(?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\
(?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+]+)|\
(?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\
(?# 6: LPAR )(\()|\
(?# 7: RPAR )(\))|\
@@ -2863,8 +2894,15 @@ def search_response
break
when T_SPACE
shift_token
else
when T_NUMBER
data.push(number)
when T_LPAR
# TODO: include the MODSEQ value in a response
shift_token
match(T_ATOM)
match(T_SPACE)
match(T_NUMBER)
match(T_RPAR)
end
end
else
18 changes: 9 additions & 9 deletions lib/ruby/stdlib/open3.rb
Original file line number Diff line number Diff line change
@@ -214,11 +214,11 @@ class << self
# stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts])
#
# The arguments env, cmd and opts are passed to Open3.popen3 except
# opts[:stdin_data] and opts[:binmode]. See Process.spawn.
# <code>opts[:stdin_data]</code> and <code>opts[:binmode]</code>. See Process.spawn.
#
# If opts[:stdin_data] is specified, it is sent to the command's standard input.
# If <code>opts[:stdin_data]</code> is specified, it is sent to the command's standard input.
#
# If opts[:binmode] is true, internal pipes are set to binary mode.
# If <code>opts[:binmode]</code> is true, internal pipes are set to binary mode.
#
# Examples:
#
@@ -272,11 +272,11 @@ def capture3(*cmd, stdin_data: '', binmode: false, **opts)
# stdout_str, status = Open3.capture2([env,] cmd... [, opts])
#
# The arguments env, cmd and opts are passed to Open3.popen3 except
# opts[:stdin_data] and opts[:binmode]. See Process.spawn.
# <code>opts[:stdin_data]</code> and <code>opts[:binmode]</code>. See Process.spawn.
#
# If opts[:stdin_data] is specified, it is sent to the command's standard input.
# If <code>opts[:stdin_data]</code> is specified, it is sent to the command's standard input.
#
# If opts[:binmode] is true, internal pipes are set to binary mode.
# If <code>opts[:binmode]</code> is true, internal pipes are set to binary mode.
#
# Example:
#
@@ -320,11 +320,11 @@ def capture2(*cmd, stdin_data: nil, binmode: false, **opts)
# stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts])
#
# The arguments env, cmd and opts are passed to Open3.popen3 except
# opts[:stdin_data] and opts[:binmode]. See Process.spawn.
# <code>opts[:stdin_data]</code> and <code>opts[:binmode]</code>. See Process.spawn.
#
# If opts[:stdin_data] is specified, it is sent to the command's standard input.
# If <code>opts[:stdin_data]</code> is specified, it is sent to the command's standard input.
#
# If opts[:binmode] is true, internal pipes are set to binary mode.
# If <code>opts[:binmode]</code> is true, internal pipes are set to binary mode.
#
# Example:
#
6 changes: 4 additions & 2 deletions lib/ruby/stdlib/pp.rb
Original file line number Diff line number Diff line change
@@ -469,8 +469,10 @@ def pretty_print(q) # :nodoc:
q.comma_breakable
q.group {
q.text sprintf("rdev=0x%x", self.rdev)
q.breakable
q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
if self.rdev_major && self.rdev_minor
q.breakable
q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
end
}
q.comma_breakable
q.text "size="; q.pp self.size; q.comma_breakable
2 changes: 1 addition & 1 deletion lib/ruby/stdlib/psych.rb
Original file line number Diff line number Diff line change
@@ -217,7 +217,7 @@

module Psych
# The version is Psych you're using
VERSION = '2.0.6'
VERSION = '2.0.8'

# The version of libyaml Psych is using
LIBYAML_VERSION = Psych.libyaml_version.join '.'
15 changes: 15 additions & 0 deletions lib/ruby/stdlib/psych/visitors/to_ruby.rb
Original file line number Diff line number Diff line change
@@ -271,6 +271,21 @@ def visit_Psych_Nodes_Mapping o
end
map

when /^!ruby\/marshalable:(.*)$/
name = $1
klass = resolve_class(name)
obj = register(o, klass.allocate)

if obj.respond_to?(:init_with)
init_with(obj, revive_hash({}, o), o)
elsif obj.respond_to?(:marshal_load)
marshal_data = o.children.map(&method(:accept))
obj.marshal_load(marshal_data)
obj
else
raise ArgumentError, "Cannot deserialize #{name}"
end

else
revive_hash(register(o, {}), o)
end
14 changes: 14 additions & 0 deletions lib/ruby/stdlib/psych/visitors/yaml_tree.rb
Original file line number Diff line number Diff line change
@@ -27,6 +27,8 @@ def register target, node

def key? target
@obj_to_node.key? target.object_id
rescue NoMethodError
false
end

def id_for target
@@ -411,6 +413,18 @@ def visit_Symbol o
end
end

def visit_BasicObject o
tag = Psych.dump_tags[o.class]
tag ||= "!ruby/marshalable:#{o.class.name}"

map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
register(o, map)

o.marshal_dump.each(&method(:accept))

@emitter.end_mapping
end

private
# FIXME: Remove the index and count checks in Psych 3.0
NULL = "\x00"
4 changes: 4 additions & 0 deletions lib/ruby/stdlib/resolv.rb
Original file line number Diff line number Diff line change
@@ -1070,6 +1070,10 @@ def generate_candidates(name)
candidates = []
end
candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)})
fname = Name.create("#{name}.")
if !candidates.include?(fname)
candidates << fname
end
end
return candidates
end
2 changes: 1 addition & 1 deletion lib/ruby/stdlib/rexml/document.rb
Original file line number Diff line number Diff line change
@@ -281,7 +281,7 @@ def record_entity_expansion
def document
self
end

private
def build( source )
Parsers::TreeParser.new( source, self ).parse
4 changes: 2 additions & 2 deletions lib/ruby/stdlib/rexml/dtd/elementdecl.rb
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ module DTD
class ElementDecl < Child
START = "<!ELEMENT"
START_RE = /^\s*#{START}/um
PATTERN_RE = /^\s*(#{START}.*?)>/um
PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
# PATTERN_RE = /^\s*(#{START}.*?)>/um
PATTERN_RE = /^\s*#{START}\s+((?:[:\w][-\.\w]*:)?[-!\*\.\w]*)(.*?)>/
#\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)

def initialize match
1 change: 1 addition & 0 deletions lib/ruby/stdlib/rexml/entity.rb
Original file line number Diff line number Diff line change
@@ -157,6 +157,7 @@ def value

# This is a set of entity constants -- the ones defined in the XML
# specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+.
# CAUTION: these entities does not have parent and document
module EntityConst
# +>+
GT = Entity.new( 'gt', '>' )
12 changes: 0 additions & 12 deletions lib/ruby/stdlib/rexml/rexml.rb
Original file line number Diff line number Diff line change
@@ -28,16 +28,4 @@ module REXML

Copyright = COPYRIGHT
Version = VERSION

@@entity_expansion_text_limit = 10_240

# Set the entity expansion limit. By default the limit is set to 10240.
def self.entity_expansion_text_limit=( val )
@@entity_expansion_text_limit = val
end

# Get the entity expansion limit. By default the limit is set to 10240.
def self.entity_expansion_text_limit
return @@entity_expansion_text_limit
end
end
14 changes: 8 additions & 6 deletions lib/ruby/stdlib/tsort.rb
Original file line number Diff line number Diff line change
@@ -171,9 +171,7 @@ def tsort
# p TSort.tsort(each_node, each_child) # raises TSort::Cyclic
#
def TSort.tsort(each_node, each_child)
result = []
TSort.tsort_each(each_node, each_child) {|element| result << element}
result
TSort.tsort_each(each_node, each_child).to_a
end

# The iterator version of the #tsort method.
@@ -221,6 +219,8 @@ def tsort_each(&block) # :yields: node
# # 1
#
def TSort.tsort_each(each_node, each_child) # :yields: node
return to_enum(__method__, each_node, each_child) unless block_given?

TSort.each_strongly_connected_component(each_node, each_child) {|component|
if component.size == 1
yield component.first
@@ -276,9 +276,7 @@ def strongly_connected_components
# #=> [[4], [2, 3], [1]]
#
def TSort.strongly_connected_components(each_node, each_child)
result = []
TSort.each_strongly_connected_component(each_node, each_child) {|component| result << component}
result
TSort.each_strongly_connected_component(each_node, each_child).to_a
end

# The iterator version of the #strongly_connected_components method.
@@ -340,6 +338,8 @@ def each_strongly_connected_component(&block) # :yields: nodes
# # [1]
#
def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
return to_enum(__method__, each_node, each_child) unless block_given?

id_map = {}
stack = []
each_node.call {|node|
@@ -404,6 +404,8 @@ def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) #
# # [1]
#
def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
return to_enum(__method__, node, each_child, id_map, stack) unless block_given?

minimum_id = node_id = id_map[node] = id_map.size
stack_length = stack.length
stack << node
40 changes: 14 additions & 26 deletions lib/ruby/stdlib/unicode_normalize/normalize.rb
Original file line number Diff line number Diff line change
@@ -71,42 +71,28 @@ def self.hangul_comp_one(string)
## Canonical Ordering
def self.canonical_ordering_one(string)
sorting = string.each_char.collect { |c| [c, CLASS_TABLE[c]] }
(sorting.length-2).downto(0) do |i| # bubble sort
(sorting.length-2).downto(0) do |i| # almost, but not exactly bubble sort
(0..i).each do |j|
later_class = sorting[j+1].last
if 0<later_class and later_class<sorting[j].last
sorting[j], sorting[j+1] = sorting[j+1], sorting[j]
end
end
end
return sorting.collect(&:first).join
return sorting.collect(&:first).join('')
end

## Normalization Forms for Patterns (not whole Strings)
def self.nfd_one(string)
string = string.dup
(0...string.length).each do |position|
if decomposition = DECOMPOSITION_TABLE[string[position]]
string[position] = decomposition
end
end
string = string.chars.map! {|c| DECOMPOSITION_TABLE[c] || c}.join('')
canonical_ordering_one(hangul_decomp_one(string))
end

def self.nfkd_one(string)
string = string.dup
position = 0
while position < string.length
if decomposition = KOMPATIBLE_TABLE[string[position]]
string[position] = decomposition
else
position += 1
end
end
string
string.chars.map! {|c| KOMPATIBLE_TABLE[c] || c}.join('')
end

def self.nfc_one (string)
def self.nfc_one(string)
nfd_string = nfd_one string
start = nfd_string[0]
last_class = CLASS_TABLE[start]-1
@@ -116,7 +102,7 @@ def self.nfc_one (string)
if last_class<accent_class and composite = COMPOSITION_TABLE[start+accent]
start = composite
else
accents += accent
accents << accent
last_class = accent_class
end
end
@@ -125,7 +111,8 @@ def self.nfc_one (string)

def self.normalize(string, form = :nfc)
encoding = string.encoding
if encoding == Encoding::UTF_8
case encoding
when Encoding::UTF_8
case form
when :nfc then
string.gsub REGEXP_C, NF_HASH_C
@@ -138,9 +125,9 @@ def self.normalize(string, form = :nfc)
else
raise ArgumentError, "Invalid normalization form #{form}."
end
elsif encoding == Encoding::US_ASCII
when Encoding::US_ASCII
string
elsif UNICODE_ENCODINGS.include? encoding
when *UNICODE_ENCODINGS
normalize(string.encode(Encoding::UTF_8), form).encode(encoding)
else
raise Encoding::CompatibilityError, "Unicode Normalization not appropriate for #{encoding}"
@@ -149,7 +136,8 @@ def self.normalize(string, form = :nfc)

def self.normalized?(string, form = :nfc)
encoding = string.encoding
if encoding == Encoding::UTF_8
case encoding
when Encoding::UTF_8
case form
when :nfc then
string.scan REGEXP_C do |match|
@@ -168,9 +156,9 @@ def self.normalized?(string, form = :nfc)
else
raise ArgumentError, "Invalid normalization form #{form}."
end
elsif encoding == Encoding::US_ASCII
when Encoding::US_ASCII
true
elsif UNICODE_ENCODINGS.include? encoding
when *UNICODE_ENCODINGS
normalized? string.encode(Encoding::UTF_8), form
else
raise Encoding::CompatibilityError, "Unicode Normalization not appropriate for #{encoding}"
1,163 changes: 1,163 additions & 0 deletions lib/ruby/stdlib/unicode_normalize/tables.rb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/ruby/stdlib/uri.rb
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@

module URI
# :stopdoc:
VERSION_CODE = '000911'.freeze
VERSION_CODE = '001000'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:

4 changes: 2 additions & 2 deletions lib/ruby/stdlib/uri/generic.rb
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ def initialize(scheme,
if arg_check
self.scheme = scheme
self.userinfo = userinfo
self.host = host
self.hostname = host
self.port = port
self.path = path
self.query = query
@@ -851,7 +851,7 @@ def query=(v)
v.encode!(Encoding::UTF_8) rescue nil
v.delete!("\t\r\n")
v.force_encoding(Encoding::ASCII_8BIT)
v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n){'%%%02X' % $&.ord}
v.gsub!(/(?!%\h\h|[!$-&(-;=?-Z_a-~])./n.freeze){'%%%02X'.freeze % $&.ord}
v.force_encoding(Encoding::US_ASCII)
@query = v
end
2 changes: 1 addition & 1 deletion lib/ruby/stdlib/uri/mailto.rb
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ class MailTo < Generic
HEADER_REGEXP = /\A(?<hfield>(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g<hfield>)*\z/
# practical regexp for email address
# http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
EMAIL_REGEXP = /\A[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
# :startdoc:

#
4 changes: 2 additions & 2 deletions lib/ruby/stdlib/uri/rfc2396_parser.rb
Original file line number Diff line number Diff line change
@@ -98,11 +98,11 @@ class RFC2396_Parser
#
def initialize(opts = {})
@pattern = initialize_pattern(opts)
@pattern.each_value {|v| v.freeze}
@pattern.each_value(&:freeze)
@pattern.freeze

@regexp = initialize_regexp(@pattern)
@regexp.each_value {|v| v.freeze}
@regexp.each_value(&:freeze)
@regexp.freeze
end

4 changes: 2 additions & 2 deletions lib/ruby/stdlib/uri/rfc3986_parser.rb
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ module URI
class RFC3986_Parser # :nodoc:
# URI defined in RFC3986
# this regexp is modified not to host is not empty string
RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/

def split(uri) #:nodoc:
begin
2 changes: 2 additions & 0 deletions lib/ruby/stdlib/webrick/httpstatus.rb
Original file line number Diff line number Diff line change
@@ -8,6 +8,8 @@
#
# $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $

require 'webrick/accesslog'

module WEBrick

##
97 changes: 56 additions & 41 deletions lib/ruby/stdlib/webrick/server.rb
Original file line number Diff line number Diff line change
@@ -106,6 +106,7 @@ def initialize(config={}, default=Config::General)
@logger.info("ruby #{rubyv}")

@listeners = []
@shutdown_pipe = nil
unless @config[:DoNotListen]
if @config[:Listen]
warn(":Listen option is deprecated; use GenericServer#listen")
@@ -115,7 +116,6 @@ def initialize(config={}, default=Config::General)
@config[:Port] = @listeners[0].addr[1]
end
end
@shutdown_pipe_w = nil
end

##
@@ -131,6 +131,7 @@ def [](key)

def listen(address, port)
@listeners += Utils::create_listeners(address, port, @logger)
setup_shutdown_pipe
end

##
@@ -158,21 +159,20 @@ def start(&block)
raise ServerError, "already started." if @status != :Stop
server_type = @config[:ServerType] || SimpleServer

shutdown_pipe_r, shutdown_pipe_w = IO.pipe
@shutdown_pipe_w = shutdown_pipe_w

server_type.start{
@logger.info \
"#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
call_callback(:StartCallback)

shutdown_pipe = @shutdown_pipe

thgroup = ThreadGroup.new
@status = :Running
begin
while @status == :Running
begin
if svrs = IO.select([shutdown_pipe_r, *@listeners], nil, nil, 2.0)
if svrs[0].include? shutdown_pipe_r
if svrs = IO.select([shutdown_pipe[0], *@listeners], nil, nil, 2.0)
if svrs[0].include? shutdown_pipe[0]
break
end
svrs[0].each{|svr|
@@ -198,16 +198,9 @@ def start(&block)
raise
end
end

ensure
shutdown_pipe_r.close
if !shutdown_pipe_w.closed?
begin
shutdown_pipe_w.close
rescue IOError # Another thread closed shutdown_pipe_w.
end
end
@shutdown_pipe_w = nil
cleanup_shutdown_pipe(shutdown_pipe)
cleanup_listener
@status = :Shutdown
@logger.info "going to shutdown ..."
thgroup.list.each{|th| th.join if th[:WEBrickThread] }
@@ -234,34 +227,15 @@ def stop
def shutdown
stop

shutdown_pipe_w = @shutdown_pipe_w
@shutdown_pipe_w = nil
if shutdown_pipe_w && !shutdown_pipe_w.closed?
begin
shutdown_pipe_w.close
rescue IOError # Another thread closed shutdown_pipe_w.
end
end

@listeners.each{|s|
if @logger.debug?
addr = s.addr
@logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
end
begin
s.shutdown
rescue Errno::ENOTCONN
# when `Errno::ENOTCONN: Socket is not connected' on some platforms,
# call #close instead of #shutdown.
# (ignore @config[:ShutdownSocketWithoutClose])
s.close
else
unless @config[:ShutdownSocketWithoutClose]
s.close
shutdown_pipe = @shutdown_pipe # another thread may modify @shutdown_pipe.
if shutdown_pipe
if !shutdown_pipe[1].closed?
begin
shutdown_pipe[1].close
rescue IOError # closed by another thread.
end
end
}
@listeners.clear
end
end

##
@@ -346,5 +320,46 @@ def call_callback(callback_name, *args)
cb.call(*args)
end
end

def setup_shutdown_pipe
if !@shutdown_pipe
@shutdown_pipe = IO.pipe
end
@shutdown_pipe
end

def cleanup_shutdown_pipe(shutdown_pipe)
@shutdown_pipe = nil
shutdown_pipe.each {|io|
if !io.closed?
begin
io.close
rescue IOError # another thread closed io.
end
end
}
end

def cleanup_listener
@listeners.each{|s|
if @logger.debug?
addr = s.addr
@logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
end
begin
s.shutdown
rescue Errno::ENOTCONN
# when `Errno::ENOTCONN: Socket is not connected' on some platforms,
# call #close instead of #shutdown.
# (ignore @config[:ShutdownSocketWithoutClose])
s.close
else
unless @config[:ShutdownSocketWithoutClose]
s.close
end
end
}
@listeners.clear
end
end # end of GenericServer
end
1 change: 1 addition & 0 deletions lib/ruby/stdlib/webrick/ssl.rb
Original file line number Diff line number Diff line change
@@ -162,6 +162,7 @@ def listen(address, port) # :nodoc:
}
end
@listeners += listeners
setup_shutdown_pipe
end

##
10 changes: 2 additions & 8 deletions lib/ruby/stdlib/win32/importer.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
begin
require 'fiddle/import'
importer = Fiddle::Importer
rescue LoadError
require 'dl/import'
importer = DL::Importer
end
require 'fiddle/import'

module Win32
end

Win32.module_eval do
Importer = importer
Importer = Fiddle::Importer
end
11 changes: 7 additions & 4 deletions lib/ruby/stdlib/win32/registry.rb
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ module Win32

WCHAR = Encoding::UTF_16LE
WCHAR_NUL = "\0".encode(WCHAR).freeze
WCHAR_CR = "\r".encode(WCHAR).freeze
WCHAR_SIZE = WCHAR_NUL.bytesize
LOCALE = Encoding.find(Encoding.locale_charmap)

@@ -171,8 +172,10 @@ def initialize(code)
@code = code
msg = WCHAR_NUL * 1024
len = FormatMessageW.call(0x1200, 0, code, 0, msg, 1024, 0)
msg = msg[0, len].encode(LOCALE)
super msg.tr("\r".encode(msg.encoding), '').chomp
msg = msg.byteslice(0, len * WCHAR_SIZE)
msg.delete!(WCHAR_CR)
msg.chomp!
super msg.encode(LOCALE)
end
attr_reader :code
end
@@ -283,15 +286,15 @@ def EnumValue(hkey, index)
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
size = packdw(Constants::MAX_KEY_LENGTH)
check RegEnumValueW.call(hkey, index, name, size, 0, 0, 0, 0)
name[0, unpackdw(size)]
name.byteslice(0, unpackdw(size) * WCHAR_SIZE)
end

def EnumKey(hkey, index)
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
size = packdw(Constants::MAX_KEY_LENGTH)
wtime = ' ' * 8
check RegEnumKeyExW.call(hkey, index, name, size, 0, 0, 0, wtime)
[ name[0, unpackdw(size)], unpackqw(wtime) ]
[ name.byteslice(0, unpackdw(size) * WCHAR_SIZE), unpackqw(wtime) ]
end

def QueryValue(hkey, name)
12 changes: 6 additions & 6 deletions spec/ffi/function_spec.rb
Original file line number Diff line number Diff line change
@@ -63,12 +63,12 @@ class << self; self; end
end

it 'can wrap a blocking function' do
fp = FFI::Function.new(:void, [ :int ], @libtest.find_function('testBlocking'), :blocking => true)
time = Time.now
threads = []
threads << Thread.new { fp.call(2) }
threads << Thread.new(time) { expect(Time.now - time).to be < 1 }
threads.each { |t| t.join }
# fp = FFI::Function.new(:void, [ :int ], @libtest.find_function('testBlocking'), :blocking => true)
# time = Time.now
# threads = []
# threads << Thread.new { fp.call(2) }
# threads << Thread.new(time) { expect(Time.now - time).to be < 1 }
# threads.each { |t| t.join }
end

it 'autorelease flag is set to true by default' do

0 comments on commit 81a4810

Please sign in to comment.