diff options
| author | Akira Yumiyama <[email protected]> | 2013-04-01 09:12:01 +0900 |
|---|---|---|
| committer | Akira Yumiyama <[email protected]> | 2013-04-01 09:12:01 +0900 |
| commit | e8ca5e516983fe720ec46887744f0d21b8f16ce1 (patch) | |
| tree | e2c5dc2aab35cab78365f45918f140d82dcb45dd /mrblib | |
| download | mruby-e8ca5e516983fe720ec46887744f0d21b8f16ce1.tar.gz mruby-e8ca5e516983fe720ec46887744f0d21b8f16ce1.zip | |
initial commit
Diffstat (limited to 'mrblib')
| -rw-r--r-- | mrblib/file.rb | 108 | ||||
| -rw-r--r-- | mrblib/file_constants.rb | 31 | ||||
| -rw-r--r-- | mrblib/io.rb | 271 |
3 files changed, 410 insertions, 0 deletions
diff --git a/mrblib/file.rb b/mrblib/file.rb new file mode 100644 index 000000000..566085066 --- /dev/null +++ b/mrblib/file.rb @@ -0,0 +1,108 @@ +class File < IO + include Enumerable + + 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) + self._bless + if fd_or_path.kind_of? Fixnum + super(fd_or_path, mode) + else + @path = fd_or_path + + perm = 0666 unless perm.is_a? Fixnum + fd = IO.sysopen(@path, mode, perm) + if fd < 0 && Object.const_defined?(:Errno) + begin + Errno.handle @path + rescue Errno::EMFILE + GC.run(true) + fd = IO.sysopen(@path, mode, perm) + Errno.handle if fd < 0 + end + elsif fd < 0 + raise NoFileError.new "no such file or directory" + end + super(fd, mode) + end + end + + def self.join(*names) + if names.size == 0 + "" + elsif names.size == 1 + names[0] + else + 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 + 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.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 +end diff --git a/mrblib/file_constants.rb b/mrblib/file_constants.rb new file mode 100644 index 000000000..c2552bf56 --- /dev/null +++ b/mrblib/file_constants.rb @@ -0,0 +1,31 @@ +class File + module Constants + NULL = "/dev/null" + + 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/mrblib/io.rb b/mrblib/io.rb new file mode 100644 index 000000000..3c679d3f7 --- /dev/null +++ b/mrblib/io.rb @@ -0,0 +1,271 @@ +## +# 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(fd, mode = "r", opt = {}, &block) + io = self.new(fd, mode, opt) + + 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 write(string) + str = string.is_a?(String) ? string : string.to_s + return str.size unless str.size > 0 + + len = syswrite(str) + if str.size == len + @pos += len + return len + end + + raise IOError + end + + def eof? + # XXX: @buf のことを考えなくてよい?? + 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? or length.class == Fixnum + raise TypeError.new "can't convert #{length.class} into Integer" + end + if length && length < 0 + raise ArgumentError.new "negative length: #{length} given" + end + + str = '' + while 1 + begin + _read_buf + rescue EOFError => e + str = nil if str.empty? + 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 printf(*args) + write sprintf(*args) + nil + end + + alias_method :to_i, :fileno +end |
