hashery 1.5.0 → 2.0.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.
- data/.ruby +30 -17
- data/.yardopts +1 -0
- data/Config.rb +28 -0
- data/{QED.rdoc → DEMO.rdoc} +0 -0
- data/HISTORY.rdoc +37 -0
- data/LICENSE.txt +26 -0
- data/NOTICE.txt +46 -0
- data/README.rdoc +10 -7
- data/lib/hashery.rb +6 -6
- data/lib/hashery.yml +30 -17
- data/lib/hashery/association.rb +169 -109
- data/lib/hashery/casting_hash.rb +128 -135
- data/lib/hashery/core_ext.rb +89 -61
- data/lib/hashery/crud_hash.rb +365 -0
- data/lib/hashery/dictionary.rb +545 -345
- data/lib/hashery/fuzzy_hash.rb +177 -125
- data/lib/hashery/ini_hash.rb +321 -0
- data/lib/hashery/key_hash.rb +54 -179
- data/lib/hashery/linked_list.rb +245 -191
- data/lib/hashery/lru_hash.rb +292 -202
- data/lib/hashery/open_cascade.rb +133 -78
- data/lib/hashery/open_hash.rb +127 -61
- data/lib/hashery/ordered_hash.rb +128 -122
- data/lib/hashery/path_hash.rb +238 -0
- data/lib/hashery/property_hash.rb +144 -80
- data/lib/hashery/query_hash.rb +85 -29
- data/lib/hashery/stash.rb +7 -3
- data/lib/hashery/static_hash.rb +46 -41
- data/test/case_association.rb +65 -4
- data/test/case_dictionary.rb +149 -5
- data/test/{case_keyhash.rb → case_key_hash.rb} +20 -14
- data/test/case_lru_hash.rb +162 -0
- data/test/{case_opencascade.rb → case_open_cascade.rb} +4 -8
- data/test/case_open_hash.rb +87 -0
- data/test/case_query_hash.rb +226 -0
- data/test/helper.rb +8 -0
- metadata +33 -63
- data/COPYING.rdoc +0 -45
- data/lib/hashery/basic_object.rb +0 -74
- data/lib/hashery/basic_struct.rb +0 -288
- data/lib/hashery/basicobject.rb +0 -1
- data/lib/hashery/basicstruct.rb +0 -1
- data/lib/hashery/castinghash.rb +0 -1
- data/lib/hashery/fuzzyhash.rb +0 -1
- data/lib/hashery/ini.rb +0 -268
- data/lib/hashery/keyhash.rb +0 -1
- data/lib/hashery/linkedlist.rb +0 -1
- data/lib/hashery/lruhash.rb +0 -1
- data/lib/hashery/memoizer.rb +0 -64
- data/lib/hashery/open_object.rb +0 -1
- data/lib/hashery/opencascade.rb +0 -1
- data/lib/hashery/openhash.rb +0 -1
- data/lib/hashery/openobject.rb +0 -1
- data/lib/hashery/orderedhash.rb +0 -1
- data/lib/hashery/ostructable.rb +0 -186
- data/lib/hashery/propertyhash.rb +0 -1
- data/lib/hashery/queryhash.rb +0 -1
- data/lib/hashery/statichash.rb +0 -1
- data/qed/01_openhash.rdoc +0 -57
- data/qed/02_queryhash.rdoc +0 -21
- data/qed/03_castinghash.rdoc +0 -13
- data/qed/04_statichash.rdoc +0 -22
- data/qed/05_association.rdoc +0 -59
- data/qed/06_opencascade.rdoc +0 -58
- data/qed/07_fuzzyhash.rdoc +0 -141
- data/qed/08_properyhash.rdoc +0 -38
- data/qed/09_ostructable.rdoc +0 -56
- data/qed/applique/ae.rb +0 -1
- data/test/case_basicstruct.rb +0 -192
- data/test/case_openhash.rb +0 -22
data/lib/hashery/casting_hash.rb
CHANGED
@@ -1,165 +1,158 @@
|
|
1
|
-
|
2
|
-
# are passed through casting procedures.
|
3
|
-
#--
|
4
|
-
# TODO: Handle default_proc.
|
5
|
-
#++
|
6
|
-
class CastingHash < Hash
|
1
|
+
require 'hashery/crud_hash'
|
7
2
|
|
8
|
-
|
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
|
3
|
+
module Hashery
|
27
4
|
|
5
|
+
# CastingHash is just like CRUDHash, except that both keys and values
|
6
|
+
# can be passed through casting procedures.
|
28
7
|
#
|
29
|
-
|
30
|
-
@key_proc
|
31
|
-
end
|
8
|
+
class CastingHash < CRUDHash
|
32
9
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
10
|
+
#
|
11
|
+
# Like `#new` but can take a priming Hash or Array-pairs.
|
12
|
+
#
|
13
|
+
# hash - Hash-like object.
|
14
|
+
#
|
15
|
+
# Examples
|
16
|
+
#
|
17
|
+
# CastingHash[:a,1,:b,2]
|
18
|
+
#
|
19
|
+
# Returns `CastingHash`.
|
20
|
+
#
|
21
|
+
def self.[](hash)
|
22
|
+
s = new
|
23
|
+
hash.each{ |k,v| s[k] = v }
|
24
|
+
s
|
25
|
+
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
#
|
28
|
+
# Unlike traditional Hash a CastingHash's block argument
|
29
|
+
# coerces key/value pairs when #store is called.
|
30
|
+
#
|
31
|
+
# default - Default value.
|
32
|
+
# cast_proc - Casting procedure.
|
33
|
+
#
|
34
|
+
def initialize(default=nil, &cast_proc)
|
35
|
+
@cast_proc = cast_proc
|
36
|
+
super(default, &nil)
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
#
|
40
|
+
# The cast procedure.
|
41
|
+
#
|
42
|
+
# proc - Casting procedure.
|
43
|
+
#
|
44
|
+
# Returns `Proc` used for casting.
|
45
|
+
#
|
46
|
+
def cast_proc(&proc)
|
47
|
+
@cast_proc = proc if proc
|
48
|
+
@cast_proc
|
49
|
+
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
#
|
52
|
+
# Set `cast_proc`. This procedure must take two arguments (`key, value`)
|
53
|
+
# and return the same.
|
54
|
+
#
|
55
|
+
# proc - Casting procedure.
|
56
|
+
#
|
57
|
+
# Returns +proc+.
|
58
|
+
#
|
59
|
+
def cast_proc=(proc)
|
60
|
+
raise ArgumentError unless Proc === proc or NilClass === proc
|
61
|
+
@cast_proc = proc
|
62
|
+
end
|
52
63
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
64
|
+
#
|
65
|
+
# CRUD method for create and update. Unlike the parent class
|
66
|
+
# the key, value pair are passed threw the cast_proc before
|
67
|
+
# being set in the underlying hash table.
|
68
|
+
#
|
69
|
+
# key - Key of entry.
|
70
|
+
# value - Value of entry.
|
71
|
+
#
|
72
|
+
# Returns the +value+.
|
73
|
+
#
|
74
|
+
def store(key, value)
|
75
|
+
super(*cast_pair(key, value))
|
76
|
+
end
|
57
77
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
78
|
+
#
|
79
|
+
# Replace current entries with those from another Hash,
|
80
|
+
# or Hash-like object. Each entry is run through the
|
81
|
+
# casting procedure as it is added.
|
82
|
+
#
|
83
|
+
# other - Hash-like object.
|
84
|
+
#
|
85
|
+
# Returns +self+.
|
86
|
+
#
|
87
|
+
def replace(other)
|
88
|
+
super cast(other)
|
67
89
|
end
|
68
|
-
end
|
69
90
|
|
70
|
-
|
71
|
-
|
72
|
-
|
91
|
+
#
|
92
|
+
# Convert the CastingHash to a regular Hash.
|
93
|
+
#
|
94
|
+
# Returns an ordinary `Hash`.
|
95
|
+
#
|
96
|
+
def to_hash
|
97
|
+
h = {}; each{ |k,v| h[k] = v }; h
|
98
|
+
end
|
73
99
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
100
|
+
#
|
101
|
+
# Returns an ordinary `Hash`.
|
102
|
+
#
|
103
|
+
alias_method :to_h, :to_hash
|
78
104
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
105
|
+
#
|
106
|
+
# Recast all entries via the cast procedure.
|
107
|
+
#
|
108
|
+
# TODO: Isn't this the same as `#rehash`?
|
109
|
+
#
|
110
|
+
# Returns +self+.
|
111
|
+
#
|
112
|
+
def recast!
|
113
|
+
replace self
|
114
|
+
end
|
83
115
|
|
84
|
-
|
85
|
-
def has_key?(k)
|
86
|
-
super(key_proc[k])
|
87
|
-
end
|
116
|
+
private
|
88
117
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
118
|
+
#
|
119
|
+
# If `cast_proc` is defined then use it to process key-value pair,
|
120
|
+
# otherwise return them as is.
|
121
|
+
#
|
122
|
+
# key - Key of entry.
|
123
|
+
# value - Value of entry.
|
124
|
+
#
|
125
|
+
# Returns `Array` of key-value pair.
|
126
|
+
#
|
127
|
+
def cast_pair(key, value)
|
128
|
+
if cast_proc
|
129
|
+
return cast_proc.call(key, value)
|
130
|
+
else
|
131
|
+
return key, value
|
103
132
|
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
133
|
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
134
|
|
135
|
+
#
|
136
|
+
# Cast a given +hash+ according to the `#key_proc` and `#value_proc`.
|
137
|
+
#
|
138
|
+
# hash - A `Hash` or anything the responds to `#each` like a hash.
|
139
|
+
#
|
140
|
+
# Returns a recasted `Hash`.
|
152
141
|
#
|
153
142
|
def cast(hash)
|
154
|
-
h
|
143
|
+
h = {}
|
155
144
|
hash.each do |k,v|
|
156
|
-
|
145
|
+
k, v = cast_pair(k, v)
|
146
|
+
h[k] = v
|
157
147
|
end
|
158
148
|
h
|
159
149
|
end
|
160
150
|
|
151
|
+
end
|
152
|
+
|
161
153
|
end
|
162
154
|
|
155
|
+
# TODO: Should we add #to_casting_hash to Hash classs?
|
163
156
|
|
164
157
|
#class Hash
|
165
158
|
#
|
data/lib/hashery/core_ext.rb
CHANGED
@@ -1,82 +1,110 @@
|
|
1
|
-
|
1
|
+
class Hash
|
2
2
|
|
3
|
-
# This module is included into Ruby's core Hash class.
|
4
3
|
#
|
5
|
-
#
|
6
|
-
|
4
|
+
# Create a hash given an `initial_hash`.
|
5
|
+
#
|
6
|
+
# initial_hash - Hash or hash-like object to use as priming data.
|
7
|
+
# block - Procedure used by initialize (e.g. default_proc).
|
8
|
+
#
|
9
|
+
# Returns a `Hash`.
|
10
|
+
#
|
11
|
+
def self.create(initial_hash={}, &block)
|
12
|
+
o = new &block
|
13
|
+
o.update(initial_hash)
|
14
|
+
o
|
15
|
+
end
|
7
16
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
17
|
+
#
|
18
|
+
# Alias for `#[]`.
|
19
|
+
#
|
20
|
+
alias :read :[]
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
22
|
+
#
|
23
|
+
# Convert to Hash.
|
24
|
+
#
|
25
|
+
def to_hash
|
26
|
+
dup # -or- `h = {}; each{ |k,v| h[k] = v }; h` ?
|
27
|
+
end
|
17
28
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
29
|
+
#
|
30
|
+
# For a Hash, `#to_h` is the same as `#to_hash`.
|
31
|
+
#
|
32
|
+
alias :to_h :to_hash
|
33
|
+
|
34
|
+
#
|
35
|
+
# Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
|
36
|
+
#
|
37
|
+
# key_map - Hash of old key to new key.
|
38
|
+
# block - Procedure to convert keys, which can take just the key
|
39
|
+
# or both key and value as arguments.
|
40
|
+
#
|
41
|
+
# Examples
|
42
|
+
#
|
43
|
+
# foo = { :name=>'Gavin', :wife=>:Lisa }
|
44
|
+
# foo.rekey!{ |k| k.to_s } #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
45
|
+
# foo.inspect #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
46
|
+
#
|
47
|
+
# Returns `Hash`.
|
48
|
+
#
|
49
|
+
def rekey(key_map=nil, &block)
|
50
|
+
if !(key_map or block)
|
51
|
+
block = lambda{|k| k.to_sym}
|
52
|
+
end
|
28
53
|
|
29
|
-
|
54
|
+
key_map ||= {}
|
30
55
|
|
31
|
-
|
56
|
+
hash = {}
|
32
57
|
|
33
|
-
|
34
|
-
|
35
|
-
|
58
|
+
(keys - key_map.keys).each do |key|
|
59
|
+
hash[key] = self[key]
|
60
|
+
end
|
36
61
|
|
37
|
-
|
38
|
-
|
39
|
-
|
62
|
+
key_map.each do |from, to|
|
63
|
+
hash[to] = self[from] if key?(from)
|
64
|
+
end
|
40
65
|
|
41
|
-
|
66
|
+
hash2 = {}
|
42
67
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
hash.each do |k, v|
|
52
|
-
nk = block[k,v]
|
53
|
-
#nk = (NA == nk ? k : nk) # TODO:
|
54
|
-
hash2[nk] = v
|
55
|
-
end
|
68
|
+
if block
|
69
|
+
case block.arity
|
70
|
+
when 0
|
71
|
+
raise ArgumentError, "arity of 0 for #{block.inspect}"
|
72
|
+
when 2
|
73
|
+
hash.each do |k,v|
|
74
|
+
nk = block.call(k,v)
|
75
|
+
hash2[nk] = v
|
56
76
|
end
|
57
77
|
else
|
58
|
-
|
78
|
+
hash.each do |k,v|
|
79
|
+
nk = block[k]
|
80
|
+
hash2[nk] = v
|
81
|
+
end
|
59
82
|
end
|
60
|
-
|
61
|
-
hash2
|
83
|
+
else
|
84
|
+
hash2 = hash
|
62
85
|
end
|
63
86
|
|
64
|
-
|
65
|
-
|
66
|
-
# foo = { :name=>'Gavin', :wife=>:Lisa }
|
67
|
-
# foo.rekey!{ |k| k.to_s } #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
68
|
-
# foo #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
69
|
-
#
|
70
|
-
# CREDIT: Trans, Gavin Kistner
|
71
|
-
|
72
|
-
def rekey!(key_map=nil, &block)
|
73
|
-
replace(rekey(key_map, &block))
|
74
|
-
end
|
87
|
+
hash2
|
88
|
+
end
|
75
89
|
|
90
|
+
#
|
91
|
+
# Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
|
92
|
+
#
|
93
|
+
# key_map - Hash of old key to new key.
|
94
|
+
# block - Procedure to convert keys, which can take just the key
|
95
|
+
# or both key and value as arguments.
|
96
|
+
#
|
97
|
+
# Examples
|
98
|
+
#
|
99
|
+
# foo = { :name=>'Gavin', :wife=>:Lisa }
|
100
|
+
# foo.rekey!{ |k| k.to_s } #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
101
|
+
# foo #=> { "name"=>"Gavin", "wife"=>:Lisa }
|
102
|
+
#
|
103
|
+
# Returns `Hash`.
|
104
|
+
#
|
105
|
+
def rekey!(key_map=nil, &block)
|
106
|
+
replace(rekey(key_map, &block))
|
76
107
|
end
|
77
108
|
|
78
109
|
end
|
79
110
|
|
80
|
-
class Hash #:nodoc:
|
81
|
-
include Hashery::CoreExt
|
82
|
-
end
|