RUBY-240 Add StringIO methods to GridIO
This commit is contained in:
parent
db1213fc5d
commit
002ddb06fc
|
@ -168,6 +168,91 @@ module Mongo
|
||||||
def tell
|
def tell
|
||||||
@file_position
|
@file_position
|
||||||
end
|
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
|
# Creates or updates the document from the files collection that
|
||||||
# stores the chunks' metadata. The file becomes available only after
|
# stores the chunks' metadata. The file becomes available only after
|
||||||
|
@ -256,7 +341,7 @@ module Mongo
|
||||||
if length.nil?
|
if length.nil?
|
||||||
to_read = remaining
|
to_read = remaining
|
||||||
else
|
else
|
||||||
to_read = length > remaining ? remaining : length
|
to_read = length > remaining ? remaining : length
|
||||||
end
|
end
|
||||||
return nil unless remaining > 0
|
return nil unless remaining > 0
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,78 @@ class GridIOTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
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
|
context "Seeking" do
|
||||||
setup do
|
setup do
|
||||||
@filename = 'test'
|
@filename = 'test'
|
||||||
|
|
Loading…
Reference in New Issue