anchor.diff:  -module(keylist).
  --export([fetch/2, from_list/1, append/2, prepend/2,
  -	 delete/2, deletefirstvalue/2, set/3, copy/2, appendlist/2, map/2]).
  +
  +%%--------------------------------------------------------------------
  +%% External exports
  +%%--------------------------------------------------------------------
  +-export([
  +	 fetch/2, 
  +	 from_list/1, 
  +	 append/2, 
  +	 prepend/2,
  +	 delete/2, 
  +	 deletefirstvalue/2, 
  +	 set/3, 
  +	 copy/2, 
  +	 appendlist/2, 
  +	 map/2
  +	]).
  +
  +%%--------------------------------------------------------------------
  +%% Internal exports
  +%%--------------------------------------------------------------------
  +
  +%%--------------------------------------------------------------------
  +%% Include files
  +%%--------------------------------------------------------------------
  +
  +%%--------------------------------------------------------------------
  +%% Records
  +%%--------------------------------------------------------------------
   
   -record(keylist, {list}).
   -record(keyelem, {key, casekey, item}).
  +
  +%%--------------------------------------------------------------------
  +%% Macros
  +%%--------------------------------------------------------------------
  +
  +%%====================================================================
  +%% External functions
  +%%====================================================================
  +
  +%%--------------------------------------------------------------------
  +%% Function: fetch(Key, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           header - all RFC 3261 formats are accepted 
  +%%           List = keylist record()
  +%% Descrip.: return the contens that of the header that matches Key
  +%% Returns : E#keyelem.item
  +%%--------------------------------------------------------------------
  +fetch(Key, List) when record(List, keylist) ->
  +    fetchcase(to_lower(Key), List#keylist.list);
  +fetch(Key, List) ->
  +    erlang:fault("Keylist not wellformed", [Key, List]).
  +
  +fetchcase(Key, []) ->
  +    [];
  +fetchcase(Key, [Elem | List]) when record(Elem, keyelem), Elem#keyelem.casekey == Key ->
  +    Elem#keyelem.item;
  +fetchcase(Key, [Elem | List]) when record(Elem, keyelem) ->
  +    fetchcase(Key, List);
  +fetchcase(Key, [Elem | List]) ->
  +    erlang:fault("Keylist element not wellformed", [Key, [Elem | List]]).
  +
  +%%--------------------------------------------------------------------
  +%% Function: appendlist(Keylist, List)
  +%%           Keylist = list() of {Key, Item}
  +%%           List = keylist record()
  +%% Descrip.: do one append/2 for each entry in Keylist
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +appendlist(Keylist, List) when record(Keylist, keylist) ->
  +    Func = fun ({Key, Item}, KeylistAcc) ->
  +		   append({Key, Item}, KeylistAcc)
  +	   end,
  +    lists:foldl(Func, Keylist, List).
  +
  +%%--------------------------------------------------------------------
  +%% Function: from_list(List)
  +%%           List = list() of {Key, Item}
  +%% Descrip.: create a empty keylist and add the List elements with 
  +%%           append/2
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +from_list(List) ->
  +    appendlist(empty(), List).
  +
  +%% Function: empty()
  +%% Descrip.: Return an empty keylist.
  +%% Returns : keylist record()
  +empty() ->
  +    #keylist{list=[]}.
  +
  +%%--------------------------------------------------------------------
  +%% Function: append({Key, NewValueList}, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           NewValueList = new entries for keyelem identified by Key
  +%%           List = keylist record()
  +%% Descrip.: add NewValueList to tail of element (#keyelem.item) in 
  +%%           List (or create new entry if Key is unkown)
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +append({Key, NewValueList}, List) when record(List, keylist) ->
  +    mod(Key, fun (Valuelist) ->
  +			 lists:append(Valuelist, NewValueList)
  +		 end, List).
  +
  +%%--------------------------------------------------------------------
  +%% Function: prepend({Key, NewValueList}, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           NewValueList = new entries for keyelem identified by Key
  +%%           List = keylist record()
  +%% Descrip.: add NewValueList to head of element (#keyelem.item) in 
  +%%           List (or create new entry if Key is unkown)
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +prepend({Key, NewValueList}, List) when record(List, keylist) ->
  +    mod(Key, fun (Valuelist) ->
  +			 lists:append(NewValueList, Valuelist)
  +		 end, List).
  +
  +%%--------------------------------------------------------------------
  +%% Function: delete(Key, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           List = keylist record()
  +%% Descrip.: remove a entry from keylist record() (#keylist.list)
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +delete(Key, List) when record(List, keylist) ->
  +    Casekey = to_lower(Key),
  +    #keylist{list=del(Casekey, List#keylist.list)}.
  +
  +%% Descrip.: delete first element (E) in List,
  +%%           where E#keyelem.casekey == to_lower(Key)
  +%% Returns : list() of keyelem records()
  +del(Key, []) ->
  +    [];
  +del(Key, [Elem | List]) when record(Elem, keyelem), Elem#keyelem.casekey == Key ->
  +    List;
  +del(Key, [Elem | List]) when record(Elem, keyelem) ->
  +    [Elem | del(Key, List)].
  +
  +%%--------------------------------------------------------------------
  +%% Function: deletefirstvalue(Key, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           List = keylist record()
  +%% Descrip.: remove the first entry from a element (#keyelem.item) 
  +%%           in keylist record() (#keylist.list)
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +deletefirstvalue(Key, List) when record(List, keylist) ->
  +    mod(Key, fun (Valuelist) ->
  +			 case Valuelist of
  +			     [Item | Rest] ->
  +				 Rest;
  +			     [] ->
  +				 []
  +			 end
  +		 end, List).
  +
  +%%--------------------------------------------------------------------
  +%% Function: set(Key, Valuelist, List)
  +%%           Key = string(), the name of a field in a sip message 
  +%%           ValueList = 
  +%%           List = keylist record()
  +%% Descrip.: replace all items in E#keyelem.item where Key matches 
  +%%           key in E
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +set(Key, Valuelist, List) when record(List, keylist) ->
  +    mod(Key, fun (_) ->
  +			 Valuelist
  +		 end, List).
  +
  +%%--------------------------------------------------------------------
  +%% Function: copy(Keylist, Keys)
  +%%           Keylist = list() of keyelem record()
  +%%           Keys = list() of string()
  +%% Descrip.: return Keylist only containing the fields in Keys
  +%% Returns : keylist record()
  +%%--------------------------------------------------------------------
  +copy(Keylist, Keys) when record(Keylist, keylist) ->
  +    Casekeys = to_lower_list(Keys),
  +    Func = fun(Key, Item) ->
  +		   lists:member(Key, Casekeys)
  +	   end,
  +    filter(Func, Keylist).
  +
  +%% Function: filter(Func, Keylist)
  +%%           Func = fun(E) -> bool(), predicate function
  +%%           Keylist = list() of keyelem record() 
  +%% Descrip.: 
  +%% Returns : keylist record()
  +filter(Func, Keylist) when record(Keylist, keylist) ->
  +    Pred = fun(Elem) ->
  +		   Func(Elem#keyelem.casekey, Elem#keyelem.item)
  +	   end,
  +    #keylist{list=lists:filter(Pred, Keylist#keylist.list)}.
  +
  +%%--------------------------------------------------------------------
  +%% Function: map(Func, Keylist)
  +%%           Func = fun(Key, Casekey, Item) -> term()
  +%%           Keylist = keylist record()
  +%% Descrip.: apply Func to all elements in Keylist (#keylist.list)
  +%% Returns : list() of term()
  +%%--------------------------------------------------------------------
  +map(Func, Keylist) when record(Keylist, keylist) ->
  +    Pred = fun(Elem) ->
  +		   Func(Elem#keyelem.key, Elem#keyelem.casekey, Elem#keyelem.item)
  +	   end,
  +    lists:map(Pred, Keylist#keylist.list).
  +
  +
  +%%====================================================================
  +%% Behaviour functions
  +%%====================================================================
  +
  +%%====================================================================
  +%% Internal functions
  +%%====================================================================
  +
  +%%--------------------------------------------------------------------
  +%% Function: to_lower(Key)
  +%%           Key = string(), the name of a field in a sip message 
  +%% Descrip.: convert header key, to a standard format - lowercase and
  +%%           verbose string() 
  +%% Returns : string()
  +%% XXX something like "normalize" might be a more descriptive name 
  +%% divulging the true purpouse of "to_lower"
  +%%--------------------------------------------------------------------
   
   % This is to support the compact headers we are required to support
   % by RFC3261 7.3.3.
  
positive.code:     [#keyelem{key=Key,
  	      casekey=Casekey,
  	      item=Func([])}];
  modcase(Key, Casekey, Func, [Elem | List]) when record(Elem, keyelem), Elem#keyelem.casekey == Casekey ->
      [Elem#keyelem{item=Func(Elem#keyelem.item)} | List];
  modcase(Key, Casekey, Func, [Elem | List]) when record(Elem, keyelem) ->
      [Elem | modcase(Key, Casekey, Func, List)].
  
  del(Key, []) ->
      [];
  del(Key, [Elem | List]) when record(Elem, keyelem), Elem#keyelem.casekey == Key ->
      List;
  del(Key, [Elem | List]) when record(Elem, keyelem) ->
      [Elem | del(Key, List)].
  
  filter(Func, Keylist) when record(Keylist, keylist) ->
      Pred = fun(Elem) ->
  		   Func(Elem#keyelem.casekey, Elem#keyelem.item)
  	   end,
      #keylist{list=lists:filter(Pred, Keylist#keylist.list)}.
  
  copy(Keylist, Keys) when record(Keylist, keylist) ->
      Casekeys = to_lower_list(Keys),
      Func = fun(Key, Item) ->
  		   lists:member(Key, Casekeys)
  	   end,
      filter(Func, Keylist).
  
  map(Func, Keylist) when record(Keylist, keylist) ->
      Pred = fun(Elem) ->
  		   Func(Elem#keyelem.key, Elem#keyelem.casekey, Elem#keyelem.item)
  	   end,
      lists:map(Pred, Keylist#keylist.list).
  
negative.code: to_lower(Key) ->
      Key.
  
  %%--------------------------------------------------------------------
  %% Function: to_lower_list(Keys)
  %%           Keys = list() of string(), the name of a field in a sip 
  %%           message 
  %% Descrip.: convert header key, to a standard format - lowercase and
  %%           verbose string() 
  %% Returns : list() of string()
  %%--------------------------------------------------------------------
  to_lower_list(Keys) ->
      lists:map(fun(Key) ->
  		      to_lower(Key)
  	      end, Keys).
  
  %%--------------------------------------------------------------------
  %% Function: mod(Key, Func, List)
  %%           Key = string(), the name of a field in a sip message 
  %%           Func = fun()
  %%           List = keylist record()
  %% Descrip.: apply Func to all elements E; 
  %%           E#keyelem{item = F(E#keyelem.item)} - in List, where
  %%           E#keyelem.casekey == to_lower(Key)
  %%           A new #keyelem{key=Key, 
  %%                          casekey=to_lower(CaseKey), 
  %%                          item=Func([])} 
  %%           is added if Key isn't found
  %% Returns : keylist record()
  %%--------------------------------------------------------------------
  mod(Key, Func, List) when record(List, keylist) ->
      Casekey = to_lower(Key),
      #keylist{list=modcase(Key, Casekey, Func, List#keylist.list)}.
  