motion-map 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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