module FileBsearch

Constants

VERSION

Public Class Methods

exist?(*args) click to toggle source

args

returner

true  ... data is exist
false ... data is not exist
# File lib/file_bsearch/main.rb, line 11
def exist?(*args)

  # pass to index method
  # - true if returner is Integer
  index(*args).is_a?(Integer)
end
get_lines(file, prefix, encoding = nil, *args) click to toggle source

returner

Array object
# File lib/file_bsearch/get_lines.rb, line 8
def get_lines(file, prefix, encoding = nil, *args)

  file      = init_file(file, encoding)
  prefix    = prefix.to_s

  # pass to scan method
  pos = scan_around_lines_seed(file, prefix, *args)

  if pos.is_a?(Integer)

    file.seek(pos)
    lines  = file.around_lines(/^#{Regexp.escape(prefix)}/)
    result = lines.chomp.split(/[\r\n]+/) if lines.bytesize > 0
  end

  result || []
end
index(file, needle, encoding = nil, *args, &block) click to toggle source

args

file ... File object || path for String object

returner

position in target file
# File lib/file_bsearch/main.rb, line 23
def index(file, needle, encoding = nil, *args, &block)

  file = init_file(file, encoding)

  # pass to scan method
  scan(file, needle, *args, &block)
end
init_file(file, encoding) click to toggle source

args

file ... File object || path for String object

returner

File object
# File lib/file_bsearch/common.rb, line 69
def init_file(file, encoding)

  # check the file argument
  # - if not File object, open it as String for file path
  file = File.open(file.to_s) unless file.is_a?(File)
  FileCharLicker.attach(file, encoding)

  file
end
scan(file, needle, min = 0, max = nil, &block) click to toggle source

args

  file ... File object
needle ... search text
   min ... min of file pointer for search
   max ... max of file pointer for search
 block ... comparison process

returner

position in file
# File lib/file_bsearch/common.rb, line 17
def scan(file, needle, min = 0, max = nil, &block)

  max     ||= file.size
  block   ||= proc { |a, b| a <=> b }
  needle    = needle.to_s
  old_pos   = -1

  # reset pointer
  file.rewind

  # loop for search
  # - if over max point, not found
  # - if EOF, not found
  # - if pointer did not moved, not found
  while max > file.pos \
      && (line = file.current_line) \
      && file.pos != old_pos

    old_pos = file.pos
    code    = block.call(line.chomp, needle)

    # for debug
    # p "-- #{needle}, " + {
    #   text: line.chomp,
    #   code: code,
    #    min: min,
    #    max: max,
    #    pos: file.pos
    #   }.to_s
    # sleep 0.05

    # comparison
    # - if not match, update either range values
    # - if match, return
    case code
    when -1 then min = file.pos - 1
    when  1 then max = file.pos - line.bytesize
    else return file.pos - line.bytesize
    end

    # move to mid point
    file.seek((min + max) / 2)
  end

  false
end

Private Class Methods

scan_around_lines_seed(file, prefix, *args) click to toggle source
# File lib/file_bsearch/get_lines.rb, line 28
def scan_around_lines_seed(file, prefix, *args)
  scan(file, nil, *args) do |line|
    line[0, prefix.size] <=> prefix
  end
end