summaryrefslogtreecommitdiff
path: root/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb')
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb98
1 files changed, 98 insertions, 0 deletions
diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
new file mode 100644
index 0000000000..7e80672a07
--- /dev/null
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
@@ -0,0 +1,98 @@
+class Bundler::Thor
+ module CoreExt #:nodoc:
+ if RUBY_VERSION >= "1.9"
+ class OrderedHash < ::Hash
+ end
+ else
+ # This class is based on the Ruby 1.9 ordered hashes.
+ #
+ # It keeps the semantics and most of the efficiency of normal hashes
+ # while also keeping track of the order in which elements were set.
+ #
+ class OrderedHash #:nodoc:
+ include Enumerable
+
+ Node = Struct.new(:key, :value, :next, :prev)
+
+ def initialize
+ @hash = {}
+ end
+
+ def [](key)
+ @hash[key] && @hash[key].value
+ end
+
+ def []=(key, value)
+ if node = @hash[key] # rubocop:disable AssignmentInCondition
+ node.value = value
+ else
+ node = Node.new(key, value)
+
+ if !defined?(@first) || @first.nil?
+ @first = @last = node
+ else
+ node.prev = @last
+ @last.next = node
+ @last = node
+ end
+ end
+
+ @hash[key] = node
+ value
+ end
+
+ def delete(key)
+ if node = @hash[key] # rubocop:disable AssignmentInCondition
+ prev_node = node.prev
+ next_node = node.next
+
+ next_node.prev = prev_node if next_node
+ prev_node.next = next_node if prev_node
+
+ @first = next_node if @first == node
+ @last = prev_node if @last == node
+
+ value = node.value
+ end
+
+ @hash.delete(key)
+ value
+ end
+
+ def keys
+ map { |k, v| k }
+ end
+
+ def values
+ map { |k, v| v }
+ end
+
+ def each
+ return unless defined?(@first) && @first
+ yield [@first.key, @first.value]
+ node = @first
+ yield [node.key, node.value] while node = node.next # rubocop:disable AssignmentInCondition
+ self
+ end
+
+ def merge(other)
+ hash = self.class.new
+
+ each do |key, value|
+ hash[key] = value
+ end
+
+ other.each do |key, value|
+ hash[key] = value
+ end
+
+ hash
+ end
+
+ def empty?
+ @hash.empty?
+ end
+ end
+ end
+ end
+end