utilrb 0.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.
Files changed (65) hide show
  1. data/Changes.txt +20 -0
  2. data/License.txt +26 -0
  3. data/Manifest.txt +64 -0
  4. data/README.txt +44 -0
  5. data/Rakefile +46 -0
  6. data/bm/allocation.rb +7 -0
  7. data/bm/speed.rb +19 -0
  8. data/ext/extconf.rb +5 -0
  9. data/ext/faster.cc +48 -0
  10. data/ext/swap.cc +61 -0
  11. data/ext/value_set.cc +290 -0
  12. data/lib/utilrb.rb +2 -0
  13. data/lib/utilrb/array.rb +2 -0
  14. data/lib/utilrb/array/to_s.rb +16 -0
  15. data/lib/utilrb/common.rb +50 -0
  16. data/lib/utilrb/enumerable.rb +2 -0
  17. data/lib/utilrb/enumerable/null.rb +18 -0
  18. data/lib/utilrb/enumerable/random_element.rb +16 -0
  19. data/lib/utilrb/enumerable/sequence.rb +24 -0
  20. data/lib/utilrb/enumerable/uniq.rb +61 -0
  21. data/lib/utilrb/exception.rb +2 -0
  22. data/lib/utilrb/exception/full_message.rb +8 -0
  23. data/lib/utilrb/gc.rb +2 -0
  24. data/lib/utilrb/gc/force.rb +11 -0
  25. data/lib/utilrb/hash.rb +2 -0
  26. data/lib/utilrb/hash/slice.rb +6 -0
  27. data/lib/utilrb/hash/to_s.rb +6 -0
  28. data/lib/utilrb/hash/to_sym_keys.rb +6 -0
  29. data/lib/utilrb/kernel.rb +2 -0
  30. data/lib/utilrb/kernel/arity.rb +10 -0
  31. data/lib/utilrb/kernel/options.rb +69 -0
  32. data/lib/utilrb/kernel/poll.rb +24 -0
  33. data/lib/utilrb/kernel/require.rb +12 -0
  34. data/lib/utilrb/kernel/swap.rb +2 -0
  35. data/lib/utilrb/logger.rb +3 -0
  36. data/lib/utilrb/logger/forward.rb +15 -0
  37. data/lib/utilrb/logger/hierarchy.rb +34 -0
  38. data/lib/utilrb/module.rb +2 -0
  39. data/lib/utilrb/module/ancestor_p.rb +6 -0
  40. data/lib/utilrb/module/attr_enumerable.rb +28 -0
  41. data/lib/utilrb/module/define_method.rb +30 -0
  42. data/lib/utilrb/module/include.rb +30 -0
  43. data/lib/utilrb/module/inherited_enumerable.rb +122 -0
  44. data/lib/utilrb/object.rb +2 -0
  45. data/lib/utilrb/object/address.rb +14 -0
  46. data/lib/utilrb/object/attribute.rb +89 -0
  47. data/lib/utilrb/object/singleton_class.rb +53 -0
  48. data/lib/utilrb/objectstats.rb +52 -0
  49. data/lib/utilrb/time.rb +2 -0
  50. data/lib/utilrb/time/to_hms.rb +6 -0
  51. data/lib/utilrb/unbound_method.rb +2 -0
  52. data/lib/utilrb/unbound_method/call.rb +5 -0
  53. data/lib/utilrb/value_set.rb +17 -0
  54. data/test/test_array.rb +9 -0
  55. data/test/test_config.rb +4 -0
  56. data/test/test_enumerable.rb +89 -0
  57. data/test/test_gc.rb +39 -0
  58. data/test/test_hash.rb +22 -0
  59. data/test/test_kernel.rb +70 -0
  60. data/test/test_misc.rb +42 -0
  61. data/test/test_module.rb +127 -0
  62. data/test/test_object.rb +65 -0
  63. data/test/test_objectstats.rb +19 -0
  64. data/test/test_unbound_method.rb +23 -0
  65. metadata +128 -0
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
@@ -0,0 +1,6 @@
1
+ class Module
2
+ # Check if +klass+ is an ancestor of this class/module
3
+ def has_ancestor?(klass); ancestors.find { |a| a == klass } end
4
+ end
5
+
6
+
@@ -0,0 +1,28 @@
1
+ require 'utilrb/object/attribute'
2
+
3
+ class Module
4
+ # Define 'name' to be a read-only enumerable attribute. The method
5
+ # defines a +attr_name+ read-only attribute and an enumerator method
6
+ # each_#{name}. +init_block+ is used to initialize the attribute.
7
+ #
8
+ # The enumerator method accepts a +key+ argument. If the attribute is
9
+ # a key => enumerable map, then the +key+ attribute can be used to iterate
10
+ #
11
+ # +enumerator+ is the name of the enumeration method
12
+ def attr_enumerable(name, attr_name = name, enumerator = :each, &init_block)
13
+ class_eval do
14
+ attribute(attr_name, &init_block)
15
+ end
16
+ class_eval <<-EOF
17
+ def each_#{name}(key = nil, &iterator)
18
+ return unless #{attr_name}
19
+ if key
20
+ #{attr_name}[key].#{enumerator}(&iterator)
21
+ else
22
+ #{attr_name}.#{enumerator}(&iterator)
23
+ end
24
+ end
25
+ EOF
26
+ end
27
+ end
28
+
@@ -0,0 +1,30 @@
1
+ class Module
2
+ # Emulate block-passing by converting the block into a Proc object
3
+ # and passing it to the given block as last argument
4
+ # dule)
5
+ #
6
+ # For instance
7
+ # define_method('my_method') do |a, &block|
8
+ # end
9
+ #
10
+ # Is written as
11
+ # define_method_with_block('my_method') do |block, a|
12
+ # end
13
+ #
14
+ # The block is given first to allow the following construct:
15
+ #
16
+ # define_method_with_block('my_method') do |block, *args|
17
+ # end
18
+ #
19
+ # +block+ is +nil+ if no block is given on the method call
20
+ #
21
+ def define_method_with_block(name, &mdef)
22
+ class_eval <<-EOD
23
+ def #{name}(*args, &block)
24
+ dmwb_#{name}_user_definition(block, *args)
25
+ end
26
+ EOD
27
+ define_method("dmwb_#{name}_user_definition", &mdef)
28
+ end
29
+ end
30
+
@@ -0,0 +1,30 @@
1
+ class Module
2
+ unless (method(:__instance_include__) rescue nil)
3
+ alias :__instance_include__ :include
4
+ end
5
+
6
+ # Includes a module in this one, with support for class extensions
7
+ #
8
+ # If a module defines a ClassExtension submodule, then
9
+ # * if it is included in a module, the target's ClassExtension
10
+ # module includes the source ClassExtension (and if there is no
11
+ # ClassExtension in the target, it is created)
12
+ # * if it is included in a Class, the ClassExtension module
13
+ # extends the class.
14
+ def include(mod)
15
+ __instance_include__ mod
16
+ return unless mod.const_defined?(:ClassExtension)
17
+
18
+ if is_a?(Module) && !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)
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,122 @@
1
+ require 'utilrb/object/attribute'
2
+ require 'utilrb/object/singleton_class'
3
+ require 'utilrb/enumerable/uniq'
4
+ require 'utilrb/module/include'
5
+
6
+ class Module
7
+ def define_inherited_enumerable(name, attribute_name = name, options = Hash.new, &init) # :nodoc:
8
+ # Set up the attribute accessor
9
+ attribute(attribute_name, &init)
10
+ class_eval { private "#{attribute_name}=" }
11
+
12
+ options[:enum_with] ||= :each
13
+
14
+ if options[:map]
15
+ class_eval <<-EOF
16
+ def each_#{name}(key = nil, uniq = true)
17
+ if key
18
+ if #{attribute_name}.has_key?(key)
19
+ yield(#{attribute_name}[key])
20
+ return self if uniq
21
+ end
22
+ elsif uniq
23
+ @enum_#{name}_uniq ||= enum_uniq(:each_#{name}, nil, false) { |k, v| k }
24
+ @enum_#{name}_uniq.each { |el| yield(el) }
25
+ return self
26
+ else
27
+ #{attribute_name}.#{options[:enum_with]} { |el| yield(el) }
28
+ end
29
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:each_#{name}) }
30
+ superclass.each_#{name}(key, uniq) { |el| yield(el) }
31
+ end
32
+ self
33
+ end
34
+ def has_#{name}?(key)
35
+ return true if #{attribute_name}[key]
36
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:has_#{name}) }
37
+ superclass.has_#{name}(key)
38
+ end
39
+ end
40
+ EOF
41
+ else
42
+ class_eval <<-EOF
43
+ def each_#{name}(&iterator)
44
+ #{attribute_name}.#{options[:enum_with]}(&iterator) if #{attribute_name}
45
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:each_#{name}) }
46
+ superclass.each_#{name} { |el| yield(el) }
47
+ end
48
+ self
49
+ end
50
+ EOF
51
+ end
52
+ end
53
+
54
+ # Defines an attribute as being enumerable in the class instance and in the
55
+ # whole class inheritance hierarchy. More specifically, it defines a
56
+ # <tt>each_#{name}(&iterator)</tt> instance method and a <tt>each_#{name}(&iterator)</tt>
57
+ # class method which iterates (in order) on
58
+ # - the instance #{name} attribute
59
+ # - the singleton class #{name} attribute
60
+ # - the class #{name} attribute
61
+ # - the superclass #{name} attribute
62
+ # - the superclass' superclass #{name} attribute
63
+ # ...
64
+ #
65
+ # This method can be used on modules, in which case the module is used as if
66
+ # it was part of the inheritance hierarchy.
67
+ #
68
+ # The +name+ option defines the enumeration method name (+value+ will
69
+ # define a +each_value+ method). +attribute_name+ defines the attribute
70
+ # name. +init+ is a block called to initialize the attribute.
71
+ # Valid options in +options+ are:
72
+ # map:: the attribute should respond to +[]+. The enumeration method takes two
73
+ # arguments, +key+ and +uniq+. If +key+ is given, we iterate on the values
74
+ # given by <tt>attribute[key]</tt>. If +uniq+ is true, the enumeration will
75
+ # yield at most one value for each +key+ found (so, if both +key+ and +uniq+ are
76
+ # given, the enumeration yields at most one value)
77
+ #
78
+ # For instance
79
+ #
80
+ # class A
81
+ # class_inherited_enumerable("value", "enum") { Array.new }
82
+ # end
83
+ # module M
84
+ # inherited_enumerable("attr") { Array.new }
85
+ # end
86
+ # class B < A
87
+ # include M
88
+ # end
89
+ # b = B.new
90
+ #
91
+ # A.enum << 1
92
+ # B.enum << 2
93
+ # M.attr << 1
94
+ # class << b
95
+ # enum << 3
96
+ # attr << 4
97
+ # end
98
+ # M.attr << 2
99
+ #
100
+ # A.each_enum => 1
101
+ # B.each_enum => 2, 1
102
+ # b.singleton_class.each_enum => 3, 2, 1
103
+ # b.singleton_class.each_attr => 4, 1, 2
104
+ #
105
+ def inherited_enumerable(name, attribute_name = name, options = Hash.new, &init)
106
+ singleton_class.class_eval { define_inherited_enumerable(name, attribute_name, options, &init) }
107
+
108
+ if is_a?(Module) && !is_a?(Class)
109
+ unless const_defined?(:ClassExtension)
110
+ const_set(:ClassExtension, Module.new)
111
+ end
112
+ class_extension = const_get(:ClassExtension)
113
+ class_extension.class_eval do
114
+ define_inherited_enumerable(name, attribute_name, options, &init)
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+
122
+
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
@@ -0,0 +1,14 @@
1
+
2
+ class Object
3
+ # Return the object address (for non immediate
4
+ # objects).
5
+ def address; Object.address_from_id(object_id) end
6
+
7
+ # Converts the object_id of a non-immediate object
8
+ # to its 32 bits address
9
+ def self.address_from_id(id)
10
+ id = 0xFFFFFFFF - ~id if id < 0
11
+ (id * 2) & 0xFFFFFFFF
12
+ end
13
+ end
14
+
@@ -0,0 +1,89 @@
1
+ require 'utilrb/common'
2
+ require 'utilrb/object/singleton_class'
3
+
4
+ Utilrb.unless_faster do
5
+ class Object
6
+ # :call-seq
7
+ # attribute :name => default_value
8
+ # attribute(:name) { default_value }
9
+ #
10
+ # In the first form, defines a read-write attribute
11
+ # named 'name' with default_value for default value.
12
+ # In the second form, the block is called if the attribute
13
+ # is read before it has been ever written, and its return
14
+ # value is used as default value.
15
+ def attribute(attr_def, &init)
16
+ if Hash === attr_def
17
+ name, defval = attr_def.to_a.flatten
18
+ else
19
+ name = attr_def
20
+ end
21
+
22
+ class_eval do
23
+ attr_writer name
24
+ define_method("#{name}_defval") do
25
+ defval || (instance_eval(&init) if init)
26
+ end
27
+ end
28
+
29
+ class_eval <<-EOD
30
+ def #{name}
31
+ if defined? @#{name} then @#{name}
32
+ else @#{name} = #{name}_defval
33
+ end
34
+ end
35
+ EOD
36
+ end
37
+ end
38
+ end
39
+
40
+ Utilrb.if_faster do
41
+ class Object
42
+ # :call-seq
43
+ # attribute :name => default_value
44
+ # attribute(:name) { default_value }
45
+ #
46
+ # In the first form, defines a read-write attribute
47
+ # named 'name' with default_value for default value.
48
+ # In the second form, the block is called if the attribute
49
+ # is read before it has been ever written, and its return
50
+ # value is used as default value.
51
+ def attribute(attr_def, &init)
52
+ if Hash === attr_def
53
+ name, defval = attr_def.to_a.flatten
54
+ else
55
+ name = attr_def
56
+ end
57
+
58
+ if is_singleton? || instance_of?(Module)
59
+ class_eval do
60
+ attr_writer name
61
+ define_method("#{name}_defval") do
62
+ defval || (instance_eval(&init) if init)
63
+ end
64
+ end
65
+
66
+ class_eval <<-EOD
67
+ def #{name}
68
+ if defined? @#{name} then @#{name}
69
+ else @#{name} = #{name}_defval
70
+ end
71
+ end
72
+ EOD
73
+ else
74
+ class_eval { attr_writer name }
75
+ define_method(name) do
76
+ singleton_class.class_eval { attr_reader name }
77
+ instance_variable_set("@#{name}", defval || (instance_eval(&init) if init))
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ class Object
85
+ def class_attribute(attr_def, &init)
86
+ singleton_class.class_eval { attribute(attr_def, &init) }
87
+ end
88
+ end
89
+
@@ -0,0 +1,53 @@
1
+ require 'utilrb/object/address'
2
+ if RUBY_VERSION >= "1.9"
3
+ class Object
4
+ def has_singleton?; defined? @singleton_class end
5
+ def singleton_class
6
+ if defined? @singleton_class
7
+ return @singleton_class
8
+ else
9
+ @singleton_class = class << self
10
+ class << self
11
+ alias __ancestors__ ancestors
12
+ def ancestors; __ancestors__.unshift(self) end
13
+ end
14
+
15
+ self
16
+ end
17
+
18
+ @singleton_class
19
+ end
20
+ end
21
+ end
22
+ else
23
+ class Object
24
+ def has_singleton?
25
+ defined? @singleton_class
26
+ end
27
+ def singleton_class
28
+ if defined? @singleton_class
29
+ return @singleton_class
30
+ else
31
+ klass = class << self; self end
32
+ instance = self
33
+ klass.class_eval do
34
+ @singleton_instance = instance
35
+ @superclass = instance.class
36
+ class << self
37
+ attr_reader :superclass
38
+ attr_reader :singleton_instance
39
+ def name
40
+ "#{@superclass.name}!0x#{@singleton_instance.address.to_s(16)}"
41
+ end
42
+
43
+ alias __ancestors__ ancestors
44
+ def ancestors; __ancestors__.unshift(self) end
45
+ end
46
+ end
47
+
48
+ @singleton_class = klass
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,52 @@
1
+ require 'utilrb/gc/force'
2
+
3
+ module ObjectStats
4
+ # Allocates no object
5
+ def self.count
6
+ count = 0
7
+ ObjectSpace.each_object { |obj| count += 1}
8
+
9
+ count
10
+ end
11
+
12
+ # Allocates 1 Hash, which is included in the count
13
+ def self.count_by_class
14
+ by_class = Hash.new(0)
15
+ ObjectSpace.each_object { |obj|
16
+ by_class[obj.class] += 1
17
+ by_class
18
+ }
19
+ by_class
20
+ end
21
+
22
+ # Profiles the memory allocation in the block
23
+ # If alive is true, then only non-gcable objects
24
+ # are returned.
25
+ def self.profile(alive = false)
26
+ already_disabled = GC.disable
27
+ before = count_by_class
28
+ yield
29
+ after = count_by_class
30
+ GC.enable unless already_disabled
31
+
32
+ after[Hash] -= 1 # Correction for the call of count_by_class
33
+ profile = before.
34
+ merge(after) { |klass, old, new| new - old }.
35
+ delete_if { |klass, count| count == 0 }
36
+ end
37
+
38
+ def self.stats(filter = nil)
39
+ total_count = 0
40
+ output = ""
41
+ count_by_class.each do |klass, obj_count|
42
+ total_count += obj_count
43
+ if !filter || klass.name =~ filter
44
+ output << klass.name << " " << obj_count.to_s << "\n"
45
+ end
46
+ end
47
+
48
+ (output << "Total object count: #{total_count}")
49
+ end
50
+ end
51
+
52
+
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)