anchor.diff:  %%  1. IPsBlob consists of buckets, each bucket is associated with some
   %%     16-bit IP (M.N.*.*) and contains IP ranges associated with a zone hash:
   %%
  -%% <<StartIP_1:8, EndIP_1:8, Zone_1:16, StartIP_2:8, EndIP_2:8, Zone_2:16, ...>>
  +%%  StartIP_1:8, EndIP_1:8, Zone_1:16, StartIP_2:8, EndIP_2:8, Zone_2:16, ...
   %%
   %%      Thus, every IP range uses 4 bytes: 2 bytes for start and end of
   %%      the range and 2 bytes for zone hash.
  
positive.code:     {IPsBlob, IPsIndex} = ips_index(IPZoneKV),
      {IPsBlob, IPsIndex, Zones}.
  
  %% @spec lookup(ip24()) -> binary() | notfound
  %% @doc Searches for 24-bit IP in the database generated from ACL file. Returns
  %%      a binary name of the zone or notfound if there's no zone associated with
  %%      the IP.
  %%
  %%      Possible IP formats:
  %%          {127,0,0}
  %%          <<"127.0.0">>
  %%          "127.0.0"
  %%          <<127,0,0>>
  %%
  lookup(IP, Database) when is_list(IP) ->
      lookup(parse_ip(list_to_binary(IP)), Database);
  lookup({A, B, C}, Database) ->
      lookup(<<A:8, B:8, C:8>>, Database);
  lookup(<<Prefix:16/integer, C:8>>, {IPsBlob, IPsIndex, Zones}) ->
      IndexOffset = Prefix * 4,
      <<_:(IndexOffset)/binary, BucketOffset:16/integer, BucketSize:16/integer, _/binary>> = IPsIndex,
  
negative.code: ]).
  
  %% @type ip24() = list() | binary() | {int(), int(), int()}
  %% @type ip32() = list() | binary() | {int(), int(), int(), int()}
  %% @type ip() = ip24() | ip32() | invalid_ip
  %% @type acldb() = {binary(), binary(), tuple()}
  
  %% @spec parse_file(string() | atom()) -> acldb()
  %% @doc Parses an ACL file and converts it to an IP -> Zone index.
  %%
  %%  IPs DATABASE FORMAT
  