Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

More utility functions.

  • Loading branch information...
commit d5cf959671e32647e797ad347c047b528121a17b 1 parent 41bd9b7
@vjache authored
Showing with 150 additions and 4 deletions.
  1. +150 −4 src/zlists_file.erl
View
154 src/zlists_file.erl
@@ -28,7 +28,18 @@
%%
%% Exported Functions
%%
--export([read/2, expand_binary/2]).
+-export([read/2,
+ expand_binary/2,
+ as_berps/2,
+ read_berps/1,
+ read_berps/2,
+ open_berps/1,
+ open_berps/2,
+ close_on_eof/1,
+ close_on_eof/2,
+ consult_berps/1,
+ write_berps/2,
+ dump_berps/2]).
%%
%% API Functions
@@ -61,9 +72,12 @@ read(Fd, Sz) ->
-spec expand_binary(BinZList :: zlists:zlist(binary()),
BinSize :: non_neg_integer()) -> zlists:zlist(binary()).
-expand_binary([Bin|ZTail],Sz) when byte_size(Bin) >= Sz ->
- <<Chunk:Sz/binary,BTail/binary>> = Bin,
- [Chunk,BTail|ZTail];
+expand_binary([Bin|ZTail]=BinZList,Sz) when byte_size(Bin) >= Sz ->
+ if byte_size(Bin) == Sz -> BinZList;
+ true ->
+ <<Chunk:Sz/binary,BTail/binary>> = Bin,
+ [Chunk,BTail|ZTail]
+ end;
expand_binary([Bin],Sz) when byte_size(Bin) < Sz ->
[Bin];
expand_binary([Bin|ZTail],Sz) ->
@@ -72,7 +86,139 @@ expand_binary([Bin|ZTail],Sz) ->
[] -> [Bin]
end.
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Takes a Z-List of bytes representing BERPs and returns Z-List of terms. An
+%% input Z-List either Z-List of binaries or Z-List of integers B in [0..255].
+%% @end
+%%-------------------------------------------------------------------------------
+-spec as_berps(BytesZList :: zlists:zlist(binary()) | zlists:zlist(non_neg_integer()),
+ Opts :: [safe]) -> zlists:zlist(term()).
+as_berps([],_Opts) -> [];
+as_berps([Bin|_]=BinZList,Opts)
+ when is_binary(Bin) ->
+ case expand_binary(BinZList, 4) of
+ [<<0 :32/unsigned-integer>>] -> [];
+ [<<Sz:32/unsigned-integer>>|T] ->
+ [<<Bert:Sz/binary>>|T1]=expand_binary(T, Sz),
+ [binary_to_term(Bert, Opts)|fun()-> as_berps(zlists:expand(1,T1),Opts) end]
+ end;
+as_berps(ZList,Opts) ->
+ case zlists:expand(4,ZList) of
+ []-> throw({dbg, ZList});
+ [0,0,0,0] -> [];
+ [A,B,C,D|T] ->
+ <<Sz:32/unsigned-integer>> = <<A,B,C,D>>,
+ {Data,T1}=zlists:scroll(Sz,T),
+ [binary_to_term(list_to_binary(Data),Opts)|fun()-> as_berps(zlists:expand(1,T1),Opts) end]
+ end.
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Equivalent to read_berps(Io, []).
+%% @end
+%%-------------------------------------------------------------------------------
+-spec read_berps(IoDevice :: file:io_device()) -> zlists:zlist(term()).
+read_berps(Io) ->
+ read_berps(Io, []).
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Returns a Z-List of terms contained in an IO device as BERPs.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec read_berps(IoDevice :: file:io_device(),
+ Opts :: [safe]) -> zlists:zlist(term()).
+read_berps(Io, Opts) ->
+ case file:read(Io, 4) of
+ eof -> [];
+ {ok,<<Sz:32/unsigned-integer>>} ->
+ {ok,<<Bert:Sz/binary>>}=file:read(Io, Sz),
+ [binary_to_term(Bert, Opts)|fun()-> read_berps(Io) end]
+ end.
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Just a helper function to open a BERP file as a Z-List at one op.
+%% Checks if suffix is ".gz" to decide enflate or not.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec open_berps(Filename :: file:filename()) -> {file:io_device(), zlists:zlist(term())}.
+open_berps(Filename) ->
+ IsGZip = is_gz(Filename),
+ open_berps(Filename, IsGZip).
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Just a helper function to open a BERP file as a Z-List at one op.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec open_berps(Filename :: file:filename(),
+ IsGZip :: boolean()) -> {file:io_device(), zlists:zlist(term())}.
+open_berps(Filename, IsGZip) ->
+ {ok,Io}=file:open(
+ Filename,
+ [read,raw,
+ binary,read_ahead | if IsGZip-> [compressed]; true -> [] end ]),
+ {Io, read_berps(Io)}.
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Reads entire file into one binary, and wraps it with Z-List that will parse
+%% it as a sequence of BERPs.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec consult_berps(Filename :: file:filename()) -> zlists:zlist(term()).
+consult_berps(Filename) ->
+ {ok,Data}=file:read_file(Filename),
+ IsGZip=is_gz(Filename),
+ IData= if IsGZip -> zlib:gunzip(Data); true -> Data end,
+ as_berps([IData], []).
+
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Writes a terms passed as Z-List to IO device using BERP format.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec write_berps(IoDevice :: file:io_device(), Terms :: zlists:zlist(term()) ) -> ok.
+write_berps(Io, ZList) ->
+ zlists:foreach(
+ fun(Term) ->
+ Bin = term_to_binary(Term),
+ Sz = byte_size(Bin),
+ ok=file:write(Io, <<Sz:32/unsigned-integer,Bin/binary>>)
+ end,
+ ZList).
+%%-------------------------------------------------------------------------------
+%% @doc
+%% Writes a terms passed as Z-List to file using BERP format.
+%% @end
+%%-------------------------------------------------------------------------------
+-spec dump_berps(Filename :: file:filename(), Terms :: zlists:zlist(term()) ) -> ok.
+dump_berps(Filename, ZList) ->
+ IsGZip = is_gz(Filename),
+ {ok,Io}=file:open(Filename,
+ [write,raw,
+ binary,delayed_write | if IsGZip-> [compressed]; true -> [] end ]),
+ try write_berps(Io, ZList)
+ after
+ file:close(Io)
+ end.
+
+close_on_eof({Io, ZList}) ->
+ close_on_eof(Io, ZList).
+
+close_on_eof(Io, ZList) ->
+ zlists:new(ZList, fun()-> file:close(Io),[] end).
+
%%
%% Local Functions
%%
+is_gz(Filename) ->
+ lists:suffix(
+ ".gz",
+ if is_list(Filename) -> Filename;
+ is_atom(Filename) -> atom_to_list(Filename);
+ is_binary(Filename) -> binary_to_list(Filename)
+ end).
Please sign in to comment.
Something went wrong with that request. Please try again.