require 'ext_arr' require 'stringio' require 'strscan' class ExtArc < ExtArr def str_to_entry(str) str end def entry_to_str(entry) entry.to_s end def reindex_by_scan(pattern=/\r?\n|$/) index_format = index.format reindex do |index| io.scan do |scan_pos, string| scanner = StringScanner.new(string) while advanced = scanner.search_full(pattern, true, false) break unless advanced > 0 index.unframed_write [scan_pos, advanced] scan_pos += advanced end scanner.restsize end end end def reindex_by_sep(options={}) options = { :sep_string => $/, :entry_follows_sep => false, :exclude_sep => false }.merge(options) sep_string = options[:sep_string] entry_follows_sep = options[:entry_follows_sep] exclude_sep = options[:exclude_sep] sep_string_length = sep_string.length reindex do |index| current_pos = 0 entry_begin = 0 io_length = io.length io.each_line(sep_string) do |line| # Note positions MUST be built up using line.length # io.pos cannot return positions greater than ~2.1e9 current_pos += line.length entry_end = current_pos - (entry_follows_sep && current_pos != io_length ? 1 : 0) unless entry_end == entry_begin if exclude_sep if entry_follows_sep entry_begin += sep_string_length else entry_end -= sep_string_length end end index.unframed_write [entry_begin, entry_end-entry_begin] entry_begin = entry_end end end end end def reindex_by_line(options={}) # :nodoc: options = { :sep_string => $/, :break_before => false, :exclude_break => false }.merge(options) sep_string = options[:sep_string] break_before = options[:break_before] exclude_break = options[:exclude_break] reindex do |index| last_pos = 0 current_pos = 0 range_begin = 0 io.each_line(sep_string) do |line| # Note positions MUST be built up using line.length # io.pos cannot return positions greater than ~2.1e9 last_pos = current_pos current_pos += line.length if (block_given? ? yield(line) : true) range_end = (break_before || exclude_break) ? last_pos : current_pos unless range_end == range_begin index.unframed_write [range_begin, range_end-range_begin] end range_begin = (break_before && !exclude_break) ? last_pos : current_pos end end range_end = current_pos unless range_end == range_begin index.unframed_write [range_begin, range_end-range_begin] end end end end