mongo-ruby-driver/lib/bson/ordered_hash.rb

187 lines
4.0 KiB
Ruby
Raw Normal View History

# encoding: UTF-8
2010-04-05 18:09:06 +00:00
# --
2011-01-17 17:26:32 +00:00
# Copyright (C) 2008-2011 10gen Inc.
2010-04-05 18:09:06 +00:00
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ++
# A hash in which the order of keys are preserved.
#
# Under Ruby 1.9 and greater, this class has no added methods because Ruby's
# Hash already keeps its keys ordered by order of insertion.
2010-05-07 01:25:18 +00:00
module BSON
class OrderedHash < Hash
def ==(other)
begin
case other
when BSON::OrderedHash
keys == other.keys && values == other.values
else
super
end
2010-05-07 01:25:18 +00:00
rescue
false
end
2010-04-05 18:09:06 +00:00
end
2010-05-07 01:25:18 +00:00
# We only need the body of this class if the RUBY_VERSION is before 1.9
if RUBY_VERSION < '1.9'
attr_accessor :ordered_keys
def self.[] *args
oh = BSON::OrderedHash.new
if Hash === args[0]
oh.merge! args[0]
elsif (args.size % 2) != 0
raise ArgumentError, "odd number of elements for Hash"
else
0.step(args.size - 1, 2) do |key|
value = key + 1
oh[args[key]] = args[value]
end
2010-04-05 18:09:06 +00:00
end
2010-05-07 01:25:18 +00:00
oh
2010-04-05 18:09:06 +00:00
end
2010-05-07 01:25:18 +00:00
def initialize(*a, &b)
@ordered_keys = []
2011-04-28 22:32:32 +00:00
super
end
def yaml_initialize(tag, val)
@ordered_keys = []
super
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def keys
2011-06-21 03:13:32 +00:00
@ordered_keys.dup
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def []=(key, value)
unless has_key?(key)
@ordered_keys << key
end
2010-05-07 01:25:18 +00:00
super(key, value)
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def each
@ordered_keys.each { |k| yield k, self[k] }
self
end
alias :each_pair :each
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def to_a
@ordered_keys.map { |k| [k, self[k]] }
end
2010-08-27 19:50:42 +00:00
2010-05-07 01:25:18 +00:00
def values
collect { |k, v| v }
end
2010-04-05 18:09:06 +00:00
2011-06-15 20:25:20 +00:00
def replace(other)
2011-06-21 03:13:32 +00:00
@ordered_keys.replace(other.keys)
2011-06-15 20:25:20 +00:00
super
end
2010-05-07 01:25:18 +00:00
def merge(other)
oh = self.dup
oh.merge!(other)
oh
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def merge!(other)
@ordered_keys += other.keys # unordered if not an BSON::OrderedHash
@ordered_keys.uniq!
super(other)
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
alias :update :merge!
2011-06-21 03:13:32 +00:00
2011-03-23 23:49:33 +00:00
def dup
result = OrderedHash.new
@ordered_keys.each do |key|
result[key] = self[key]
end
result
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def inspect
str = "#<BSON::OrderedHash:0x#{self.object_id.to_s(16)} {"
2010-05-07 01:25:18 +00:00
str << (@ordered_keys || []).collect { |k| "\"#{k}\"=>#{self.[](k).inspect}" }.join(", ")
str << '}>'
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def delete(key, &block)
@ordered_keys.delete(key) if @ordered_keys
super
end
2010-04-05 18:09:06 +00:00
2010-05-07 01:25:18 +00:00
def delete_if(&block)
self.each do |k,v|
2010-05-07 01:25:18 +00:00
if yield k, v
delete(k)
end
end
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
2010-08-23 18:19:32 +00:00
def reject(&block)
clone = self.clone
return clone unless block_given?
clone.delete_if(&block)
2010-08-23 18:19:32 +00:00
end
2011-04-15 20:10:38 +00:00
def reject!(&block)
changed = false
self.each do |k,v|
if yield k, v
changed = true
delete(k)
end
end
changed ? self : nil
2011-04-15 20:10:38 +00:00
end
2010-05-07 01:25:18 +00:00
def clear
super
@ordered_keys = []
end
2010-04-05 18:09:06 +00:00
if RUBY_VERSION =~ /1.8.6/
def hash
code = 17
each_pair do |key, value|
code = 37 * code + key.hash
code = 37 * code + value.hash
end
code & 0x7fffffff
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
def eql?(o)
if o.instance_of? BSON::OrderedHash
self.hash == o.hash
else
false
end
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
end
2010-08-27 19:50:42 +00:00
def clone
Marshal::load(Marshal.dump(self))
end
2010-05-07 01:25:18 +00:00
end
2010-04-05 18:09:06 +00:00
end
end