summaryrefslogtreecommitdiffhomepage
path: root/mrblib
diff options
context:
space:
mode:
authorAkira Yumiyama <[email protected]>2013-04-01 09:12:01 +0900
committerAkira Yumiyama <[email protected]>2013-04-01 09:12:01 +0900
commite8ca5e516983fe720ec46887744f0d21b8f16ce1 (patch)
treee2c5dc2aab35cab78365f45918f140d82dcb45dd /mrblib
downloadmruby-e8ca5e516983fe720ec46887744f0d21b8f16ce1.tar.gz
mruby-e8ca5e516983fe720ec46887744f0d21b8f16ce1.zip
initial commit
Diffstat (limited to 'mrblib')
-rw-r--r--mrblib/file.rb108
-rw-r--r--mrblib/file_constants.rb31
-rw-r--r--mrblib/io.rb271
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