hashery 1.4.0 → 1.5.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 (54) hide show
  1. data/.ruby +57 -92
  2. data/.yardopts +8 -0
  3. data/COPYING.rdoc +45 -0
  4. data/HISTORY.rdoc +18 -0
  5. data/QED.rdoc +1 -0
  6. data/README.rdoc +42 -16
  7. data/lib/hashery.rb +16 -9
  8. data/lib/hashery.yml +57 -92
  9. data/lib/hashery/association.rb +3 -1
  10. data/lib/hashery/basic_object.rb +74 -0
  11. data/lib/hashery/basic_struct.rb +288 -1
  12. data/lib/hashery/basicobject.rb +1 -74
  13. data/lib/hashery/basicstruct.rb +1 -280
  14. data/lib/hashery/casting_hash.rb +171 -1
  15. data/lib/hashery/castinghash.rb +1 -171
  16. data/lib/hashery/core_ext.rb +82 -0
  17. data/lib/hashery/dictionary.rb +3 -0
  18. data/lib/hashery/fuzzy_hash.rb +154 -1
  19. data/lib/hashery/fuzzyhash.rb +1 -154
  20. data/lib/hashery/ini.rb +3 -2
  21. data/lib/hashery/key_hash.rb +186 -0
  22. data/lib/hashery/keyhash.rb +1 -0
  23. data/lib/hashery/linked_list.rb +195 -1
  24. data/lib/hashery/linkedlist.rb +1 -195
  25. data/lib/hashery/lru_hash.rb +273 -1
  26. data/lib/hashery/lruhash.rb +1 -273
  27. data/lib/hashery/open_cascade.rb +99 -1
  28. data/lib/hashery/open_hash.rb +77 -1
  29. data/lib/hashery/opencascade.rb +1 -99
  30. data/lib/hashery/openhash.rb +1 -77
  31. data/lib/hashery/ordered_hash.rb +168 -1
  32. data/lib/hashery/orderedhash.rb +1 -167
  33. data/lib/hashery/property_hash.rb +97 -1
  34. data/lib/hashery/propertyhash.rb +1 -97
  35. data/lib/hashery/query_hash.rb +35 -1
  36. data/lib/hashery/queryhash.rb +1 -35
  37. data/lib/hashery/stash.rb +3 -174
  38. data/lib/hashery/static_hash.rb +48 -1
  39. data/lib/hashery/statichash.rb +1 -48
  40. data/qed/06_opencascade.rdoc +12 -12
  41. data/test/case_association.rb +29 -15
  42. data/test/case_basicstruct.rb +192 -0
  43. data/test/case_dictionary.rb +149 -109
  44. data/test/case_keyhash.rb +175 -0
  45. data/test/case_opencascade.rb +89 -43
  46. data/test/case_openhash.rb +15 -11
  47. metadata +85 -78
  48. data/LICENSE +0 -206
  49. data/NOTICE +0 -11
  50. data/lib/hashery/sparse_array.rb +0 -1
  51. data/lib/hashery/sparsearray.rb +0 -577
  52. data/test/case_openobject.rb +0 -130
  53. data/test/case_sparsearray.rb +0 -316
  54. data/test/case_stash.rb +0 -131
@@ -1,280 +1 @@
1
- require 'hashery/basicobject'
2
-
3
- #require 'facets/hash/to_h'
4
- #require 'facets/kernel/object_class'
5
- #require 'facets/kernel/object_hexid'
6
-
7
- # = BasicStruct
8
- #
9
- # BasicObject is very similar to Ruby's own OpenStruct, but it offers some
10
- # advantages. With OpenStruct, slots with the same name as predefined
11
- # Object methods cannot be used. With BasicObject, almost any slot can be
12
- # defined. BasicObject is a subclass of BasicObject to ensure all method
13
- # slots, except those that are absolutely essential, are open for use.
14
- #
15
- #--
16
- # If you wish to pass an BasicObject to a routine that normal takes a Hash,
17
- # but are uncertain it can handle the distictions properly you can convert
18
- # easily to a Hash using #as_hash! and the result will automatically be
19
- # converted back to an BasicObject on return.
20
- #
21
- # o = BasicObject.new(:a=>1,:b=>2)
22
- # o.as_hash!{ |h| h.update(:a=>6) }
23
- # o #=> #<BasicObject {:a=>6,:b=>2}>
24
- #++
25
- #
26
- # Unlike a Hash, all BasicObject's keys are symbols and all keys are converted
27
- # to such using #to_sym on the fly.
28
-
29
- class BasicStruct < BasicObject
30
-
31
- #PUBLIC_METHODS = /(^__|^instance_|^object_|^\W|^as$|^send$|^class$|\?$)/
32
- #protected(*public_instance_methods.select{ |m| m !~ PUBLIC_METHODS })
33
-
34
- def self.[](hash=nil)
35
- new(hash)
36
- end
37
-
38
- # Inititalizer for BasicObject is slightly different than that of Hash.
39
- # It does not take a default parameter, but an initial priming Hash,
40
- # like OpenStruct. The initializer can still take a default block
41
- # however. To set the default value use <code>#default!(value)</code>.
42
- #
43
- # BasicObject.new(:a=>1).default!(0)
44
- #
45
- def initialize(hash=nil, &yld)
46
- @table = Hash.new(&yld)
47
- if hash
48
- hash.each{ |k,v| store(k,v) }
49
- end
50
- end
51
-
52
- #
53
- def initialize_copy(orig)
54
- orig.each{ |k,v| store(k,v) }
55
- end
56
-
57
- # Object inspection.
58
- # TODO: Need to get __class__ and __id__ in hex form.
59
- def inspect
60
- #@table.inspect
61
- hexid = __id__
62
- klass = "BasicObject" # __class__
63
- "#<#{klass}:#{hexid} #{@table.inspect}>"
64
- end
65
-
66
- # Convert to an associative array.
67
- def to_a
68
- @table.to_a
69
- end
70
-
71
- #
72
- def to_h
73
- @table.dup
74
- end
75
-
76
- #
77
- def to_hash
78
- @table.dup
79
- end
80
-
81
- #
82
- def to_basicstruct
83
- self
84
- end
85
-
86
- # Convert to an assignment procedure.
87
- def to_proc(response=false)
88
- hash = @table
89
- if response
90
- lambda do |o|
91
- hash.each do |k,v|
92
- o.__send__("#{k}=", v) rescue nil
93
- end
94
- end
95
- else
96
- lambda do |o|
97
- hash.each{ |k,v| o.__send__("#{k}=", v) }
98
- end
99
- end
100
- end
101
-
102
- # NOT SURE ABOUT THIS
103
- def as_hash
104
- @table
105
- end
106
-
107
- # Is a given +key+ defined?
108
- def key?(key)
109
- @table.key?(key.to_sym)
110
- end
111
-
112
- #
113
- def is_a?(klass)
114
- return true if klass == Hash # TODO: Is this wise? How to fake a subclass?
115
- return true if klass == BasicObject
116
- false
117
- end
118
-
119
- # Iterate over each key-value pair.
120
- def each(&yld)
121
- @table.each(&yld)
122
- end
123
-
124
- # Set the default value.
125
- def default!(default)
126
- @table.default = default
127
- end
128
-
129
- # Check equality.
130
- def ==( other )
131
- case other
132
- when BasicObject
133
- @table == other.as_hash
134
- when Hash
135
- @table == other
136
- else
137
- if other.respond_to?(:to_hash)
138
- @table == other.to_hash
139
- else
140
- false
141
- end
142
- end
143
- end
144
-
145
- #
146
- def eql?( other )
147
- case other
148
- when BasicObject
149
- @table.eql?(other.as_hash)
150
- else
151
- false
152
- end
153
- end
154
-
155
- #
156
- def <<(x)
157
- case x
158
- when Hash
159
- @table.update(x)
160
- when Array
161
- x.each_slice(2) do |(k,v)|
162
- @table[k] = v
163
- end
164
- end
165
- end
166
-
167
- #
168
- def []=(key, value)
169
- @table[key.to_sym] = value
170
- end
171
-
172
- #
173
- def [](key)
174
- @table[key.to_sym]
175
- end
176
-
177
- #
178
- def merge!(other)
179
- BasicObject.new(@table.merge!(other))
180
- end
181
-
182
- #
183
- def update!(other)
184
- @table.update(other)
185
- self
186
- end
187
-
188
- protected
189
-
190
- def store(k, v)
191
- @table.store(k.to_sym, v)
192
- end
193
-
194
- def fetch(k, *d, &b)
195
- @table.fetch(k.to_sym, *d, &b)
196
- end
197
-
198
- #def as_hash!
199
- # Functor.new do |op,*a,&b|
200
- # result = @table.__send__(op,*a,&b)
201
- # case result
202
- # when Hash
203
- # BasicObject.new(result)
204
- # else
205
- # result
206
- # end
207
- # end
208
- #end
209
-
210
- #def define_slot(key, value=nil)
211
- # @table[key.to_sym] = value
212
- #end
213
-
214
- #def protect_slot( key )
215
- # (class << self; self; end).class_eval {
216
- # protected key rescue nil
217
- # }
218
- #end
219
-
220
- def method_missing(sym, *args, &blk)
221
- type = sym.to_s[-1,1]
222
- key = sym.to_s.sub(/[=?!]$/,'').to_sym
223
- case type
224
- when '='
225
- store(key, args[0])
226
- when '!'
227
- @table.__send__(key, *args, &blk)
228
- # if key?(key)
229
- # fetch(key)
230
- # else
231
- # store(key, BasicObject.new)
232
- # end
233
- when '?'
234
- fetch(key)
235
- else
236
- fetch(key)
237
- end
238
- end
239
-
240
- end
241
-
242
- # Core Extensions
243
-
244
- class Hash
245
- # Convert a Hash into a BasicStruct.
246
- def to_basicstruct
247
- BasicStruct[self]
248
- end
249
- end
250
-
251
- =begin
252
- class NilClass
253
- # Nil converts to an empty BasicObject.
254
- def to_basicstruct
255
- BasicObject.new
256
- end
257
- end
258
-
259
- class Proc
260
- # Translates a Proc into an BasicObject. By droping an BasicObject into
261
- # the Proc, the resulting assignments incured as the procedure is
262
- # evaluated produce the BasicObject. This technique is simlar to that
263
- # of MethodProbe.
264
- #
265
- # p = lambda { |x|
266
- # x.word = "Hello"
267
- # }
268
- # o = p.to_basicstruct
269
- # o.word #=> "Hello"
270
- #
271
- # NOTE The Proc must have an arity of one --no more and no less.
272
- def to_basicstruct
273
- raise ArgumentError, 'bad arity for converting Proc to basicstruct' if arity != 1
274
- o = BasicObject.new
275
- self.call( o )
276
- o
277
- end
278
- end
279
- =end
280
-
1
+ require 'hashery/basic_struct'
@@ -1 +1,171 @@
1
- require 'hashery/castinghash'
1
+ # CastingHash is just like Hash, except that all keys and values
2
+ # are passed through casting procedures.
3
+ #--
4
+ # TODO: Handle default_proc.
5
+ #++
6
+ class CastingHash < Hash
7
+
8
+ # Default key conversion procedure.
9
+ KEY_PROC = lambda{ |x| x } #.to_s }
10
+
11
+ # Default value conversion procedure.
12
+ VAL_PROC = lambda{ |x| x }
13
+
14
+ #
15
+ def self.[](hash)
16
+ s = new
17
+ hash.each{ |k,v| s[k] = v }
18
+ s
19
+ end
20
+
21
+ #
22
+ def initialize(hash={}, value_cast=nil, &key_cast)
23
+ @key_proc = (key_cast || KEY_PROC)
24
+ @value_proc = (value_cast || VAL_PROC).to_proc
25
+ hash.each{ |k,v| self[k] = v }
26
+ end
27
+
28
+ #
29
+ def key_proc
30
+ @key_proc
31
+ end
32
+
33
+ #
34
+ def key_proc=(proc)
35
+ @key_proc = proc.to_proc
36
+ end
37
+
38
+ #
39
+ def value_proc
40
+ @value_proc
41
+ end
42
+
43
+ #
44
+ def value_proc=(proc)
45
+ @value_proc = proc.to_proc
46
+ end
47
+
48
+ #
49
+ def [](k)
50
+ super(key_proc[k])
51
+ end
52
+
53
+ #
54
+ def []=(k,v)
55
+ super(key_proc[k], value_proc[v])
56
+ end
57
+
58
+ #
59
+ def <<(other)
60
+ case other
61
+ when Hash
62
+ super(cast(other))
63
+ when Array
64
+ self[other[0]] = other[1]
65
+ else
66
+ raise ArgumentError
67
+ end
68
+ end
69
+
70
+ def fetch(k)
71
+ super(key_proc[k])
72
+ end
73
+
74
+ #
75
+ def store(k, v)
76
+ super(key_proc[k], value_proc[v])
77
+ end
78
+
79
+ #
80
+ def key?(k)
81
+ super(key_proc[k])
82
+ end
83
+
84
+ #
85
+ def has_key?(k)
86
+ super(key_proc[k])
87
+ end
88
+
89
+ # Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
90
+ #
91
+ # foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
92
+ # foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
93
+ # foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
94
+ #
95
+ def rekey!(*args, &block)
96
+ # for backward comptability (DEPRECATE?).
97
+ block = args.pop.to_sym.to_proc if args.size == 1
98
+ if args.empty?
99
+ block = lambda{|k| k} unless block
100
+ keys.each do |k|
101
+ nk = block[k]
102
+ self[nk] = delete(k) #if nk
103
+ end
104
+ else
105
+ raise ArgumentError, "3 for 2" if block
106
+ to, from = *args
107
+ self[to] = delete(from) if has_key?(from)
108
+ end
109
+ self
110
+ end
111
+
112
+ #
113
+ def rekey(*args, &block)
114
+ dup.rekey!(*args, &block)
115
+ end
116
+
117
+ #
118
+ def delete(k)
119
+ super(key_proc[k])
120
+ end
121
+
122
+ #
123
+ def update(other)
124
+ super(cast(other))
125
+ end
126
+
127
+ # Same as #update.
128
+ def merge!(other)
129
+ super(cast(other))
130
+ end
131
+
132
+ #
133
+ def replace(other)
134
+ super(cast(other))
135
+ end
136
+
137
+ #
138
+ def values_at(*keys)
139
+ super(keys.map(&key_proc))
140
+ end
141
+
142
+ #
143
+ def to_hash
144
+ h = {}; each{ |k,v| h[k] = v }; h
145
+ end
146
+
147
+ #
148
+ alias_method :to_h, :to_hash
149
+
150
+ private
151
+
152
+ #
153
+ def cast(hash)
154
+ h
155
+ hash.each do |k,v|
156
+ h[key_proc[k]] = value_proc[v]
157
+ end
158
+ h
159
+ end
160
+
161
+ end
162
+
163
+
164
+ #class Hash
165
+ #
166
+ # # Convert a Hash to a CastingHash.
167
+ # def to_casting_hash(value_cast=nil, &key_cast)
168
+ # CastingHash.new(self, value_cast, &key_cast)
169
+ # end
170
+ #
171
+ #end