/org.erlide.kernel.common/src/erlide_util.erl

https://github.com/fhix/erlide · Erlang · 205 lines · 161 code · 29 blank · 15 comment · 2 complexity · 1c750f3daea8964a3688f72ee9188711 MD5 · raw file

  1. %% Author: jakob
  2. %% Created: 25 okt 2007
  3. -module(erlide_util).
  4. %% -define(DEBUG, 1).
  5. %%
  6. %% Include files
  7. %%
  8. -include("erlide.hrl").
  9. -include_lib("kernel/include/file.hrl").
  10. %%
  11. %% Exported Functions
  12. %%
  13. -export([check_and_renew_cached/5, check_and_renew_cached/6, check_cached/3, renew_cached/4, read_cache_date_and_version/1, read_cache/1]).
  14. -export([pack/1, unpack/1, join/2]).
  15. -export([reverse2/1]).
  16. -export([get_between_strs/3, get_all_between_strs/3, get_from_str/2, get_upto_str/2 ,split_lines/1]).
  17. -export([get_auto_imported/1, add_auto_imported/1]).
  18. %%
  19. %% API Functions
  20. %%
  21. -define(SEP, ";").
  22. unpack(F) ->
  23. string:tokens(F, ?SEP).
  24. pack(L) ->
  25. join(L, ?SEP).
  26. check_cached(SourceFileName, CacheFileName, Version) ->
  27. ?D({SourceFileName, CacheFileName}),
  28. SourceModDate = case file:read_file_info(SourceFileName) of
  29. {ok, Info} ->
  30. Info#file_info.mtime;
  31. {error, enoent} ->
  32. {{1900, 1, 1}, {0, 0, 0}}
  33. end,
  34. ?D(SourceModDate),
  35. SV = read_cache_date_and_version(CacheFileName),
  36. ?D(SV),
  37. case same_date_and_version(SV, {SourceModDate, Version}) of
  38. true ->
  39. {cache, read_cache(CacheFileName)};
  40. _ ->
  41. {no_cache, SourceModDate}
  42. end.
  43. same_date_and_version({{Date, {H, M, S1}}, V}, {{Date, {H, M, S2}}, V}) ->
  44. S1 div 2 =:= S2 div 2;
  45. same_date_and_version(_, _) ->
  46. false.
  47. reverse2(L) when is_list(L) ->
  48. lists:reverse([lists:reverse(A) || A <- L]).
  49. renew_cached(SourceFileName, CacheFileName, Version, Term) ->
  50. SourceModDate = case file:read_file_info(SourceFileName) of
  51. {ok, Info} ->
  52. Info#file_info.mtime;
  53. {error, enoent} ->
  54. {{1900, 1, 1}, {0, 0, 0}}
  55. end,
  56. ?D(SourceFileName),
  57. renew_cache(SourceModDate, Version, CacheFileName, Term).
  58. check_and_renew_cached(SourceFileName, CacheFileName, Version,
  59. RenewFun, UseCache) ->
  60. check_and_renew_cached(SourceFileName, CacheFileName, Version,
  61. RenewFun, fun(D) -> D end, UseCache).
  62. check_and_renew_cached(SourceFileName, _CacheFileName, _Version,
  63. RenewFun, _CachedFun, false) ->
  64. Term = RenewFun(SourceFileName),
  65. {dont_use_cache, Term};
  66. check_and_renew_cached(SourceFileName, CacheFileName,
  67. Version, RenewFun, CachedFun,
  68. true) ->
  69. ?D(check_and_renew_cached),
  70. case check_cached(SourceFileName, CacheFileName, Version) of
  71. {cache, Cached} ->
  72. ?D({from_cache, CacheFileName}),
  73. R = {cached, CachedFun(Cached)},
  74. ?D(got_cached),
  75. R;
  76. {no_cache, SourceModDate} ->
  77. ?D(SourceModDate),
  78. Term = RenewFun(SourceFileName),
  79. ?D({renewing, CacheFileName, UpdateCache}),
  80. renew_cache(SourceModDate, Version, CacheFileName, Term),
  81. {renewed, Term}
  82. end.
  83. get_from_str(Text, Start) ->
  84. case string:str(Text, Start) of
  85. 0 ->
  86. Text;
  87. N ->
  88. string:substr(Text, N + length(Start))
  89. end.
  90. get_between_strs(Text, Start, End) ->
  91. get_upto_str(get_from_str(Text, Start), End).
  92. get_all_between_strs(Text, Start, End) ->
  93. {One, Next} = split_at(get_from_str(Text, Start), End),
  94. case Next of
  95. "" ->
  96. [One];
  97. _ ->
  98. [One | get_all_between_strs(Next, Start, End)]
  99. end.
  100. get_upto_str(Text, End) ->
  101. case string:rstr(Text, End) of
  102. 0 ->
  103. Text;
  104. N ->
  105. string:substr(Text, 1, N-1)
  106. end.
  107. split_at(Text, End) ->
  108. case string:str(Text, End) of
  109. 0 ->
  110. {Text, ""};
  111. N ->
  112. {string:substr(Text, 1, N-1), string:substr(Text, N+length(End))}
  113. end.
  114. split_lines(<<B/binary>>) ->
  115. split_lines(binary_to_list(B));
  116. split_lines(L) when is_list(L) ->
  117. split_lines(L, [], []).
  118. split_lines([], [], Acc) ->
  119. lists:reverse(Acc);
  120. split_lines([], LineAcc, Acc) ->
  121. split_lines([], [], [lists:reverse(LineAcc) | Acc]);
  122. split_lines([$\n, $\r | Rest], LineAcc, Acc) ->
  123. split_lines(Rest, [], [lists:reverse(LineAcc) | Acc]);
  124. split_lines([$\n | Rest], LineAcc, Acc) ->
  125. split_lines(Rest, [], [lists:reverse(LineAcc) | Acc]);
  126. split_lines([$\r | Rest], LineAcc, Acc) ->
  127. split_lines(Rest, [], [lists:reverse(LineAcc) | Acc]);
  128. split_lines([C | Rest], LineAcc, Acc) ->
  129. split_lines(Rest, [C | LineAcc], Acc).
  130. join([], Sep) when is_list(Sep) ->
  131. [];
  132. join([H|T], Sep) ->
  133. H ++ lists:append([Sep ++ X || X <- T]).
  134. add_auto_imported(Imports) ->
  135. [{erlang, get_auto_imported("")} | Imports].
  136. get_auto_imported(Prefix) when is_list(Prefix) ->
  137. case catch erlang:module_info(exports) of
  138. Val when is_list(Val) ->
  139. lists:filter(fun({N, A}) ->
  140. lists:prefix(Prefix, atom_to_list(N)) andalso
  141. erl_internal:bif(N, A)
  142. end, Val);
  143. _Error ->
  144. ?D(_Error),
  145. error
  146. end.
  147. %%
  148. %% Local Functions
  149. %%
  150. renew_cache(SourceFileModDate, Version, CacheFileName, Term) ->
  151. ?D(SourceFileModDate),
  152. BinDate = date_to_bin(SourceFileModDate),
  153. B = term_to_binary(Term, [compressed]),
  154. _Delete = file:delete(CacheFileName),
  155. _Write = file:write_file(CacheFileName, <<BinDate/binary, Version:16/integer-big, B/binary>>),
  156. ?D(_Write),
  157. ?D(CacheFileName).
  158. bin_to_date(<<Y:15/integer-big, Mo:4, D:5, H:5, M:6, S:5>>) ->
  159. {{Y, Mo, D}, {H, M, S*2}}.
  160. date_to_bin({{Y, Mo, D}, {H, M, S}}) ->
  161. <<Y:15/integer-big, Mo:4, D:5, H:5, M:6, (S div 2):5>>.
  162. read_cache_date_and_version(CacheFileName) ->
  163. case file:open(CacheFileName, [read, binary]) of
  164. {ok, F} ->
  165. {ok, BinDateAndVersion} = file:read(F, 7),
  166. file:close(F),
  167. <<BinDate:5/binary, Version:16/integer-big>> = BinDateAndVersion,
  168. {bin_to_date(BinDate), Version};
  169. _ ->
  170. {{{0, 0, 0}, {0, 0, 0}}, 0}
  171. end.
  172. read_cache(CacheFileName) ->
  173. {ok, B} = file:read_file(CacheFileName),
  174. ?D(CacheFileName),
  175. <<_:5/binary, _:16/integer-big, BinTerm/binary>> = B,
  176. binary_to_term(BinTerm).