From 3c965fe7b6f717804bdef238ffa8aeff0bce83d4 Mon Sep 17 00:00:00 2001 From: aj Date: Wed, 3 Nov 2010 02:49:13 -0700 Subject: [PATCH] added debug build, fleshing out the tzdata parser. currently broken --- Makefile | 11 +++++- src/ezic.erl | 9 ++--- src/ezic_loader.erl | 95 +++++++++++++++++++++++++++++++++++++++++++++ src/ezic_record.erl | 82 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 src/ezic_loader.erl create mode 100644 src/ezic_record.erl diff --git a/Makefile b/Makefile index 7dc9809..7fca5ae 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ ERLC_WARNINGS = -W1 MNESIA_DIR = db RUN_INIT = +DEBUG = +OPTIONS = all : clean compile @@ -14,7 +16,7 @@ test : all erl -noshell -pa ebin -s test_master start -s erlang halt compile : - erlc $(ERLC_WARNINGS) $(OPTIONS) -o ./ebin ./src/*.erl + erlc $(DEBUG) $(ERLC_WARNINGS) $(OPTIONS) -o ./ebin ./src/*.erl -erl -noshell -pa ebin -s erldev make_app . -s erlang halt clean : @@ -22,4 +24,9 @@ clean : run : - erl -pa ebin -mnesia dir $(MNESIA_DIR) $(RUN_INIT) \ No newline at end of file + erl -pa ebin -mnesia dir $(MNESIA_DIR) $(RUN_INIT) + + +debug : DEBUG = +debug_info +debug : RUN_INIT = -s debugger start +debug : all \ No newline at end of file diff --git a/src/ezic.erl b/src/ezic.erl index 26c3968..c35ac19 100644 --- a/src/ezic.erl +++ b/src/ezic.erl @@ -1,11 +1,10 @@ -module(ezic). - --export([refresh_db/1]). --export([time2time/3]). +-export([load/1, time2time/3]). -refresh_db(_Folder) -> - void. +load(Folder) -> + ezic_loader:load(Folder). + time2time(_DateTime, _FromTimeZone, _ToTimeZone) -> void. diff --git a/src/ezic_loader.erl b/src/ezic_loader.erl new file mode 100644 index 0000000..ee65c22 --- /dev/null +++ b/src/ezic_loader.erl @@ -0,0 +1,95 @@ +-module(ezic_loader). +-include("include/ezic.hrl"). +-export([load/1]). + + +load(File) -> + {ok, Records} = + case filelib:is_dir(File) of + true -> {ok, parse_dir(File)}; + false -> case filelib:is_regular(File) of + true -> {ok, parse_file(File)}; + false -> {error, {badFile, File}} + end + end, + flatten(Records). + % @todo store in mnesia + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% INTERNAL +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +% returns a list of tzdata records for all files in folder +% note: assumes every file in the folder is a tzdata file +% this method does not recurse. +parse_dir(Folder) -> + {ok, Files} = file:list_dir(Folder), + lists:flatten([ parse_file(filename:join(Folder,File)) || File <- Files ]). + + + +% returns a list of tzdata records from file +parse_file(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), + case length(StrLine) > 0 of + false -> parse_lines(file:read_line(File), File, Records); + true -> parse_lines_2(StrLine, File, Records) + end. + + +parse_lines_2(Line, File, Records) -> + [Type | Data] = string:tokens(Line, " \t"), + {ok, PrevType, PrevName} = prev_rec_type(Records), + {ok, Record} = build_record(Type, Data, {PrevType, PrevName}), + parse_lines(file:read_line(File), File, [Record|Records]). + + +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) -> + Line1= string:strip(Line), + Line2= string:strip(Line1, both, $\n), + CPos= string:chr(Line2, $#), + case CPos of + 0 -> Line2; + _ -> string:sub_string(Line2, 1, CPos-1) + end. + + + +build_record("Rule", Data,_) -> + ezic_record:rule(Data); +build_record("Zone", Data,_) -> + ezic_record:zone(Data); +build_record("Link", Data,_) -> + ezic_record:link(Data); +build_record(GmtOff, Data, {"Zone", PrevName}) -> + ezic_record:zone([PrevName,GmtOff|Data]); + +build_record(Type, Data, PT) -> + {error, {badLine, Type, Data, PT}}. + + +% converts tzdata records to flattened records +% returns list of #flatzone{} +flatten(Records) when is_list(Records) -> + void. diff --git a/src/ezic_record.erl b/src/ezic_record.erl new file mode 100644 index 0000000..e6dca8c --- /dev/null +++ b/src/ezic_record.erl @@ -0,0 +1,82 @@ +-module(ezic_record). +-include("include/ezic.hrl"). +-export([rule/1,zone/1,link/1]). + + +rule([Name,From,To,Type,In,On,At,Save,Letters]) -> + {ok, #rule{ + name=Name, from=From, to=To, type=Type, + in=In, on=On, at=At, save=Save, letters=Letters + }}. + +zone([Name,GmtOff,Rules,Format | UntilTokens]) -> + Until = parse_until(UntilTokens), + {ok, #zone{ + name=Name, gmtoff=GmtOff, rules=Rules, + format=Format, until=Until + }}. + +link([From,To]) -> + {ok, #link{from=From, to=To}}. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% INTERNAL +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +parse_until([]) -> + current; +parse_until([YS]) -> + Y= list_to_integer(YS), + {Y,1,1}; +parse_until([YS,MS]) -> + Y= list_to_integer(YS), + M=month_to_num(MS), + {Y,M,1}; +parse_until([YS,MS,DS]) -> + Y= list_to_integer(YS), + M=month_to_num(MS), + D= list_to_integer(DS), + {Y,M,D}; +% @todo broken: time flags must be accounted for +parse_until([YS,MS,DS,TS]) -> + Y= list_to_integer(YS), + M=month_to_num(MS), + D= list_to_integer(DS), + TimeTokens=string:tokens(TS, ":"), + {{Y,M,D},parse_time(TimeTokens)}. + + + +parse_time("-") -> + {0,0,0}; +parse_time([HS]) -> + H= list_to_integer(HS), + {H,0,0}; +parse_time([HS,MS]) -> + H= list_to_integer(HS), + M= list_to_integer(MS), + {H,M,0}; +parse_time([HS,MS,SS]) -> + H= list_to_integer(HS), + M= list_to_integer(MS), + S= list_to_integer(SS), + {H,M,S}. + + + + + +month_to_num("Jan") -> 1; +month_to_num("Feb") -> 2; +month_to_num("Mar") -> 3; +month_to_num("Apr") -> 4; +month_to_num("May") -> 5; +month_to_num("Jun") -> 6; +month_to_num("Jul") -> 7; +month_to_num("Aug") -> 8; +month_to_num("Sep") -> 9; +month_to_num("Oct") -> 10; +month_to_num("Nov") -> 11; +month_to_num("Dec") -> 12.