146 lines
3.4 KiB
Ruby
146 lines
3.4 KiB
Ruby
module Polecat
|
|
module Storage
|
|
# This class is a storage engine based on a simple hash.
|
|
class BinaryStorage < Storage
|
|
def initialize
|
|
@root = nil
|
|
end
|
|
|
|
# add a new key value pair
|
|
def add key, value = nil
|
|
if key.class == Node
|
|
new_node = key
|
|
else
|
|
check_key key
|
|
new_node = Node.new key, value
|
|
end
|
|
|
|
if @root.nil?
|
|
@root = new_node
|
|
else
|
|
cur_node = @root
|
|
while cur_node.lower != new_node && cur_node.upper != new_node
|
|
if cur_node.key > new_node.key
|
|
if cur_node.lower.nil?
|
|
cur_node.lower = new_node
|
|
else
|
|
cur_node = cur_node.lower
|
|
end
|
|
elsif cur_node.key <= new_node.key
|
|
if cur_node.upper.nil?
|
|
cur_node.upper = new_node
|
|
else
|
|
cur_node = cur_node.upper
|
|
end
|
|
end
|
|
end # end of while
|
|
end
|
|
end
|
|
alias :[]= :add
|
|
|
|
def delete key
|
|
check_key key
|
|
|
|
cur_node = @root
|
|
parent = nil
|
|
while !cur_node.nil?
|
|
if cur_node.key == key
|
|
if parent.nil?
|
|
@root = nil
|
|
else
|
|
if parent.lower == cur_node
|
|
parent.lower = nil
|
|
else
|
|
parent.upper = nil
|
|
end
|
|
end
|
|
|
|
add cur_node.lower unless cur_node.lower.nil?
|
|
add cur_node.upper unless cur_node.upper.nil?
|
|
return cur_node.value
|
|
else
|
|
if cur_node.key < key
|
|
parent = cur_node
|
|
cur_node = cur_node.upper
|
|
else
|
|
parent = cur_node
|
|
cur_node = cur_node.lower
|
|
end
|
|
end
|
|
end
|
|
nil
|
|
end
|
|
|
|
def interval lower, upper, node = @root
|
|
check_key lower
|
|
check_key upper
|
|
|
|
select do |key|
|
|
lower <= key && key <= upper
|
|
end
|
|
end
|
|
|
|
def find key
|
|
check_key key
|
|
|
|
cur_node = @root
|
|
until cur_node.nil?
|
|
if cur_node.key == key
|
|
return cur_node.value
|
|
elsif
|
|
if cur_node.key > key
|
|
cur_node = cur_node.lower
|
|
else
|
|
cur_node = cur_node.upper
|
|
end
|
|
end
|
|
end
|
|
nil
|
|
end
|
|
alias :[] :find
|
|
|
|
def select node = @root, &block
|
|
if node.nil?
|
|
[]
|
|
else
|
|
rs = []
|
|
rs << node.value if block.call(node.key)
|
|
rs += (select node.lower, &block)
|
|
rs += (select node.upper, &block)
|
|
end
|
|
end
|
|
|
|
def count node = @root
|
|
if node.nil?
|
|
0
|
|
else
|
|
1 + (count node.lower) + (count node.upper)
|
|
end
|
|
end
|
|
|
|
def each node = @root, &block
|
|
return if node.nil?
|
|
each node.lower, &block unless node.lower.nil?
|
|
yield node.key, node.value
|
|
each node.upper, &block unless node.upper.nil?
|
|
end
|
|
|
|
def check_key key
|
|
unless key.respond_to?(:<=>) && key.respond_to?(:<=)
|
|
raise ArgumentError, 'key does not support #<=>'
|
|
end
|
|
end
|
|
private :check_key
|
|
|
|
class Node
|
|
attr_accessor :value, :lower, :upper
|
|
attr_reader :key
|
|
def initialize key, value
|
|
@key = key
|
|
@value = value
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|