mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
375 lines
6.0 KiB
Ruby
375 lines
6.0 KiB
Ruby
##
|
|
# IO
|
|
|
|
class IOError < StandardError; end
|
|
class EOFError < IOError; end
|
|
|
|
class IO
|
|
SEEK_SET = 0
|
|
SEEK_CUR = 1
|
|
SEEK_END = 2
|
|
|
|
BUF_SIZE = 4096
|
|
|
|
def self.for_fd *args
|
|
self.new(*args)
|
|
end
|
|
|
|
def self.open(*args, &block)
|
|
io = self.new(*args)
|
|
|
|
return io unless block
|
|
|
|
begin
|
|
yield io
|
|
ensure
|
|
begin
|
|
io.close unless io.closed?
|
|
rescue StandardError
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.popen(command, mode = 'r', &block)
|
|
io = self._popen(command, mode)
|
|
return io unless block
|
|
|
|
begin
|
|
yield io
|
|
ensure
|
|
begin
|
|
io.close unless io.closed?
|
|
rescue IOError
|
|
# nothing
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
def self.read(path, length=nil, offset=nil, opt=nil)
|
|
if not opt.nil? # 4 arguments
|
|
offset ||= 0
|
|
elsif not offset.nil? # 3 arguments
|
|
if offset.is_a? Hash
|
|
opt = offset
|
|
offset = 0
|
|
else
|
|
opt = {}
|
|
end
|
|
elsif not length.nil? # 2 arguments
|
|
if length.is_a? Hash
|
|
opt = length
|
|
offset = 0
|
|
length = nil
|
|
else
|
|
offset = 0
|
|
opt = {}
|
|
end
|
|
else # only 1 argument
|
|
opt = {}
|
|
offset = 0
|
|
length = nil
|
|
end
|
|
|
|
str = ""
|
|
fd = -1
|
|
io = nil
|
|
begin
|
|
if path[0] == "|"
|
|
io = IO.popen(path[1..-1], (opt[:mode] || "r"))
|
|
else
|
|
fd = IO.sysopen(path)
|
|
io = IO.open(fd, opt[:mode] || "r")
|
|
end
|
|
io.seek(offset) if offset > 0
|
|
str = io.read(length)
|
|
ensure
|
|
if io
|
|
io.close
|
|
elsif fd != -1
|
|
IO._sysclose(fd)
|
|
end
|
|
end
|
|
str
|
|
end
|
|
|
|
def flush
|
|
# mruby-io always writes immediately (no output buffer).
|
|
raise IOError, "closed stream" if self.closed?
|
|
self
|
|
end
|
|
|
|
def write(string)
|
|
str = string.is_a?(String) ? string : string.to_s
|
|
return str.size unless str.size > 0
|
|
|
|
len = syswrite(str)
|
|
if len != -1
|
|
@pos += len
|
|
return len
|
|
end
|
|
|
|
raise IOError
|
|
end
|
|
|
|
def eof?
|
|
return true if @buf && @buf.size > 0
|
|
|
|
ret = false
|
|
char = ''
|
|
|
|
begin
|
|
char = sysread(1)
|
|
rescue EOFError => e
|
|
ret = true
|
|
ensure
|
|
_ungets(char)
|
|
end
|
|
|
|
ret
|
|
end
|
|
alias_method :eof, :eof?
|
|
|
|
def pos
|
|
raise IOError if closed?
|
|
@pos
|
|
end
|
|
alias_method :tell, :pos
|
|
|
|
def pos=(i)
|
|
seek(i, SEEK_SET)
|
|
end
|
|
|
|
def seek(i, whence = SEEK_SET)
|
|
raise IOError if closed?
|
|
@pos = sysseek(i, whence)
|
|
@buf = ''
|
|
0
|
|
end
|
|
|
|
def _read_buf
|
|
return @buf if @buf && @buf.size > 0
|
|
@buf = sysread(BUF_SIZE)
|
|
end
|
|
|
|
def _ungets(substr)
|
|
raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
|
|
raise IOError if @pos == 0 || @pos.nil?
|
|
@pos -= substr.size
|
|
if @buf.empty?
|
|
@buf = substr
|
|
else
|
|
@buf = substr + @buf
|
|
end
|
|
nil
|
|
end
|
|
|
|
def ungetc(char)
|
|
raise IOError if @pos == 0 || @pos.nil?
|
|
_ungets(char)
|
|
nil
|
|
end
|
|
|
|
def read(length = nil)
|
|
unless length.nil?
|
|
unless length.is_a? Fixnum
|
|
raise TypeError.new "can't convert #{length.class} into Integer"
|
|
end
|
|
if length < 0
|
|
raise ArgumentError.new "negative length: #{length} given"
|
|
end
|
|
if length == 0
|
|
return "" # easy case
|
|
end
|
|
end
|
|
|
|
str = ''
|
|
while 1
|
|
begin
|
|
_read_buf
|
|
rescue EOFError => e
|
|
str = nil if str.empty? and (not length.nil?) and length != 0
|
|
break
|
|
end
|
|
|
|
if length && (str.size + @buf.size) >= length
|
|
len = length - str.size
|
|
str += @buf[0, len]
|
|
@pos += len
|
|
@buf = @buf[len, @buf.size - len]
|
|
break
|
|
else
|
|
str += @buf
|
|
@pos += @buf.size
|
|
@buf = ''
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
|
|
def readline(arg = $/, limit = nil)
|
|
case arg
|
|
when String
|
|
rs = arg
|
|
when Fixnum
|
|
rs = $/
|
|
limit = arg
|
|
else
|
|
raise ArgumentError
|
|
end
|
|
|
|
if rs.nil?
|
|
return read
|
|
end
|
|
|
|
if rs == ""
|
|
rs = $/ + $/
|
|
end
|
|
|
|
str = ""
|
|
while 1
|
|
begin
|
|
_read_buf
|
|
rescue EOFError => e
|
|
str = nil if str.empty?
|
|
break
|
|
end
|
|
|
|
if limit && (str.size + @buf.size) >= limit
|
|
len = limit - str.size
|
|
str += @buf[0, len]
|
|
@pos += len
|
|
@buf = @buf[len, @buf.size - len]
|
|
break
|
|
elsif idx = @buf.index(rs)
|
|
len = idx + rs.size
|
|
str += @buf[0, len]
|
|
@pos += len
|
|
@buf = @buf[len, @buf.size - len]
|
|
break
|
|
else
|
|
str += @buf
|
|
@pos += @buf.size
|
|
@buf = ''
|
|
end
|
|
end
|
|
|
|
raise EOFError.new "end of file reached" if str.nil?
|
|
|
|
str
|
|
end
|
|
|
|
def gets(*args)
|
|
begin
|
|
readline(*args)
|
|
rescue EOFError => e
|
|
nil
|
|
end
|
|
end
|
|
|
|
def readchar
|
|
_read_buf
|
|
c = @buf[0]
|
|
@buf = @buf[1, @buf.size]
|
|
@pos += 1
|
|
c
|
|
end
|
|
|
|
def getc
|
|
begin
|
|
readchar
|
|
rescue EOFError => e
|
|
nil
|
|
end
|
|
end
|
|
|
|
# 15.2.20.5.3
|
|
def each(&block)
|
|
while line = self.gets
|
|
block.call(line)
|
|
end
|
|
self
|
|
end
|
|
|
|
# 15.2.20.5.4
|
|
def each_byte(&block)
|
|
while char = self.getc
|
|
block.call(char)
|
|
end
|
|
self
|
|
end
|
|
|
|
# 15.2.20.5.5
|
|
alias each_line each
|
|
|
|
alias each_char each_byte
|
|
|
|
def readlines
|
|
ary = []
|
|
while (line = gets)
|
|
ary << line
|
|
end
|
|
ary
|
|
end
|
|
|
|
def puts(*args)
|
|
i = 0
|
|
len = args.size
|
|
while i < len
|
|
s = args[i].to_s
|
|
write s
|
|
write "\n" if (s[-1] != "\n")
|
|
i += 1
|
|
end
|
|
write "\n" if len == 0
|
|
nil
|
|
end
|
|
|
|
def print(*args)
|
|
i = 0
|
|
len = args.size
|
|
while i < len
|
|
write args[i].to_s
|
|
i += 1
|
|
end
|
|
end
|
|
|
|
def printf(*args)
|
|
write sprintf(*args)
|
|
nil
|
|
end
|
|
|
|
alias_method :to_i, :fileno
|
|
end
|
|
|
|
STDIN = IO.open(0, "r")
|
|
STDOUT = IO.open(1, "w")
|
|
STDERR = IO.open(2, "w")
|
|
|
|
$stdin = STDIN
|
|
$stdout = STDOUT
|
|
$stderr = STDERR
|
|
|
|
module Kernel
|
|
def print(*args)
|
|
STDOUT.print(*args)
|
|
end
|
|
|
|
def puts(*args)
|
|
STDOUT.puts(*args)
|
|
end
|
|
|
|
def printf(*args)
|
|
STDOUT.printf(*args)
|
|
end
|
|
|
|
def gets(*args)
|
|
STDIN.gets(*args)
|
|
end
|
|
|
|
def getc(*args)
|
|
STDIN.getc(*args)
|
|
end
|
|
end
|