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,167 +1 @@
1
- # = OrderedHash
2
- #
3
- # A simple ordered hash implmentation, for users of
4
- # Ruby 1.8.7 or less.
5
- #
6
- # NOTE: As of Ruby 1.9+ this class is not needed, since
7
- # Ruby 1.9's standard Hash tracks inseration order.
8
- #
9
- # This implementation derives from the same class in
10
- # ActiveSupport library.
11
-
12
- class OrderedHash < ::Hash
13
- def to_yaml_type
14
- "!tag:yaml.org,2002:omap"
15
- end
16
-
17
- def to_yaml(opts = {})
18
- YAML.quick_emit(self, opts) do |out|
19
- out.seq(taguri, to_yaml_style) do |seq|
20
- each do |k, v|
21
- seq.add(k => v)
22
- end
23
- end
24
- end
25
- end
26
-
27
- # Hash is ordered in Ruby 1.9!
28
- if RUBY_VERSION < '1.9'
29
- def initialize(*args, &block)
30
- super
31
- @keys = []
32
- end
33
-
34
- def self.[](*args)
35
- ordered_hash = new
36
-
37
- if (args.length == 1 && args.first.is_a?(Array))
38
- args.first.each do |key_value_pair|
39
- next unless (key_value_pair.is_a?(Array))
40
- ordered_hash[key_value_pair[0]] = key_value_pair[1]
41
- end
42
-
43
- return ordered_hash
44
- end
45
-
46
- unless (args.size % 2 == 0)
47
- raise ArgumentError.new("odd number of arguments for Hash")
48
- end
49
-
50
- args.each_with_index do |val, ind|
51
- next if (ind % 2 != 0)
52
- ordered_hash[val] = args[ind + 1]
53
- end
54
-
55
- ordered_hash
56
- end
57
-
58
- def initialize_copy(other)
59
- super(other)
60
- @keys = other.keys
61
- end
62
-
63
- def []=(key, value)
64
- @keys << key unless key?(key)
65
- super(key, value)
66
- end
67
-
68
- def delete(key)
69
- if has_key? key
70
- index = @keys.index(key)
71
- @keys.delete_at(index)
72
- end
73
- super(key)
74
- end
75
-
76
- def delete_if
77
- super
78
- sync_keys!
79
- self
80
- end
81
-
82
- def reject!
83
- super
84
- sync_keys!
85
- self
86
- end
87
-
88
- def reject(&block)
89
- dup.reject!(&block)
90
- end
91
-
92
- def keys
93
- @keys.dup
94
- end
95
-
96
- def values
97
- @keys.collect{ |key| self[key] }
98
- end
99
-
100
- def to_hash
101
- self
102
- end
103
-
104
- def to_a
105
- @keys.map{ |key| [ key, self[key] ] }
106
- end
107
-
108
- def each_key
109
- @keys.each{ |key| yield(key) }
110
- end
111
-
112
- def each_value
113
- @keys.each{ |key| yield(self[key]) }
114
- end
115
-
116
- def each
117
- @keys.each{ |key| yield(key, self[key]) }
118
- end
119
-
120
- alias_method :each_pair, :each
121
-
122
- def clear
123
- super
124
- @keys.clear
125
- self
126
- end
127
-
128
- def shift
129
- k = @keys.first
130
- v = delete(k)
131
- [k, v]
132
- end
133
-
134
- def merge!(other_hash)
135
- other_hash.each{ |k,v| self[k] = v }
136
- self
137
- end
138
-
139
- def merge(other_hash)
140
- dup.merge!(other_hash)
141
- end
142
-
143
- # When replacing with another hash, the initial order of our
144
- # keys must come from the other hash, ordered or not.
145
- def replace(other)
146
- super
147
- @keys = other.keys
148
- self
149
- end
150
-
151
- def inspect
152
- "#<OrderedHash #{super}>"
153
- end
154
-
155
- private
156
- def sync_keys!
157
- @keys.delete_if{ |k| !key?(k) }
158
- end
159
- end
160
- end
161
-
162
- require 'yaml'
163
-
164
- YAML.add_builtin_type("omap") do |type, val|
165
- ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
166
- end
167
-
1
+ require 'hashery/ordered_hash'
@@ -1 +1,97 @@
1
- require 'hashery/propertyhash'
1
+ # A PropertyHash is the same as a regular Hash except it strictly limits the
2
+ # allowed keys.
3
+ #
4
+ # There are two ways to use it.
5
+ #
6
+ # 1) As an object in itself.
7
+ #
8
+ # h = PropertyHash.new(:a=>1, :b=>2)
9
+ # h[:a] #=> 1
10
+ # h[:a] = 3
11
+ # h[:a] #=> 3
12
+ #
13
+ # But if we try to set key that was not fixed, then we will get an error.
14
+ #
15
+ # h[:x] = 5 #=> ArgumentError
16
+ #
17
+ # 2) As a superclass.
18
+ #
19
+ # class MyPropertyHash < PropertyHash
20
+ # property :a, :default => 1
21
+ # property :b, :default => 2
22
+ # end
23
+ #
24
+ # h = MyPropertyHash.new
25
+ # h[:a] #=> 1
26
+ # h[:a] = 3
27
+ # h[:a] #=> 3
28
+ #
29
+ # Again, if we try to set key that was not fixed, then we will get an error.
30
+ #
31
+ # h[:x] = 5 #=> ArgumentError
32
+ #
33
+ class PropertyHash < Hash
34
+
35
+ #
36
+ def self.properties
37
+ @properties ||= (
38
+ parent = ancestors[1]
39
+ if parent.respond_to?(:properties)
40
+ parent.properties
41
+ else
42
+ {}
43
+ end
44
+ )
45
+ end
46
+
47
+ #
48
+ def self.property(key, opts={})
49
+ properties[key] = opts[:default]
50
+ end
51
+
52
+ #
53
+ def initialize(properties={})
54
+ super()
55
+ fixed = self.class.properties.merge(properties)
56
+ replace(fixed)
57
+ end
58
+
59
+ #
60
+ def []=(k,v)
61
+ assert_key!(k)
62
+ super(k,v)
63
+ end
64
+
65
+ #
66
+ def update(h)
67
+ h.keys.each{ |k| assert_key!(k) }
68
+ super(h)
69
+ end
70
+
71
+ #
72
+ def merge!(h)
73
+ h.keys.each{ |k| assert_key!(k) }
74
+ super(h)
75
+ end
76
+
77
+ #
78
+ def <<(a)
79
+ k,v = *a
80
+ self[k] = v
81
+ end
82
+
83
+ # Add a new acceptable key.
84
+ # TODO: Should this be supported?
85
+ def accept_key!(k,v=nil)
86
+ self[k] = v
87
+ end
88
+
89
+ private
90
+
91
+ def assert_key!(key)
92
+ unless key?(key)
93
+ raise ArgumentError, "The key '#{key}' is not defined for this FixedHash."
94
+ end
95
+ end
96
+
97
+ end
@@ -1,97 +1 @@
1
- # A PropertyHash is the same as a regular Hash except it strictly limits the
2
- # allowed keys.
3
- #
4
- # There are two ways to use it.
5
- #
6
- # 1) As an object in itself.
7
- #
8
- # h = PropertyHash.new(:a=>1, :b=>2)
9
- # h[:a] #=> 1
10
- # h[:a] = 3
11
- # h[:a] #=> 3
12
- #
13
- # But if we try to set key that was not fixed, then we will get an error.
14
- #
15
- # h[:x] = 5 #=> ArgumentError
16
- #
17
- # 2) As a superclass.
18
- #
19
- # class MyPropertyHash < PropertyHash
20
- # property :a, :default => 1
21
- # property :b, :default => 2
22
- # end
23
- #
24
- # h = MyPropertyHash.new
25
- # h[:a] #=> 1
26
- # h[:a] = 3
27
- # h[:a] #=> 3
28
- #
29
- # Again, if we try to set key that was not fixed, then we will get an error.
30
- #
31
- # h[:x] = 5 #=> ArgumentError
32
- #
33
- class PropertyHash < Hash
34
-
35
- #
36
- def self.properties
37
- @properties ||= (
38
- parent = ancestors[1]
39
- if parent.respond_to?(:properties)
40
- parent.properties
41
- else
42
- {}
43
- end
44
- )
45
- end
46
-
47
- #
48
- def self.property(key, opts={})
49
- properties[key] = opts[:default]
50
- end
51
-
52
- #
53
- def initialize(properties={})
54
- super()
55
- fixed = self.class.properties.merge(properties)
56
- replace(fixed)
57
- end
58
-
59
- #
60
- def []=(k,v)
61
- assert_key!(k)
62
- super(k,v)
63
- end
64
-
65
- #
66
- def update(h)
67
- h.keys.each{ |k| assert_key!(k) }
68
- super(h)
69
- end
70
-
71
- #
72
- def merge!(h)
73
- h.keys.each{ |k| assert_key!(k) }
74
- super(h)
75
- end
76
-
77
- #
78
- def <<(a)
79
- k,v = *a
80
- self[k] = v
81
- end
82
-
83
- # Add a new acceptable key.
84
- # TODO: Should this be supported?
85
- def accept_key!(k,v=nil)
86
- self[k] = v
87
- end
88
-
89
- private
90
-
91
- def assert_key!(key)
92
- unless key?(key)
93
- raise ArgumentError, "The key '#{key}' is not defined for this FixedHash."
94
- end
95
- end
96
-
97
- end
1
+ require 'hashery/property_hash'
@@ -1 +1,35 @@
1
- require 'hashery/queryhash'
1
+ # = QueryHash
2
+ #
3
+ # QueryHash is a similar to OpenHash. Like OpenHash,
4
+ # entries can be assigned via setter methods, but
5
+ # entries can only be looked up via query methods
6
+ # (i.e. methods ending in a ?-mark), hence the name
7
+ # of this class.
8
+ #
9
+ # A QueryHash is not quite as elegant as an OpenHash
10
+ # in that reader methods must end in ?-marks, but
11
+ # it remains fully compatible with Hash regardless
12
+ # of it's settings.
13
+
14
+ class QueryHash < Hash
15
+
16
+ def to_h
17
+ dup
18
+ end
19
+
20
+ def to_hash
21
+ dup
22
+ end
23
+
24
+ def method_missing(s,*a,&b)
25
+ case s.to_s
26
+ when /\=$/
27
+ self[s.to_s.chomp('=').to_sym] = a[0]
28
+ when /\?$/
29
+ self[s.to_s.chomp('?').to_sym]
30
+ else
31
+ super(s,*a,&b)
32
+ end
33
+ end
34
+
35
+ end
@@ -1,35 +1 @@
1
- # = QueryHash
2
- #
3
- # QueryHash is a similar to OpenHash. Like OpenHash,
4
- # entries can be assigned via setter methods, but
5
- # entries can only be looked up via query methods
6
- # (i.e. methods ending in a ?-mark), hence the name
7
- # of this class.
8
- #
9
- # A QueryHash is not quite as elegant as an OpenHash
10
- # in that reader methods must end in ?-marks, but
11
- # it remains fully compatible with Hash regardless
12
- # of it's settings.
13
-
14
- class QueryHash < Hash
15
-
16
- def to_h
17
- dup
18
- end
19
-
20
- def to_hash
21
- dup
22
- end
23
-
24
- def method_missing(s,*a,&b)
25
- case s.to_s
26
- when /\=$/
27
- self[s.to_s.chomp('=').to_sym] = a[0]
28
- when /\?$/
29
- self[s.to_s.chomp('?').to_sym]
30
- else
31
- super(s,*a,&b)
32
- end
33
- end
34
-
35
- end
1
+ require 'hashery/query_hash'
@@ -1,181 +1,10 @@
1
- # Stash is just like Hash, except that all keys are
2
- # converted to Strings.
3
- #
4
- # Note this doesn't yet handle default_proc.
1
+ require 'hashery/keyhash'
5
2
 
6
- class Stash < Hash
7
-
8
- #
9
- def self.[](*hash)
10
- s = new
11
- super(*hash).each{ |k,v| s[k] = v }
12
- s
13
- end
14
-
15
- #
16
- def [](key)
17
- super(convert_key(key))
18
- end
19
-
20
- #
21
- def []=(key,value)
22
- super(convert_key(key), value)
23
- end
24
-
25
- #
26
- def <<(other)
27
- case other
28
- when Hash
29
- super(other.rekey{ |key| convert_key(key) })
30
- when Array
31
- self[other[0]] = other[1]
32
- else
33
- raise ArgumentError
34
- end
35
- end
36
-
37
- #
38
- def fetch(key)
39
- super(convert_key(key))
40
- end
41
-
42
- #
43
- def store(key, value)
44
- super(convert_key(key), value)
45
- end
46
-
47
- #
48
- def key?(key)
49
- super(convert_key(key))
50
- end
51
-
52
- #
53
- def has_key?(key)
54
- super(convert_key(key))
55
- end
56
-
57
- #
58
- def include?(key)
59
- super(convert_key(key))
60
- end
61
-
62
- #
63
- def member?(key)
64
- super(convert_key(key))
65
- end
66
-
67
-
68
- # Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
69
- #
70
- # foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
71
- # foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
72
- # foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
73
- #
74
- def rekey!(*args, &block)
75
- # for backward comptability (TODO: DEPRECATE?).
76
- block = args.pop.to_sym.to_proc if args.size == 1
77
- if args.empty?
78
- block = lambda{|k| k} unless block
79
- keys.each do |k|
80
- nk = block[k]
81
- self[nk.to_s]=delete(k) #if nk
82
- end
83
- else
84
- raise ArgumentError, "3 for 2" if block
85
- to, from = *args
86
- self[to] = delete(from) if has_key?(from)
87
- end
88
- self
89
- end
90
-
91
- #
92
- def rekey(*args, &block)
93
- dup.rekey!(*args, &block)
94
- end
95
-
96
- #
97
- def delete(key)
98
- super(convert_key(key))
99
- end
100
-
101
- #
102
- def update(other)
103
- super(other.rekey{ |key| convert_key(key) })
104
- end
105
-
106
- # Same as #update.
107
- def merge!(other)
108
- super(other.rekey{ |key| convert_key(key) })
109
- end
110
-
111
- #
112
- def merge(other)
113
- super(other.rekey{ |key| convert_key(key) })
114
- end
115
-
116
- #
117
- def replace(other)
118
- super(other.rekey{ |key| convert_key(key) })
119
- end
120
-
121
- #
122
- def values_at(*keys)
123
- super(*keys.map{ |key| convert_key(key) })
124
- end
125
-
126
- #
127
- def to_hash
128
- h = {}
129
- each{ |k,v| h[k] = v }
130
- h
131
- end
132
-
133
- alias_method :to_h, :to_hash
134
-
135
- private
136
-
137
- def convert_key(key)
138
- key.to_s
139
- end
140
-
141
- end
3
+ Stash = KeyHash
142
4
 
143
5
  class Hash
144
-
145
- # Convert a Hash to a Stash object.
6
+ # Convert Hash to Stash.
146
7
  def to_stash
147
8
  Stash[self]
148
9
  end
149
-
150
- # Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
151
- #
152
- # foo = { :name=>'Gavin', :wife=>:Lisa }
153
- # foo.rekey!{ |k| k.to_s } #=> { "name"=>"Gavin", "wife"=>:Lisa }
154
- # foo.inspect #=> { "name"=>"Gavin", "wife"=>:Lisa }
155
- #
156
- # This method comes from Ruby Facets.
157
-
158
- def rekey!(*args, &block)
159
- # for backward comptability (TODO: DEPRECATE).
160
- block = args.pop.to_sym.to_proc if args.size == 1
161
- if args.empty?
162
- block = lambda{|k| k.to_sym} unless block
163
- keys.each do |k|
164
- nk = block[k]
165
- self[nk]=delete(k) if nk
166
- end
167
- else
168
- raise ArgumentError, "3 for 2" if block
169
- to, from = *args
170
- self[to] = self.delete(from) if self.has_key?(from)
171
- end
172
- self
173
- end
174
-
175
- # Non-inplace #rekey! method.
176
- def rekey(*args, &block)
177
- dup.rekey!(*args, &block)
178
- end
179
-
180
10
  end
181
-