RUBY-240 Add StringIO methods to GridIO
This commit is contained in:
parent
db1213fc5d
commit
002ddb06fc
@ -168,6 +168,91 @@ module Mongo
|
||||
def tell
|
||||
@file_position
|
||||
end
|
||||
alias :pos :tell
|
||||
|
||||
# Rewind the file. This is equivalent to seeking to the zeroth position.
|
||||
#
|
||||
# @return [Integer] the position of the file after rewinding (always zero).
|
||||
def rewind
|
||||
raise GridError, "file not opened for read" unless @mode[0] == "r"
|
||||
seek(0)
|
||||
end
|
||||
|
||||
# Return a boolean indicating whether the position pointer is
|
||||
# at the end of the file.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def eof
|
||||
raise GridError, "file not opened for read" unless @mode[0] == "r"
|
||||
@file_position >= @file_length
|
||||
end
|
||||
alias :eof? :eof
|
||||
|
||||
# Return the next line from a GridFS file. This probably
|
||||
# makes sense only if you're storing plain text. This method
|
||||
# has a somewhat tricky API, which it inherits from Ruby's
|
||||
# StringIO#gets.
|
||||
#
|
||||
# @param [String, Integer] separator or length. If a separator,
|
||||
# read up to the separator. If a length, read the +length+ number
|
||||
# of bytes. If nil, read the entire file.
|
||||
# @param [Integer] length If a separator is provided, then
|
||||
# read until either finding the separator or
|
||||
# passing over the +length+ number of bytes.
|
||||
#
|
||||
# @return [String]
|
||||
def gets(separator="\n", length=nil)
|
||||
if separator.nil?
|
||||
read_all
|
||||
elsif separator.is_a?(Integer)
|
||||
read_length(separator)
|
||||
elsif separator.length > 1
|
||||
result = ''
|
||||
len = 0
|
||||
match_idx = 0
|
||||
match_num = separator.length - 1
|
||||
to_match = separator[match_idx]
|
||||
if length
|
||||
matcher = lambda {|idx, num| idx < num && len < length }
|
||||
else
|
||||
matcher = lambda {|idx, num| idx < num}
|
||||
end
|
||||
while matcher.call(match_idx, match_num) && char = getc
|
||||
result << char
|
||||
len += 1
|
||||
if char == to_match
|
||||
while match_idx < match_num do
|
||||
match_idx += 1
|
||||
to_match = separator[match_idx]
|
||||
char = getc
|
||||
result << char
|
||||
if char != to_match
|
||||
match_idx = 0
|
||||
to_match = separator[match_idx]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
else
|
||||
result = ''
|
||||
len = 0
|
||||
while char = getc
|
||||
result << char
|
||||
len += 1
|
||||
break if char == separator || (length ? len >= length : false)
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# Return the next byte from the GridFS file.
|
||||
#
|
||||
# @return [String]
|
||||
def getc
|
||||
read_length(1)
|
||||
end
|
||||
|
||||
# Creates or updates the document from the files collection that
|
||||
# stores the chunks' metadata. The file becomes available only after
|
||||
@ -256,7 +341,7 @@ module Mongo
|
||||
if length.nil?
|
||||
to_read = remaining
|
||||
else
|
||||
to_read = length > remaining ? remaining : length
|
||||
to_read = length > remaining ? remaining : length
|
||||
end
|
||||
return nil unless remaining > 0
|
||||
|
||||
|
@ -32,6 +32,78 @@ class GridIOTest < Test::Unit::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
context "StringIO methods" do
|
||||
setup do
|
||||
@filename = 'test'
|
||||
@mode = 'w'
|
||||
@data = "012345678\n" * 100000
|
||||
@file = GridIO.new(@files, @chunks, @filename, @mode)
|
||||
@file.write(@data)
|
||||
@file.close
|
||||
end
|
||||
|
||||
should "read data character by character using" do
|
||||
bytes = 0
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
while char = file.getc
|
||||
bytes += 1
|
||||
end
|
||||
assert_equal bytes, 1_000_000
|
||||
end
|
||||
|
||||
should "read length is a length is given" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.gets(1000)
|
||||
assert_equal string.length, 1000
|
||||
bytes = 0
|
||||
bytes += string.length
|
||||
while string = file.gets(1000)
|
||||
bytes += string.length
|
||||
end
|
||||
assert_equal bytes, 1_000_000
|
||||
end
|
||||
|
||||
should "read to the end of the line by default and assign to $_" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.gets
|
||||
assert_equal 10, string.length
|
||||
end
|
||||
|
||||
should "read to a given separator" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.gets("5")
|
||||
assert_equal 6, string.length
|
||||
end
|
||||
|
||||
should "read a multi-character separator" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.gets("45")
|
||||
assert_equal 6, string.length
|
||||
string = file.gets("45")
|
||||
assert_equal "678\n012345", string
|
||||
string = file.gets("\n01")
|
||||
assert_equal "678\n01", string
|
||||
end
|
||||
|
||||
should "read a mult-character separator with a length" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.gets("45", 3)
|
||||
assert_equal 3, string.length
|
||||
end
|
||||
|
||||
should "tell position, eof, and rewind" do
|
||||
file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
|
||||
string = file.read(1000)
|
||||
assert_equal 1000, file.pos
|
||||
assert !file.eof?
|
||||
file.read
|
||||
assert file.eof?
|
||||
file.rewind
|
||||
assert_equal 0, file.pos
|
||||
assert_equal 1_000_000, file.read.length
|
||||
end
|
||||
end
|
||||
|
||||
context "Seeking" do
|
||||
setup do
|
||||
@filename = 'test'
|
||||
|
Loading…
Reference in New Issue
Block a user