## # A LookupTable is similar to a Hash in that keys are used to set and # reference values. However, unlike Hash, whether a key matches an # entry in LookupTable is determined by using the == comparison operator # in C code. In effect, two keys are equal if they are the same pointer. # # NOTE: the value used to determine the bin is the "pointer" value of # key >> 2. This makes it possible to calculate the bin from Ruby with # the same result as in C. For example: # # l = LookupTable.new # loc = :a.hash & (l.bins - 1) # => 12 # class LookupTable # def show # @values # end # end # # l[:a] = 1 # l.show # => #:a, @value=>1, # @next=>nil>, nil, nil, nil> # # where ... is ten "nil, " entries. # # LookupTable is intended to be used with Symbol or Fixnum keys because # it is a strict identity map. Usage of Strings as keys will likely result # in strange behavior. # LookupTable is NOT intended to be used generally like Hash. module Rubinius class LookupTable include Enumerable class Bucket attr_reader :key attr_reader :value attr_reader :next end attr_reader :values attr_reader :bins attr_reader_specific :entries, :size alias_method :length, :size def self.allocate Rubinius.primitive :lookuptable_allocate raise PrimitiveFailure, "LookupTable.allocate primitive failed" end def initialize(hash=nil) return unless hash hash.each do |k, v| self[k] = v end end private :initialize def duplicate Rubinius.primitive :lookuptable_duplicate raise PrimitiveFailure, "LookupTable#duplicate primitive failed" end def dup copy = duplicate Rubinius.privately do copy.initialize_copy self end copy end alias_method :clone, :dup def fetch(key, return_on_failure) Rubinius.primitive :lookuptable_fetch raise PrimitiveFailure, "LookupTable#fetch primitive failed" end def key?(key) Rubinius.primitive :lookuptable_has_key raise PrimitiveFailure, "LookupTable#key? primitive failed" end alias_method :has_key?, :key? alias_method :include?, :key? alias_method :member?, :key? def delete(key) Rubinius.primitive :lookuptable_delete raise PrimitiveFailure, "LookupTable#delete primitive failed" end def keys Rubinius.primitive :lookuptable_keys raise PrimitiveFailure, "LookupTable#keys primitive failed" end def values Rubinius.primitive :lookuptable_values raise PrimitiveFailure, "LookupTable#values primitive failed" end def each max = @bins i = 0 vals = @values while i < max entry = vals.at(i) while entry yield entry.key, entry.value entry = entry.next end i += 1 end self end def empty? @entries == 0 end def to_s "#<#{self.class}:0x#{object_id.to_s(16)} #{entries} entries>" end def inspect ents = collect { |k, v| " #{k.inspect}=>#{v.inspect}" }.join(",") "#<#{self.class}#{ents}>" end end end