cicphash 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/cicphash.rb +288 -0
  2. data/test/test_cicphash.rb +401 -0
  3. metadata +46 -0
data/cicphash.rb ADDED
@@ -0,0 +1,288 @@
1
+ # Copyright (c) 2007 Jeremy Evans
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ # Case Insensitive, Case Preserving Hash
22
+ #
23
+ # CICPHash has the exact same interface as Hash, but is case insensitive
24
+ # and case preserving. Any value can be used as a key. However, you
25
+ # cannot have two keys in the same CICPHash that would be the same if when
26
+ # converted to strings would be equal or differing only in case.
27
+ #
28
+ # For example, all of the following keys would be considered equalivalent:
29
+ # 'ab', 'Ab', 'AB', 'aB', :ab, :Ab, :AB, :aB, ['A', :b], [nil, :A, nil, 'b'].
30
+ #
31
+ # CICPHash uses a last match wins policy. If an key-value pair is added to
32
+ # a CICPHash and a case insensitive variant of the key is already in the hash
33
+ # the instance of the key in the hash becomes the same the most recently added
34
+ # key (and obviously the value is updated to reflect the new value).
35
+ #
36
+ # You can change the rules determining which keys are equal by modifying the
37
+ # private convert_key method. By default, it is set to key.to_s.downcase.
38
+ # This method should produce the same output for any keys that you want to
39
+ # consider equal. For example, if you want :a and :A to be equal but :a to be
40
+ # different than "a", maybe key.inspect.downcase would work for you.
41
+ class CICPHash
42
+ include Enumerable
43
+
44
+ def self.[](*items)
45
+ if items.length % 2 != 0
46
+ if items.length == 1 && items.first.is_a?(Hash)
47
+ new.merge(items.first)
48
+ else
49
+ raise ArgumentError, "odd number of arguments for CICPHash"
50
+ end
51
+ else
52
+ hash = new
53
+ loop do
54
+ break if items.length == 0
55
+ key = items.shift
56
+ value = items.shift
57
+ hash[key] = value
58
+ end
59
+ hash
60
+ end
61
+ end
62
+
63
+ def initialize(*default, &block)
64
+ if default.length > 1 || default.length == 1 && block_given?
65
+ raise ArgumentError, "wrong number of arguments"
66
+ end
67
+ @name_hash = {}
68
+ @hash = {}
69
+ @default = default.first unless block_given?
70
+ @default_proc = Proc.new(&block) if block_given?
71
+ end
72
+
73
+ def ==(hash)
74
+ to_hash == hash.to_hash
75
+ end
76
+
77
+ def [](key)
78
+ new_key = convert_key(key)
79
+ if @hash.include?(new_key)
80
+ @hash[new_key]
81
+ elsif @default_proc
82
+ @default_proc.call(self, key)
83
+ else
84
+ @default
85
+ end
86
+ end
87
+
88
+ def []=(key, value)
89
+ new_key = convert_key(key)
90
+ @name_hash[new_key] = key
91
+ @hash[new_key] = value
92
+ end
93
+ alias store :[]=
94
+
95
+ def clear
96
+ @name_hash.clear
97
+ @hash.clear
98
+ end
99
+
100
+ def default
101
+ @default
102
+ end
103
+
104
+ def default=(value)
105
+ @default = value
106
+ end
107
+
108
+ def default_proc
109
+ @default_proc
110
+ end
111
+
112
+ def delete(key)
113
+ new_key = convert_key(key)
114
+ @name_hash.delete(new_key)
115
+ @hash.delete(new_key)
116
+ end
117
+
118
+ def delete_if(&block)
119
+ hash = CICPHash.new
120
+ each{|key, value| block.call(key, value) ? delete(key) : (hash[key] = value)}
121
+ hash
122
+ end
123
+
124
+ def each
125
+ @hash.each{|key, value| yield @name_hash[key], value }
126
+ end
127
+ alias each_pair each
128
+
129
+ def each_key
130
+ @hash.each_key{|key| yield @name_hash[key] }
131
+ end
132
+
133
+ def each_value
134
+ @hash.each_value{|value| yield value }
135
+ end
136
+
137
+ def empty?
138
+ @hash.empty?
139
+ end
140
+
141
+ def fetch(key, *default, &block)
142
+ raise ArgumentError, "wrong number of arguments (#{default.length+1} for 2)" if default.length > 1
143
+ if include?(key)
144
+ self[key]
145
+ elsif block_given?
146
+ block.call(key)
147
+ elsif default.length == 1
148
+ default.first
149
+ else
150
+ raise IndexError, "key not found"
151
+ end
152
+ end
153
+
154
+ def has_key?(key)
155
+ @hash.has_key?(convert_key(key))
156
+ end
157
+ alias include? has_key?
158
+ alias key? has_key?
159
+ alias member? has_key?
160
+
161
+ def has_value?(value)
162
+ @hash.has_value?(value)
163
+ end
164
+ alias value? has_value?
165
+
166
+ def index(value)
167
+ @name_hash[@hash.index(value)]
168
+ end
169
+
170
+ def inspect
171
+ to_hash.inspect
172
+ end
173
+
174
+ def invert
175
+ hash = CICPHash.new
176
+ each{|key, value| hash[value] = key}
177
+ hash
178
+ end
179
+
180
+ def keys
181
+ @name_hash.values
182
+ end
183
+
184
+ def length
185
+ @hash.length
186
+ end
187
+ alias size length
188
+
189
+ def merge(hash, &block)
190
+ new_hash = CICPHash.new.merge!(self)
191
+ hash.each do |key, value|
192
+ new_hash[key] = if block_given? && new_hash.include?(key)
193
+ block.call(key, new_hash[key], hash[key])
194
+ else
195
+ value
196
+ end
197
+ end
198
+ new_hash
199
+ end
200
+
201
+ def rehash
202
+ @name_hash.keys.each do |key|
203
+ new_key = @name_hash[key].to_s.downcase
204
+ if new_key != key
205
+ @name_hash[new_key] = @name_hash.delete(key)
206
+ @hash[new_key] = @hash.delete(key)
207
+ end
208
+ end
209
+ self
210
+ end
211
+
212
+ def reject(&block)
213
+ hash = CICPHash.new
214
+ each{|key, value| hash[key] = self[key] unless block.call(key, value)}
215
+ hash
216
+ end
217
+
218
+ def reject!(&block)
219
+ hash = CICPHash.new
220
+ changes = false
221
+ each{|key, value| block.call(key, value) ? (changes = true; delete(key)) : (hash[key] = value)}
222
+ changes ? hash : nil
223
+ end
224
+
225
+ def replace(hash)
226
+ clear
227
+ update(hash)
228
+ end
229
+
230
+ def select(&block)
231
+ array = []
232
+ each{|key, value| array << [key, value] if block.call(key, value)}
233
+ array
234
+ end
235
+
236
+ def shift
237
+ return nil if @name_hash.length == 0
238
+ key, value = @name_hash.shift
239
+ [value, @hash.delete(key)]
240
+ end
241
+
242
+ def sort(&block)
243
+ block_given? ? to_a.sort(&block) : to_a.sort
244
+ end
245
+
246
+ def to_a
247
+ array = []
248
+ each{|key, value| array << [key, value]}
249
+ array
250
+ end
251
+
252
+ def to_hash
253
+ hash = {}
254
+ each{|key, value| hash[key] = value}
255
+ hash
256
+ end
257
+
258
+ def to_s
259
+ to_a.join
260
+ end
261
+
262
+ def update(hash, &block)
263
+ hash.each do |key, value|
264
+ self[key] = if block_given? && include?(key)
265
+ block.call(key, self[key], hash[key])
266
+ else
267
+ value
268
+ end
269
+ end
270
+ self
271
+ end
272
+ alias merge! update
273
+
274
+ def values
275
+ @hash.values
276
+ end
277
+
278
+ def values_at(*keys)
279
+ keys.collect{|key| self[key]}
280
+ end
281
+ alias indexes values_at
282
+ alias indices values_at
283
+
284
+ private
285
+ def convert_key(key)
286
+ key.to_s.downcase
287
+ end
288
+ end
@@ -0,0 +1,401 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'cicphash'
4
+ require 'test/unit'
5
+
6
+ class CICPHashTest < Test::Unit::TestCase
7
+ def setup
8
+ @h = CICPHash[]
9
+ @fh = CICPHash['AB'=>1, :cd=>2, 3=>4]
10
+ end
11
+
12
+ def test_constructors_and_equality
13
+ # Test CICPHash.[]
14
+ assert_equal Hash[], CICPHash[]
15
+ assert_equal Hash[1=>2], CICPHash[1=>2]
16
+ assert_equal Hash[1=>2, 3=>4], CICPHash[1=>2, 3=>4]
17
+ assert_equal Hash[1,2,3,4], CICPHash[1,2,3,4]
18
+ assert_equal Hash[:ab,:c,:de,:f], CICPHash[:ab,:c,:de,:f]
19
+ assert_not_equal Hash[:AB,:c,:de,:f], CICPHash[:ab,:c,:de,:f]
20
+ assert_raises(ArgumentError){CICPHash[1]}
21
+ assert_raises(ArgumentError){CICPHash[1,2,3]}
22
+
23
+ # Test CICPHash.new
24
+ h, ch = Hash.new, CICPHash.new
25
+ assert_equal h, ch
26
+ h, ch = Hash.new(1), CICPHash.new(1)
27
+ assert_equal h, ch
28
+ assert_equal h[3], ch[3]
29
+ h[3], ch[3] = [2, 2]
30
+ assert_equal h[3], ch[3]
31
+ h, ch = Hash.new{|h,k| k*2}, CICPHash.new{|h,k| k*2}
32
+ assert_equal h[3], ch[3]
33
+ h[3], ch[3] = [2, 2]
34
+ assert_equal h[3], ch[3]
35
+ assert_raises(ArgumentError){CICPHash.new(1){|hash,k| key}}
36
+ end
37
+
38
+ def test_latest_assignment_wins
39
+ assert_equal Hash[], @h
40
+ @h['a'] = 1
41
+ assert_equal Hash['a'=>1], @h
42
+ @h['A'] = 2
43
+ assert_equal Hash['A'=>2], @h
44
+ @h[:ab] = 3
45
+ assert_equal Hash['A'=>2, :ab=>3], @h
46
+ @h['AB'] = 4
47
+ assert_equal Hash['A'=>2, 'AB'=>4], @h
48
+ @h[1] = 5
49
+ assert_equal Hash['A'=>2, 'AB'=>4, 1=>5], @h
50
+ @h['1'] = 6
51
+ assert_equal Hash['A'=>2, 'AB'=>4, '1'=>6], @h
52
+ end
53
+
54
+ def test_store_and_retrieve
55
+ assert_equal nil, @h[1]
56
+ @h[1] = 2
57
+ assert_equal 2, @h[1]
58
+ assert_equal 2, @h[:'1']
59
+ assert_equal 2, @h['1']
60
+ assert_equal 2, @h[[1]]
61
+ @h['a'] = 3
62
+ assert_equal 3, @h['a']
63
+ assert_equal 3, @h['A']
64
+ assert_equal 3, @h[:a]
65
+ assert_equal 3, @h[:A]
66
+ assert_equal 3, @h[[:A]]
67
+ @h['AB'] = 5
68
+ assert_equal 5, @h['ab']
69
+ assert_equal 5, @h['AB']
70
+ assert_equal 5, @h['aB']
71
+ assert_equal 5, @h['Ab']
72
+ assert_equal 5, @h[:ab]
73
+ assert_equal 5, @h[:AB]
74
+ assert_equal 5, @h[:aB]
75
+ assert_equal 5, @h[:Ab]
76
+ assert_equal 5, @h[[:ab]]
77
+ @h[[['A'],[:b],[[['cD']]]]] = 6
78
+ assert_equal 6, @h['abcd']
79
+ assert_equal 6, @h['ABCD']
80
+ assert_equal 6, @h[:AbCd]
81
+ assert_equal 6, @h[:aBcD]
82
+ assert_equal 6, @h[[[:A],['b'],:C,[[['d']]]]]
83
+ @h.store(7, 8)
84
+ assert_equal 8, @h[7]
85
+ assert_equal 8, @h[:'7']
86
+ assert_equal 8, @h['7']
87
+ assert_equal 8, @h[[7]]
88
+ end
89
+
90
+ def test_clear
91
+ assert_equal 3, @fh.length
92
+ @fh.clear
93
+ assert_equal Hash[], @fh
94
+ assert_equal 0, @fh.length
95
+ end
96
+
97
+ def test_defaults
98
+ assert_equal nil, @fh.default
99
+ assert_equal nil, @fh.default_proc
100
+ assert_equal nil, @fh[55]
101
+ assert_equal 3, CICPHash.new(3).default
102
+ assert_equal nil, CICPHash.new(3).default_proc
103
+ assert_equal 3, CICPHash.new(3)[1]
104
+
105
+ @fh.default = 4
106
+ assert_equal 4, @fh.default
107
+ assert_equal nil, @fh.default_proc
108
+ assert_equal 4, @fh[55]
109
+
110
+ h = CICPHash.new(5)
111
+ assert_equal 5, h.default
112
+ assert_equal nil, h.default_proc
113
+ assert_equal 5, h[55]
114
+
115
+ h = CICPHash.new{|hash, key| 1234}
116
+ assert_equal nil, h.default
117
+ assert_not_equal nil, h.default_proc
118
+ assert_equal 1234, h[55]
119
+
120
+ h = CICPHash.new{|hash, key| hash[key] = 1234; nil}
121
+ assert_equal nil, h.default
122
+ assert_not_equal nil, h.default_proc
123
+ assert_equal nil, h[55]
124
+ assert_equal 1234, h[55]
125
+ end
126
+
127
+ def test_delete
128
+ assert_equal 3, @fh.length
129
+ assert_equal 1, @fh.delete(:ab)
130
+ assert_equal 2, @fh.length
131
+ assert_equal nil, @fh.delete(:ab)
132
+ assert_equal 2, @fh.length
133
+ end
134
+
135
+ def test_delete_if_and_reject
136
+ assert_equal 3, @fh.length
137
+ hash = @fh.reject{|key, value| key.to_s.length >= 2}
138
+ assert_equal 1, hash.length
139
+ assert_equal Hash[3=>4], hash
140
+ assert_equal 3, @fh.length
141
+ hash = @fh.delete_if{|key, value| key.to_s.length >= 2}
142
+ assert_equal 1, hash.length
143
+ assert_equal Hash[3=>4], hash
144
+ assert_equal 1, @fh.length
145
+ assert_equal Hash[3=>4], @fh
146
+ assert_equal nil, @fh.reject!{|key, value| key.to_s.length >= 2}
147
+ hash = @fh.reject!{|key, value| key.to_s.length == 1}
148
+ assert_equal 0, hash.length
149
+ assert_equal Hash[], hash
150
+ assert_equal 0, @fh.length
151
+ assert_equal Hash[], @fh
152
+ end
153
+
154
+ def test_each
155
+ i = 0
156
+ @h.each{i+=1}
157
+ assert_equal 0, i
158
+ items = [['AB',1], [:cd,2], [3,4]]
159
+ @fh.each do |k,v|
160
+ assert items.include?([k,v])
161
+ items -= [[k,v]]
162
+ end
163
+ assert_equal [], items
164
+ end
165
+
166
+ def test_each_key
167
+ i = 0
168
+ @h.each{i+=1}
169
+ assert_equal 0, i
170
+ keys = ['AB', :cd, 3]
171
+ @fh.each_key do |k|
172
+ assert keys.include?(k)
173
+ keys -= [k]
174
+ end
175
+ assert_equal [], keys
176
+ end
177
+
178
+ def test_each_value
179
+ i = 0
180
+ @h.each{i+=1}
181
+ assert_equal 0, i
182
+ values = [1, 2, 4]
183
+ @fh.each_value do |v|
184
+ assert values.include?(v)
185
+ values -= [v]
186
+ end
187
+ assert_equal [], values
188
+ end
189
+
190
+ def test_empty
191
+ assert @h.empty?
192
+ assert !@fh.empty?
193
+ end
194
+
195
+ def test_fetch
196
+ assert_raises(ArgumentError){@h.fetch(1,2,3)}
197
+ assert_raises(ArgumentError){@h.fetch(1,2,3){4}}
198
+ assert_raises(IndexError){@h.fetch(1)}
199
+ @h.default = 33
200
+ assert_raises(IndexError){@h.fetch(1)}
201
+ @h[1] = 2
202
+ assert_equal 2, @h.fetch(1)
203
+ assert_equal 3, @h.fetch(2, 3)
204
+ assert_equal 4, @h.fetch(2, 3){4}
205
+ assert_equal 6, @h.fetch(2, 3){|k| k*3}
206
+ assert_equal 1, @fh.fetch(:ab)
207
+ assert_equal 2, @fh.fetch(:CD, 3)
208
+ assert_equal 4, @fh.fetch([3], 3){8}
209
+ assert_equal 4, @fh.fetch([3], 3){|k| k*3}
210
+ assert_raises(IndexError){CICPHash.new{34}.fetch(1)}
211
+ end
212
+
213
+ def test_has_key
214
+ 'include? has_key? key? member?'.split.each do |meth|
215
+ assert !@h.send(meth,1)
216
+ assert @fh.send(meth,'AB')
217
+ assert @fh.send(meth,:cd)
218
+ assert @fh.send(meth,3)
219
+ assert @fh.send(meth,:ab)
220
+ assert @fh.send(meth,'CD')
221
+ assert @fh.send(meth,[[[3]]])
222
+ assert !@fh.send(meth,1)
223
+ end
224
+ end
225
+
226
+ def test_has_value
227
+ 'value? has_value?'.split.each do |meth|
228
+ assert !@h.send(meth,1)
229
+ assert @fh.send(meth,1)
230
+ assert @fh.send(meth,2)
231
+ assert @fh.send(meth,4)
232
+ assert !@fh.send(meth,3)
233
+ end
234
+ end
235
+
236
+ def test_index
237
+ assert_equal nil, @h.index(1)
238
+ assert_equal 'AB', @fh.index(1)
239
+ assert_equal :cd, @fh.index(2)
240
+ assert_equal nil, @fh.index(3)
241
+ assert_equal 3, @fh.index(4)
242
+ end
243
+
244
+ def test_inspect_and_to_s
245
+ assert_equal '{}', CICPHash[].inspect
246
+ assert_equal '', CICPHash[].to_s
247
+ assert_equal '{1=>2}', CICPHash[1=>2].inspect
248
+ assert_equal '12', CICPHash[1=>2].to_s
249
+ assert ['{:ab=>"CD", [:"3"]=>4}', '{[:"3"]=>4, :ab=>"CD"}'].include?(CICPHash[:ab=>'CD', [:'3']=>4].inspect)
250
+ assert ['abCD34', '34abCD'].include?(CICPHash[:ab=>'CD', [:'3']=>4].to_s)
251
+ end
252
+
253
+ def test_invert
254
+ assert_equal Hash[].invert, CICPHash[].invert
255
+ assert_equal Hash[1=>2].invert, CICPHash[1=>2].invert
256
+ assert_equal Hash[1=>2, 3=>4].invert, CICPHash[1=>2, 3=>4].invert
257
+ assert_equal Hash[1,2,3,4].invert, CICPHash[1,2,3,4].invert
258
+ assert_equal Hash[:ab,:c,:de,:f].invert, CICPHash[:ab,:c,:de,:f].invert
259
+ assert_not_equal Hash[:ab,:c,:de,:f].invert, CICPHash[:aB,:c,:de,:f].invert
260
+ assert [{2=>1},{2=>3}].include?(CICPHash[1,2,3,2].invert)
261
+ end
262
+
263
+ def test_keys
264
+ assert_equal [], @h.keys
265
+ assert [[:aB, 1],[1, :aB]].include?(CICPHash[:aB,:c,1,:f].keys)
266
+ end
267
+
268
+ def test_length
269
+ assert_equal 0, @h.length
270
+ assert_equal 0, @h.size
271
+ assert_equal 3, @fh.length
272
+ assert_equal 3, @fh.size
273
+ @h[1] = 2
274
+ assert_equal 1, @h.length
275
+ assert_equal 1, @h.size
276
+ @fh.delete(:AB)
277
+ assert_equal 2, @fh.length
278
+ assert_equal 2, @fh.size
279
+ end
280
+
281
+ def test_merge_and_update
282
+ assert_equal @h, @h.merge({})
283
+ assert_equal @fh, @fh.merge({})
284
+ assert_equal CICPHash[:ab=>55], @h.merge({:ab=>55})
285
+ assert_equal CICPHash[], @h
286
+ assert_equal CICPHash[:ab=>55], @h.update({:ab=>55})
287
+ assert_equal CICPHash[:ab=>55], @h
288
+ assert_equal CICPHash[:ab=>55, :cd=>2, 3=>4], @fh.merge({:ab=>55})
289
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4], @fh
290
+ assert_equal CICPHash[:ab=>55, :cd=>2, 3=>4], @fh.merge!({:ab=>55})
291
+ assert_equal CICPHash[:ab=>55, :cd=>2, 3=>4], @fh
292
+ assert_equal CICPHash[:ab=>'abss55', :cd=>2, 3=>4], @fh.merge({:ab=>'ss'}){|k,ov,nv| [k,nv,ov].join}
293
+ assert_equal CICPHash[:ab=>55, :cd=>2, 3=>4], @fh
294
+ assert_equal CICPHash[:ab=>'abss55', :cd=>2, 3=>4], @fh.update({:ab=>'ss'}){|k,ov,nv| [k,nv,ov].join}
295
+ assert_equal CICPHash[:ab=>'abss55', :cd=>2, 3=>4], @fh
296
+ assert_equal CICPHash[:ab=>'abssabss55', :cd=>2, 3=>4], @fh.merge!({:ab=>'ss'}){|k,ov,nv| [k,nv,ov].join}
297
+ assert_equal CICPHash[:ab=>'abssabss55', :cd=>2, 3=>4], @fh
298
+ end
299
+
300
+ def test_update
301
+ assert_equal Hash[], @h.update({})
302
+ assert_equal Hash[:ab,2], @h.update({:ab=>2})
303
+ assert_equal Hash[:ab,2], @h
304
+ assert_equal Hash['AB',2], @h.update({'AB'=>2})
305
+ assert_equal Hash['AB',2], @h
306
+ assert_equal Hash[[:a,:B],3,4,5], @h.update([:a,:B]=>3, 4=>5) do |k,ov,nv|
307
+ asset_equal [:a,:B], k
308
+ asset_equal 2, ov
309
+ asset_equal 3, nv
310
+ end
311
+ assert_equal Hash[[:a,:B],3,4,5], @h
312
+ end
313
+
314
+ def test_rehash
315
+ assert_equal @h, @h.rehash
316
+ assert_equal @fh, @fh.rehash
317
+ x = 'BLAH'
318
+ @fh[x] = 23
319
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'BLAH'=>23], @fh
320
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'BLAH'=>23], @fh.rehash
321
+ x.downcase!
322
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'blah'=>23], @fh
323
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'blah'=>23], @fh.rehash
324
+ x.replace("DIFF")
325
+ assert_equal 23, @fh['blah']
326
+ assert_equal nil, @fh['DIFF']
327
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'DIFF'=>23], @fh
328
+ assert_equal CICPHash['AB'=>1, :cd=>2, 3=>4, 'DIFF'=>23], @fh.rehash
329
+ assert_equal nil, @fh['blah']
330
+ assert_equal 23, @fh['DIFF']
331
+ end
332
+
333
+ def test_replace
334
+ assert_equal @h, @h.replace(@h)
335
+ assert_equal @fh, @fh.replace(@fh)
336
+ assert_equal @fh, @h.replace(@fh)
337
+ assert_equal Hash[], @fh.replace(Hash[])
338
+ end
339
+
340
+ def test_select
341
+ assert_equal [], @h.select{true}
342
+ assert_equal [], @h.select{false}
343
+ assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.select{true}.sort_by{|x| x.to_s}
344
+ assert_equal [], @fh.select{false}
345
+ assert_equal [[:cd,2]], @fh.select{|k,v| k.is_a?(Symbol)}
346
+ assert_equal [[3,4]], @fh.select{|k,v| v == 4}
347
+ end
348
+
349
+ def test_shift
350
+ assert_equal nil, @h.shift
351
+ array = @fh.to_a
352
+ i = 3
353
+ loop do
354
+ assert i >= 0
355
+ kv = @fh.shift
356
+ if kv.nil?
357
+ assert_equal [], array
358
+ break
359
+ else
360
+ i -= 1
361
+ assert array.include?(kv)
362
+ array -= [kv]
363
+ end
364
+ end
365
+ assert_equal [], array
366
+ assert_equal 0, i
367
+ end
368
+
369
+ def test_sort
370
+ assert_equal [], @h.sort
371
+ assert_equal [], @h.sort{|a,b| a.to_s<=>b.to_s}
372
+ assert_equal [['AB',1], ['CD',4], ['EF',2]], CICPHash['CD',4,'AB',1,'EF',2].sort
373
+ assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.sort{|a,b| a.to_s<=>b.to_s}
374
+ end
375
+
376
+ def test_to_a
377
+ assert_equal [], @h.to_a
378
+ assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.to_a.sort{|a,b| a.to_s<=>b.to_s}
379
+ end
380
+
381
+ def test_to_hash
382
+ assert_equal Hash[], @h.to_hash
383
+ assert_equal Hash[3,4,'AB',1,:cd,2], @fh.to_hash
384
+ end
385
+
386
+ def test_values
387
+ assert_equal [], @h.values
388
+ assert_equal [:c, :f], CICPHash[:aB,:f,1,:c].values.sort_by{|x|x.to_s}
389
+ end
390
+
391
+ def test_values_at
392
+ assert_equal [], @h.values_at()
393
+ assert_equal [nil], @h.values_at(1)
394
+ assert_equal [nil, nil], @h.values_at(1, 1)
395
+ assert_equal [], @fh.values_at()
396
+ assert_equal [1], @fh.values_at(:ab)
397
+ assert_equal [2, 1], @fh.values_at('CD', :ab)
398
+ assert_equal [2, nil, 1], @fh.values_at('CD', 32, :ab)
399
+ assert_equal [4, 2, nil, 1], @fh.values_at([[[3]],''], 'CD', 32, :ab)
400
+ end
401
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: cicphash
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-08-12 00:00:00 -07:00
8
+ summary: Case Insensitive Cash Preserving Hash
9
+ require_paths:
10
+ - .
11
+ email: code@jeremyevans.net
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: cicphash
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
+ - Jeremy Evans
31
+ files:
32
+ - cicphash.rb
33
+ test_files:
34
+ - test/test_cicphash.rb
35
+ rdoc_options: []
36
+
37
+ extra_rdoc_files: []
38
+
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ requirements: []
44
+
45
+ dependencies: []
46
+