summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-io/mrblib
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-12-07 18:11:06 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-12-07 18:11:06 +0900
commitd75266dd1bade53255044460a9cd74596addaa84 (patch)
treeac97feb393da5597855dd8f79a7b8feba17c5c14 /mrbgems/mruby-io/mrblib
parent10ed730e4bd921cf4d8fe6f6d2e3cb3f0840f3b7 (diff)
parent3c8e1f94c44252c836f79a48bb17726da28e2756 (diff)
downloadmruby-d75266dd1bade53255044460a9cd74596addaa84.tar.gz
mruby-d75266dd1bade53255044460a9cd74596addaa84.zip
Add 'mrbgems/mruby-io/' from commit '3c8e1f94c44252c836f79a48bb17726da28e2756'
git-subtree-dir: mrbgems/mruby-io git-subtree-mainline: 10ed730e4bd921cf4d8fe6f6d2e3cb3f0840f3b7 git-subtree-split: 3c8e1f94c44252c836f79a48bb17726da28e2756
Diffstat (limited to 'mrbgems/mruby-io/mrblib')
-rw-r--r--mrbgems/mruby-io/mrblib/file.rb208
-rw-r--r--mrbgems/mruby-io/mrblib/file_constants.rb29
-rw-r--r--mrbgems/mruby-io/mrblib/io.rb387
-rw-r--r--mrbgems/mruby-io/mrblib/kernel.rb15
4 files changed, 639 insertions, 0 deletions
diff --git a/mrbgems/mruby-io/mrblib/file.rb b/mrbgems/mruby-io/mrblib/file.rb
new file mode 100644
index 000000000..514efc1c6
--- /dev/null
+++ b/mrbgems/mruby-io/mrblib/file.rb
@@ -0,0 +1,208 @@
+class File < IO
+ class FileError < Exception; end
+ class NoFileError < FileError; end
+ class UnableToStat < FileError; end
+ class PermissionError < FileError; end
+
+ 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.expand_path(path, default_dir = '.')
+ def 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
+
+ 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
diff --git a/mrbgems/mruby-io/mrblib/file_constants.rb b/mrbgems/mruby-io/mrblib/file_constants.rb
new file mode 100644
index 000000000..a68ee2598
--- /dev/null
+++ b/mrbgems/mruby-io/mrblib/file_constants.rb
@@ -0,0 +1,29 @@
+class File
+ module Constants
+ RDONLY = 0
+ WRONLY = 1
+ RDWR = 2
+ NONBLOCK = 4
+ APPEND = 8
+
+ BINARY = 0
+ SYNC = 128
+ NOFOLLOW = 256
+ CREAT = 512
+ TRUNC = 1024
+ EXCL = 2048
+
+ NOCTTY = 131072
+ DSYNC = 4194304
+
+ FNM_SYSCASE = 0
+ FNM_NOESCAPE = 1
+ FNM_PATHNAME = 2
+ FNM_DOTMATCH = 4
+ FNM_CASEFOLD = 8
+ end
+end
+
+class File
+ include File::Constants
+end
diff --git a/mrbgems/mruby-io/mrblib/io.rb b/mrbgems/mruby-io/mrblib/io.rb
new file mode 100644
index 000000000..02c8141c5
--- /dev/null
+++ b/mrbgems/mruby-io/mrblib/io.rb
@@ -0,0 +1,387 @@
+##
+# 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
+ 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 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 str.size unless str.size > 0
+ if 0 < @buf.length
+ # 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
+ buf = _read_buf
+ return buf.size == 0
+ rescue EOFError
+ return true
+ end
+ end
+ alias_method :eof, :eof?
+
+ def pos
+ raise IOError if closed?
+ sysseek(0, SEEK_CUR) - @buf.length
+ 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.size > 0
+ @buf = sysread(BUF_SIZE)
+ end
+
+ def ungetc(substr)
+ raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
+ if @buf.empty?
+ @buf = substr.dup
+ else
+ @buf = substr + @buf
+ 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.size) ? length : @buf.size
+ array.push @buf[0, consume]
+ @buf = @buf[consume, @buf.size - 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 = $/, 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
+
+ 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 = @buf[limit, @buf.size - limit]
+ break
+ elsif idx = @buf.index(rs)
+ len = idx + rs.size
+ array.push @buf[0, len]
+ @buf = @buf[len, @buf.size - 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
+ c = @buf[0]
+ @buf = @buf[1, @buf.size]
+ c
+ end
+
+ def getc
+ begin
+ readchar
+ rescue EOFError
+ 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
+ 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
+
+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
diff --git a/mrbgems/mruby-io/mrblib/kernel.rb b/mrbgems/mruby-io/mrblib/kernel.rb
new file mode 100644
index 000000000..373b76f98
--- /dev/null
+++ b/mrbgems/mruby-io/mrblib/kernel.rb
@@ -0,0 +1,15 @@
+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
+end