tofuhash 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/tofuhash/tofuhash.rb +159 -0
- data/lib/tofuhash/tofukey.rb +90 -0
- data/lib/tofuhash.rb +44 -0
- data/readme.txt +100 -0
- data/test/test-tofuhash.rb +285 -0
- metadata +53 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
# TofuHash
|
2
|
+
#
|
3
|
+
# Links:
|
4
|
+
# * readme.txt[link:files/readme_txt.html]
|
5
|
+
# * source: http://github.com/ghouston/tofuhash/tree/master
|
6
|
+
#
|
7
|
+
# A varient of Hash which can change the lookup behavior of keys.
|
8
|
+
# The default TofuHash will match Symbol and String without reguard
|
9
|
+
# to case. By subclassing TofuKey, this behavior can be changed.
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# License:
|
13
|
+
#
|
14
|
+
# (The MIT License + Free Software Foundation Advertising Prohibition)
|
15
|
+
#
|
16
|
+
# Copyright (c) 2007 Gregory N. Houston
|
17
|
+
#
|
18
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
19
|
+
# of this software and associated documentation files (the "Software"), to deal
|
20
|
+
# in the Software without restriction, including without limitation the rights
|
21
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
22
|
+
# copies of the Software, and to permit persons to whom the Software is
|
23
|
+
# furnished to do so, subject to the following conditions:
|
24
|
+
#
|
25
|
+
# The above copyright notice and this permission notice shall be included in
|
26
|
+
# all copies or substantial portions of the Software.
|
27
|
+
#
|
28
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
29
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
30
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
31
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
32
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
33
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
34
|
+
# THE SOFTWARE.
|
35
|
+
#
|
36
|
+
# Except as contained in this notice, the name(s) of the above copyright holders
|
37
|
+
# shall not be used in advertising or otherwise to promote the sale, use or other
|
38
|
+
# dealings in this Software without prior written authorization.
|
39
|
+
#
|
40
|
+
class TofuHash < Hash
|
41
|
+
module Version
|
42
|
+
MAJOR = 0
|
43
|
+
MINOR = 1
|
44
|
+
REVISION = 0
|
45
|
+
STRING = [MAJOR, MINOR, REVISION].join('.')
|
46
|
+
end
|
47
|
+
|
48
|
+
# see Hash.new
|
49
|
+
def initialize ( default = nil )
|
50
|
+
if block_given?
|
51
|
+
if default
|
52
|
+
raise ArgumentError, "Can't initialize Hash with both a default value and a block"
|
53
|
+
end
|
54
|
+
super() { |hash,key| yield(hash, decode(key)) }
|
55
|
+
else
|
56
|
+
super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# see Hash#encode
|
61
|
+
def encode( key )
|
62
|
+
TofuKey.new(key)
|
63
|
+
end
|
64
|
+
|
65
|
+
# see Hash#decode
|
66
|
+
def decode( key )
|
67
|
+
key.decode
|
68
|
+
end
|
69
|
+
|
70
|
+
class << self
|
71
|
+
# see Hash.[]
|
72
|
+
def [](*args)
|
73
|
+
if args.size == 1 && args[0].instance_of?( Object::Hash )
|
74
|
+
h = TofuHash.new
|
75
|
+
args[0].each { |k,v| h.store( k,v ) }
|
76
|
+
h
|
77
|
+
elsif (args.size % 2 != 0)
|
78
|
+
raise ArgumentError, "odd number of arguments for TofuHash"
|
79
|
+
else
|
80
|
+
h = TofuHash.new
|
81
|
+
1.step( args.size, 2 ) { |i| h.store(args[i-1],args[i]) }
|
82
|
+
h
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# see Hash#[]=
|
88
|
+
def []= key,value
|
89
|
+
super( encode(key), value )
|
90
|
+
end
|
91
|
+
|
92
|
+
alias :regular_each :each unless method_defined?(:regular_each)
|
93
|
+
|
94
|
+
# see Hash#each
|
95
|
+
def each &block
|
96
|
+
self.regular_each do |key, value|
|
97
|
+
block.call( decode(key), value )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# see Hash#store
|
102
|
+
def store key, value
|
103
|
+
super( encode(key), value )
|
104
|
+
end
|
105
|
+
|
106
|
+
# see Hash#[]
|
107
|
+
def [] key
|
108
|
+
super( encode(key) )
|
109
|
+
end
|
110
|
+
|
111
|
+
# see Hash#has_key?
|
112
|
+
def has_key? key
|
113
|
+
super( encode(key) )
|
114
|
+
end
|
115
|
+
|
116
|
+
# see Hash#keys
|
117
|
+
def keys
|
118
|
+
# collect will call each which decodes the key
|
119
|
+
self.collect { |k,v| k }
|
120
|
+
end
|
121
|
+
|
122
|
+
alias_method :regular_inspect, :inspect unless method_defined?(:regular_inspect)
|
123
|
+
|
124
|
+
# see Hash#values_at
|
125
|
+
def values_at( *args )
|
126
|
+
values = Array.new
|
127
|
+
args.each { |key| values << self[key] }
|
128
|
+
values
|
129
|
+
end
|
130
|
+
|
131
|
+
# see Hash#to_a
|
132
|
+
def to_a
|
133
|
+
aux = []
|
134
|
+
self.each do |key,value|
|
135
|
+
aux << [ key, value ]
|
136
|
+
end
|
137
|
+
aux
|
138
|
+
end
|
139
|
+
|
140
|
+
# see Hash#include?
|
141
|
+
def include?(key)
|
142
|
+
super(encode(key))
|
143
|
+
end
|
144
|
+
|
145
|
+
alias :regular_delete_if :delete_if
|
146
|
+
|
147
|
+
# see Hash#delete_if
|
148
|
+
def delete_if(&block)
|
149
|
+
self.regular_delete_if do |key, value|
|
150
|
+
block.call( decode(key), value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Deletes every key-value pair for which block evaluates to false.
|
155
|
+
def delete_unless #:yield:
|
156
|
+
delete_if{ |key, value| ! yield(key, value) }
|
157
|
+
end
|
158
|
+
|
159
|
+
end # class TofuHash
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# TofuKey
|
2
|
+
#
|
3
|
+
# Links:
|
4
|
+
# * readme.txt[link:files/readme_txt.html]
|
5
|
+
# * source: http://github.com/ghouston/tofuhash/tree/master
|
6
|
+
#
|
7
|
+
# For use with TofuHash. A wrapper for the key of a Hash which will alter the behavior of keys.
|
8
|
+
# The behavior provided by default is case-insensitive, and indifferent access for strings and symbols.
|
9
|
+
# By subclassing TofuHash, you can create your own behavior.
|
10
|
+
#
|
11
|
+
# License:
|
12
|
+
#
|
13
|
+
# (The MIT License + Free Software Foundation Advertising Prohibition)
|
14
|
+
#
|
15
|
+
# Copyright (c) 2007 Gregory N. Houston
|
16
|
+
#
|
17
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
18
|
+
# of this software and associated documentation files (the "Software"), to deal
|
19
|
+
# in the Software without restriction, including without limitation the rights
|
20
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
21
|
+
# copies of the Software, and to permit persons to whom the Software is
|
22
|
+
# furnished to do so, subject to the following conditions:
|
23
|
+
#
|
24
|
+
# The above copyright notice and this permission notice shall be included in
|
25
|
+
# all copies or substantial portions of the Software.
|
26
|
+
#
|
27
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
28
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
29
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
30
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
31
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
32
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
33
|
+
# THE SOFTWARE.
|
34
|
+
#
|
35
|
+
# Except as contained in this notice, the name(s) of the above copyright holders
|
36
|
+
# shall not be used in advertising or otherwise to promote the sale, use or other
|
37
|
+
# dealings in this Software without prior written authorization.
|
38
|
+
#
|
39
|
+
class TofuKey
|
40
|
+
attr_reader :original_key, :coded_key
|
41
|
+
|
42
|
+
# preserve the key (Strings are cloned and frozen just like Hash's behavior); then encodes the key for fast comparison
|
43
|
+
def initialize( key )
|
44
|
+
if key.instance_of? String
|
45
|
+
@original_key = key.clone.freeze
|
46
|
+
else
|
47
|
+
@original_key = key
|
48
|
+
end
|
49
|
+
encode
|
50
|
+
end
|
51
|
+
|
52
|
+
# stores a @coded_key which is used for quick comparison and as the hash key. the default encoding will
|
53
|
+
# convert Symbols to downcased strings; anything responding to downcase is converted via downcase.
|
54
|
+
def encode
|
55
|
+
if @original_key.instance_of? Symbol
|
56
|
+
@coded_key = @original_key.to_s.downcase
|
57
|
+
elsif @original_key.respond_to? :downcase
|
58
|
+
@coded_key = @original_key.downcase
|
59
|
+
else
|
60
|
+
@coded_key = @original_key
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# returns the preserved key
|
65
|
+
def decode
|
66
|
+
@original_key
|
67
|
+
end
|
68
|
+
|
69
|
+
# get the hash of the key, which calls #hash on the encoded key.
|
70
|
+
def hash
|
71
|
+
@coded_key.hash
|
72
|
+
end
|
73
|
+
|
74
|
+
# compares the encoded key to another object.
|
75
|
+
#
|
76
|
+
# given symbols are converted to downcase strings before comparison.
|
77
|
+
# given objects which respond to downcase are downcased before comparison.
|
78
|
+
# given TofuKey will compare the encoded keys.
|
79
|
+
def eql? obj
|
80
|
+
if obj.instance_of? Symbol
|
81
|
+
@coded_key.eql?( obj.to_s.downcase )
|
82
|
+
elsif obj.instance_of? TofuKey
|
83
|
+
@coded_key.eql?( obj.coded_key )
|
84
|
+
elsif obj.respond_to? :downcase
|
85
|
+
@coded_key.eql?( obj.downcase )
|
86
|
+
else
|
87
|
+
@coded_key.eql?( obj )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/tofuhash.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# TofuHash
|
2
|
+
#
|
3
|
+
# Links:
|
4
|
+
# * readme.txt[link:files/readme_txt.html]
|
5
|
+
# * source: http://github.com/ghouston/tofuhash/tree/master
|
6
|
+
#
|
7
|
+
# A varient of Hash which can change the lookup behavior of keys.
|
8
|
+
# The default TofuHash will match Symbol and String without reguard
|
9
|
+
# to case. By subclassing TofuKey, this behavior can be changed.
|
10
|
+
#
|
11
|
+
# License:
|
12
|
+
#
|
13
|
+
# (The MIT License + Free Software Foundation Advertising Prohibition)
|
14
|
+
#
|
15
|
+
# Copyright (c) 2007 Gregory N. Houston
|
16
|
+
#
|
17
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
18
|
+
# of this software and associated documentation files (the "Software"), to deal
|
19
|
+
# in the Software without restriction, including without limitation the rights
|
20
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
21
|
+
# copies of the Software, and to permit persons to whom the Software is
|
22
|
+
# furnished to do so, subject to the following conditions:
|
23
|
+
#
|
24
|
+
# The above copyright notice and this permission notice shall be included in
|
25
|
+
# all copies or substantial portions of the Software.
|
26
|
+
#
|
27
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
28
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
29
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
30
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
31
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
32
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
33
|
+
# THE SOFTWARE.
|
34
|
+
#
|
35
|
+
# Except as contained in this notice, the name(s) of the above copyright holders
|
36
|
+
# shall not be used in advertising or otherwise to promote the sale, use or other
|
37
|
+
# dealings in this Software without prior written authorization.
|
38
|
+
#
|
39
|
+
unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
40
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__)))
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'tofuhash/tofukey'
|
44
|
+
require 'tofuhash/tofuhash'
|
data/readme.txt
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
= TofuHash
|
2
|
+
by Gregory N. Houston
|
3
|
+
|
4
|
+
TofuHash makes it possible to use a Hash without having to
|
5
|
+
worry about the differences between using String, Symbol,
|
6
|
+
uppercase and downcase for the keys.
|
7
|
+
TofuHash is both a case-insensitive Hash, and indifferent
|
8
|
+
to access by String or Symbol.
|
9
|
+
|
10
|
+
for Example:
|
11
|
+
|
12
|
+
require 'tofuhash'
|
13
|
+
h = TofuHash[ :aSymbol => "symbol", "MixedCaseString" => "string", 11 => "number" ]
|
14
|
+
puts h["asymbol"] #=> "symbol"
|
15
|
+
puts h[:mixedCaseString] #=> "string"
|
16
|
+
puts h[11] #=> "number"
|
17
|
+
|
18
|
+
Version:: 0.1.0 A useful and well tested subset of Hash methods is available.
|
19
|
+
|
20
|
+
Tested to work with:
|
21
|
+
Ruby 1.8.6
|
22
|
+
Ruby 1.9.1
|
23
|
+
|
24
|
+
How is TofuHash differenct than Hash?
|
25
|
+
* TofuHash wraps the key into a TofuKey which is used internally inside TofuHash.
|
26
|
+
The TofuKey defines new behavior for handling the key. By
|
27
|
+
default it will treat Symbol, String, and uppercase vs downcase as the same. This
|
28
|
+
behavior can be changed by creating TofuHash and providing an alternative
|
29
|
+
version of TofuKey.
|
30
|
+
|
31
|
+
* TofuHash adds the method TofuHash#delete_unless
|
32
|
+
|
33
|
+
== Links:
|
34
|
+
|
35
|
+
Start Here:: http://tofuhash.rubyforge.org
|
36
|
+
|
37
|
+
Project:: http://rubyforge.org/projects/tofuhash
|
38
|
+
Documents:: http://tofuhash.rubyforge.org
|
39
|
+
RubyGems:: Install with: <b>gem install tofuhash</b>
|
40
|
+
Download:: Download from RubyForge at http://rubyforge.org/projects/tofuhash/
|
41
|
+
Authors Blog:: http://ghouston.blogspot.com
|
42
|
+
Browse Source:: link:rcov/index.html
|
43
|
+
Source code is hosted on Github at: http://github.com/ghouston/tofuhash/tree/master
|
44
|
+
|
45
|
+
== LICENSE:
|
46
|
+
|
47
|
+
(The MIT License + Free Software Foundation Advertising Prohibition)
|
48
|
+
|
49
|
+
Copyright (c) 2007 Gregory N. Houston
|
50
|
+
|
51
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
52
|
+
of this software and associated documentation files (the "Software"), to deal
|
53
|
+
in the Software without restriction, including without limitation the rights
|
54
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
55
|
+
copies of the Software, and to permit persons to whom the Software is
|
56
|
+
furnished to do so, subject to the following conditions:
|
57
|
+
|
58
|
+
The above copyright notice and this permission notice shall be included in
|
59
|
+
all copies or substantial portions of the Software.
|
60
|
+
|
61
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
62
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
63
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
64
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
65
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
66
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
67
|
+
THE SOFTWARE.
|
68
|
+
|
69
|
+
Except as contained in this notice, the name(s) of the above copyright holders
|
70
|
+
shall not be used in advertising or otherwise to promote the sale, use or other
|
71
|
+
dealings in this Software without prior written authorization.
|
72
|
+
|
73
|
+
The file test-tofuhash.rb is released under the Ruby License since it
|
74
|
+
contains source code based on Ruby's released source.
|
75
|
+
|
76
|
+
== Credits:
|
77
|
+
|
78
|
+
Inspired by:
|
79
|
+
* http://pastie.caboo.se/154304 and used with Stefan Rusterholz's permission;
|
80
|
+
* HashWithIndifferentAccess in Rail's ActiveSupport.
|
81
|
+
|
82
|
+
Contributors:
|
83
|
+
* Greg Houston (http://ghouston.blogspot.com) original release and project maintainer
|
84
|
+
* Nacho Caballero (http://github.com/nachocab/) added #to_a, #delete_if, #delete_unless, #include?
|
85
|
+
|
86
|
+
== Release History:
|
87
|
+
|
88
|
+
Feb 28 2009 - 0.1.0 release on rubyforge. Added gem, rdoc, rcov output.
|
89
|
+
Added TofuHash::Version module
|
90
|
+
|
91
|
+
Feb 15 2009 - 0.0.2 released on git hub. Merged in pull request from
|
92
|
+
http://github.com/nachocab/tofuhash/tree/master [Thanks nachocab!]
|
93
|
+
nachocab added to_a, delete_if, delete_unless, include? methods. nachocab also
|
94
|
+
updated the exception raised when TofuHash#initialize is called with both
|
95
|
+
a default value and default block. It now raises "wrong number of arguments"
|
96
|
+
which matches the behavior of Hash. I (ghouston) tweaked the test cases to match
|
97
|
+
the examples from Hash's ri documentation.
|
98
|
+
|
99
|
+
Dec 12 2008 - 0.0.1 released on git hub. Working solution, only more complete
|
100
|
+
testing is needed. Know issues: a) Hash doesn't know how to compare with TofuHash.
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'pp'
|
3
|
+
require 'lib/tofuhash'
|
4
|
+
|
5
|
+
=begin rdoc
|
6
|
+
test-tofuhash.rb
|
7
|
+
|
8
|
+
Test cases for TofuHash. This includes modified versions of Ruby's unit tests
|
9
|
+
for Hash, and Ruby's Hash examples in the ri documentation. Plus some custom
|
10
|
+
tests to validate similarities between Hash and TofuHash.
|
11
|
+
|
12
|
+
Version: see readme.txt for details.
|
13
|
+
|
14
|
+
License:
|
15
|
+
|
16
|
+
tofuhash.rb is released under the MIT License + Free Software Foundation
|
17
|
+
Advertising Prohibition. see readme.txt file for details.
|
18
|
+
|
19
|
+
test-tofuhash.rb (this file) is released under the Ruby License since it
|
20
|
+
contains source code based on Ruby's released source.
|
21
|
+
=end
|
22
|
+
|
23
|
+
module TofuHashTesting
|
24
|
+
class Test_TofuHash < Test::Unit::TestCase
|
25
|
+
def test_new
|
26
|
+
assert_raise ArgumentError do
|
27
|
+
h = TofuHash.new( :default ) { |hash,key| key }
|
28
|
+
end
|
29
|
+
|
30
|
+
h = TofuHash.new
|
31
|
+
assert_equal( 0, h.size )
|
32
|
+
assert_equal( nil, h[:missing] )
|
33
|
+
|
34
|
+
h = TofuHash.new( :default )
|
35
|
+
assert_equal( 0, h.size )
|
36
|
+
assert_equal( :default, h[:missing] )
|
37
|
+
|
38
|
+
h = TofuHash.new do |hash,key|
|
39
|
+
assert_equal( :missing, key )
|
40
|
+
assert_same( h, hash )
|
41
|
+
hash[key] = :default_block
|
42
|
+
end
|
43
|
+
assert_equal( 0, h.size )
|
44
|
+
assert_equal( :default_block, h[:missing] )
|
45
|
+
assert_equal( 1, h.size )
|
46
|
+
assert_equal( [:missing], h.keys )
|
47
|
+
assert_equal( [:default_block], h.values )
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_values_at
|
51
|
+
h = TofuHash[21=>22,22=>24,23=>26,24=>28]
|
52
|
+
assert_equal([24,26], h.values_at( 22, 23 ))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_keys
|
56
|
+
h = TofuHash["Alpha"=>2,:betA=>4,"gAmmA"=>6]
|
57
|
+
assert_equal( ["Alpha",:betA,"gAmmA"], h.keys.sort { |a,b| a.to_s <=> b.to_s } )
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_square_bracket_initializer
|
61
|
+
h = TofuHash[:a=>:b, :c=>:d]
|
62
|
+
assert_equal( TofuHash, h.class )
|
63
|
+
assert_equal( :b, h[:a] )
|
64
|
+
assert_equal( :d, h[:c] )
|
65
|
+
assert_equal( 2, h.size )
|
66
|
+
|
67
|
+
assert_raise ArgumentError do
|
68
|
+
h = TofuHash[1,2,3]
|
69
|
+
end
|
70
|
+
|
71
|
+
h = TofuHash[:happy, :sad, :rich, :poor]
|
72
|
+
assert_equal( TofuHash, h.class )
|
73
|
+
assert_equal( :sad, h[:happy] )
|
74
|
+
assert_equal( :poor, h[:rich] )
|
75
|
+
assert_equal( 2, h.size )
|
76
|
+
h = TofuHash[]
|
77
|
+
assert_equal( 0, h.size )
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_store
|
81
|
+
h = TofuHash.new
|
82
|
+
h.store('Alpha',1)
|
83
|
+
h.store(1,'ALPHA')
|
84
|
+
assert_equal( 1, h['AlPhA'] )
|
85
|
+
assert_equal( 'ALPHA', h[1] )
|
86
|
+
|
87
|
+
h['Beta']=2
|
88
|
+
h[2] = 'Beta'
|
89
|
+
assert_equal( 2, h['bEtA'] )
|
90
|
+
assert_equal( 'Beta', h[2] )
|
91
|
+
|
92
|
+
h[:Gamma]=3
|
93
|
+
h[3] = 'Gamma'
|
94
|
+
assert_equal( 3, h[:Gamma] )
|
95
|
+
assert_equal( 3, h['Gamma'] )
|
96
|
+
assert_equal( 3, h['gAmMA'] )
|
97
|
+
assert_equal( 3, h[:gAMMA] )
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_each
|
101
|
+
h = TofuHash[15,16, 11,12, 19,20, 17,18, 13,14]
|
102
|
+
h.each { |k,v| assert_equal( k+1, v ) }
|
103
|
+
end
|
104
|
+
end # class Test_TofuHash
|
105
|
+
|
106
|
+
# copied from /ruby/src/ruby-1.8.6/test/ruby/test_hash.rb
|
107
|
+
# modified to use TofuHash instead of Hash
|
108
|
+
class TestHash < Test::Unit::TestCase
|
109
|
+
def test_hash
|
110
|
+
x = TofuHash[1=>2, 2=>4, 3=>6]
|
111
|
+
y = TofuHash[1, 2, 2, 4, 3, 6]
|
112
|
+
assert_equal(2, x[1])
|
113
|
+
|
114
|
+
assert(begin
|
115
|
+
for k,v in y
|
116
|
+
raise if k*2 != v
|
117
|
+
end
|
118
|
+
true
|
119
|
+
rescue
|
120
|
+
false
|
121
|
+
end)
|
122
|
+
|
123
|
+
assert_equal(3, x.length)
|
124
|
+
assert(x.has_key?(1))
|
125
|
+
assert(x.has_value?(4))
|
126
|
+
assert_equal([4,6], x.values_at(2,3))
|
127
|
+
assert_equal(TofuHash[1=>2, 2=>4, 3=>6], x)
|
128
|
+
|
129
|
+
z = y.keys.join(":")
|
130
|
+
assert_equal("1:2:3", z)
|
131
|
+
|
132
|
+
z = y.values.join(":")
|
133
|
+
assert_equal("2:4:6", z)
|
134
|
+
assert_equal(x, y)
|
135
|
+
|
136
|
+
y.shift
|
137
|
+
assert_equal(2, y.length)
|
138
|
+
|
139
|
+
z = [1,2]
|
140
|
+
y[z] = 256
|
141
|
+
assert_equal(256, y[z])
|
142
|
+
|
143
|
+
x = TofuHash.new(0)
|
144
|
+
x[1] = 1
|
145
|
+
assert_equal(1, x[1])
|
146
|
+
assert_equal(0, x[2])
|
147
|
+
|
148
|
+
x = TofuHash.new([])
|
149
|
+
assert_equal([], x[22])
|
150
|
+
assert_same(x[22], x[22])
|
151
|
+
|
152
|
+
x = TofuHash.new{[]}
|
153
|
+
assert_equal([], x[22])
|
154
|
+
assert_not_same(x[22], x[22])
|
155
|
+
|
156
|
+
x = TofuHash.new{|h,k| z = k; h[k] = k*2}
|
157
|
+
z = 0
|
158
|
+
assert_equal(44, x[22])
|
159
|
+
assert_equal(22, z)
|
160
|
+
z = 0
|
161
|
+
assert_equal(44, x[22])
|
162
|
+
assert_equal(0, z)
|
163
|
+
x.default = 5
|
164
|
+
assert_equal(5, x[23])
|
165
|
+
|
166
|
+
x = TofuHash.new
|
167
|
+
def x.default(k)
|
168
|
+
k = decode(k)
|
169
|
+
$z = k
|
170
|
+
self[k] = k*2
|
171
|
+
end
|
172
|
+
$z = 0
|
173
|
+
assert_equal(44, x[22])
|
174
|
+
assert_equal(22, $z)
|
175
|
+
$z = 0
|
176
|
+
assert_equal(44, x[22])
|
177
|
+
assert_equal(0, $z)
|
178
|
+
end
|
179
|
+
|
180
|
+
class MyClass
|
181
|
+
attr_reader :str
|
182
|
+
def initialize(str)
|
183
|
+
@str = str
|
184
|
+
end
|
185
|
+
def eql?(o)
|
186
|
+
o.is_a?(MyClass) && str == o.str
|
187
|
+
end
|
188
|
+
def hash
|
189
|
+
@str.hash
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_ri_hash_code
|
194
|
+
a = MyClass.new("some string")
|
195
|
+
b = MyClass.new("some string")
|
196
|
+
assert( a.eql?( b ) ) #=> true
|
197
|
+
|
198
|
+
h = TofuHash.new #was: h={}
|
199
|
+
|
200
|
+
h[a] = 1
|
201
|
+
assert_equal( h[a],1 ) #=> 1
|
202
|
+
assert_equal( h[b],1 ) #=> 1
|
203
|
+
|
204
|
+
h[b] = 2
|
205
|
+
assert_equal( h[a],2 ) #=> 2
|
206
|
+
assert_equal( h[b],2 ) #=> 2
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_ri_hash_new_code
|
210
|
+
h = TofuHash.new("Go Fish")
|
211
|
+
h["a"] = 100
|
212
|
+
h["b"] = 200
|
213
|
+
assert_equal( h["a"], 100 ) #=> 100
|
214
|
+
assert_equal( h["c"], "Go Fish" ) #=> "Go Fish"
|
215
|
+
# The following alters the single default object
|
216
|
+
assert_equal( h["c"].upcase!, "GO FISH" ) #=> "GO FISH"
|
217
|
+
assert_equal( h["d"], "GO FISH" ) #=> "GO FISH"
|
218
|
+
assert_equal( h.keys, ["a","b"] ) #=> ["a", "b"]
|
219
|
+
|
220
|
+
# While this creates a new default object each time
|
221
|
+
h = TofuHash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
|
222
|
+
assert_equal( h["c"], "Go Fish: c" ) #=> "Go Fish: c"
|
223
|
+
assert_equal( h["c"].upcase!, "GO FISH: C" ) #=> "GO FISH: C"
|
224
|
+
assert_equal( h["d"], "Go Fish: d" ) #=> "Go Fish: d"
|
225
|
+
assert_equal( h.keys, ["c","d"] ) #=> ["c", "d"]
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_ri_hash_square_bracket_code
|
229
|
+
assert_equal( TofuHash["a", 100, "b", 200], {"a"=>100, "b"=>200} ) #=> {"a"=>100, "b"=>200}
|
230
|
+
assert_equal( TofuHash["a" => 100, "b" => 200], {"a"=>100, "b"=>200} ) #=> {"a"=>100, "b"=>200}
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_to_a
|
234
|
+
hash = TofuHash["a" => 2, "b" => 1]
|
235
|
+
assert_equal [["a",2],["b",1]], hash.to_a
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_ri_to_a
|
239
|
+
h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
|
240
|
+
result = h.to_a
|
241
|
+
sorted = h.to_a.sort { |a,b| a[0] <=> b[0] }
|
242
|
+
assert_equal( [['a',100],['c',300],['d',400]], sorted )
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_include?
|
246
|
+
hash = TofuHash["a" => 2, "b" => 1]
|
247
|
+
assert( hash.include?( 'a' ))
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_ri_include?
|
251
|
+
h = { "a" => 100, "b" => 200 }
|
252
|
+
assert( h.has_key?("a") )
|
253
|
+
assert_equal( false, h.has_key?("z"))
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_ri_delete_if
|
257
|
+
h = TofuHash["a" => 100, "b" => 200, "c" => 300]
|
258
|
+
h.delete_if { |key,value| key >= 'b' }
|
259
|
+
assert_equal TofuHash['a' => 100], h
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_delete_unless
|
263
|
+
hash = TofuHash["a" => 2, "b" => 1]
|
264
|
+
hash.delete_unless { |k,v| k == 'b' }
|
265
|
+
assert_equal TofuHash['b' => 1], hash
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_ri_hash_equality
|
269
|
+
=begin
|
270
|
+
TODO: KNOWN ISSUE, Hash doesn't know how to compare to TofuHash.
|
271
|
+
|
272
|
+
h1 = TofuHash[ "a" => 1, "c" => 2 ]
|
273
|
+
h2 = { 7 => 35, "c" => 2, "a" => 1 }
|
274
|
+
h3 = TofuHash[ "a" => 1, "c" => 2, 7 => 35 ]
|
275
|
+
h4 = TofuHash[ "a" => 1, "d" => 2, "f" => 35 ]
|
276
|
+
puts "h1"
|
277
|
+
assert_equal( h1 == h2, false ) #=> false
|
278
|
+
puts "h2"
|
279
|
+
assert_equal( h2 == h3, true ) #=>
|
280
|
+
puts "h3"
|
281
|
+
assert_equal( h3 == h4, false ) #=> false
|
282
|
+
=end
|
283
|
+
end
|
284
|
+
end # class TestHash
|
285
|
+
end # module TofuHash
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: tofuhash
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2009-02-28 00:00:00 -06:00
|
8
|
+
summary: TofuHash, a Hash that is case-insensitive and treats symbols and strings as equals (customizable); always preserving the original key.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage: http://tofuhash.rubyforge.org/
|
13
|
+
rubyforge_project: tofuhash
|
14
|
+
description: TofuHash, a Hash that is case-insensitive and treats symbols and strings as equals (customizable); always preserving the original key.
|
15
|
+
autorequire: tofuhash
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Gregory N. Houston
|
31
|
+
files:
|
32
|
+
- lib/tofuhash/tofuhash.rb
|
33
|
+
- lib/tofuhash/tofukey.rb
|
34
|
+
- lib/tofuhash.rb
|
35
|
+
- test/test-tofuhash.rb
|
36
|
+
- readme.txt
|
37
|
+
test_files:
|
38
|
+
- test/test-tofuhash.rb
|
39
|
+
rdoc_options:
|
40
|
+
- --main
|
41
|
+
- readme.txt
|
42
|
+
- --title
|
43
|
+
- TofuHash (rdoc)
|
44
|
+
extra_rdoc_files:
|
45
|
+
- readme.txt
|
46
|
+
executables: []
|
47
|
+
|
48
|
+
extensions: []
|
49
|
+
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
dependencies: []
|
53
|
+
|