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