motion-map 0.0.1 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjcyN2I4NjUxNDc2NWI0Y2VlNGYxYWIwMGNkYzljY2I5MTMxMjZhNw==
4
+ Y2EwY2E2M2Q3NzJlYWVhMjA4ODY3ZmE1ZTJmNmRlZTE1MTY5M2ExYQ==
5
5
  data.tar.gz: !binary |-
6
- NDJlNTgxODg4ZDRlNzI1YzQxNjRlNmRmYzUwOGNmMDZlODJkZjUyMg==
6
+ YjBmZWFmYmVhMGJjZWMwNjdmZjdjMzBiZDkxMTRjMzE1ZjYxNjZlMQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YTEyMmM1MGU2N2NmYzUzNjUxNDJlZjE3ODEyOWMxNTc4NWIyNzMzZWFjNzJi
10
- NzZiYWE3MzY4YTU4YzVkYjkxYWViODFlNjM0ZGI2Yjk5YjA4YTliN2EwMDFh
11
- NjEzYjQwMjdjZTIwZmE0NDhhOTM3OWExZGJmOTIzNWY1MzhjNzE=
9
+ MDkyMjJlMTQ2MzdhNjlhZWUzMGYwNGJjMDgwOTQ0ZTZlZWU0NmFkZDMyOTVi
10
+ OGQyYTkxYmJkN2E4NDM0OTU0NDkwYWI3ZGJiYTRlMGRhNDM5Y2NhZDdlZmQ1
11
+ OWYyZjZhOWFmOGNlNTM1MDQwMDU3NzQxMjQyZWY1M2QyMTFlYzI=
12
12
  data.tar.gz: !binary |-
13
- NGYzOGZlMTQ1NDdiMmQwOTY0NzRhYTYwM2M1N2NkZTk2ZjFhNzVmZjM1ZjNk
14
- ZTVhYjNiMDZiMDQzYjk4Y2Q5ODk5MGE0ZTRhNzQzNWU4NTVhNWIzYmZlOGIy
15
- MjJiMmQwM2NlMDkzZDY2NGFkN2RkNDRkYTZlMWVmMDRmMzg0MmM=
13
+ MGU2MTBhN2RjOTZkN2I0NjQwMGJkOGI1YTliNmRmNWI1NWM5NjdhOTg4NzVh
14
+ N2RhZDU1MzM0NjJiZjY0ODM0ZTExOTY2ZTUyODM4NmVlNGIzMTU4MWZkOWVi
15
+ ZTRkZmQ4YmQwYzliODU0Y2FhOTRmMjAzYTBhZjQzM2RiZWI4OTU=
data/README.md CHANGED
@@ -4,7 +4,7 @@ Adding a bit more sizzles to the boring ol' hashes for RubyMotion.
4
4
 
5
5
  ## ATTA BOY!
6
6
 
7
- This is most entirely lifted from the awesome Map from Ara T. Howard (https://github.com/ahoward/map).
7
+ This is most entirely lifted from the awesome Map gem from Ara T. Howard (https://github.com/ahoward/map).
8
8
  Made some adaptations to make it work in the RubyMotion world, but all the heavy lifting is his.
9
9
 
10
10
  Hence all credits and ATTA BOY! should go to Ara for some very nice work!
@@ -1,1028 +1,1002 @@
1
- class Map < Hash
2
- class << Map
3
- def allocate
4
- super.instance_eval do
5
- @keys = []
6
- self
1
+ module MotionMap
2
+ class Map < Hash
3
+ class << self
4
+ def allocate
5
+ super.instance_eval do
6
+ @keys = []
7
+ self
8
+ end
7
9
  end
8
- end
9
10
 
10
- def new(*args, &block)
11
- allocate.instance_eval do
12
- initialize(*args, &block)
13
- self
14
- end
15
- end
16
- alias_method '[]', 'new'
11
+ def new(*args, &block)
12
+ allocate.instance_eval do
13
+ initialize(*args, &block)
14
+ self
15
+ end
16
+ end
17
+ alias_method '[]', 'new'
17
18
 
18
- def for(*args, &block)
19
- if(args.size == 1 and block.nil?)
20
- return args.first if args.first.class == self
19
+ def for(*args, &block)
20
+ if(args.size == 1 and block.nil?)
21
+ return args.first if args.first.class == self
22
+ end
23
+ new(*args, &block)
21
24
  end
22
- new(*args, &block)
23
- end
24
25
 
25
- def coerce(other)
26
- case other
27
- when Map
28
- other
29
- else
30
- allocate.update(other.to_hash)
31
- end
32
- end
26
+ def coerce(other)
27
+ case other
28
+ when MotionMap::Map
29
+ other
30
+ else
31
+ allocate.update(other.to_hash)
32
+ end
33
+ end
33
34
 
34
- # iterate over arguments in pairs smartly.
35
- #
36
- def each_pair(*args, &block)
37
- size = args.size
38
- parity = size % 2 == 0 ? :even : :odd
39
- first = args.first
35
+ # iterate over arguments in pairs smartly.
36
+ #
37
+ def each_pair(*args, &block)
38
+ size = args.size
39
+ parity = size % 2 == 0 ? :even : :odd
40
+ first = args.first
40
41
 
41
- if block.nil?
42
- result = []
43
- block = lambda{|*kv| result.push(kv)}
44
- else
45
- result = args
46
- end
42
+ if block.nil?
43
+ result = []
44
+ block = lambda{|*kv| result.push(kv)}
45
+ else
46
+ result = args
47
+ end
47
48
 
48
- return args if size == 0
49
+ return args if size == 0
49
50
 
50
- if size == 1
51
- if first.respond_to?(:each_pair)
52
- first.each_pair do |key, val|
53
- block.call(key, val)
51
+ if size == 1
52
+ if first.respond_to?(:each_pair)
53
+ first.each_pair do |key, val|
54
+ block.call(key, val)
55
+ end
56
+ return args
54
57
  end
55
- return args
56
- end
57
58
 
58
- if first.respond_to?(:each_slice)
59
- first.each_slice(2) do |key, val|
60
- block.call(key, val)
59
+ if first.respond_to?(:each_slice)
60
+ first.each_slice(2) do |key, val|
61
+ block.call(key, val)
62
+ end
63
+ return args
61
64
  end
62
- return args
65
+ raise(ArgumentError, 'odd number of arguments for Map')
63
66
  end
64
- raise(ArgumentError, 'odd number of arguments for Map')
65
- end
66
67
 
67
- array_of_pairs = args.all?{|a| a.is_a?(Array) and a.size == 2}
68
+ array_of_pairs = args.all?{|a| a.is_a?(Array) and a.size == 2}
68
69
 
69
- if array_of_pairs
70
- args.each do |pair|
71
- key, val, *ignored = pair
72
- block.call(key, val)
73
- end
74
- else
75
- 0.step(args.size - 1, 2) do |a|
76
- key = args[a]
77
- val = args[a + 1]
78
- block.call(key, val)
70
+ if array_of_pairs
71
+ args.each do |pair|
72
+ key, val, *ignored = pair
73
+ block.call(key, val)
74
+ end
75
+ else
76
+ 0.step(args.size - 1, 2) do |a|
77
+ key = args[a]
78
+ val = args[a + 1]
79
+ block.call(key, val)
80
+ end
79
81
  end
80
- end
81
82
 
82
- args
83
- end
83
+ args
84
+ end
84
85
 
85
- def intersection(a, b)
86
- a, b, i = Map.for(a), Map.for(b), Map.new
87
- a.depth_first_each{|key, val| i.set(key, val) if b.has?(key)}
88
- i
89
- end
86
+ def intersection(a, b)
87
+ a, b, i = MotionMap::Map.for(a), MotionMap::Map.for(b), MotionMap::Map.new
88
+ a.depth_first_each{|key, val| i.set(key, val) if b.has?(key)}
89
+ i
90
+ end
90
91
 
91
- def match(haystack, needle)
92
- intersection(haystack, needle) == needle
93
- end
94
- end
92
+ def match(haystack, needle)
93
+ intersection(haystack, needle) == needle
94
+ end
95
+ end
95
96
 
96
- def keys
97
- @keys ||= []
98
- end
97
+ def keys
98
+ @keys ||= []
99
+ end
99
100
 
100
- def initialize(*args, &block)
101
- case args.size
102
- when 0
103
- super(&block)
104
- when 1
105
- first = args.first
106
- case first
107
- when nil, false
108
- nil
109
- when Hash
110
- initialize_from_hash(first)
111
- when Array
112
- initialize_from_array(first)
113
- else
114
- if first.respond_to?(:to_hash)
115
- initialize_from_hash(first.to_hash)
116
- else
101
+ def initialize(*args, &block)
102
+ case args.size
103
+ when 0
104
+ super(&block)
105
+ when 1
106
+ first = args.first
107
+ case first
108
+ when nil, false
109
+ nil
110
+ when Hash
117
111
  initialize_from_hash(first)
118
- end
119
- end
120
- else
121
- initialize_from_array(args)
122
- end
123
- end
112
+ when Array
113
+ initialize_from_array(first)
114
+ else
115
+ if first.respond_to?(:to_hash)
116
+ initialize_from_hash(first.to_hash)
117
+ else
118
+ initialize_from_hash(first)
119
+ end
120
+ end
121
+ else
122
+ initialize_from_array(args)
123
+ end
124
+ end
124
125
 
125
- def initialize_from_hash(hash)
126
- map = self
127
- map.update(hash)
128
- map.default = hash.default
129
- end
126
+ def initialize_from_hash(hash)
127
+ map = self
128
+ map.update(hash)
129
+ map.default = hash.default
130
+ end
130
131
 
131
- def initialize_from_array(array)
132
- map = self
133
- Map.each_pair(array){|key, val| map[key] = val}
134
- end
132
+ def initialize_from_array(array)
133
+ map = self
134
+ MotionMap::Map.each_pair(array){|key, val| map[key] = val}
135
+ end
135
136
 
136
- def klass
137
- self.class
138
- end
137
+ def klass
138
+ self.class
139
+ end
139
140
 
140
- def Map.map_for(hash)
141
- hash = klass.coerce(hash)
142
- hash.default = hash.default
143
- hash
144
- end
145
- def map_for(hash)
146
- klass.map_for(hash)
147
- end
141
+ def self.map_for(hash)
142
+ hash = klass.coerce(hash)
143
+ hash.default = hash.default
144
+ hash
145
+ end
146
+ def map_for(hash)
147
+ klass.map_for(hash)
148
+ end
148
149
 
149
- def self.convert_key(key)
150
- key = key.kind_of?(Symbol) ? key.to_s : key
151
- end
152
-
153
- def convert_key(key)
154
- if klass.respond_to?(:convert_key)
155
- klass.convert_key(key)
156
- else
157
- Map.convert_key(key)
150
+ def self.convert_key(key)
151
+ key = key.kind_of?(Symbol) ? key.to_s : key
158
152
  end
159
- end
160
153
 
161
- def self.convert_value(value)
162
- case value
163
- when Hash
164
- coerce(value)
165
- when Array
166
- value.map!{|v| convert_value(v)}
154
+ def convert_key(key)
155
+ if klass.respond_to?(:convert_key)
156
+ klass.convert_key(key)
167
157
  else
168
- value
158
+ MotionMap::Map.convert_key(key)
159
+ end
169
160
  end
170
- end
171
- def convert_value(value)
172
- if klass.respond_to?(:convert_value)
173
- klass.convert_value(value)
174
- else
175
- Map.convert_value(value)
161
+
162
+ def self.convert_value(value)
163
+ case value
164
+ when Hash
165
+ coerce(value)
166
+ when Array
167
+ value.map!{|v| convert_value(v)}
168
+ else
169
+ value
170
+ end
176
171
  end
177
- end
178
- alias_method('convert_val', 'convert_value')
172
+ def convert_value(value)
173
+ if klass.respond_to?(:convert_value)
174
+ klass.convert_value(value)
175
+ else
176
+ MotionMap::Map.convert_value(value)
177
+ end
178
+ end
179
+ alias_method('convert_val', 'convert_value')
179
180
 
180
181
 
181
- def convert(key, val)
182
- [convert_key(key), convert_value(val)]
183
- end
182
+ def convert(key, val)
183
+ [convert_key(key), convert_value(val)]
184
+ end
184
185
 
185
- def copy
186
- default = self.default
187
- self.default = nil
188
- copy = Marshal.load(Marshal.dump(self)) rescue Dup.bind(self).call()
189
- copy.default = default
190
- copy
191
- ensure
192
- self.default = default
193
- end
186
+ def copy
187
+ default = self.default
188
+ self.default = nil
189
+ copy = Marshal.load(Marshal.dump(self)) rescue Dup.bind(self).call()
190
+ copy.default = default
191
+ copy
192
+ ensure
193
+ self.default = default
194
+ end
194
195
 
195
- Dup = instance_method(:dup) unless defined?(Dup)
196
+ Dup = instance_method(:dup) unless defined?(Dup)
196
197
 
197
- def dup
198
- copy
199
- end
198
+ def dup
199
+ copy
200
+ end
200
201
 
201
- def clone
202
- copy
203
- end
202
+ def clone
203
+ copy
204
+ end
204
205
 
205
- def default(key = nil)
206
- key.is_a?(Symbol) && include?(key = key.to_s) ? self[key] : super
207
- end
206
+ def default(key = nil)
207
+ key.is_a?(Symbol) && include?(key = key.to_s) ? self[key] : super
208
+ end
208
209
 
209
- def default=(value)
210
- raise ArgumentError.new("Map doesn't work so well with a non-nil default value!") unless value.nil?
211
- end
210
+ def default=(value)
211
+ raise ArgumentError.new("Map doesn't work so well with a non-nil default value!") unless value.nil?
212
+ end
212
213
 
213
- # writer/reader methods
214
- #
215
- alias_method '__set__', '[]=' unless method_defined?('__set__')
216
- alias_method '__get__', '[]' unless method_defined?('__get__')
217
- alias_method '__update__', 'update' unless method_defined?('__update__')
214
+ # writer/reader methods
215
+ #
216
+ alias_method '__set__', '[]=' unless method_defined?('__set__')
217
+ alias_method '__get__', '[]' unless method_defined?('__get__')
218
+ alias_method '__update__', 'update' unless method_defined?('__update__')
218
219
 
219
- def []=(key, val)
220
- key, val = convert(key, val)
221
- keys.push(key) unless has_key?(key)
222
- __set__(key, val)
223
- end
224
- alias_method 'store', '[]='
220
+ def []=(key, val)
221
+ key, val = convert(key, val)
222
+ keys.push(key) unless has_key?(key)
223
+ __set__(key, val)
224
+ end
225
+ alias_method 'store', '[]='
225
226
 
226
- def [](key)
227
- key = convert_key(key)
228
- __get__(key)
229
- end
227
+ def [](key)
228
+ key = convert_key(key)
229
+ __get__(key)
230
+ end
230
231
 
231
- def fetch(key, *args, &block)
232
- key = convert_key(key)
233
- super(key, *args, &block)
234
- end
232
+ def fetch(key, *args, &block)
233
+ key = convert_key(key)
234
+ super(key, *args, &block)
235
+ end
235
236
 
236
- def key?(key)
237
- super(convert_key(key))
238
- end
239
- alias_method 'include?', 'key?'
240
- alias_method 'has_key?', 'key?'
241
- alias_method 'member?', 'key?'
237
+ def key?(key)
238
+ super(convert_key(key))
239
+ end
240
+ alias_method 'include?', 'key?'
241
+ alias_method 'has_key?', 'key?'
242
+ alias_method 'member?', 'key?'
242
243
 
243
- def update(*args)
244
- Map.each_pair(*args){|key, val| store(key, val)}
245
- self
246
- end
247
- alias_method 'merge!', 'update'
244
+ def update(*args)
245
+ MotionMap::Map.each_pair(*args){|key, val| store(key, val)}
246
+ self
247
+ end
248
+ alias_method 'merge!', 'update'
248
249
 
249
- def merge(*args)
250
- copy.update(*args)
251
- end
252
- alias_method '+', 'merge'
250
+ def merge(*args)
251
+ copy.update(*args)
252
+ end
253
+ alias_method '+', 'merge'
253
254
 
254
- def reverse_merge(hash)
255
- map = copy
256
- map.each{|key, val| Map[key] = val unless Map.key?(key)}
257
- map
258
- end
255
+ def reverse_merge(hash)
256
+ map = copy
257
+ map.each{|key, val| MotionMap::Map[key] = val unless MotionMap::Map.key?(key)}
258
+ map
259
+ end
259
260
 
260
- def reverse_merge!(hash)
261
- replace(reverse_merge(hash))
262
- end
261
+ def reverse_merge!(hash)
262
+ replace(reverse_merge(hash))
263
+ end
263
264
 
264
- def values
265
- array = []
266
- keys.each{|key| array.push(self[key])}
267
- array
268
- end
269
- alias_method 'vals', 'values'
265
+ def values
266
+ array = []
267
+ keys.each{|key| array.push(self[key])}
268
+ array
269
+ end
270
+ alias_method 'vals', 'values'
270
271
 
271
- def values_at(*keys)
272
- keys.map{|key| self[key]}
273
- end
272
+ def values_at(*keys)
273
+ keys.map{|key| self[key]}
274
+ end
274
275
 
275
- def first
276
- [keys.first, self[keys.first]]
277
- end
276
+ def first
277
+ [keys.first, self[keys.first]]
278
+ end
278
279
 
279
- def last
280
- [keys.last, self[keys.last]]
281
- end
280
+ def last
281
+ [keys.last, self[keys.last]]
282
+ end
282
283
 
283
- # iterator methods
284
- #
285
- def each_with_index
286
- keys.each_with_index{|key, index| yield([key, self[key]], index)}
287
- self
288
- end
284
+ # iterator methods
285
+ #
286
+ def each_with_index
287
+ keys.each_with_index{|key, index| yield([key, self[key]], index)}
288
+ self
289
+ end
289
290
 
290
- def each_key
291
- keys.each{|key| yield(key)}
292
- self
293
- end
291
+ def each_key
292
+ keys.each{|key| yield(key)}
293
+ self
294
+ end
294
295
 
295
- def each_value
296
- keys.each{|key| yield self[key]}
297
- self
298
- end
296
+ def each_value
297
+ keys.each{|key| yield self[key]}
298
+ self
299
+ end
299
300
 
300
- def each
301
- keys.each{|key| yield(key, self[key])}
302
- self
303
- end
304
- alias_method 'each_pair', 'each'
305
-
306
- # mutators
307
- #
308
- def delete(key)
309
- key = convert_key(key)
310
- keys.delete(key)
311
- super(key)
312
- end
301
+ def each
302
+ keys.each{|key| yield(key, self[key])}
303
+ self
304
+ end
305
+ alias_method 'each_pair', 'each'
313
306
 
314
- def clear
315
- keys.clear
316
- super
317
- end
307
+ # mutators
308
+ #
309
+ def delete(key)
310
+ key = convert_key(key)
311
+ keys.delete(key)
312
+ super(key)
313
+ end
318
314
 
319
- def delete_if
320
- to_delete = []
321
- keys.each{|key| to_delete.push(key) if yield(key,self[key])}
322
- to_delete.each{|key| delete(key)}
323
- self
324
- end
315
+ def clear
316
+ keys.clear
317
+ super
318
+ end
325
319
 
326
- # See: https://github.com/rubinius/rubinius/blob/98c516820d9f78bd63f29dab7d5ec9bc8692064d/kernel/common/hash19.rb#L476-L484
327
- def keep_if( &block )
328
- raise RuntimeError.new( "can't modify frozen #{ self.class.name }" ) if frozen?
329
- return to_enum( :keep_if ) unless block_given?
330
- each { | key , val | delete key unless yield( key , val ) }
331
- self
332
- end
320
+ def delete_if
321
+ to_delete = []
322
+ keys.each{|key| to_delete.push(key) if yield(key,self[key])}
323
+ to_delete.each{|key| delete(key)}
324
+ self
325
+ end
333
326
 
334
- def replace(*args)
335
- clear
336
- update(*args)
337
- end
327
+ # See: https://github.com/rubinius/rubinius/blob/98c516820d9f78bd63f29dab7d5ec9bc8692064d/kernel/common/hash19.rb#L476-L484
328
+ def keep_if( &block )
329
+ raise RuntimeError.new( "can't modify frozen #{ self.class.name }" ) if frozen?
330
+ return to_enum( :keep_if ) unless block_given?
331
+ each { | key , val | delete key unless yield( key , val ) }
332
+ self
333
+ end
338
334
 
339
- # ordered container specific methods
340
- #
341
- def shift
342
- unless empty?
343
- key = keys.first
344
- val = delete(key)
345
- [key, val]
335
+ def replace(*args)
336
+ clear
337
+ update(*args)
346
338
  end
347
- end
348
339
 
349
- def unshift(*args)
350
- Map.each_pair(*args) do |key, val|
351
- if key?(key)
352
- delete(key)
353
- else
354
- keys.unshift(key)
340
+ # ordered container specific methods
341
+ #
342
+ def shift
343
+ unless empty?
344
+ key = keys.first
345
+ val = delete(key)
346
+ [key, val]
355
347
  end
356
- __set__(key, val)
357
348
  end
358
- self
359
- end
360
349
 
361
- def push(*args)
362
- Map.each_pair(*args) do |key, val|
363
- if key?(key)
364
- delete(key)
365
- else
366
- keys.push(key)
350
+ def unshift(*args)
351
+ MotionMap::Map.each_pair(*args) do |key, val|
352
+ if key?(key)
353
+ delete(key)
354
+ else
355
+ keys.unshift(key)
356
+ end
357
+ __set__(key, val)
367
358
  end
368
- __set__(key, val)
359
+ self
369
360
  end
370
- self
371
- end
372
361
 
373
- def pop
374
- unless empty?
375
- key = keys.last
376
- val = delete(key)
377
- [key, val]
362
+ def push(*args)
363
+ MotionMap::Map.each_pair(*args) do |key, val|
364
+ if key?(key)
365
+ delete(key)
366
+ else
367
+ keys.push(key)
368
+ end
369
+ __set__(key, val)
370
+ end
371
+ self
378
372
  end
379
- end
380
-
381
- # equality / sorting / matching support
382
- #
383
- def ==(other)
384
- case other
385
- when Map
386
- return false if keys != other.keys
387
- super(other)
388
-
389
- when Hash
390
- self == Map.from_hash(other, self)
391
373
 
392
- else
393
- false
374
+ def pop
375
+ unless empty?
376
+ key = keys.last
377
+ val = delete(key)
378
+ [key, val]
379
+ end
394
380
  end
395
- end
396
-
397
- def <=>(other)
398
- cmp = keys <=> klass.coerce(other).keys
399
- return cmp unless cmp.zero?
400
- values <=> klass.coerce(other).values
401
- end
402
-
403
- def =~(hash)
404
- to_hash == klass.coerce(hash).to_hash
405
- end
406
-
407
- # reordering support
408
- #
409
- def reorder(order = {})
410
- order = Map.for(order)
411
- map = Map.new
412
- keys = order.depth_first_keys | depth_first_keys
413
- keys.each{|key| map.set(key, get(key))}
414
- map
415
- end
416
381
 
417
- def reorder!(order = {})
418
- replace(reorder(order))
419
- end
382
+ # equality / sorting / matching support
383
+ #
384
+ def ==(other)
385
+ case other
386
+ when MotionMap::Map
387
+ return false if keys != other.keys
388
+ super(other)
420
389
 
421
- # support for building ordered hasshes from a Map's own image
422
- #
423
- def Map.from_hash(hash, order = nil)
424
- map = Map.for(hash)
425
- map.reorder!(order) if order
426
- map
427
- end
390
+ when Hash
391
+ self == MotionMap::Map.from_hash(other, self)
428
392
 
429
- def invert
430
- inverted = klass.allocate
431
- inverted.default = self.default
432
- keys.each{|key| inverted[self[key]] = key }
433
- inverted
434
- end
393
+ else
394
+ false
395
+ end
396
+ end
435
397
 
436
- def reject(&block)
437
- dup.delete_if(&block)
438
- end
398
+ def <=>(other)
399
+ cmp = keys <=> klass.coerce(other).keys
400
+ return cmp unless cmp.zero?
401
+ values <=> klass.coerce(other).values
402
+ end
439
403
 
440
- def reject!(&block)
441
- hash = reject(&block)
442
- self == hash ? nil : hash
443
- end
404
+ def =~(hash)
405
+ to_hash == klass.coerce(hash).to_hash
406
+ end
444
407
 
445
- def select
446
- array = []
447
- each{|key, val| array << [key,val] if yield(key, val)}
448
- array
449
- end
408
+ # reordering support
409
+ #
410
+ def reorder(order = {})
411
+ order = MotionMap::Map.for(order)
412
+ map = MotionMap::Map.new
413
+ keys = order.depth_first_keys | depth_first_keys
414
+ keys.each{|key| map.set(key, get(key))}
415
+ map
416
+ end
450
417
 
451
- def inspect(*args, &block)
452
- super.inspect
453
- end
418
+ def reorder!(order = {})
419
+ replace(reorder(order))
420
+ end
454
421
 
455
- def to_hash
456
- hash = Hash.new(default)
457
- each do |key, val|
458
- val = val.to_hash if val.respond_to?(:to_hash)
459
- hash[key] = val
422
+ # support for building ordered hasshes from a Map's own image
423
+ #
424
+ def self.from_hash(hash, order = nil)
425
+ map = MotionMap::Map.for(hash)
426
+ map.reorder!(order) if order
427
+ map
460
428
  end
461
- hash
462
- end
463
429
 
464
- def to_array
465
- array = []
466
- each{|*pair| array.push(pair)}
467
- array
468
- end
469
- alias_method 'to_a', 'to_array'
430
+ def invert
431
+ inverted = klass.allocate
432
+ inverted.default = self.default
433
+ keys.each{|key| inverted[self[key]] = key }
434
+ inverted
435
+ end
470
436
 
471
- def to_list
472
- list = []
473
- each_pair do |key, val|
474
- list[key.to_i] = val if(key.is_a?(Numeric) or key.to_s =~ %r/^\d+$/)
437
+ def reject(&block)
438
+ dup.delete_if(&block)
475
439
  end
476
- list
477
- end
478
440
 
479
- def to_s
480
- to_array.to_s
481
- end
441
+ def reject!(&block)
442
+ hash = reject(&block)
443
+ self == hash ? nil : hash
444
+ end
482
445
 
483
- # a sane method missing that only supports writing values or reading
484
- # *previously set* values
485
- #
486
- def method_missing(*args, &block)
487
- method = args.first.to_s
488
- case method
489
- when /=$/
490
- key = args.shift.to_s.chomp('=')
491
- value = args.shift
492
- self[key] = value
493
- when /\?$/
494
- key = args.shift.to_s.chomp('?')
495
- self.has?( key )
496
- else
497
- key = method
498
- unless has_key?(key)
499
- return(block ? fetch(key, &block) : super(*args))
500
- end
501
- self[key]
446
+ def select
447
+ array = []
448
+ each{|key, val| array << [key,val] if yield(key, val)}
449
+ array
502
450
  end
503
- end
504
451
 
505
- def respond_to?(method, *args, &block)
506
- has_key = has_key?(method)
507
- setter = method.to_s =~ /=\Z/o
508
- !!((!has_key and setter) or has_key or super)
509
- end
452
+ def inspect(*args, &block)
453
+ super.inspect
454
+ end
510
455
 
511
- def id
512
- return self[:id] if has_key?(:id)
513
- return self[:_id] if has_key?(:_id)
514
- raise NoMethodError
515
- end
456
+ def to_hash
457
+ hash = Hash.new(default)
458
+ each do |key, val|
459
+ val = val.to_hash if val.respond_to?(:to_hash)
460
+ hash[key] = val
461
+ end
462
+ hash
463
+ end
516
464
 
517
- # support for compound key indexing and depth first iteration
518
- #
519
- def get(*keys)
520
- keys = key_for(keys)
465
+ def to_array
466
+ array = []
467
+ each{|*pair| array.push(pair)}
468
+ array
469
+ end
470
+ alias_method 'to_a', 'to_array'
521
471
 
522
- if keys.size <= 1
523
- if !self.has_key?(keys.first) && block_given?
524
- return yield
525
- else
526
- return self[keys.first]
472
+ def to_list
473
+ list = []
474
+ each_pair do |key, val|
475
+ list[key.to_i] = val if(key.is_a?(Numeric) or key.to_s =~ %r/^\d+$/)
527
476
  end
477
+ list
528
478
  end
529
479
 
530
- keys, key = keys[0..-2], keys[-1]
531
- collection = self
480
+ def to_s
481
+ to_array.to_s
482
+ end
532
483
 
533
- keys.each do |k|
534
- if Map.collection_has?(collection, k)
535
- collection = Map.collection_key(collection, k)
536
- else
537
- collection = nil
484
+ # a sane method missing that only supports writing values or reading
485
+ # *previously set* values
486
+ #
487
+ def method_missing(*args, &block)
488
+ method = args.first.to_s
489
+ case method
490
+ when /=$/
491
+ key = args.shift.to_s.chomp('=')
492
+ value = args.shift
493
+ self[key] = value
494
+ when /\?$/
495
+ key = args.shift.to_s.chomp('?')
496
+ self.has?( key )
497
+ else
498
+ key = method
499
+ unless has_key?(key)
500
+ return(block ? fetch(key, &block) : super(*args))
501
+ end
502
+ self[key]
538
503
  end
504
+ end
539
505
 
540
- unless collection.respond_to?('[]')
541
- leaf = collection
542
- return leaf
543
- end
506
+ def respond_to?(method, *args, &block)
507
+ has_key = has_key?(method)
508
+ setter = method.to_s =~ /=\Z/o
509
+ !!((!has_key and setter) or has_key or super)
544
510
  end
545
511
 
546
- if !Map.collection_has?(collection, key) && block_given?
547
- default_value = yield
548
- else
549
- Map.collection_key(collection, key)
512
+ def id
513
+ return self[:id] if has_key?(:id)
514
+ return self[:_id] if has_key?(:_id)
515
+ raise NoMethodError
550
516
  end
551
- end
552
517
 
553
- def has?(*keys)
554
- keys = key_for(keys)
555
- collection = self
518
+ # support for compound key indexing and depth first iteration
519
+ #
520
+ def get(*keys)
521
+ keys = key_for(keys)
556
522
 
557
- return Map.collection_has?(collection, keys.first) if keys.size <= 1
523
+ if keys.size <= 1
524
+ if !self.has_key?(keys.first) && block_given?
525
+ return yield
526
+ else
527
+ return self[keys.first]
528
+ end
529
+ end
558
530
 
559
- keys, key = keys[0..-2], keys[-1]
531
+ keys, key = keys[0..-2], keys[-1]
532
+ collection = self
560
533
 
561
- keys.each do |k|
562
- if Map.collection_has?(collection, k)
563
- collection = Map.collection_key(collection, k)
564
- else
565
- collection = nil
534
+ keys.each do |k|
535
+ if MotionMap::Map.collection_has?(collection, k)
536
+ collection = MotionMap::Map.collection_key(collection, k)
537
+ else
538
+ collection = nil
539
+ end
540
+
541
+ unless collection.respond_to?('[]')
542
+ leaf = collection
543
+ return leaf
544
+ end
566
545
  end
567
546
 
568
- return collection unless collection.respond_to?('[]')
547
+ if !MotionMap::Map.collection_has?(collection, key) && block_given?
548
+ default_value = yield
549
+ else
550
+ MotionMap::Map.collection_key(collection, key)
551
+ end
569
552
  end
570
553
 
571
- return false unless(collection.is_a?(Hash) or collection.is_a?(Array))
554
+ def has?(*keys)
555
+ keys = key_for(keys)
556
+ collection = self
572
557
 
573
- Map.collection_has?(collection, key)
574
- end
558
+ return MotionMap::Map.collection_has?(collection, keys.first) if keys.size <= 1
575
559
 
576
- def Map.blank?(value)
577
- return value.blank? if value.respond_to?(:blank?)
560
+ keys, key = keys[0..-2], keys[-1]
578
561
 
579
- case value
580
- when String
581
- value.strip.empty?
582
- when Numeric
583
- value == 0
584
- when false
585
- true
586
- else
587
- value.respond_to?(:empty?) ? value.empty? : !value
588
- end
589
- end
562
+ keys.each do |k|
563
+ if MotionMap::Map.collection_has?(collection, k)
564
+ collection = MotionMap::Map.collection_key(collection, k)
565
+ else
566
+ collection = nil
567
+ end
590
568
 
591
- def blank?(*keys)
592
- return empty? if keys.empty?
593
- !has?(*keys) or Map.blank?(get(*keys))
594
- end
569
+ return collection unless collection.respond_to?('[]')
570
+ end
595
571
 
596
- def Map.collection_key(collection, key, &block)
597
- case collection
598
- when Array
599
- begin
600
- key = Integer(key)
601
- rescue
602
- raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]")
603
- end
604
- collection[key]
572
+ return false unless(collection.is_a?(Hash) or collection.is_a?(Array))
605
573
 
606
- when Hash
607
- collection[key]
574
+ MotionMap::Map.collection_has?(collection, key)
575
+ end
608
576
 
609
- else
610
- raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]")
577
+ def self.blank?(value)
578
+ return value.blank? if value.respond_to?(:blank?)
579
+
580
+ case value
581
+ when String
582
+ value.strip.empty?
583
+ when Numeric
584
+ value == 0
585
+ when false
586
+ true
587
+ else
588
+ value.respond_to?(:empty?) ? value.empty? : !value
589
+ end
611
590
  end
612
- end
613
591
 
614
- def collection_key(*args, &block)
615
- Map.collection_key(*args, &block)
616
- end
592
+ def blank?(*keys)
593
+ return empty? if keys.empty?
594
+ !has?(*keys) or MotionMap::Map.blank?(get(*keys))
595
+ end
617
596
 
618
- def Map.collection_has?(collection, key, &block)
619
- has_key =
597
+ def self.collection_key(collection, key, &block)
620
598
  case collection
621
599
  when Array
622
- key = (Integer(key) rescue -1)
623
- (0...collection.size).include?(key)
600
+ begin
601
+ key = Integer(key)
602
+ rescue
603
+ raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]")
604
+ end
605
+ collection[key]
624
606
 
625
607
  when Hash
626
- collection.has_key?(key)
608
+ collection[key]
627
609
 
628
610
  else
629
611
  raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]")
630
612
  end
613
+ end
631
614
 
632
- block.call(key) if(has_key and block)
633
-
634
- has_key
635
- end
615
+ def collection_key(*args, &block)
616
+ MotionMap::Map.collection_key(*args, &block)
617
+ end
636
618
 
637
- def collection_has?(*args, &block)
638
- Map.collection_has?(*args, &block)
639
- end
619
+ def self.collection_has?(collection, key, &block)
620
+ has_key =
621
+ case collection
622
+ when Array
623
+ key = (Integer(key) rescue -1)
624
+ (0...collection.size).include?(key)
640
625
 
641
- def Map.collection_set(collection, key, value, &block)
642
- set_key = false
626
+ when Hash
627
+ collection.has_key?(key)
643
628
 
644
- case collection
645
- when Array
646
- begin
647
- key = Integer(key)
648
- rescue
649
- raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]=#{ value.inspect }")
629
+ else
630
+ raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]")
650
631
  end
651
- set_key = true
652
- collection[key] = value
653
632
 
654
- when Hash
655
- set_key = true
656
- collection[key] = value
633
+ block.call(key) if(has_key and block)
657
634
 
658
- else
659
- raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]=#{ value.inspect }")
635
+ has_key
660
636
  end
661
637
 
662
- block.call(key) if(set_key and block)
663
-
664
- [key, value]
665
- end
638
+ def collection_has?(*args, &block)
639
+ MotionMap::Map.collection_has?(*args, &block)
640
+ end
666
641
 
667
- def collection_set(*args, &block)
668
- Map.collection_set(*args, &block)
669
- end
642
+ def self.collection_set(collection, key, value, &block)
643
+ set_key = false
670
644
 
671
- def set(*args)
672
- case
673
- when args.empty?
674
- return []
675
- when args.size == 1 && args.first.is_a?(Hash)
676
- hash = args.shift
677
- else
678
- hash = {}
679
- value = args.pop
680
- key = Array(args).flatten
681
- hash[key] = value
682
- end
645
+ case collection
646
+ when Array
647
+ begin
648
+ key = Integer(key)
649
+ rescue
650
+ raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]=#{ value.inspect }")
651
+ end
652
+ set_key = true
653
+ collection[key] = value
683
654
 
684
- strategy = hash.map{|key, value| [Array(key), value]}
655
+ when Hash
656
+ set_key = true
657
+ collection[key] = value
685
658
 
686
- strategy.each do |key, value|
687
- leaf_for(key, :autovivify => true) do |leaf, k|
688
- Map.collection_set(leaf, k, value)
659
+ else
660
+ raise(IndexError, "(#{ collection.inspect })[#{ key.inspect }]=#{ value.inspect }")
689
661
  end
690
- end
691
662
 
692
- self
693
- end
663
+ block.call(key) if(set_key and block)
694
664
 
695
- def add(*args)
696
- case
697
- when args.empty?
698
- return []
699
- when args.size == 1 && args.first.is_a?(Hash)
700
- hash = args.shift
701
- else
702
- hash = {}
703
- value = args.pop
704
- key = Array(args).flatten
705
- hash[key] = value
665
+ [key, value]
706
666
  end
707
667
 
708
- exploded = Map.explode(hash)
709
-
710
- exploded[:branches].each do |key, type|
711
- set(key, type.new) unless get(key).is_a?(type)
668
+ def collection_set(*args, &block)
669
+ MotionMap::Map.collection_set(*args, &block)
712
670
  end
713
671
 
714
- exploded[:leaves].each do |key, value|
715
- set(key, value)
716
- end
672
+ def set(*args)
673
+ case
674
+ when args.empty?
675
+ return []
676
+ when args.size == 1 && args.first.is_a?(Hash)
677
+ hash = args.shift
678
+ else
679
+ hash = {}
680
+ value = args.pop
681
+ key = Array(args).flatten
682
+ hash[key] = value
683
+ end
717
684
 
718
- self
719
- end
685
+ strategy = hash.map{|key, value| [Array(key), value]}
720
686
 
721
- def Map.explode(hash)
722
- accum = {:branches => [], :leaves => []}
687
+ strategy.each do |key, value|
688
+ leaf_for(key, :autovivify => true) do |leaf, k|
689
+ MotionMap::Map.collection_set(leaf, k, value)
690
+ end
691
+ end
723
692
 
724
- hash.each do |key, value|
725
- Map._explode(key, value, accum)
693
+ self
726
694
  end
727
695
 
728
- branches = accum[:branches]
729
- leaves = accum[:leaves]
730
-
731
- sort_by_key_size = proc{|a,b| a.first.size <=> b.first.size}
732
-
733
- branches.sort!(&sort_by_key_size)
734
- leaves.sort!(&sort_by_key_size)
735
-
736
- accum
737
- end
738
-
739
- def Map._explode(key, value, accum = {:branches => [], :leaves => []})
740
- key = Array(key).flatten
741
-
742
- case value
743
- when Array
744
- accum[:branches].push([key, Array])
696
+ def add(*args)
697
+ case
698
+ when args.empty?
699
+ return []
700
+ when args.size == 1 && args.first.is_a?(Hash)
701
+ hash = args.shift
702
+ else
703
+ hash = {}
704
+ value = args.pop
705
+ key = Array(args).flatten
706
+ hash[key] = value
707
+ end
745
708
 
746
- value.each_with_index do |v, k|
747
- Map._explode(key + [k], v, accum)
748
- end
709
+ exploded = MotionMap::Map.explode(hash)
749
710
 
750
- when Hash
751
- accum[:branches].push([key, Map])
711
+ exploded[:branches].each do |key, type|
712
+ set(key, type.new) unless get(key).is_a?(type)
713
+ end
752
714
 
753
- value.each do |k, v|
754
- Map._explode(key + [k], v, accum)
755
- end
715
+ exploded[:leaves].each do |key, value|
716
+ set(key, value)
717
+ end
756
718
 
757
- else
758
- accum[:leaves].push([key, value])
719
+ self
759
720
  end
760
721
 
761
- accum
762
- end
722
+ def self.explode(hash)
723
+ accum = {:branches => [], :leaves => []}
763
724
 
764
- def Map.add(*args)
765
- args.flatten!
766
- args.compact!
725
+ hash.each do |key, value|
726
+ MotionMap::Map._explode(key, value, accum)
727
+ end
767
728
 
768
- Map.for(args.shift).tap do |map|
769
- args.each{|arg| map.add(arg)}
770
- end
771
- end
729
+ branches = accum[:branches]
730
+ leaves = accum[:leaves]
772
731
 
773
- def Map.combine(*args)
774
- Map.add(*args)
775
- end
732
+ sort_by_key_size = proc{|a,b| a.first.size <=> b.first.size}
776
733
 
777
- def combine!(*args, &block)
778
- add(*args, &block)
779
- end
734
+ branches.sort!(&sort_by_key_size)
735
+ leaves.sort!(&sort_by_key_size)
780
736
 
781
- def combine(*args, &block)
782
- dup.tap do |map|
783
- map.combine!(*args, &block)
737
+ accum
784
738
  end
785
- end
786
739
 
787
- def leaf_for(key, options = {}, &block)
788
- leaf = self
789
- key = Array(key).flatten
790
- k = key.first
740
+ def self._explode(key, value, accum = {:branches => [], :leaves => []})
741
+ key = Array(key).flatten
791
742
 
792
- key.each_cons(2) do |a, b|
793
- exists = Map.collection_has?(leaf, a)
743
+ case value
744
+ when Array
745
+ accum[:branches].push([key, Array])
794
746
 
795
- case b
796
- when Numeric
797
- if options[:autovivify]
798
- Map.collection_set(leaf, a, Array.new) unless exists
747
+ value.each_with_index do |v, k|
748
+ MotionMap::Map._explode(key + [k], v, accum)
799
749
  end
800
750
 
801
- when String, Symbol
802
- if options[:autovivify]
803
- Map.collection_set(leaf, a, Map.new) unless exists
751
+ when Hash
752
+ accum[:branches].push([key, MotionMap::Map])
753
+ value.each do |k, v|
754
+ MotionMap::Map._explode(key + [k], v, accum)
804
755
  end
756
+
757
+ else
758
+ accum[:leaves].push([key, value])
805
759
  end
806
760
 
807
- leaf = Map.collection_key(leaf, a)
808
- k = b
761
+ accum
809
762
  end
810
763
 
811
- block ? block.call(leaf, k) : [leaf, k]
812
- end
813
-
814
- def rm(*args)
815
- paths, path = args.partition{|arg| arg.is_a?(Array)}
816
- paths.push(path)
764
+ def self.add(*args)
765
+ args.flatten!
766
+ args.compact!
817
767
 
818
- paths.each do |path|
819
- if path.size == 1
820
- delete(*path)
821
- next
768
+ MotionMap::Map.for(args.shift).tap do |map|
769
+ args.each{|arg| map.add(arg)}
822
770
  end
771
+ end
823
772
 
824
- branch, leaf = path[0..-2], path[-1]
825
- collection = get(branch)
826
-
827
- case collection
828
- when Hash
829
- key = leaf
830
- collection.delete(key)
831
- when Array
832
- index = leaf
833
- collection.delete_at(index)
834
- else
835
- raise(IndexError, "(#{ collection.inspect }).rm(#{ path.inspect })")
836
- end
773
+ def self.combine(*args)
774
+ MotionMap::Map.add(*args)
837
775
  end
838
- paths
839
- end
840
776
 
841
- def forcing(forcing=nil, &block)
842
- @forcing ||= nil
777
+ def combine!(*args, &block)
778
+ add(*args, &block)
779
+ end
843
780
 
844
- if block
845
- begin
846
- previous = @forcing
847
- @forcing = forcing
848
- block.call()
849
- ensure
850
- @forcing = previous
781
+ def combine(*args, &block)
782
+ dup.tap do |map|
783
+ map.combine!(*args, &block)
851
784
  end
852
- else
853
- @forcing
854
785
  end
855
- end
856
786
 
857
- def forcing?(forcing=nil)
858
- @forcing ||= nil
859
- @forcing == forcing
860
- end
787
+ def leaf_for(key, options = {}, &block)
788
+ leaf = self
789
+ key = Array(key).flatten
790
+ k = key.first
861
791
 
862
- def apply(other)
863
- Map.for(other).depth_first_each do |keys, value|
864
- set(keys => value) unless !get(keys).nil?
865
- end
866
- self
867
- end
792
+ key.each_cons(2) do |a, b|
793
+ exists = MotionMap::Map.collection_has?(leaf, a)
868
794
 
869
- def Map.alphanumeric_key_for(key)
870
- return key if key.is_a?(Numeric)
795
+ case b
796
+ when Numeric
797
+ if options[:autovivify]
798
+ MotionMap::Map.collection_set(leaf, a, Array.new) unless exists
799
+ end
871
800
 
872
- digity, stringy, digits = %r/^(~)?(\d+)$/iomx.match(key).to_a
801
+ when String, Symbol
802
+ if options[:autovivify]
803
+ MotionMap::Map.collection_set(leaf, a, MotionMap::Map.new) unless exists
804
+ end
805
+ end
873
806
 
874
- digity ? stringy ? String(digits) : Integer(digits) : key
875
- end
807
+ leaf = MotionMap::Map.collection_key(leaf, a)
808
+ k = b
809
+ end
876
810
 
877
- def alphanumeric_key_for(key)
878
- Map.alphanumeric_key_for(key)
879
- end
811
+ block ? block.call(leaf, k) : [leaf, k]
812
+ end
880
813
 
881
- def self.key_for(*keys)
882
- return keys.flatten
883
- end
814
+ def rm(*args)
815
+ paths, path = args.partition{|arg| arg.is_a?(Array)}
816
+ paths.push(path)
884
817
 
885
- def key_for(*keys)
886
- self.class.key_for(*keys)
887
- end
818
+ paths.each do |path|
819
+ if path.size == 1
820
+ delete(*path)
821
+ next
822
+ end
888
823
 
889
- ## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
890
- #
891
- def Map.depth_first_each(enumerable, path = [], accum = [], &block)
892
- Map.pairs_for(enumerable) do |key, val|
893
- path.push(key)
894
- if((val.is_a?(Hash) or val.is_a?(Array)) and not val.empty?)
895
- Map.depth_first_each(val, path, accum)
896
- else
897
- accum << [path.dup, val]
824
+ branch, leaf = path[0..-2], path[-1]
825
+ collection = get(branch)
826
+
827
+ case collection
828
+ when Hash
829
+ key = leaf
830
+ collection.delete(key)
831
+ when Array
832
+ index = leaf
833
+ collection.delete_at(index)
834
+ else
835
+ raise(IndexError, "(#{ collection.inspect }).rm(#{ path.inspect })")
836
+ end
898
837
  end
899
- path.pop()
900
- end
901
- if block
902
- accum.each{|keys, val| block.call(keys, val)}
903
- else
904
- accum
838
+ paths
905
839
  end
906
- end
907
840
 
908
- def Map.depth_first_keys(enumerable, path = [], accum = [], &block)
909
- accum = Map.depth_first_each(enumerable, path = [], accum = [], &block)
910
- accum.map!{|kv| kv.first}
911
- accum
912
- end
841
+ def forcing(forcing=nil, &block)
842
+ @forcing ||= nil
913
843
 
914
- def Map.depth_first_values(enumerable, path = [], accum = [], &block)
915
- accum = Map.depth_first_each(enumerable, path = [], accum = [], &block)
916
- accum.map!{|kv| kv.last}
917
- accum
918
- end
844
+ if block
845
+ begin
846
+ previous = @forcing
847
+ @forcing = forcing
848
+ block.call()
849
+ ensure
850
+ @forcing = previous
851
+ end
852
+ else
853
+ @forcing
854
+ end
855
+ end
919
856
 
920
- def Map.pairs_for(enumerable, *args, &block)
921
- if block.nil?
922
- pairs, block = [], lambda{|*pair| pairs.push(pair)}
923
- else
924
- pairs = false
857
+ def forcing?(forcing=nil)
858
+ @forcing ||= nil
859
+ @forcing == forcing
925
860
  end
926
861
 
927
- result =
928
- case enumerable
929
- when Hash
930
- enumerable.each_pair(*args, &block)
931
- when Array
932
- enumerable.each_with_index(*args) do |val, key|
933
- block.call(key, val)
934
- end
935
- else
936
- enumerable.each_pair(*args, &block)
862
+ def apply(other)
863
+ MotionMap::Map.for(other).depth_first_each do |keys, value|
864
+ set(keys => value) unless !get(keys).nil?
937
865
  end
866
+ self
867
+ end
938
868
 
939
- pairs ? pairs : result
940
- end
869
+ def self.alphanumeric_key_for(key)
870
+ return key if key.is_a?(Numeric)
941
871
 
942
- def Map.breadth_first_each(enumerable, accum = [], &block)
943
- levels = []
872
+ digity, stringy, digits = %r/^(~)?(\d+)$/iomx.match(key).to_a
944
873
 
945
- keys = Map.depth_first_keys(enumerable)
874
+ digity ? stringy ? String(digits) : Integer(digits) : key
875
+ end
946
876
 
947
- keys.each do |key|
948
- key.size.times do |i|
949
- k = key.slice(0, i + 1)
950
- level = k.size - 1
951
- levels[level] ||= Array.new
952
- last = levels[level].last
953
- levels[level].push(k) unless last == k
954
- end
877
+ def alphanumeric_key_for(key)
878
+ MotionMap::Map.alphanumeric_key_for(key)
955
879
  end
956
880
 
957
- levels.each do |level|
958
- level.each do |key|
959
- val = enumerable.get(key)
960
- block ? block.call(key, val) : accum.push([key, val])
881
+ def self.key_for(*keys)
882
+ return keys.flatten
883
+ end
884
+
885
+ def key_for(*keys)
886
+ self.class.key_for(*keys)
887
+ end
888
+
889
+ ## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
890
+ #
891
+ def self.depth_first_each(enumerable, path = [], accum = [], &block)
892
+ self.pairs_for(enumerable) do |key, val|
893
+ path.push(key)
894
+ if((val.is_a?(Hash) or val.is_a?(Array)) and not val.empty?)
895
+ MotionMap::Map.depth_first_each(val, path, accum)
896
+ else
897
+ accum << [path.dup, val]
898
+ end
899
+ path.pop()
900
+ end
901
+ if block
902
+ accum.each{|keys, val| block.call(keys, val)}
903
+ else
904
+ accum
961
905
  end
962
906
  end
963
907
 
964
- block ? enumerable : accum
965
- end
908
+ def self.depth_first_keys(enumerable, path = [], accum = [], &block)
909
+ accum = self.depth_first_each(enumerable, path = [], accum = [], &block)
910
+ accum.map!{|kv| kv.first}
911
+ accum
912
+ end
966
913
 
967
- def Map.keys_for(enumerable)
968
- keys = enumerable.respond_to?(:keys) ? enumerable.keys : Array.new(enumerable.size){|i| i}
969
- end
914
+ def self.depth_first_values(enumerable, path = [], accum = [], &block)
915
+ accum = self.depth_first_each(enumerable, path = [], accum = [], &block)
916
+ accum.map!{|kv| kv.last}
917
+ accum
918
+ end
970
919
 
971
- def depth_first_each(*args, &block)
972
- Map.depth_first_each(enumerable=self, *args, &block)
973
- end
920
+ def self.pairs_for(enumerable, *args, &block)
921
+ if block.nil?
922
+ pairs, block = [], lambda{|*pair| pairs.push(pair)}
923
+ else
924
+ pairs = false
925
+ end
974
926
 
975
- def depth_first_keys(*args, &block)
976
- Map.depth_first_keys(enumerable=self, *args, &block)
977
- end
927
+ result =
928
+ case enumerable
929
+ when Hash
930
+ enumerable.each_pair(*args, &block)
931
+ when Array
932
+ enumerable.each_with_index(*args) do |val, key|
933
+ block.call(key, val)
934
+ end
935
+ else
936
+ enumerable.each_pair(*args, &block)
937
+ end
978
938
 
979
- def depth_first_values(*args, &block)
980
- Map.depth_first_values(enumerable=self, *args, &block)
981
- end
939
+ pairs ? pairs : result
940
+ end
982
941
 
983
- def breadth_first_each(*args, &block)
984
- Map.breadth_first_each(enumerable=self, *args, &block)
985
- end
942
+ def self.breadth_first_each(enumerable, accum = [], &block)
943
+ levels = []
986
944
 
987
- def contains(other)
988
- other = other.is_a?(Hash) ? Map.coerce(other) : other
989
- breadth_first_each{|key, value| return true if value == other}
990
- return false
991
- end
992
- alias_method 'contains?', 'contains'
945
+ keys = MotionMap::Map.depth_first_keys(enumerable)
993
946
 
994
- ## for rails' extract_options! compat
995
- #
996
- def extractable_options?
997
- true
998
- end
947
+ keys.each do |key|
948
+ key.size.times do |i|
949
+ k = key.slice(0, i + 1)
950
+ level = k.size - 1
951
+ levels[level] ||= Array.new
952
+ last = levels[level].last
953
+ levels[level].push(k) unless last == k
954
+ end
955
+ end
999
956
 
1000
- ## for mongoid type system support
1001
- #
1002
- def serialize(object)
1003
- ::Map.for(object)
1004
- end
957
+ levels.each do |level|
958
+ level.each do |key|
959
+ val = enumerable.get(key)
960
+ block ? block.call(key, val) : accum.push([key, val])
961
+ end
962
+ end
1005
963
 
1006
- def deserialize(object)
1007
- ::Map.for(object)
1008
- end
964
+ block ? enumerable : accum
965
+ end
1009
966
 
1010
- def Map.demongoize(object)
1011
- Map.for(object)
1012
- end
967
+ def self.keys_for(enumerable)
968
+ keys = enumerable.respond_to?(:keys) ? enumerable.keys : Array.new(enumerable.size){|i| i}
969
+ end
1013
970
 
1014
- def Map.evolve(object)
1015
- Map.for(object)
1016
- end
971
+ def depth_first_each(*args, &block)
972
+ MotionMap::Map.depth_first_each(enumerable=self, *args, &block)
973
+ end
974
+
975
+ def depth_first_keys(*args, &block)
976
+ MotionMap::Map.depth_first_keys(enumerable=self, *args, &block)
977
+ end
978
+
979
+ def depth_first_values(*args, &block)
980
+ MotionMap::Map.depth_first_values(enumerable=self, *args, &block)
981
+ end
1017
982
 
1018
- def mongoize
1019
- self
983
+ def breadth_first_each(*args, &block)
984
+ MotionMap::Map.breadth_first_each(enumerable=self, *args, &block)
985
+ end
986
+
987
+ # Make RM Not happy ;-(
988
+ # def contains(other)
989
+ # other = other.is_a?(Hash) ? MotionMap::Map.coerce(other) : other
990
+ # breadth_first_each{|key, value| return true if value == other}
991
+ # return false
992
+ # end
993
+ # alias_method 'contains?', 'contains'
1020
994
  end
1021
995
  end
1022
996
 
1023
- module Kernel
1024
- private
1025
- def Map(*args, &block)
1026
- Map.new(*args, &block)
1027
- end
1028
- end
997
+ # module Kernel
998
+ # private
999
+ # def Map(*args, &block)
1000
+ # Map.new(*args, &block)
1001
+ # end
1002
+ # end