diff --git a/lib/elixir/lib/io.ex b/lib/elixir/lib/io.ex index 8c8236cc9b..57a3a2121a 100644 --- a/lib/elixir/lib/io.ex +++ b/lib/elixir/lib/io.ex @@ -44,7 +44,9 @@ defmodule IO do @doc """ Reads `count` characters from the IO device or until - the end of the line if `:line` is given. It returns: + the end of the line if `:line` is given. If `:all` is + given, returns empty string instead of `:eof`. + It returns: * `data` - the input characters @@ -54,9 +56,21 @@ defmodule IO do for instance, `{:error, :estale}` if reading from an NFS volume """ - @spec read(device, :line | non_neg_integer) :: chardata | nodata + @spec read(device, :all | :line | non_neg_integer) :: chardata | nodata def read(device \\ group_leader, chars_or_line) + def read(device, :all) do + do_read_all(map_dev(device), "") + end + + defp do_read_all(mapped_dev, acc) do + case :io.get_line(mapped_dev, "") do + line when is_binary(line) -> do_read_all(mapped_dev, acc <> line) + :eof -> acc + other -> other + end + end + def read(device, :line) do :io.get_line(map_dev(device), '') end @@ -67,7 +81,9 @@ defmodule IO do @doc """ Reads `count` bytes from the IO device or until - the end of the line if `:line` is given. It returns: + the end of the line if `:line` is given. If `:all` is + given, returns empty string instead of `:eof`. + It returns: * `data` - the input characters @@ -80,9 +96,21 @@ defmodule IO do Note: do not use this function on IO devices in unicode mode as it will return the wrong result. """ - @spec binread(device, :line | non_neg_integer) :: iodata | nodata + @spec binread(device, :all | :line | non_neg_integer) :: iodata | nodata def binread(device \\ group_leader, chars_or_line) + def binread(device, :all) do + do_binread_all(map_dev(device), "") + end + + defp do_binread_all(mapped_dev, acc) do + case :file.read_line(mapped_dev) do + {:ok, data} -> do_binread_all(mapped_dev, acc <> data) + :eof -> acc + other -> other + end + end + def binread(device, :line) do case :file.read_line(map_dev(device)) do {:ok, data} -> data diff --git a/lib/elixir/test/elixir/io_test.exs b/lib/elixir/test/elixir/io_test.exs index 7d46dbbf56..12032f9fe7 100644 --- a/lib/elixir/test/elixir/io_test.exs +++ b/lib/elixir/test/elixir/io_test.exs @@ -58,6 +58,20 @@ defmodule IOTest do assert File.close(file) == :ok end + test :readall do + {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__)) + assert "FOO\n" == IO.read(file, :all) + assert "" == IO.read(file, :all) + assert File.close(file) == :ok + end + + test :readall_with_utf8_and_binary do + {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) + assert "Русский\n日\n" == IO.read(file, :all) + assert "" == IO.read(file, :all) + assert File.close(file) == :ok + end + test :readline do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__)) assert "FOO\n" == IO.read(file, :line) @@ -72,6 +86,13 @@ defmodule IOTest do assert File.close(file) == :ok end + test :binreadall do + {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__)) + assert "Русский\n日\n" == IO.binread(file, :all) + assert "" == IO.binread(file, :all) + assert File.close(file) == :ok + end + test :binreadline do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__)) assert "Русский\n" == IO.binread(file, :line)