lib/binarysearch/search.rb in binarysearch-0.0.1 vs lib/binarysearch/search.rb in binarysearch-0.0.2
- old
+ new
@@ -1,73 +1,94 @@
require 'readbytes'
module BinarySearch
class Search
- INDEX_SIZE = 4 #TODO is there a sizeof(long) ?
+ #TODO is there a sizeof(long) ?
+ INDEX_SIZE = 4
+ # Returns a new Search object. +db+ is the file having the data used
+ # for your searches. +db_idx+ is the index created with
+ # BinarySearch#index if it's nil, it will construct a filename appending
+ # '<em>.idx</em>' to the value +db+ has.
def initialize(db, db_idx=nil)
@db = File.open(db, 'r')
db_idx = db + '.idx' if db_idx.nil?
@db_idx = File.open(db_idx, 'r')
@db_size = File.stat(db_idx).size / INDEX_SIZE
@db_pos = 0
end
+ # Close the files.
def close
@db.close
@db_idx.close
@db = @db_idx = nil
end
- def search(record)
+ # Searches object +key+ in the file using binary search. If found returns
+ # what your implementation of parse returned, +nil+ otherwise.
+ def search(key)
from = 0
to = @db_size - 1
pivot = nil
while from < to
middle = (from + to) / 2
pivot = read(middle)
- if lt(record, pivot)
+ if lt(key, pivot)
to = middle
next
- elsif gt(record, pivot)
+ elsif gt(key, pivot)
from = middle + 1
next
end
result = nil
- result = pivot if eq(record, pivot)
+ result = pivot if eq(key, pivot)
return result
end
if from == to
pivot = read(from)
return pivot if eq(pivot, pivot)
end
end
- def read(offset)
- @db_idx.seek(offset * INDEX_SIZE)
+ protected
+
+ # Reads and parses the line at position +index+.
+ def read(index)
+ @db_idx.seek(index * INDEX_SIZE)
pos = @db_idx.readbytes(INDEX_SIZE).unpack('L')[0]
@db.seek(pos)
parse(@db.gets)
end
+ # Parse a record read from the file. This method raises an exception.
+ # You must implement this method to parse the file according to your needs.
def parse(what)
raise 'you must implemented this method!'
end
+ # Compares two records read from the file and checks whether +a+ is
+ # greater than +b+. This method raises an exception; you must implement
+ # it in your subclass to compare records according to your needs.
def gt(a, b)
raise 'you must implemented this method!'
end
+ # Compares two records read from the file and checks whether +a+ is less
+ # than +b+. It's implemented using #gt and #eq.
def lt(a, b)
not gt(a, b) and not eq(a, b)
end
+ # Checks if two records are the same. This method raises an exception; you
+ # must implement it in your subclass to compare records according to your
+ # needs.
def eq(a, b)
raise 'you must implemented this method!'
end
end