summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPaolo Bosetti <[email protected]>2014-03-03 13:15:57 +0100
committerPaolo Bosetti <[email protected]>2014-03-03 13:15:57 +0100
commitd9f3fd868a1c4778dbd7119a00c79ef020dc6048 (patch)
treee81ddb23d69030748e524148427fee7a5ba22f56
parentee2859de6e8c95335db65746775737ad1bff35c8 (diff)
parentf7c054bd39f0809641ab474771f0f85a5282c72e (diff)
downloadmruby-d9f3fd868a1c4778dbd7119a00c79ef020dc6048.tar.gz
mruby-d9f3fd868a1c4778dbd7119a00c79ef020dc6048.zip
Merge branch 'master' of https://github.com/iij/mruby-io into test
Conflicts: src/io.c
-rw-r--r--README.md46
-rw-r--r--mrblib/file.rb1
-rw-r--r--mrblib/io.rb55
-rw-r--r--src/file.c5
-rw-r--r--src/file_test.c5
-rw-r--r--src/io.c48
-rw-r--r--test/io.rb25
7 files changed, 138 insertions, 47 deletions
diff --git a/README.md b/README.md
index 51b6d1851..ee7d640eb 100644
--- a/README.md
+++ b/README.md
@@ -4,28 +4,6 @@ mruby-io
IO, File module for mruby
-## License
-
-Copyright (c) 2013 Internet Initiative Japan Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
## Implemented methods
### IO
@@ -40,7 +18,7 @@ DEALINGS IN THE SOFTWARE.
| IO.foreach | | |
| IO.pipe | | |
| IO.popen | o | |
-| IO.read | | |
+| IO.read | o | |
| IO.readlines | | |
| IO.select | | |
| IO.sysopen | o | |
@@ -183,3 +161,25 @@ DEALINGS IN THE SOFTWARE.
| File#size | | |
| File#truncate | | |
+
+## License
+
+Copyright (c) 2013 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/mrblib/file.rb b/mrblib/file.rb
index aaa88616f..4087593a5 100644
--- a/mrblib/file.rb
+++ b/mrblib/file.rb
@@ -9,7 +9,6 @@ class File < IO
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
diff --git a/mrblib/io.rb b/mrblib/io.rb
index ca687aee0..4c69a4b99 100644
--- a/mrblib/io.rb
+++ b/mrblib/io.rb
@@ -41,6 +41,59 @@ class IO
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).
+ self
+ end
+
def write(string)
str = string.is_a?(String) ? string : string.to_s
return str.size unless str.size > 0
@@ -125,7 +178,7 @@ class IO
begin
_read_buf
rescue EOFError => e
- str = nil if str.empty?
+ str = nil if str.empty? and (not length.nil?) and length != 0
break
end
diff --git a/src/file.c b/src/file.c
index 7868eafaf..324cc81f2 100644
--- a/src/file.c
+++ b/src/file.c
@@ -8,7 +8,12 @@
#include "mruby/class.h"
#include "mruby/data.h"
#include "mruby/string.h"
+
+#if MRUBY_RELEASE_NO < 10000
#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
#include <fcntl.h>
#include <limits.h>
diff --git a/src/file_test.c b/src/file_test.c
index 792440547..37b139c78 100644
--- a/src/file_test.c
+++ b/src/file_test.c
@@ -8,7 +8,12 @@
#include "mruby/class.h"
#include "mruby/data.h"
#include "mruby/string.h"
+
+#if MRUBY_RELEASE_NO < 10000
#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
#if defined(_WIN32) || defined(_WIN64)
#define LSTAT stat
diff --git a/src/io.c b/src/io.c
index 7b9b23b18..c8318e4a1 100644
--- a/src/io.c
+++ b/src/io.c
@@ -3,16 +3,19 @@
*/
#include "mruby.h"
-
#include "mruby/hash.h"
-#include "mruby/data.h"
-#include "mruby/khash.h"
#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/data.h"
#include "mruby/string.h"
#include "mruby/variable.h"
#include "mruby/ext/io.h"
+
+#if MRUBY_RELEASE_NO < 10000
#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
#if defined(_WIN32) || defined(_WIN64)
#include <io.h>
@@ -25,9 +28,16 @@
#endif
static int mrb_io_modestr_to_flags(mrb_state *mrb, const char *modestr);
-static int mrb_io_modenum_to_flags(mrb_state *mrb, int modenum);
static int mrb_io_flags_to_modenum(mrb_state *mrb, int flags);
+#if MRUBY_RELEASE_NO < 10000
+static struct RClass *
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_class_get(mrb, name);
+}
+#endif
+
static int
mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
{
@@ -371,26 +381,22 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int noraise)
}
mrb_value
-mrb_io_bless(mrb_state *mrb, mrb_value io)
+mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
{
- if (mrb_type(io) != MRB_TT_DATA) {
- mrb_raise(mrb, E_TYPE_ERROR, "expected IO object");
- return mrb_nil_value();
- }
-
- DATA_TYPE(io) = &mrb_io_type;
- DATA_PTR(io) = NULL;
- DATA_PTR(io) = mrb_io_alloc(mrb);
+ mrb_value io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
- return io;
+ return mrb_io_initialize(mrb, io);
}
mrb_value
-mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
+mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
{
- mrb_value io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
-
- return mrb_io_initialize(mrb, io);
+ mrb_int fd;
+ mrb_get_args(mrb, "i", &fd);
+ if (close(fd) == -1) {
+ mrb_sys_fail(mrb, "close");
+ }
+ return mrb_fixnum_value(0);
}
mrb_value
@@ -549,7 +555,7 @@ mrb_io_pid(mrb_state *mrb, mrb_value io)
static struct timeval
time2timeval(mrb_state *mrb, mrb_value time)
{
- struct timeval t;
+ struct timeval t = { 0, 0 };
switch (mrb_type(time)) {
case MRB_TT_FIXNUM:
@@ -762,12 +768,12 @@ mrb_init_io(mrb_state *mrb)
mrb_include_module(mrb, io, mrb_module_get(mrb, "Enumerable")); /* 15.2.20.3 */
#ifndef _WIN32
mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, io, "_sysclose", mrb_io_s_sysclose, MRB_ARGS_REQ(1));
#endif
mrb_define_class_method(mrb, io, "for_fd", mrb_io_s_for_fd, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(2));
- mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ANY());
mrb_define_class_method(mrb, io, "select", mrb_io_s_select, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ANY());
- mrb_define_method(mrb, io, "_bless", mrb_io_bless, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/
mrb_define_method(mrb, io, "sysread", mrb_io_sysread, MRB_ARGS_ANY());
mrb_define_method(mrb, io, "sysseek", mrb_io_sysseek, MRB_ARGS_REQ(1));
diff --git a/test/io.rb b/test/io.rb
index 49a2a3f97..02507a9d4 100644
--- a/test/io.rb
+++ b/test/io.rb
@@ -130,7 +130,7 @@ assert('IO#read') do
io = IO.new fd
assert_equal 'mruby', io.read(5)
assert_equal $mrbtest_io_msg[5,100] + "\n", io.read
- assert_equal nil, io.read
+ assert_equal "", io.read
io.close
io.closed?
end
@@ -251,6 +251,29 @@ assert('IO.popen') do
io.closed?
end
+assert('IO.read') do
+ # empty file
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.close
+ assert_equal "", IO.read($mrbtest_io_wfname)
+ assert_equal nil, IO.read($mrbtest_io_wfname, 1)
+
+ # one byte file
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.write "123"
+ io.close
+ assert_equal "123", IO.read($mrbtest_io_wfname)
+ assert_equal "", IO.read($mrbtest_io_wfname, 0)
+ assert_equal "1", IO.read($mrbtest_io_wfname, 1)
+ assert_equal "", IO.read($mrbtest_io_wfname, 0, 10)
+ assert_equal "23", IO.read($mrbtest_io_wfname, 2, 1)
+ assert_equal "23", IO.read($mrbtest_io_wfname, 10, 1)
+ assert_equal "", IO.read($mrbtest_io_wfname, nil, 10)
+ assert_equal nil, IO.read($mrbtest_io_wfname, 1, 10)
+end
+
assert('IO#fileno') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd