require 'external/io' require 'external/chunkable' require 'external/enumerable' require 'tempfile' module External #-- # Base provides the basic array functionality shared by ExtArr and Index, # essentially wrapping the IO functions required to access and utilized external # array data with the standard array functions. Bases can be opened with # in any of the IO modes; the capabilities of Base will be reduced accordingly # (ie read-only Bases cannot write values using []=, for instance). # # It is VERY IMPORTANT to realize that the underlying IO will be opened using the # given mode. The 'w' mode will overwrite all existing data; 'r+' is a safer mode # for full read-write functionality. Note that since Base actively scans over # the IO, append modes essentially behaves like write, but does not overwrite existing # data. # # To work properly, Base must be subclassed with methods: # * length # * io_fetch #++ # # class Base class << self def open(fd=nil, mode="r", options={}) fd = File.open(fd, mode) unless fd == nil ab = self.new(fd, options) if block_given? begin yield(ab) ensure ab.close end else ab end end end include External::Enumerable include External::Chunkable attr_reader :io # Initializes a new Base given the file descriptor, mode and options. # (see open_io for details on what io is opened for a given file descriptor) # # If mode contains an 's', then the Base will be initialized in strio # mode where the underlying IO will be a StringIO. In this case the fd # will be used as the string to initialize the StringIO. # # Standard options for Base include: # nil_value:: the value written to file for nils, and converted to nil on read # (default ' ') # max_gap:: the maximum gap size used by Offset (default 10000) # max_chunk_size:: the chunk size used by Offset (default 1M) def initialize(io=nil) self.io = (io.nil? ? Tempfile.new("array_base") : io) end # True if io is closed. def closed? io.closed? end # Closes io. def close io.close unless io.closed? end protected # Sets io and extends the input io with External::Position. def io=(io) io.extend External::IO unless io.kind_of?(External::IO) @io = io end end end