Skip to content

Instantly share code, notes, and snippets.

@wildchild
Created September 4, 2009 14:44
Show Gist options
  • Save wildchild/180926 to your computer and use it in GitHub Desktop.
Save wildchild/180926 to your computer and use it in GitHub Desktop.
Extremely fast lookup country by IP address
%% This is http://code.google.com/p/ip2country-erlang on steroids.
%% Database: http://software77.net/cgi-bin/ip-country/geo-ip.pl?action=download
%% Speed: over 200000 lookups in a second.
-module(ip2country).
-compile(export_all).
for_each_line_in_file(Name, Proc, Acc) ->
{ok, Device} = file:open(Name, [read]),
for_each_line(Device, Proc, Acc).
for_each_line(Device, Proc, Acc) ->
case io:get_line(Device, "") of
eof ->
file:close(Device),
build_tree(lists:keysort(1, Acc));
Line ->
case Proc(Line) of
skip ->
for_each_line(Device, Proc, Acc);
Value ->
Acc1 = [Value|Acc],
for_each_line(Device, Proc, Acc1)
end
end.
load_csv_file(Filename) ->
Fun = fun(Line) ->
case string:left(Line, 1) of
"\n" -> skip;
"#" -> skip;
_ ->
Params = string:tokens(Line, ","),
F = fun(Elem) -> string:strip(string:strip(Elem, both, $\n), both, $") end,
Params2 = lists:map(F, Params),
[Min, Max, _, _, Ctry, _, _] = Params2,
{list_to_integer(Min), list_to_integer(Max), Ctry}
end
end,
for_each_line_in_file(Filename, Fun, []).
build_tree([]) ->
undefined;
build_tree(L) ->
{Left, Right} = lists:split(round(length(L)/2), L),
[{Min, Max, Country}|LeftSide] = lists:reverse(Left),
{Min, Max, Country, build_tree(lists:reverse(LeftSide)), build_tree(Right)}.
lookup(Tree, IP) when is_list(IP) ->
lookup(Tree, ip2int(IP));
lookup({Min, Max, Country, _Left, _Right}, IP) when IP >= Min, IP =< Max ->
Country;
lookup({_Min, Max, _Country, _Left, Right}, IP) when IP >= Max ->
lookup(Right, IP);
lookup({Min, _Max, _Country, Left, _Right}, IP) when IP =< Min ->
lookup(Left, IP);
lookup(undefined, _) ->
false.
ip2int(StrIP) ->
{ok, {A, B, C, D}} = inet_parse:address(StrIP),
D + C * 256 + B * 256 * 256 + A * 256 * 256 * 256.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment