hashery 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -41,10 +41,11 @@
41
41
  #
42
42
  # === Example object
43
43
  #
44
- # A Ini#comment stores:
44
+ # Ini#comment stores:
45
+ #
45
46
  # "this is the first comment which will be saved in the comment attribute"
46
47
  #
47
- # A Ini object stores:
48
+ # Ini's internal hash stores:
48
49
  #
49
50
  # {
50
51
  # "mail" => "info@example.com",
@@ -0,0 +1,186 @@
1
+ require 'hashery/core_ext'
2
+
3
+ # The KeyHash class is a Hash compatible class which converts
4
+ # all keys to strings. This has two advantages. First it
5
+ # means hash entries have indifferent access. <tt>1</tt>,
6
+ # <tt>"1"</tt> and <tt>:1</tt> are all equivalent. Any object
7
+ # that defines <tt>#to_s</tt> can be used as a key. Secondly,
8
+ # since strings are garbage collected so are KeyHash objects.
9
+ #
10
+ # The KeyHash class works like a normal Hash. But notice the
11
+ # significant distinction of indifferent key access.
12
+ #
13
+ # s = KeyHash.new
14
+ # s[:x] = 1
15
+ # s[:x] #=> 1
16
+ # s['x'] #=> 1
17
+ #
18
+ # We can see that internally the key has indeed been converted
19
+ # to a String.
20
+ #
21
+ # s.to_h #=> {'x'=>1 }
22
+ #
23
+ # Becuase of the way in which KeyHash is designed, it has a nice
24
+ # secondary usage. KeyHash defines a private method called
25
+ # #convert_key. This method handles the conversion of the key
26
+ # whenever the underlying hash is altered. If you have need
27
+ # for a different kind of Hash, one the has a special restraint
28
+ # on the key, it is easy enough to subclass KeyHash and override
29
+ # the is method. Eg.
30
+ #
31
+ # class Upash < KeyHash
32
+ # def convert_key(key)
33
+ # key.to_s.upcase
34
+ # end
35
+ # end
36
+ #
37
+ # u = Upash.new
38
+ # u.replace(:a=>1, :b=>2)
39
+ # u.to_h #=> { 'A'=>1, 'B'=>2 }
40
+ #
41
+ #
42
+ # NOTE: KeyHash does not yet handle default_proc.
43
+
44
+ class KeyHash < Hash
45
+
46
+ #
47
+ def self.[](*hash)
48
+ s = new
49
+ super(*hash).each{ |k,v| s[k] = v }
50
+ s
51
+ end
52
+
53
+ #
54
+ def [](key)
55
+ super(convert_key(key))
56
+ end
57
+
58
+ #
59
+ def []=(key,value)
60
+ super(convert_key(key), value)
61
+ end
62
+
63
+ #
64
+ def <<(other)
65
+ case other
66
+ when Hash
67
+ super(other.rekey{ |key| convert_key(key) })
68
+ when Array
69
+ self[other[0]] = other[1]
70
+ else
71
+ raise ArgumentError
72
+ end
73
+ end
74
+
75
+ #
76
+ def fetch(key)
77
+ super(convert_key(key))
78
+ end
79
+
80
+ #
81
+ def store(key, value)
82
+ super(convert_key(key), value)
83
+ end
84
+
85
+ #
86
+ def key?(key)
87
+ super(convert_key(key))
88
+ end
89
+
90
+ #
91
+ def has_key?(key)
92
+ super(convert_key(key))
93
+ end
94
+
95
+ #
96
+ def include?(key)
97
+ super(convert_key(key))
98
+ end
99
+
100
+ #
101
+ def member?(key)
102
+ super(convert_key(key))
103
+ end
104
+
105
+ # Synonym for #rekey, but modifies the receiver in place (and returns it).
106
+ #
107
+ # foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
108
+ # foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
109
+ # foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
110
+ #
111
+ def rekey!(*args, &block)
112
+ # for backward comptability (TODO: DEPRECATE?).
113
+ block = args.pop.to_sym.to_proc if args.size == 1
114
+ if args.empty?
115
+ block = lambda{|k| k} unless block
116
+ keys.each do |k|
117
+ nk = block[k]
118
+ self[nk.to_s]=delete(k) #if nk
119
+ end
120
+ else
121
+ raise ArgumentError, "3 for 2" if block
122
+ to, from = *args
123
+ self[to] = delete(from) if has_key?(from)
124
+ end
125
+ self
126
+ end
127
+
128
+ #
129
+ def rekey(*args, &block)
130
+ dup.rekey!(*args, &block)
131
+ end
132
+
133
+ #
134
+ def delete(key)
135
+ super(convert_key(key))
136
+ end
137
+
138
+ #
139
+ def update(other)
140
+ super(other.rekey{ |key| convert_key(key) })
141
+ end
142
+
143
+ # Same as #update.
144
+ def merge!(other)
145
+ super(other.rekey{ |key| convert_key(key) })
146
+ end
147
+
148
+ #
149
+ def merge(other)
150
+ super(other.rekey{ |key| convert_key(key) })
151
+ end
152
+
153
+ #
154
+ def replace(other)
155
+ super(other.rekey{ |key| convert_key(key) })
156
+ end
157
+
158
+ #
159
+ def values_at(*keys)
160
+ super(*keys.map{ |key| convert_key(key) })
161
+ end
162
+
163
+ #
164
+ def to_hash
165
+ h = {}
166
+ each{ |k,v| h[k] = v }
167
+ h
168
+ end
169
+
170
+ alias_method :to_h, :to_hash
171
+
172
+ private
173
+
174
+ def convert_key(key)
175
+ key.to_s
176
+ end
177
+
178
+ end
179
+
180
+ class Hash
181
+ # Convert a Hash to a KeyHash object.
182
+ def to_keyhash
183
+ KeyHash[self]
184
+ end
185
+ end
186
+
@@ -0,0 +1 @@
1
+ require 'hashery/key_hash'
@@ -1 +1,195 @@
1
- require 'hashery/linkedlist'
1
+ # LinkedList
2
+ #
3
+ # Copyright (C) 2006 Kirk Haines <khaines@enigo.com>.
4
+ #
5
+ # General Public License (GPL)
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'enumerator'
27
+
28
+ # LinkedList implements a simple doubly linked list with efficient
29
+ # hash-like element access.
30
+ #
31
+ # This is a simple linked list implementation with efficient random
32
+ # access of data elements. It was inspired by George Moscovitis'
33
+ # LRUCache implementation found in Facets 1.7.30, but unlike the
34
+ # linked list in that cache, this one does not require the use of a
35
+ # mixin on any class to be stored. The linked list provides the
36
+ # push, pop, shift, unshift, first, last, delete and length methods
37
+ # which work just like their namesakes in the Array class, but it
38
+ # also supports setting and retrieving values by key, just like a
39
+ # hash.
40
+ #
41
+ # LinkedList was ported from the original in Kirk Hanes IOWA web framework.
42
+ #
43
+ class LinkedList
44
+
45
+ include Enumerable
46
+
47
+ # Represents a single node of the linked list.
48
+
49
+ class Node
50
+ attr_accessor :key, :value, :prev_node, :next_node
51
+
52
+ def initialize(key=nil,value=nil,prev_node=nil,next_node=nil)
53
+ @key = key
54
+ @value = value
55
+ @prev_node = prev_node
56
+ @next_node = next_node
57
+ end
58
+ end
59
+
60
+ def initialize
61
+ @head = Node.new
62
+ @tail = Node.new
63
+ @lookup = Hash.new
64
+ node_join(@head,@tail)
65
+ end
66
+
67
+ def [](v)
68
+ @lookup[v].value
69
+ end
70
+
71
+ def []=(k,v)
72
+ if @lookup.has_key?(k)
73
+ @lookup[k].value = v
74
+ else
75
+ n = Node.new(k,v,@head,@head.next_node)
76
+ node_join(n,@head.next_node)
77
+ node_join(@head,n)
78
+ @lookup[k] = n
79
+ end
80
+ v
81
+ end
82
+
83
+ def empty?
84
+ @lookup.empty?
85
+ end
86
+
87
+ def delete(k)
88
+ n = @lookup.delete(k)
89
+ v = n ? node_purge(n) : nil
90
+ v
91
+ end
92
+
93
+ def first
94
+ @head.next_node.value
95
+ end
96
+
97
+ def last
98
+ @tail.prev_node.value
99
+ end
100
+
101
+ def shift
102
+ k = @head.next_node.key
103
+ n = @lookup.delete(k)
104
+ node_delete(n) if n
105
+ end
106
+
107
+ def unshift(v)
108
+ if @lookup.has_key?(v)
109
+ n = @lookup[v]
110
+ node_delete(n)
111
+ node_join(n,@head.next_node)
112
+ node_join(@head,n)
113
+ else
114
+ n = Node.new(v,v,@head,@head.next_node)
115
+ node_join(n,@head.next_node)
116
+ node_join(@head,n)
117
+ @lookup[v] = n
118
+ end
119
+ v
120
+ end
121
+
122
+ def pop
123
+ k = @tail.prev_node.key
124
+ n = @lookup.delete(k)
125
+ node_delete(n) if n
126
+ end
127
+
128
+ def push(v)
129
+ if @lookup.has_key?(v)
130
+ n = @lookup[v]
131
+ node_delete(n)
132
+ node_join(@tail.prev_node,n)
133
+ node_join(n,@tail)
134
+ else
135
+ n = Node.new(v,v,@tail.prev_node,@tail)
136
+ node_join(@tail.prev_node,n)
137
+ node_join(n,@tail)
138
+ @lookup[v] = n
139
+ end
140
+ v
141
+ end
142
+
143
+ def queue
144
+ r = []
145
+ n = @head
146
+ while (n = n.next_node) and n != @tail
147
+ r << n.key
148
+ end
149
+ r
150
+ end
151
+
152
+ def to_a
153
+ r = []
154
+ n = @head
155
+ while (n = n.next_node) and n != @tail
156
+ r << n.value
157
+ end
158
+ r
159
+ end
160
+
161
+ def length
162
+ @lookup.length
163
+ end
164
+
165
+ def each
166
+ n = @head
167
+ while (n = n.next_node) and n != @tail
168
+ yield(n.key,n.value)
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def node_delete(n)
175
+ node_join(n.prev_node,n.next_node)
176
+ v = n.value
177
+ end
178
+
179
+ def node_purge(n)
180
+ node_join(n.prev_node,n.next_node)
181
+ v = n.value
182
+ n.value = nil
183
+ n.key = nil
184
+ n.next_node = nil
185
+ n.prev_node = nil
186
+ v
187
+ end
188
+
189
+ def node_join(a,b)
190
+ a.next_node = b
191
+ b.prev_node = a
192
+ end
193
+
194
+ end
195
+
@@ -1,195 +1 @@
1
- # LinkedList
2
- #
3
- # Copyright (C) 2006 Kirk Haines <khaines@enigo.com>.
4
- #
5
- # General Public License (GPL)
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining
8
- # a copy of this software and associated documentation files (the
9
- # "Software"), to deal in the Software without restriction, including
10
- # without limitation the rights to use, copy, modify, merge, publish,
11
- # distribute, sublicense, and/or sell copies of the Software, and to
12
- # permit persons to whom the Software is furnished to do so, subject to
13
- # the following conditions:
14
- #
15
- # The above copyright notice and this permission notice shall be
16
- # included in all copies or substantial portions of the Software.
17
- #
18
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
-
26
- require 'enumerator'
27
-
28
- # LinkedList implements a simple doubly linked list with efficient
29
- # hash-like element access.
30
- #
31
- # This is a simple linked list implementation with efficient random
32
- # access of data elements. It was inspired by George Moscovitis'
33
- # LRUCache implementation found in Facets 1.7.30, but unlike the
34
- # linked list in that cache, this one does not require the use of a
35
- # mixin on any class to be stored. The linked list provides the
36
- # push, pop, shift, unshift, first, last, delete and length methods
37
- # which work just like their namesakes in the Array class, but it
38
- # also supports setting and retrieving values by key, just like a
39
- # hash.
40
- #
41
- # LinkedList was ported from the original in Kirk Hanes IOWA web framework.
42
- #
43
- class LinkedList
44
-
45
- include Enumerable
46
-
47
- # Represents a single node of the linked list.
48
-
49
- class Node
50
- attr_accessor :key, :value, :prev_node, :next_node
51
-
52
- def initialize(key=nil,value=nil,prev_node=nil,next_node=nil)
53
- @key = key
54
- @value = value
55
- @prev_node = prev_node
56
- @next_node = next_node
57
- end
58
- end
59
-
60
- def initialize
61
- @head = Node.new
62
- @tail = Node.new
63
- @lookup = Hash.new
64
- node_join(@head,@tail)
65
- end
66
-
67
- def [](v)
68
- @lookup[v].value
69
- end
70
-
71
- def []=(k,v)
72
- if @lookup.has_key?(k)
73
- @lookup[k].value = v
74
- else
75
- n = Node.new(k,v,@head,@head.next_node)
76
- node_join(n,@head.next_node)
77
- node_join(@head,n)
78
- @lookup[k] = n
79
- end
80
- v
81
- end
82
-
83
- def empty?
84
- @lookup.empty?
85
- end
86
-
87
- def delete(k)
88
- n = @lookup.delete(k)
89
- v = n ? node_purge(n) : nil
90
- v
91
- end
92
-
93
- def first
94
- @head.next_node.value
95
- end
96
-
97
- def last
98
- @tail.prev_node.value
99
- end
100
-
101
- def shift
102
- k = @head.next_node.key
103
- n = @lookup.delete(k)
104
- node_delete(n) if n
105
- end
106
-
107
- def unshift(v)
108
- if @lookup.has_key?(v)
109
- n = @lookup[v]
110
- node_delete(n)
111
- node_join(n,@head.next_node)
112
- node_join(@head,n)
113
- else
114
- n = Node.new(v,v,@head,@head.next_node)
115
- node_join(n,@head.next_node)
116
- node_join(@head,n)
117
- @lookup[v] = n
118
- end
119
- v
120
- end
121
-
122
- def pop
123
- k = @tail.prev_node.key
124
- n = @lookup.delete(k)
125
- node_delete(n) if n
126
- end
127
-
128
- def push(v)
129
- if @lookup.has_key?(v)
130
- n = @lookup[v]
131
- node_delete(n)
132
- node_join(@tail.prev_node,n)
133
- node_join(n,@tail)
134
- else
135
- n = Node.new(v,v,@tail.prev_node,@tail)
136
- node_join(@tail.prev_node,n)
137
- node_join(n,@tail)
138
- @lookup[v] = n
139
- end
140
- v
141
- end
142
-
143
- def queue
144
- r = []
145
- n = @head
146
- while (n = n.next_node) and n != @tail
147
- r << n.key
148
- end
149
- r
150
- end
151
-
152
- def to_a
153
- r = []
154
- n = @head
155
- while (n = n.next_node) and n != @tail
156
- r << n.value
157
- end
158
- r
159
- end
160
-
161
- def length
162
- @lookup.length
163
- end
164
-
165
- def each
166
- n = @head
167
- while (n = n.next_node) and n != @tail
168
- yield(n.key,n.value)
169
- end
170
- end
171
-
172
- private
173
-
174
- def node_delete(n)
175
- node_join(n.prev_node,n.next_node)
176
- v = n.value
177
- end
178
-
179
- def node_purge(n)
180
- node_join(n.prev_node,n.next_node)
181
- v = n.value
182
- n.value = nil
183
- n.key = nil
184
- n.next_node = nil
185
- n.prev_node = nil
186
- v
187
- end
188
-
189
- def node_join(a,b)
190
- a.next_node = b
191
- b.prev_node = a
192
- end
193
-
194
- end
195
-
1
+ require 'hashery/linked_list'