diff options
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.rb | 98 |
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 |