first commit
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
class File < IO
|
||||
attr_accessor :path
|
||||
|
||||
def initialize(fd_or_path, mode = "r", perm = 0666)
|
||||
if fd_or_path.kind_of? Fixnum
|
||||
super(fd_or_path, mode)
|
||||
else
|
||||
@path = fd_or_path
|
||||
fd = IO.sysopen(@path, mode, perm)
|
||||
super(fd, mode)
|
||||
end
|
||||
end
|
||||
|
||||
def self.join(*names)
|
||||
return "" if names.empty?
|
||||
|
||||
names.map! do |name|
|
||||
case name
|
||||
when String
|
||||
name
|
||||
when Array
|
||||
if names == name
|
||||
raise ArgumentError, "recursive array"
|
||||
end
|
||||
join(*name)
|
||||
else
|
||||
raise TypeError, "no implicit conversion of #{name.class} into String"
|
||||
end
|
||||
end
|
||||
|
||||
return names[0] if names.size == 1
|
||||
|
||||
if names[0][-1] == File::SEPARATOR
|
||||
s = names[0][0..-2]
|
||||
else
|
||||
s = names[0].dup
|
||||
end
|
||||
|
||||
(1..names.size-2).each { |i|
|
||||
t = names[i]
|
||||
if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
|
||||
t = t[1..-2]
|
||||
elsif t[0] == File::SEPARATOR
|
||||
t = t[1..-1]
|
||||
elsif t[-1] == File::SEPARATOR
|
||||
t = t[0..-2]
|
||||
end
|
||||
s += File::SEPARATOR + t if t != ""
|
||||
}
|
||||
if names[-1][0] == File::SEPARATOR
|
||||
s += File::SEPARATOR + names[-1][1..-1]
|
||||
else
|
||||
s += File::SEPARATOR + names[-1]
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def self._concat_path(path, base_path)
|
||||
if path[0] == "/" || path[1] == ':' # Windows root!
|
||||
expanded_path = path
|
||||
elsif path[0] == "~"
|
||||
if (path[1] == "/" || path[1] == nil)
|
||||
dir = path[1, path.size]
|
||||
home_dir = _gethome
|
||||
|
||||
unless home_dir
|
||||
raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
|
||||
end
|
||||
|
||||
expanded_path = home_dir
|
||||
expanded_path += dir if dir
|
||||
expanded_path += "/"
|
||||
else
|
||||
splitted_path = path.split("/")
|
||||
user = splitted_path[0][1, splitted_path[0].size]
|
||||
dir = "/" + splitted_path[1, splitted_path.size].join("/")
|
||||
|
||||
home_dir = _gethome(user)
|
||||
|
||||
unless home_dir
|
||||
raise ArgumentError, "user #{user} doesn't exist"
|
||||
end
|
||||
|
||||
expanded_path = home_dir
|
||||
expanded_path += dir if dir
|
||||
expanded_path += "/"
|
||||
end
|
||||
else
|
||||
expanded_path = _concat_path(base_path, _getwd)
|
||||
expanded_path += "/" + path
|
||||
end
|
||||
|
||||
expanded_path
|
||||
end
|
||||
|
||||
def self.expand_path(path, default_dir = '.')
|
||||
expanded_path = _concat_path(path, default_dir)
|
||||
drive_prefix = ""
|
||||
if File::ALT_SEPARATOR && expanded_path.size > 2 &&
|
||||
("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
|
||||
drive_prefix = expanded_path[0, 2]
|
||||
expanded_path = expanded_path[2, expanded_path.size]
|
||||
end
|
||||
expand_path_array = []
|
||||
if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
|
||||
expanded_path.gsub!(File::ALT_SEPARATOR, '/')
|
||||
end
|
||||
while expanded_path.include?('//')
|
||||
expanded_path = expanded_path.gsub('//', '/')
|
||||
end
|
||||
|
||||
if expanded_path != "/"
|
||||
expanded_path.split('/').each do |path_token|
|
||||
if path_token == '..'
|
||||
if expand_path_array.size > 1
|
||||
expand_path_array.pop
|
||||
end
|
||||
elsif path_token == '.'
|
||||
# nothing to do.
|
||||
else
|
||||
expand_path_array << path_token
|
||||
end
|
||||
end
|
||||
|
||||
expanded_path = expand_path_array.join("/")
|
||||
if expanded_path.empty?
|
||||
expanded_path = '/'
|
||||
end
|
||||
end
|
||||
if drive_prefix.empty?
|
||||
expanded_path
|
||||
else
|
||||
drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
|
||||
end
|
||||
end
|
||||
|
||||
def self.foreach(file)
|
||||
if block_given?
|
||||
self.open(file) do |f|
|
||||
f.each {|l| yield l}
|
||||
end
|
||||
else
|
||||
return self.new(file)
|
||||
end
|
||||
end
|
||||
|
||||
def self.directory?(file)
|
||||
FileTest.directory?(file)
|
||||
end
|
||||
|
||||
def self.exist?(file)
|
||||
FileTest.exist?(file)
|
||||
end
|
||||
|
||||
def self.exists?(file)
|
||||
FileTest.exists?(file)
|
||||
end
|
||||
|
||||
def self.file?(file)
|
||||
FileTest.file?(file)
|
||||
end
|
||||
|
||||
def self.pipe?(file)
|
||||
FileTest.pipe?(file)
|
||||
end
|
||||
|
||||
def self.size(file)
|
||||
FileTest.size(file)
|
||||
end
|
||||
|
||||
def self.size?(file)
|
||||
FileTest.size?(file)
|
||||
end
|
||||
|
||||
def self.socket?(file)
|
||||
FileTest.socket?(file)
|
||||
end
|
||||
|
||||
def self.symlink?(file)
|
||||
FileTest.symlink?(file)
|
||||
end
|
||||
|
||||
def self.zero?(file)
|
||||
FileTest.zero?(file)
|
||||
end
|
||||
|
||||
def self.extname(filename)
|
||||
fname = self.basename(filename)
|
||||
return '' if fname[0] == '.' || fname.index('.').nil?
|
||||
ext = fname.split('.').last
|
||||
ext.empty? ? '' : ".#{ext}"
|
||||
end
|
||||
|
||||
def self.path(filename)
|
||||
if filename.kind_of?(String)
|
||||
filename
|
||||
elsif filename.respond_to?(:to_path)
|
||||
filename.to_path
|
||||
else
|
||||
raise TypeError, "no implicit conversion of #{filename.class} into String"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
class File
|
||||
module Constants
|
||||
FNM_SYSCASE = 0
|
||||
FNM_NOESCAPE = 1
|
||||
FNM_PATHNAME = 2
|
||||
FNM_DOTMATCH = 4
|
||||
FNM_CASEFOLD = 8
|
||||
end
|
||||
end
|
||||
|
||||
class File
|
||||
include File::Constants
|
||||
end
|
||||
@@ -0,0 +1,369 @@
|
||||
##
|
||||
# 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.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', opts={}, &block)
|
||||
if !self.respond_to?(:_popen)
|
||||
raise NotImplementedError, "popen is not supported on this platform"
|
||||
end
|
||||
io = self._popen(command, mode, opts)
|
||||
return io unless block
|
||||
|
||||
begin
|
||||
yield io
|
||||
ensure
|
||||
begin
|
||||
io.close unless io.closed?
|
||||
rescue IOError
|
||||
# nothing
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.pipe(&block)
|
||||
if !self.respond_to?(:_pipe)
|
||||
raise NotImplementedError, "pipe is not supported on this platform"
|
||||
end
|
||||
if block
|
||||
begin
|
||||
r, w = IO._pipe
|
||||
yield r, w
|
||||
ensure
|
||||
r.close unless r.closed?
|
||||
w.close unless w.closed?
|
||||
end
|
||||
else
|
||||
IO._pipe
|
||||
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
|
||||
mode = opt[:mode] || "r"
|
||||
fd = IO.sysopen(path, mode)
|
||||
io = IO.open(fd, mode)
|
||||
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 hash
|
||||
# We must define IO#hash here because IO includes Enumerable and
|
||||
# Enumerable#hash will call IO#read...
|
||||
self.__id__
|
||||
end
|
||||
|
||||
def write(string)
|
||||
str = string.is_a?(String) ? string : string.to_s
|
||||
return 0 if str.empty?
|
||||
unless @buf.empty?
|
||||
# reset real pos ignore buf
|
||||
seek(pos, SEEK_SET)
|
||||
end
|
||||
len = syswrite(str)
|
||||
len
|
||||
end
|
||||
|
||||
def <<(str)
|
||||
write(str)
|
||||
self
|
||||
end
|
||||
|
||||
def eof?
|
||||
_check_readable
|
||||
begin
|
||||
_read_buf
|
||||
return @buf.empty?
|
||||
rescue EOFError
|
||||
return true
|
||||
end
|
||||
end
|
||||
alias_method :eof, :eof?
|
||||
|
||||
def pos
|
||||
raise IOError if closed?
|
||||
sysseek(0, SEEK_CUR) - @buf.bytesize
|
||||
end
|
||||
alias_method :tell, :pos
|
||||
|
||||
def pos=(i)
|
||||
seek(i, SEEK_SET)
|
||||
end
|
||||
|
||||
def rewind
|
||||
seek(0, SEEK_SET)
|
||||
end
|
||||
|
||||
def seek(i, whence = SEEK_SET)
|
||||
raise IOError if closed?
|
||||
sysseek(i, whence)
|
||||
@buf = ''
|
||||
0
|
||||
end
|
||||
|
||||
def _read_buf
|
||||
return @buf if @buf && @buf.bytesize > 0
|
||||
sysread(BUF_SIZE, @buf)
|
||||
end
|
||||
|
||||
def ungetc(substr)
|
||||
raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
|
||||
if @buf.empty?
|
||||
@buf.replace(substr)
|
||||
else
|
||||
@buf[0,0] = substr
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def read(length = nil, outbuf = "")
|
||||
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
|
||||
|
||||
array = []
|
||||
while 1
|
||||
begin
|
||||
_read_buf
|
||||
rescue EOFError
|
||||
array = nil if array.empty? and (not length.nil?) and length != 0
|
||||
break
|
||||
end
|
||||
|
||||
if length
|
||||
consume = (length <= @buf.bytesize) ? length : @buf.bytesize
|
||||
array.push IO._bufread(@buf, consume)
|
||||
length -= consume
|
||||
break if length == 0
|
||||
else
|
||||
array.push @buf
|
||||
@buf = ''
|
||||
end
|
||||
end
|
||||
|
||||
if array.nil?
|
||||
outbuf.replace("")
|
||||
nil
|
||||
else
|
||||
outbuf.replace(array.join)
|
||||
end
|
||||
end
|
||||
|
||||
def readline(arg = "\n", limit = nil)
|
||||
case arg
|
||||
when String
|
||||
rs = arg
|
||||
when Fixnum
|
||||
rs = "\n"
|
||||
limit = arg
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
|
||||
if rs.nil?
|
||||
return read
|
||||
end
|
||||
|
||||
if rs == ""
|
||||
rs = "\n\n"
|
||||
end
|
||||
|
||||
array = []
|
||||
while 1
|
||||
begin
|
||||
_read_buf
|
||||
rescue EOFError
|
||||
array = nil if array.empty?
|
||||
break
|
||||
end
|
||||
|
||||
if limit && limit <= @buf.size
|
||||
array.push @buf[0, limit]
|
||||
@buf[0, limit] = ""
|
||||
break
|
||||
elsif idx = @buf.index(rs)
|
||||
len = idx + rs.size
|
||||
array.push @buf[0, len]
|
||||
@buf[0, len] = ""
|
||||
break
|
||||
else
|
||||
array.push @buf
|
||||
@buf = ''
|
||||
end
|
||||
end
|
||||
|
||||
raise EOFError.new "end of file reached" if array.nil?
|
||||
|
||||
array.join
|
||||
end
|
||||
|
||||
def gets(*args)
|
||||
begin
|
||||
readline(*args)
|
||||
rescue EOFError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def readchar
|
||||
_read_buf
|
||||
_readchar(@buf)
|
||||
end
|
||||
|
||||
def getc
|
||||
begin
|
||||
readchar
|
||||
rescue EOFError
|
||||
c = @buf[0]
|
||||
@buf[0,1]="" if c
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# 15.2.20.5.3
|
||||
def each(&block)
|
||||
return to_enum unless block
|
||||
|
||||
while line = self.gets
|
||||
block.call(line)
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
# 15.2.20.5.4
|
||||
def each_byte(&block)
|
||||
return to_enum(:each_byte) unless 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
|
||||
alias_method :tty?, :isatty
|
||||
end
|
||||
|
||||
STDIN = IO.open(0, "r")
|
||||
STDOUT = IO.open(1, "w")
|
||||
STDERR = IO.open(2, "w")
|
||||
|
||||
$stdin = STDIN
|
||||
$stdout = STDOUT
|
||||
$stderr = STDERR
|
||||
@@ -0,0 +1,31 @@
|
||||
module Kernel
|
||||
def `(cmd)
|
||||
IO.popen(cmd) { |io| io.read }
|
||||
end
|
||||
|
||||
def open(file, *rest, &block)
|
||||
raise ArgumentError unless file.is_a?(String)
|
||||
|
||||
if file[0] == "|"
|
||||
IO.popen(file[1..-1], *rest, &block)
|
||||
else
|
||||
File.open(file, *rest, &block)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
Reference in New Issue
Block a user