diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-12-07 18:11:06 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-12-07 18:11:06 +0900 |
| commit | d75266dd1bade53255044460a9cd74596addaa84 (patch) | |
| tree | ac97feb393da5597855dd8f79a7b8feba17c5c14 /mrbgems/mruby-io/mrblib | |
| parent | 10ed730e4bd921cf4d8fe6f6d2e3cb3f0840f3b7 (diff) | |
| parent | 3c8e1f94c44252c836f79a48bb17726da28e2756 (diff) | |
| download | mruby-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.rb | 208 | ||||
| -rw-r--r-- | mrbgems/mruby-io/mrblib/file_constants.rb | 29 | ||||
| -rw-r--r-- | mrbgems/mruby-io/mrblib/io.rb | 387 | ||||
| -rw-r--r-- | mrbgems/mruby-io/mrblib/kernel.rb | 15 |
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 |
