Current section

Files

Jump to
ephp src ephp_stream_file.erl
Raw

src/ephp_stream_file.erl

-module(ephp_stream_file).
-author('manuel@altenwald.com').
-compile([warnings_as_errors]).
-include_lib("kernel/include/file.hrl").
-include("ephp.hrl").
-behaviour(ephp_stream).
-export([
open/2,
close/1,
read/2,
read_file/1,
write/3,
position/2,
is_eof/1
]).
-spec open(ephp_stream:uri(), ephp_stream:options()) ->
{ok, file:fd()} | {error, reason()}.
%% @doc opens a file in the filesystem.
open(File, Options) ->
{Truncate, Opts} = lists:partition(fun(X) -> X =:= truncate end, Options),
case {file:open(File, [raw, binary|Opts]), Truncate} of
{{ok, IO}, [truncate]} ->
file:truncate(IO),
{ok, IO};
{OpenReturn, _} ->
OpenReturn
end.
-spec close(file:fd()) -> ok | {error, reason()}.
%% @doc closes a file.
close(PID) ->
file:close(PID).
-spec read(file:fd(), ephp_stream:options()) ->
{ok, binary()} | eof | {error, reason()}.
%% @doc reads data from the file.
read(PID, Options) ->
{size, Size} = lists:keyfind(size, 1, Options),
file:read(PID, Size).
-spec read_file(ephp_stream:uri()) -> {ok, binary()} | {error, reason()}.
%% @doc read the whole file from filesystem.
read_file(URL) ->
file:read_file(URL).
-spec write(file:fd(), binary(), ephp_stream:options()) ->
ok | {error, reason()}.
%% @doc writes data to a file.
write(PID, Data, _Options) ->
file:write(PID, Data).
-spec position(file:fd(), file:location()) -> ok | {error, reason()}.
%% @doc moves the cursor to the specified position inside of the file.
position(PID, Location) ->
case file:position(PID, Location) of
{ok, _} -> ok;
{error, Reason} -> {error, Reason}
end.
-spec is_eof(file:fd()) -> boolean() | {error, reason()}.
%% @doc returns true if EOF is achieved by the file cursor or false otherwise.
is_eof(FD) ->
%% FIXME it should to be a much better way to do this... right?
{ok, Pos} = file:position(FD, cur),
{ok, Size} = file:position(FD, eof),
{ok, Pos} = file:position(FD, Pos),
Pos =:= Size.