cicphash 1.0.0

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 (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
+