cicphash 1.0.0 → 1.1.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 +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