lib/map.rb in map-5.5.0 vs lib/map.rb in map-5.6.1
- old
+ new
@@ -1,8 +1,8 @@
# -*- encoding : utf-8 -*-
class Map < Hash
- Version = '5.5.0' unless defined?(Version)
+ Version = '5.6.1' unless defined?(Version)
Load = Kernel.method(:load) unless defined?(Load)
class << Map
def version
Map::Version
@@ -719,12 +719,11 @@
def collection_has_key?(collection, key)
case collection
when Hash
collection.has_key?(key)
when Array
- return false unless key
- (0...collection.size).include?(Integer(key))
+ (0...collection.size).include?((Integer(key) rescue -1))
end
end
def set(*args)
if args.size == 1 and args.first.is_a?(Hash)
@@ -734,49 +733,74 @@
value = args.pop
keys = args
spec[keys] = value
end
- spec.each do |keys, value|
- keys = Array(keys).flatten
+ begin
+ spec.each do |keys, value|
+ keys = Array(keys).flatten
+ collection = self
+ key = keys.pop
- collection = self
+ while((k = keys.shift)) do
+ k = alphanumeric_key_for(k)
+ collection = collection[k]
+ end
- keys = key_for(keys)
-
- if keys.size <= 1
- key = keys.first
collection[key] = value
- next
end
+ rescue
+ spec.each do |keys, value|
+ keys = Array(keys).flatten
- key = nil
+ collection = self
- keys.each_cons(2) do |a, b|
- a, b = alphanumeric_key_for(a), alphanumeric_key_for(b)
+ if keys.size <= 1
+ key = keys.first
+ collection[key] = value
+ next
+ end
- exists = collection_has_key?(collection, a)
+ leaf_for(keys, :autovivify => true) do |leaf, key|
+ leaf[key] = value
+ end
+ end
+ end
- case b
- when Numeric
- #collection[a] ||= []
+ return spec.values
+ end
+
+ def leaf_for(keys, options = {}, &block)
+ collection = self
+ key = nil
+
+ keys.each_cons(2) do |a, b|
+ a, b = alphanumeric_key_for(a), alphanumeric_key_for(b)
+
+ exists = collection_has_key?(collection, a)
+
+ case b
+ when Numeric
+ if options[:autovivify]
collection[a] = [] unless exists
- raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }]=#{ value.inspect }") unless collection[a].is_a?(Array)
+ end
+ raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }][#{ b.inspect }]") unless collection[a].is_a?(Array)
- when String, Symbol
- #collection[a] ||= {}
- collection[a] = {} unless exists
- raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }]=#{ value.inspect }") unless collection[a].is_a?(Hash)
- end
- collection = collection[a]
- key = b
+ when String, Symbol
+ if options[:autovivify]
+ collection[a] = Map.new unless exists
+ end
+ raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }][#{ b.inspect }]") unless collection[a].is_a?(Map)
end
- collection[key] = value
+ collection = collection[a]
+ key = b
end
- return spec.values
+ leaf = collection
+
+ block ? block.call(leaf, key) : [leaf, key]
end
def rm(*args)
paths, path = args.partition{|arg| arg.is_a?(Array)}
paths.push(path)
@@ -839,52 +863,15 @@
def alphanumeric_key_for(key)
Map.alphanumeric_key_for(key)
end
-## key path support
-#
- def self.dot_key_for(*keys)
- dot = keys.compact.flatten.join('.')
- dot.split(%r/\s*[,.]\s*/).map{|part| part =~ %r/^\d+$/ ? Integer(part) : part}
- end
-
- def self.dot_keys
- @@dot_keys = {} unless defined?(@@dot_keys)
- @@dot_keys
- end
-
- def self.dot_keys?
- ancestors.each do |ancestor|
- return dot_keys[ancestor] if dot_keys.has_key?(ancestor)
- end
- false
- end
-
- def dot_keys?
- @dot_keys = false unless defined?(@dot_keys)
- @dot_keys
- end
-
- def self.dot_keys!(boolean = true)
- dot_keys[self] = !!boolean
- end
-
- def dot_keys!(boolean = true)
- @dot_keys = !!boolean
- end
-
def self.key_for(*keys)
- return keys.flatten unless dot_keys?
- self.dot_key_for(*keys)
+ return keys.flatten
end
def key_for(*keys)
- if dot_keys?
- self.class.dot_key_for(*keys)
- else
- self.class.key_for(*keys)
- end
+ self.class.key_for(*keys)
end
## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
#
def Map.depth_first_each(enumerable, path = [], accum = [], &block)