anchor.diff:  ets({keys,Tab})          -> key_getter(tab(Tab));
   ets({insert,Tab,K,V})    -> inserter(tab(Tab),{K,V});
   ets({insert,Tab,KVs})    -> multi_inserter(tab(Tab),KVs);
  -ets({counter,Tab,Key})   -> update_counter(tab(Tab),ikey(Key),1);
  -ets({reset,Tab,Key})     -> reset_counter(tab(Tab),ikey(Key),0);
  -ets({next,Tab,Key})      -> next(tab(Tab),ikey(Key));
  -ets({prev,Tab,Key})      -> prev(tab(Tab),ikey(Key));
  -ets({get,Tab,Key})       -> getter(tab(Tab),lkey(Key));
  -ets({multi_get,Tab,Key}) -> multi_getter(tab(Tab),lkey(Key));
  -ets({delete,Tab,Key})    -> ets:delete(tab(Tab),ikey(Key)).
  +ets({counter,Tab,Key})   -> update_counter(tab(Tab),key_e2i(i,Key),1);
  +ets({reset,Tab,Key})     -> reset_counter(tab(Tab),key_e2i(i,Key),0);
  +ets({next,Tab,Key})      -> next(tab(Tab),key_e2i(i,Key));
  +ets({prev,Tab,Key})      -> prev(tab(Tab),key_e2i(i,Key));
  +ets({multi,Tab,Key})     -> getter(multi,tab(Tab),key_e2i(l,Key));
  +ets({single,Tab,Key})    -> getter(single,tab(Tab),key_e2i(l,Key));
  +ets({delete,Tab,Key})    -> ets:delete(tab(Tab),key_e2i(i,Key)).
   
   multi_inserter(Tab,{KVs}) ->
  -  ets:insert_new(Tab,[{ikey(binary_to_elems(K)),V} || {K,V} <- KVs]).
  +  Ops = [{mk_key(K),V} || {K,V} <- KVs],
  +  ets:insert_new(Tab,Ops).
  +
  +mk_key(K) ->
  +  key_e2i(i,string:tokens(binary_to_list(K),"/")).
   
   inserter(Tab,{Ks,V}) ->
  -  K = ikey(Ks),
  +  K = key_e2i(i,Ks),
     case ets:insert_new(Tab,{K,V}) of
       false-> throw({409,{exists,Tab,K}});
       true -> true
  
positive.code:                rets_client:get(localhost,tibbe,'a')),
    ?assertEqual({404,"multiple_hits"},
                 rets_client:get(localhost,tibbe,'a/_/_')),
    ?assertEqual({200,["a/2/x","a/1/x"]},
                 rets_client:get(localhost,tibbe,'a/_/_',multi)),
    ?assertEqual({404,"no_such_key"},
                 rets_client:get(localhost,tibbe,'b/_/_',multi)).
  
negative.code:   ets:insert(Tab,{Key,Beg}),
    Beg.
  
  %% key handling
  %% the external form of a key is the path part of an url, basically
  %% any number of slash-separated elements, each of which is
  %% string() | number(), like;
  %%  "a/ddd/b/a_b_/1/3.14/x"
  %% an element can not be a single underscore, "_". the single underscore
  %% is used as a wildcard in lookups.
  %% the internal representation is a tuple of string binaries;
  %%  {<<"a">>,<<"ddd">>,<<"b">>,<<"a_b_">>,<<"1">>,<<"3.14">>,<<"x">>}
  
  %% transform key, external to internal. there are two styles;
  %% "i", for inserts/deletes; "_" is forbidden
  %% "l", for lookups; "_" is a wildcard
  key_e2i(Style,L) -> list_to_tuple([elem(Style,E) || E <- L]).
  
  elem(i,"_") -> throw({404,key_has_underscore});
  elem(l,"_") -> '_';
  elem(_,E)   -> l2b(E).
  
  %% transform key, internal to external.
  key_i2e(T) ->
    l2b(join(tuple_to_list(T),<<"/">>)).
  
  join([E],_) -> [E];
  join([E|R],D) -> [E,D|join(R,D)].
  
  %% table names
  tab(L) ->
  