69 lines
2 KiB
Erlang
69 lines
2 KiB
Erlang
-module(machi_plist).
|
|
|
|
%%% @doc persistent list of binaries
|
|
|
|
-export([open/2, close/1, find/2, add/2]).
|
|
|
|
-ifdef(TEST).
|
|
-export([all/1]).
|
|
-endif.
|
|
|
|
-record(machi_plist,
|
|
{filename :: file:filename_all(),
|
|
fd :: file:io_device(),
|
|
list = [] :: list(string)}).
|
|
|
|
-type plist() :: #machi_plist{}.
|
|
-export_type([plist/0]).
|
|
|
|
-spec open(file:filename_all(), proplists:proplist()) ->
|
|
{ok, plist()} | {error, file:posix()}.
|
|
open(Filename, _Opt) ->
|
|
%% TODO: This decode could fail if the file didn't finish writing
|
|
%% whole contents, which should be fixed by some persistent
|
|
%% solution.
|
|
List = case file:read_file(Filename) of
|
|
{ok, <<>>} -> [];
|
|
{ok, Bin} -> binary_to_term(Bin);
|
|
{error, enoent} -> []
|
|
end,
|
|
case file:open(Filename, [read, write, raw, binary, sync]) of
|
|
{ok, Fd} ->
|
|
{ok, #machi_plist{filename=Filename,
|
|
fd=Fd,
|
|
list=List}};
|
|
Error ->
|
|
Error
|
|
end.
|
|
|
|
-spec close(plist()) -> ok.
|
|
close(#machi_plist{fd=Fd}) ->
|
|
_ = file:close(Fd).
|
|
|
|
-spec find(plist(), string()) -> boolean().
|
|
find(#machi_plist{list=List}, Name) ->
|
|
lists:member(Name, List).
|
|
|
|
-spec add(plist(), string()) -> {ok, plist()} | {error, file:posix()}.
|
|
add(Plist = #machi_plist{list=List0, fd=Fd}, Name) ->
|
|
case find(Plist, Name) of
|
|
true ->
|
|
{ok, Plist};
|
|
false ->
|
|
List = lists:append(List0, [Name]),
|
|
%% TODO: partial write could break the file with other
|
|
%% persistent info (even lose data of trimmed states);
|
|
%% needs a solution.
|
|
case file:pwrite(Fd, 0, term_to_binary(List)) of
|
|
ok ->
|
|
{ok, Plist#machi_plist{list=List}};
|
|
Error ->
|
|
Error
|
|
end
|
|
end.
|
|
|
|
-ifdef(TEST).
|
|
-spec all(plist()) -> [file:filename()].
|
|
all(#machi_plist{list=List}) ->
|
|
List.
|
|
-endif.
|