120 lines
2.8 KiB
Erlang
120 lines
2.8 KiB
Erlang
-module(ezic_loader).
|
|
-include("include/ezic.hrl").
|
|
|
|
-export([load/0, load/1]).
|
|
-define(TZDIR, filename:join("priv", "tzdata")).
|
|
|
|
|
|
|
|
load() ->
|
|
case application:get_env(tzdata_dir) of
|
|
undefined ->
|
|
load(?TZDIR);
|
|
{ok, Dir} ->
|
|
load(Dir)
|
|
end.
|
|
|
|
%% returns all records, parsed from the tzdata files in directory Dir.
|
|
load(Dir) ->
|
|
{ok, Records} =
|
|
case filelib:is_dir(Dir) of
|
|
true -> {ok, parse_dir(Dir)};
|
|
false -> erlang:error({not_a_directory, Dir})
|
|
end,
|
|
|
|
Records.
|
|
|
|
|
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% PRIVATE
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
|
% returns a list of tzdata records for all files in folder
|
|
% note: assumes every file in the folder is a tzdata file
|
|
parse_dir(Dir) ->
|
|
{ok, Files} = file:list_dir(Dir),
|
|
lists:flatten([ parse_file(filename:join(Dir,File)) || File <- Files ]).
|
|
|
|
|
|
|
|
% returns a list of tzdata records from file
|
|
parse_file(File) ->
|
|
%% io:format("Parsing File: ~p~n", [File]),
|
|
{ok, FD} = file:open(File, [read]),
|
|
parse_lines(file:read_line(FD), FD, []).
|
|
|
|
|
|
|
|
|
|
parse_lines(eof, _, Records) ->
|
|
Records;
|
|
parse_lines({ok, Line}, File, Records) ->
|
|
StrLine= clean_line(Line),
|
|
NewRecords= case length(StrLine) > 0 of
|
|
true -> [parse_to_record(StrLine, File, Records) | Records];
|
|
false -> Records
|
|
end,
|
|
parse_lines(file:read_line(File), File, NewRecords).
|
|
|
|
|
|
|
|
% the Line has data, so we parse it, build a record, and return it
|
|
parse_to_record(Line, _, Records) ->
|
|
%% io:format(" Parsing Line: ~p~n", [Line]),
|
|
[Type | Data] = string:tokens(Line, " \t"),
|
|
{ok, PrevType, PrevName} = prev_rec_type(Records),
|
|
{ok, Record} = build_record(Type, Data, {PrevType, PrevName}),
|
|
Record.
|
|
|
|
|
|
|
|
|
|
% retrieves the previous record type, in case Zone continuations occur (multiline)
|
|
prev_rec_type([]) ->
|
|
{ok, null, null};
|
|
prev_rec_type([#zone{name=Name}|_]) ->
|
|
{ok, "Zone", Name};
|
|
prev_rec_type(List) when is_list(List) ->
|
|
{ok, void, void}.
|
|
|
|
|
|
|
|
|
|
clean_line(Line) ->
|
|
%% remove spaces, newlines, and tabs
|
|
Line1= string:strip(Line),
|
|
Line2= string:strip(Line1, both, $\n),
|
|
Line3= string:strip(Line2, both, $\t),
|
|
|
|
%% remove comments and returns
|
|
FinalLine=Line3,
|
|
CPos= string:chr(FinalLine, $#),
|
|
case CPos of
|
|
0 -> FinalLine;
|
|
_ -> string:sub_string(FinalLine, 1, CPos-1)
|
|
end.
|
|
|
|
|
|
|
|
build_record("Rule", Data,_) ->
|
|
ezic_rule:parse(Data);
|
|
build_record("Zone", Data,_) ->
|
|
ezic_zone:parse(Data);
|
|
build_record("Link", Data,_) ->
|
|
ezic_record:link(Data);
|
|
build_record("Leap", Data,_) ->
|
|
ezic_record:leap(Data);
|
|
build_record(GmtOff, Data, {"Zone", PrevName}) ->
|
|
ezic_zone:parse([PrevName,GmtOff|Data]);
|
|
|
|
build_record(Type, Data, PT) ->
|
|
erlang:error(badLine, {Type, Data, PT}).
|
|
|
|
|
|
|
|
|