cicphash 1.0.0 → 1.1.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 +364 -288
  2. data/test/test_cicphash.rb +77 -20
  3. metadata +40 -39
@@ -1,288 +1,364 @@
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
1
+ # CICPHash is a case insensitive case preserving hash for ruby.
2
+ #
3
+ # * RDoc: http://cicphash.rubyforge.org
4
+ # * Source: http://github.com/jeremyevans/ruby-cicphash
5
+ #
6
+ # Copyright (c) 2007, 2012 Jeremy Evans
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ # Case Insensitive Case Preserving Hash
27
+ #
28
+ # CICPHash has the exact same interface as Hash, but is case insensitive
29
+ # and case preserving. Any value can be used as a key. However, you
30
+ # cannot have two keys in the same CICPHash that would be the same if when
31
+ # converted to strings would be equal or differing only in case.
32
+ #
33
+ # For example, all of the following keys would be considered equalivalent:
34
+ # 'ab', 'Ab', 'AB', 'aB', :ab, :Ab, :AB, :aB
35
+ #
36
+ # CICPHash uses a last match wins policy. If an key-value pair is added to
37
+ # a CICPHash and a case insensitive variant of the key is already in the hash
38
+ # the instance of the key in the hash becomes the same the most recently added
39
+ # key (and obviously the value is updated to reflect the new value).
40
+ #
41
+ # You can change the rules determining which keys are equal by modifying the
42
+ # private convert_key method. By default, it is set to key.to_s.downcase.
43
+ # This method should produce the same output for any keys that you want to
44
+ # consider equal. For example, if you want :a and :A to be equal but :a to be
45
+ # different than "a", maybe key.inspect.downcase would work for you.
46
+ class CICPHash
47
+ include Enumerable
48
+
49
+ def self.[](*items)
50
+ if items.length % 2 != 0
51
+ if items.length == 1 && items.first.is_a?(Hash)
52
+ new.merge(items.first)
53
+ else
54
+ raise ArgumentError, "odd number of arguments for CICPHash"
55
+ end
56
+ else
57
+ hash = new
58
+ loop do
59
+ break if items.length == 0
60
+ key = items.shift
61
+ value = items.shift
62
+ hash[key] = value
63
+ end
64
+ hash
65
+ end
66
+ end
67
+
68
+ def initialize(*default, &block)
69
+ if default.length > 1 || default.length == 1 && block_given?
70
+ raise ArgumentError, "wrong number of arguments"
71
+ end
72
+ @name_hash = {}
73
+ @hash = {}
74
+ @default = default.first unless block_given?
75
+ @default_proc = Proc.new(&block) if block_given?
76
+ end
77
+
78
+ def ==(hash)
79
+ to_hash == hash.to_hash
80
+ end
81
+
82
+ def [](key)
83
+ new_key = convert_key(key)
84
+ if @hash.include?(new_key)
85
+ @hash[new_key]
86
+ elsif @default_proc
87
+ @default_proc.call(self, key)
88
+ else
89
+ @default
90
+ end
91
+ end
92
+
93
+ def []=(key, value)
94
+ new_key = convert_key(key)
95
+ @name_hash[new_key] = key
96
+ @hash[new_key] = value
97
+ end
98
+ alias store :[]=
99
+
100
+ def clear
101
+ @name_hash.clear
102
+ @hash.clear
103
+ end
104
+
105
+ def clone
106
+ s = super
107
+ s.instance_variable_set(:@hash, @hash.clone)
108
+ s.instance_variable_set(:@name_hash, @name_hash.clone)
109
+ s
110
+ end
111
+
112
+ def default
113
+ @default
114
+ end
115
+
116
+ def default=(value)
117
+ @default = value
118
+ end
119
+
120
+ def default_proc
121
+ @default_proc
122
+ end
123
+
124
+ def delete(key)
125
+ new_key = convert_key(key)
126
+ @name_hash.delete(new_key)
127
+ @hash.delete(new_key)
128
+ end
129
+
130
+ def delete_if(&block)
131
+ hash = CICPHash.new
132
+ each{|key, value| block.call(key, value) ? delete(key) : (hash[key] = value)}
133
+ hash
134
+ end
135
+
136
+ def dup
137
+ s = super
138
+ s.instance_variable_set(:@hash, @hash.dup)
139
+ s.instance_variable_set(:@name_hash, @name_hash.dup)
140
+ s
141
+ end
142
+
143
+ def each
144
+ @hash.each{|key, value| yield @name_hash[key], value }
145
+ end
146
+ alias each_pair each
147
+
148
+ def each_key
149
+ @hash.each_key{|key| yield @name_hash[key] }
150
+ end
151
+
152
+ def each_value
153
+ @hash.each_value{|value| yield value }
154
+ end
155
+
156
+ def empty?
157
+ @hash.empty?
158
+ end
159
+
160
+ def fetch(key, *default, &block)
161
+ raise ArgumentError, "wrong number of arguments (#{default.length+1} for 2)" if default.length > 1
162
+ if include?(key)
163
+ self[key]
164
+ elsif block_given?
165
+ block.call(key)
166
+ elsif default.length == 1
167
+ default.first
168
+ else
169
+ raise IndexError, "key not found"
170
+ end
171
+ end
172
+
173
+ def has_key?(key)
174
+ @hash.has_key?(convert_key(key))
175
+ end
176
+ alias include? has_key?
177
+ alias key? has_key?
178
+ alias member? has_key?
179
+
180
+ def has_value?(value)
181
+ @hash.has_value?(value)
182
+ end
183
+ alias value? has_value?
184
+
185
+ if RUBY_VERSION >= '1.9'
186
+ def key(value)
187
+ @name_hash[@hash.key(value)]
188
+ end
189
+ alias index key
190
+ else
191
+ def index(value)
192
+ @name_hash[@hash.index(value)]
193
+ end
194
+ end
195
+
196
+ def inspect
197
+ to_hash.inspect
198
+ end
199
+
200
+ def invert
201
+ hash = CICPHash.new
202
+ each{|key, value| hash[value] = key}
203
+ hash
204
+ end
205
+
206
+ def keys
207
+ @name_hash.values
208
+ end
209
+
210
+ def length
211
+ @hash.length
212
+ end
213
+ alias size length
214
+
215
+ def merge(hash, &block)
216
+ new_hash = CICPHash.new.merge!(self)
217
+ hash.each do |key, value|
218
+ new_hash[key] = if block_given? && new_hash.include?(key)
219
+ block.call(key, new_hash[key], hash[key])
220
+ else
221
+ value
222
+ end
223
+ end
224
+ new_hash
225
+ end
226
+
227
+ def rehash
228
+ @name_hash.keys.each do |key|
229
+ new_key = @name_hash[key].to_s.downcase
230
+ if new_key != key
231
+ @name_hash[new_key] = @name_hash.delete(key)
232
+ @hash[new_key] = @hash.delete(key)
233
+ end
234
+ end
235
+ self
236
+ end
237
+
238
+ def reject(&block)
239
+ hash = CICPHash.new
240
+ each{|key, value| hash[key] = self[key] unless block.call(key, value)}
241
+ hash
242
+ end
243
+
244
+ def reject!(&block)
245
+ hash = CICPHash.new
246
+ changes = false
247
+ each{|key, value| block.call(key, value) ? (changes = true; delete(key)) : (hash[key] = value)}
248
+ changes ? hash : nil
249
+ end
250
+
251
+ def replace(hash)
252
+ clear
253
+ update(hash)
254
+ end
255
+
256
+ def select(&block)
257
+ array = []
258
+ each{|key, value| array << [key, value] if block.call(key, value)}
259
+ array
260
+ end
261
+
262
+ def shift
263
+ return nil if @name_hash.length == 0
264
+ key, value = @name_hash.shift
265
+ [value, @hash.delete(key)]
266
+ end
267
+
268
+ def sort(&block)
269
+ block_given? ? to_a.sort(&block) : to_a.sort
270
+ end
271
+
272
+ def to_a
273
+ array = []
274
+ each{|key, value| array << [key, value]}
275
+ array
276
+ end
277
+
278
+ def to_hash
279
+ hash = {}
280
+ each{|key, value| hash[key] = value}
281
+ hash
282
+ end
283
+
284
+ def to_s
285
+ to_a.join
286
+ end
287
+
288
+ def update(hash, &block)
289
+ hash.each do |key, value|
290
+ self[key] = if block_given? && include?(key)
291
+ block.call(key, self[key], hash[key])
292
+ else
293
+ value
294
+ end
295
+ end
296
+ self
297
+ end
298
+ alias merge! update
299
+
300
+ def values
301
+ @hash.values
302
+ end
303
+
304
+ def values_at(*keys)
305
+ keys.collect{|key| self[key]}
306
+ end
307
+ alias indexes values_at
308
+ alias indices values_at
309
+
310
+ if RUBY_VERSION >= '1.9'
311
+ def assoc(obj)
312
+ obj = convert_key(obj)
313
+ each do |k, v|
314
+ if convert_key(k) == obj
315
+ return [k, v]
316
+ end
317
+ end
318
+ nil
319
+ end
320
+
321
+ attr_writer :default_proc
322
+
323
+ def flatten(*a)
324
+ if a.empty?
325
+ to_a.flatten(1)
326
+ else
327
+ to_a.flatten(*a)
328
+ end
329
+ end
330
+
331
+ def keep_if(&block)
332
+ to_a.each do |k, v|
333
+ delete(k) unless yield(k, v)
334
+ end
335
+ self
336
+ end
337
+
338
+ def rassoc(obj)
339
+ each do |k, v|
340
+ if v == obj
341
+ return [k, v]
342
+ end
343
+ end
344
+ nil
345
+ end
346
+
347
+ def select!(&block)
348
+ mod = false
349
+ to_a.each do |k, v|
350
+ unless yield(k, v)
351
+ mod = true
352
+ delete(k)
353
+ end
354
+ end
355
+ self if mod
356
+ end
357
+ end
358
+
359
+ private
360
+
361
+ def convert_key(key)
362
+ key.to_s.downcase
363
+ end
364
+ end
@@ -1,5 +1,6 @@
1
1
  #!/usr/local/bin/ruby
2
2
 
3
+ $: << File.dirname(File.dirname(File.expand_path(__FILE__)))
3
4
  require 'cicphash'
4
5
  require 'test/unit'
5
6
 
@@ -57,13 +58,11 @@ class CICPHashTest < Test::Unit::TestCase
57
58
  assert_equal 2, @h[1]
58
59
  assert_equal 2, @h[:'1']
59
60
  assert_equal 2, @h['1']
60
- assert_equal 2, @h[[1]]
61
61
  @h['a'] = 3
62
62
  assert_equal 3, @h['a']
63
63
  assert_equal 3, @h['A']
64
64
  assert_equal 3, @h[:a]
65
65
  assert_equal 3, @h[:A]
66
- assert_equal 3, @h[[:A]]
67
66
  @h['AB'] = 5
68
67
  assert_equal 5, @h['ab']
69
68
  assert_equal 5, @h['AB']
@@ -73,18 +72,10 @@ class CICPHashTest < Test::Unit::TestCase
73
72
  assert_equal 5, @h[:AB]
74
73
  assert_equal 5, @h[:aB]
75
74
  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
75
  @h.store(7, 8)
84
76
  assert_equal 8, @h[7]
85
77
  assert_equal 8, @h[:'7']
86
78
  assert_equal 8, @h['7']
87
- assert_equal 8, @h[[7]]
88
79
  end
89
80
 
90
81
  def test_clear
@@ -150,6 +141,17 @@ class CICPHashTest < Test::Unit::TestCase
150
141
  assert_equal 0, @fh.length
151
142
  assert_equal Hash[], @fh
152
143
  end
144
+
145
+ def test_dup_and_clone
146
+ def @h.foo; 1; end
147
+ h2 = @h.dup
148
+ h3 = @h.clone
149
+ h2[1] = 2
150
+ h3[1] = 2
151
+ assert_equal CICPHash[], @h
152
+ assert_raises NoMethodError do h2.foo end
153
+ assert_equal 1, h3.foo
154
+ end
153
155
 
154
156
  def test_each
155
157
  i = 0
@@ -205,8 +207,8 @@ class CICPHashTest < Test::Unit::TestCase
205
207
  assert_equal 6, @h.fetch(2, 3){|k| k*3}
206
208
  assert_equal 1, @fh.fetch(:ab)
207
209
  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_equal 4, @fh.fetch("3", 3){8}
211
+ assert_equal 4, @fh.fetch("3", 3){|k| k*3}
210
212
  assert_raises(IndexError){CICPHash.new{34}.fetch(1)}
211
213
  end
212
214
 
@@ -218,7 +220,7 @@ class CICPHashTest < Test::Unit::TestCase
218
220
  assert @fh.send(meth,3)
219
221
  assert @fh.send(meth,:ab)
220
222
  assert @fh.send(meth,'CD')
221
- assert @fh.send(meth,[[[3]]])
223
+ assert @fh.send(meth,'3')
222
224
  assert !@fh.send(meth,1)
223
225
  end
224
226
  end
@@ -303,12 +305,12 @@ class CICPHashTest < Test::Unit::TestCase
303
305
  assert_equal Hash[:ab,2], @h
304
306
  assert_equal Hash['AB',2], @h.update({'AB'=>2})
305
307
  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
+ assert_equal Hash[:aB,3,4,5], @h.update(:aB=>3, 4=>5) do |k,ov,nv|
309
+ asset_equal :aB, k
308
310
  asset_equal 2, ov
309
311
  asset_equal 3, nv
310
312
  end
311
- assert_equal Hash[[:a,:B],3,4,5], @h
313
+ assert_equal Hash[:aB,3,4,5], @h
312
314
  end
313
315
 
314
316
  def test_rehash
@@ -340,7 +342,7 @@ class CICPHashTest < Test::Unit::TestCase
340
342
  def test_select
341
343
  assert_equal [], @h.select{true}
342
344
  assert_equal [], @h.select{false}
343
- assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.select{true}.sort_by{|x| x.to_s}
345
+ assert_equal [[3, 4], ["AB", 1], [:cd, 2]], @fh.select{true}.sort_by{|k,v| k.to_s}
344
346
  assert_equal [], @fh.select{false}
345
347
  assert_equal [[:cd,2]], @fh.select{|k,v| k.is_a?(Symbol)}
346
348
  assert_equal [[3,4]], @fh.select{|k,v| v == 4}
@@ -370,12 +372,12 @@ class CICPHashTest < Test::Unit::TestCase
370
372
  assert_equal [], @h.sort
371
373
  assert_equal [], @h.sort{|a,b| a.to_s<=>b.to_s}
372
374
  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}
375
+ assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.sort{|(ak,av),(bk,bv)| ak.to_s<=>bk.to_s}
374
376
  end
375
377
 
376
378
  def test_to_a
377
379
  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}
380
+ assert_equal [[3,4], ['AB',1], [:cd,2]], @fh.to_a.sort_by{|k,v| k.to_s}
379
381
  end
380
382
 
381
383
  def test_to_hash
@@ -396,6 +398,61 @@ class CICPHashTest < Test::Unit::TestCase
396
398
  assert_equal [1], @fh.values_at(:ab)
397
399
  assert_equal [2, 1], @fh.values_at('CD', :ab)
398
400
  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)
401
+ assert_equal [4, 2, nil, 1], @fh.values_at('3', 'CD', 32, :ab)
402
+ end
403
+
404
+ if RUBY_VERSION >= '1.9'
405
+ def test_assoc
406
+ assert_equal nil, @h.assoc(1)
407
+ assert_equal ['AB', 1], @fh.assoc(:Ab)
408
+ assert_equal [:cd, 2], @fh.assoc('CD')
409
+ assert_equal nil, @fh.assoc(4)
410
+ assert_equal [3, 4], @fh.assoc('3')
411
+ end
412
+
413
+ def test_default_proc=
414
+ @h.default_proc = proc{|h, k| k * 2}
415
+ assert_equal 'aa', @h['a']
416
+ @h[:a] = 2
417
+ assert_equal 2, @h['a']
418
+ end
419
+
420
+ def test_flatten
421
+ assert_equal [], @h.flatten
422
+ assert_equal ['AB', 1, :cd, 2, 3, 4], @fh.flatten
423
+ @fh[:X] = [5, 6]
424
+ assert_equal ['AB', 1, :cd, 2, 3, 4, :X, [5, 6]], @fh.flatten
425
+ assert_equal ['AB', 1, :cd, 2, 3, 4, :X, 5, 6], @fh.flatten(2)
426
+ end
427
+
428
+ def test_keep_if
429
+ assert_equal @h, @h.keep_if{|k, v| true}
430
+ assert_equal @fh, @fh.keep_if{|k, v| true}
431
+ assert_equal @h, @fh.dup.keep_if{|k, v| false}
432
+ assert_equal CICPHash["AB"=>1], @fh.keep_if{|k, v| k == "AB"}
433
+ end
434
+
435
+ def test_key
436
+ assert_equal nil, @h.index(1)
437
+ assert_equal 'AB', @fh.index(1)
438
+ assert_equal :cd, @fh.index(2)
439
+ assert_equal nil, @fh.index(3)
440
+ assert_equal 3, @fh.index(4)
441
+ end
442
+
443
+ def test_rassoc
444
+ assert_equal nil, @h.rassoc(1)
445
+ assert_equal ['AB', 1], @fh.rassoc(1)
446
+ assert_equal [:cd, 2], @fh.rassoc(2)
447
+ assert_equal nil, @fh.rassoc(3)
448
+ assert_equal [3, 4], @fh.rassoc(4)
449
+ end
450
+
451
+ def test_select!
452
+ assert_equal nil, @h.select!{|k, v| true}
453
+ assert_equal nil, @fh.select!{|k, v| true}
454
+ assert_equal @h, @fh.dup.select!{|k, v| false}
455
+ assert_equal CICPHash["AB"=>1], @fh.select!{|k, v| k == "AB"}
456
+ end
400
457
  end
401
458
  end
metadata CHANGED
@@ -1,46 +1,47 @@
1
- --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
3
- specification_version: 1
1
+ --- !ruby/object:Gem::Specification
4
2
  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:
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
25
6
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
- authors:
7
+ authors:
30
8
  - Jeremy Evans
31
- files:
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: code@jeremyevans.net
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
32
20
  - cicphash.rb
33
- test_files:
34
21
  - test/test_cicphash.rb
22
+ homepage: http://cicphash.rubyforge.org
23
+ licenses: []
24
+ post_install_message:
35
25
  rdoc_options: []
36
-
37
- extra_rdoc_files: []
38
-
39
- executables: []
40
-
41
- extensions: []
42
-
26
+ require_paths:
27
+ - .
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
43
40
  requirements: []
44
-
45
- dependencies: []
46
-
41
+ rubyforge_project: cicphash
42
+ rubygems_version: 1.8.23
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: Case Insensitive Case Preserving Hash
46
+ test_files:
47
+ - test/test_cicphash.rb