utilrb 1.1 → 1.2
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.
- data/{Changes.txt → History.txt} +11 -0
- data/License.txt +2 -2
- data/Manifest.txt +10 -3
- data/README.txt +10 -13
- data/Rakefile +30 -13
- data/ext/extconf.rb +6 -1
- data/ext/{ruby_internals.h → ruby_internals-1.8.h} +0 -0
- data/ext/ruby_internals-1.9.h +48 -0
- data/ext/swap.cc +5 -1
- data/ext/{faster.cc → utilrb_ext.cc} +29 -2
- data/lib/utilrb/column_formatter.rb +1 -1
- data/lib/utilrb/common.rb +21 -18
- data/lib/utilrb/dir.rb +2 -0
- data/lib/utilrb/dir/empty.rb +3 -0
- data/lib/utilrb/enumerable/uniq.rb +1 -1
- data/lib/utilrb/kernel/options.rb +3 -2
- data/lib/utilrb/kernel/swap.rb +1 -1
- data/lib/utilrb/logger/hierarchy.rb +7 -7
- data/lib/utilrb/module/ancestor_p.rb +2 -2
- data/lib/utilrb/module/define_or_reuse.rb +29 -0
- data/lib/utilrb/module/include.rb +15 -12
- data/lib/utilrb/module/inherited_enumerable.rb +4 -0
- data/lib/utilrb/object/address.rb +3 -3
- data/lib/utilrb/object/attribute.rb +2 -2
- data/lib/utilrb/object/singleton_class.rb +40 -47
- data/lib/utilrb/socket/tcp_server.rb +7 -0
- data/lib/utilrb/socket/tcp_socket.rb +7 -0
- data/lib/utilrb/time/to_hms.rb +31 -16
- data/lib/utilrb/value_set.rb +1 -1
- data/test/test_dir.rb +22 -0
- data/test/test_enumerable.rb +2 -2
- data/test/test_kernel.rb +2 -2
- data/test/test_module.rb +61 -53
- data/test/test_object.rb +25 -4
- data/test/test_pkgconfig.rb +0 -1
- data/test/test_proc.rb +23 -20
- data/test/test_time.rb +15 -2
- metadata +86 -61
data/lib/utilrb/kernel/swap.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'utilrb/common'
|
2
|
-
Utilrb.
|
2
|
+
Utilrb.require_ext('Kernel#swap!')
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'facets/module/spacename'
|
2
|
+
require 'facets/kernel/constant'
|
3
3
|
class Logger
|
4
4
|
# Define a hierarchy of loggers mapped to the module hierarchy.
|
5
5
|
# It defines the #logger accessor which either returns the logger
|
@@ -22,11 +22,11 @@ class Logger
|
|
22
22
|
attr_writer :logger
|
23
23
|
def logger
|
24
24
|
return @logger if defined?(@logger) && @logger
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
@logger = if kind_of?(Module)
|
26
|
+
constant(self.spacename).logger
|
27
|
+
else
|
28
|
+
self.class.logger
|
29
|
+
end
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'utilrb/common'
|
2
2
|
class Module
|
3
|
-
Utilrb.
|
3
|
+
Utilrb.if_ext do
|
4
4
|
# Check if +klass+ is an ancestor of this class/module
|
5
5
|
#
|
6
6
|
# It works for singleton classes as well:
|
@@ -15,7 +15,7 @@ class Module
|
|
15
15
|
self <= klass || (is_singleton? && superclass.has_ancestor?(klass))
|
16
16
|
end
|
17
17
|
end
|
18
|
-
Utilrb.
|
18
|
+
Utilrb.unless_ext do
|
19
19
|
def has_ancestor?(klass) # :nodoc:
|
20
20
|
self <= klass || superclass == klass || superclass < klass
|
21
21
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Module
|
2
|
+
if Utilrb::RUBY_IS_19
|
3
|
+
# :call-seq
|
4
|
+
# define_or_reuse(name, value) -> value
|
5
|
+
# define_or_reuse(name) { ... } -> value
|
6
|
+
#
|
7
|
+
# Defines a new constant under a given module, or reuse the
|
8
|
+
# already-existing value if the constant is already defined.
|
9
|
+
#
|
10
|
+
# In the first form, the method gets its value from its argument.
|
11
|
+
# In the second case, it calls the provided block
|
12
|
+
def define_or_reuse(name, value = nil)
|
13
|
+
if const_defined?(name, false)
|
14
|
+
const_get(name)
|
15
|
+
else
|
16
|
+
const_set(name, (value || yield))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
def define_or_reuse(name, value = nil)
|
21
|
+
if const_defined?(name)
|
22
|
+
const_get(name)
|
23
|
+
else
|
24
|
+
const_set(name, (value || yield))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -1,5 +1,7 @@
|
|
1
1
|
class Module
|
2
|
-
|
2
|
+
begin
|
3
|
+
method(:__instance_include__)
|
4
|
+
rescue NameError
|
3
5
|
alias :__instance_include__ :include
|
4
6
|
end
|
5
7
|
|
@@ -12,19 +14,20 @@ class Module
|
|
12
14
|
# * if it is included in a Class, the ClassExtension module
|
13
15
|
# extends the class.
|
14
16
|
def include(mod)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
if mod.const_defined?(:ClassExtension)
|
18
|
+
if !is_a?(Class)
|
19
|
+
unless const_defined?(:ClassExtension)
|
20
|
+
const_set(:ClassExtension, Module.new)
|
21
|
+
end
|
22
|
+
const_get(:ClassExtension).class_eval do
|
23
|
+
__instance_include__ mod.const_get(:ClassExtension)
|
24
|
+
end
|
25
|
+
else
|
26
|
+
extend mod.const_get(:ClassExtension)
|
24
27
|
end
|
25
|
-
else
|
26
|
-
extend mod.const_get(:ClassExtension)
|
27
28
|
end
|
29
|
+
|
30
|
+
__instance_include__ mod
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
@@ -14,6 +14,10 @@ class Module
|
|
14
14
|
if options[:map]
|
15
15
|
class_eval <<-EOF
|
16
16
|
def each_#{name}(key = nil, uniq = true)
|
17
|
+
if !block_given?
|
18
|
+
return enum_for(:each_#{name}, key, uniq)
|
19
|
+
end
|
20
|
+
|
17
21
|
if key
|
18
22
|
for klass in ancestors
|
19
23
|
if klass.instance_variable_defined?(:@#{attribute_name})
|
@@ -5,10 +5,10 @@ class Object
|
|
5
5
|
def address; Object.address_from_id(object_id) end
|
6
6
|
|
7
7
|
# Converts the object_id of a non-immediate object
|
8
|
-
# to its
|
8
|
+
# to its memory address
|
9
9
|
def self.address_from_id(id)
|
10
|
-
id =
|
11
|
-
(id * 2) &
|
10
|
+
id = 0xFFFFFFFFFFFFFFFF - ~id if id < 0
|
11
|
+
(id * 2) & 0xFFFFFFFFFFFFFFFF
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'utilrb/common'
|
2
2
|
require 'utilrb/object/singleton_class'
|
3
3
|
|
4
|
-
Utilrb.
|
4
|
+
Utilrb.unless_ext do
|
5
5
|
class Object
|
6
6
|
# call-seq:
|
7
7
|
# attribute :name => default_value
|
@@ -37,7 +37,7 @@ Utilrb.unless_faster do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
Utilrb.
|
40
|
+
Utilrb.if_ext do
|
41
41
|
class Object
|
42
42
|
def attribute(attr_def, &init) # :nodoc:
|
43
43
|
if Hash === attr_def
|
@@ -1,68 +1,61 @@
|
|
1
|
+
require 'utilrb/common'
|
1
2
|
require 'utilrb/object/address'
|
2
3
|
|
4
|
+
class Class
|
5
|
+
unless method_defined?(:__ancestors__)
|
6
|
+
alias __ancestors__ ancestors
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :singleton_instance
|
10
|
+
|
11
|
+
Utilrb.require_ext("Object#ancestors") do
|
12
|
+
def ancestors
|
13
|
+
if is_singleton?
|
14
|
+
__ancestors__.unshift(self)
|
15
|
+
else
|
16
|
+
__ancestors__
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
3
22
|
class Object
|
4
23
|
# Returns true if this object has its own singleton class
|
5
24
|
def has_singleton?; defined? @singleton_class end
|
6
25
|
end
|
7
26
|
|
8
|
-
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
27
|
+
class Object
|
28
|
+
# Returns the singleton class for this object.
|
29
|
+
#
|
30
|
+
# In Ruby 1.8, makes sure that the #superclass method of the singleton class
|
31
|
+
# returns the object's class (instead of Class), as Ruby 1.9 does
|
32
|
+
#
|
33
|
+
# The first element of #ancestors on the returned singleton class is
|
34
|
+
# the singleton class itself. A #singleton_instance accessor is also
|
35
|
+
# defined, which returns the object instance the class is the singleton
|
36
|
+
# of.
|
37
|
+
def singleton_class
|
38
|
+
unless defined? @singleton_class
|
39
|
+
klass = class << self; self end
|
40
|
+
klass.instance_variable_set(:@singleton_instance, self)
|
41
|
+
@singleton_class = klass
|
24
42
|
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
else
|
30
|
-
class Object
|
31
|
-
# Returns the singleton class for this object.
|
32
|
-
#
|
33
|
-
# In Ruby 1.8, makes sure that the #superclass method of the singleton class
|
34
|
-
# returns the object's class (instead of Class), as Ruby 1.9 does
|
35
|
-
#
|
36
|
-
# The first element of #ancestors on the returned singleton class is
|
37
|
-
# the singleton class itself. A #singleton_instance accessor is also
|
38
|
-
# defined, which returns the object instance the class is the singleton
|
39
|
-
# of.
|
40
|
-
def singleton_class
|
41
|
-
if defined? @singleton_class
|
42
|
-
return @singleton_class
|
43
|
-
else
|
44
|
-
klass = class << self; self end
|
43
|
+
unless Utilrb::RUBY_IS_19
|
45
44
|
instance = self
|
46
45
|
klass.class_eval do
|
47
|
-
@
|
48
|
-
@superclass = instance.class
|
46
|
+
@superclass = instance.class
|
49
47
|
class << self
|
50
48
|
attr_reader :superclass
|
51
|
-
attr_reader :singleton_instance
|
52
49
|
def name
|
53
|
-
"#{
|
54
|
-
end
|
55
|
-
|
56
|
-
alias __ancestors__ ancestors # :nodoc:
|
57
|
-
def ancestors # :nodoc:
|
58
|
-
__ancestors__.unshift(self)
|
50
|
+
"#{superclass.name}!0x#{@singleton_instance.address.to_s(16)}"
|
59
51
|
end
|
60
52
|
end
|
61
53
|
end
|
62
|
-
|
63
|
-
@singleton_class = klass
|
64
54
|
end
|
55
|
+
klass
|
65
56
|
end
|
57
|
+
|
58
|
+
@singleton_class
|
66
59
|
end
|
67
60
|
end
|
68
61
|
|
data/lib/utilrb/time/to_hms.rb
CHANGED
@@ -5,37 +5,52 @@ class Time
|
|
5
5
|
"%i:%02i:%02i.%03i" % [sec / 3600, (sec % 3600) / 60, sec % 60, usec / 1000]
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
def self.from_hms(string)
|
11
|
-
unless string =~ /(?:^|:)0*(\d*)(?:$|\.)/
|
8
|
+
def self.hms_decomposition(string)
|
9
|
+
unless string =~ /(?:^|:)0*(\d*)(?:$|\.(\d*)$)/
|
12
10
|
raise ArgumentError, "#{string} found, expected [[h:]m:]s[.ms]"
|
13
11
|
end
|
14
|
-
hm, ms = $`, $
|
12
|
+
hm, ms = $`, ($2 || "")
|
15
13
|
|
16
14
|
s = if $1.empty? then 0
|
17
15
|
else Integer($1)
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
h, m = hm.split(':')
|
19
|
+
if !m
|
20
|
+
h, m = nil, h
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
if m
|
24
|
+
m =~ /^0*(\d*)$/
|
25
|
+
m = $1
|
26
|
+
end
|
27
|
+
m = if !m || m.empty? then 0
|
28
|
+
else Integer(m)
|
29
|
+
end
|
30
|
+
|
31
|
+
if h
|
32
|
+
h =~ /^0*(\d*)$/
|
33
|
+
h = $1
|
34
|
+
end
|
35
|
+
h = if !h || h.empty? then 0
|
36
|
+
else Integer(h)
|
37
|
+
end
|
30
38
|
|
31
39
|
ms = if ms =~ /^0*$/ then 0
|
32
40
|
else
|
33
|
-
unless ms =~ /^(0*)(
|
41
|
+
unless ms =~ /^(0*)(\d+)$/
|
34
42
|
raise ArgumentError, "found #{string}, expected a number"
|
35
43
|
end
|
36
|
-
Integer($2) * (10 ** (
|
44
|
+
Integer($2) * (10 ** (3 - ($2.length + $1.length)))
|
37
45
|
end
|
38
46
|
|
39
|
-
|
47
|
+
[h, m, s, ms]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates a Time object from a h:m:s.ms representation. The following formats are allowed:
|
51
|
+
# s, s.ms, m:s, m:s.ms, h:m:s, h:m:s.ms
|
52
|
+
def self.from_hms(string)
|
53
|
+
h, m, s, ms = *hms_decomposition(string)
|
54
|
+
Time.at(h * 3600 + m * 60 + s, 1000 * ms)
|
40
55
|
end
|
41
56
|
end
|
data/lib/utilrb/value_set.rb
CHANGED
data/test/test_dir.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_config'
|
2
|
+
|
3
|
+
require 'utilrb/dir'
|
4
|
+
require 'enumerator'
|
5
|
+
|
6
|
+
class TC_Dir < Test::Unit::TestCase
|
7
|
+
def test_empty
|
8
|
+
this_dir = File.dirname(__FILE__)
|
9
|
+
assert(!Dir.new(this_dir).empty?)
|
10
|
+
|
11
|
+
begin
|
12
|
+
Dir.mkdir(test_dir_path = File.join(this_dir, 'test_empty') )
|
13
|
+
rescue Errno::EEXIST
|
14
|
+
end
|
15
|
+
|
16
|
+
test_dir = Dir.new(test_dir_path)
|
17
|
+
assert(test_dir.empty?)
|
18
|
+
ensure
|
19
|
+
Dir.delete(test_dir_path) if test_dir_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/test/test_enumerable.rb
CHANGED
@@ -54,13 +54,13 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
54
54
|
assert_equal(nil, [].random_element)
|
55
55
|
|
56
56
|
# Test on non-empty collection which defines #size
|
57
|
-
set = Hash[*(1..100).map { |i| [
|
57
|
+
set = Hash[*(1..100).map { |i| [i.to_s, i] }.flatten]
|
58
58
|
100.times { set.delete(set.random_element.first) }
|
59
59
|
assert(set.empty?)
|
60
60
|
assert_equal(nil, {}.random_element)
|
61
61
|
end
|
62
62
|
|
63
|
-
Utilrb.
|
63
|
+
Utilrb.require_ext('test_value_set') do
|
64
64
|
def test_value_set
|
65
65
|
a = [1, 3, 3, 4, 6, 8].to_value_set
|
66
66
|
b = [1, 2, 4, 3, 11, 11].to_value_set
|
data/test/test_kernel.rb
CHANGED
@@ -45,7 +45,7 @@ class TC_Kernel < Test::Unit::TestCase
|
|
45
45
|
assert_nothing_raised { check_arity(object.method(:arity_1_more), 2) }
|
46
46
|
end
|
47
47
|
|
48
|
-
Utilrb.
|
48
|
+
Utilrb.require_ext('is_singleton?') do
|
49
49
|
def test_is_singleton
|
50
50
|
klass = Class.new
|
51
51
|
singl_klass = (class << klass; self end)
|
@@ -57,7 +57,7 @@ class TC_Kernel < Test::Unit::TestCase
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
Utilrb.
|
60
|
+
Utilrb.require_ext('test_swap') do
|
61
61
|
def test_swap
|
62
62
|
obj = Array.new
|
63
63
|
Kernel.swap!(obj, Hash.new)
|
data/test/test_module.rb
CHANGED
@@ -7,20 +7,26 @@ require 'utilrb/module'
|
|
7
7
|
|
8
8
|
class TC_Module < Test::Unit::TestCase
|
9
9
|
def test_include
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
class_extension = Module.new do
|
11
|
+
def tag; end
|
12
|
+
end
|
13
|
+
|
14
|
+
m = Module.new do
|
15
|
+
const_set(:ClassExtension, class_extension)
|
16
|
+
end
|
17
|
+
|
18
|
+
m2 = Module.new { include m }
|
19
|
+
assert(m2::ClassExtension.method_defined?(:tag))
|
20
|
+
k = Class.new do
|
21
|
+
include m2
|
22
|
+
end
|
23
|
+
assert(k.respond_to?(:tag))
|
24
|
+
end
|
13
25
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
m2 = Module.new { include m }
|
19
|
-
assert(m2::ClassExtension.method_defined?(:tag))
|
20
|
-
k = Class.new do
|
21
|
-
include m2
|
22
|
-
end
|
23
|
-
assert(k.respond_to?(:tag))
|
26
|
+
def test_define_or_reuse
|
27
|
+
mod = Module.new
|
28
|
+
new_mod = mod.define_or_reuse(:Foo) { Module.new }
|
29
|
+
assert_equal(new_mod, mod.define_or_reuse(:Foo) { flunk("block called in #define_under") })
|
24
30
|
end
|
25
31
|
|
26
32
|
def test_define_method_with_block
|
@@ -43,31 +49,31 @@ class TC_Module < Test::Unit::TestCase
|
|
43
49
|
end
|
44
50
|
|
45
51
|
def test_attr_enumerable
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
klass = Class.new do
|
53
|
+
attr_enumerable(:mapped, :map) { Hash.new }
|
54
|
+
end
|
55
|
+
|
56
|
+
obj = klass.new
|
57
|
+
obj.map[:a] = [10, 20]
|
58
|
+
obj.map[:b] = 10
|
59
|
+
assert_equal( [[:a, [10, 20]], [:b, 10]].to_set, obj.enum_for(:each_mapped).to_set )
|
60
|
+
assert_equal( [10, 20], obj.enum_for(:each_mapped, :a).to_a )
|
55
61
|
end
|
56
62
|
|
57
63
|
def test_inherited_enumerable_module
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
m = Module.new do
|
65
|
+
inherited_enumerable(:signature, :signatures) { Array.new }
|
66
|
+
end
|
67
|
+
k = Class.new do
|
68
|
+
include m
|
69
|
+
inherited_enumerable(:child_attribute) { Array.new }
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add another attribute *after* k has been defined
|
73
|
+
m.class_eval do
|
74
|
+
inherited_enumerable(:mapped, :map, :map => true) { Hash.new }
|
75
|
+
end
|
76
|
+
check_inherited_enumerable(m, k)
|
71
77
|
end
|
72
78
|
|
73
79
|
def test_inherited_enumerable_class
|
@@ -87,7 +93,9 @@ class TC_Module < Test::Unit::TestCase
|
|
87
93
|
assert(object.singleton_class.respond_to?(:signatures))
|
88
94
|
object.singleton_class.signatures << :in_singleton
|
89
95
|
assert_equal([:in_singleton], object.singleton_class.signatures)
|
90
|
-
|
96
|
+
Utilrb.if_ext do
|
97
|
+
assert_equal([:in_singleton, :in_derived, :in_base], object.singleton_class.enum_for(:each_signature).to_a)
|
98
|
+
end
|
91
99
|
end
|
92
100
|
|
93
101
|
def check_inherited_enumerable(base, derived)
|
@@ -125,23 +133,23 @@ class TC_Module < Test::Unit::TestCase
|
|
125
133
|
end
|
126
134
|
|
127
135
|
def test_has_ancestor
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
136
|
+
mod = Module.new
|
137
|
+
parent = Class.new do
|
138
|
+
include mod
|
139
|
+
end
|
140
|
+
child = Class.new(parent)
|
141
|
+
singleton = child.new.singleton_class
|
142
|
+
|
143
|
+
assert(child.has_ancestor?(parent))
|
144
|
+
assert(child.has_ancestor?(mod))
|
145
|
+
assert(parent.has_ancestor?(mod))
|
146
|
+
|
147
|
+
assert(singleton.has_ancestor?(parent), singleton.superclass)
|
148
|
+
assert(singleton.has_ancestor?(mod))
|
149
|
+
assert(singleton.has_ancestor?(child))
|
150
|
+
|
151
|
+
assert(!parent.has_ancestor?(child))
|
152
|
+
assert(!parent.has_ancestor?(singleton))
|
145
153
|
end
|
146
154
|
end
|
147
155
|
|