anchor.diff: -%%%----------------------------------------------------------------
   %%% @author  Ivan Dubrov <dubrov.ivan@gmail.com>
  -%%% @doc SIP headers parsing/generation and utility functions
  +%%% @doc SIP headers parsing, formating and utility functions to construct
  +%%% header values
   %%%
  -%%% FIXME: need to verify that all binary generation properly unescapes/escapes characters!
   %%% @end
   %%% @reference See <a href="http://tools.ietf.org/html/rfc3261#section-20">RFC 3261</a> for details.
   %%% @copyright 2011 Ivan Dubrov. See LICENSE file.
  -%%%----------------------------------------------------------------
   -module(sip_headers).
   
  -%%-----------------------------------------------------------------
   %% Exports
  -%%-----------------------------------------------------------------
   -export([parse_headers/1, format_headers/1]).
   -export([parse/2, format/2]).
   -export([media/3, language/2, encoding/2, auth/2, info/2, via/3, cseq/2, address/3, retry/3]).
   -export([add_tag/3]).
   
  -%%-----------------------------------------------------------------
  -%% Macros
  -%%-----------------------------------------------------------------
  -
  -%%-----------------------------------------------------------------
  -%% Include files
  -%%-----------------------------------------------------------------
  +-type name() :: atom() | binary().
  +%% Optimized representation of entity name. When name is constructed
  +%% from the binary, a check is made if atom with this value exists.
  +%% If atom exists, it is used to represent the name of the entitiy.
  +%% Otherwise, binary is used.
  +%%
  +%% This ensures both optimal representation of name at runtime without
  +%% the danger of overloading atom table by malicious requests.
  +%%
  +%% Note that client code can always safely match against atom, since
  +%% matching against atom ensures atom is loaded (and therefore, atom
  +%% representation will be chosen by SIP libary).
  +-export_type([name/0]).
  +
  +
  +%% Includes
   -include("sip_common.hrl").
   -include("sip_parse.hrl").
   -include("sip.hrl").
   
  -%%-----------------------------------------------------------------
   %% API functions
  -%%-----------------------------------------------------------------
  -
  -%% @doc Parse binary into list of headers
  +
  +%% @doc Split binary into list of headers
   %%
   %% Convert binary containing headers into list of non-parsed headers
  -%% (with binary values). Binary must be `\r\n' separated headers. If
  -%% at least one header is present, binary must end with `\r\n'. Otherwise,
  -%% it must be empty binary.
  +%% (with binary values). Binary must contain a sequence headers, each
  +%% header terminated by `CRLF'. Empty binary is valid argument that
  +%% results in empty list returned.
   %% @end
   -spec parse_headers(binary()) -> [{Name :: atom() | binary(), Value :: binary() | term()}].
   parse_headers(<<>>) -> [];
  
positive.code: %% Header parsing/format functions
  %%-----------------------------------------------------------------
  
  parse(Name, Bin) -> process(p, Name, Bin).
  
  %% @doc Format header value into the binary.
  %% @end
  format(Name, [Value]) -> process(f, Name, Value);
  
negative.code: process(pn, <<"e">>, _Ignore) -> 'content-encoding';
  process(fn, 'content-encoding', _Ignore) -> <<"Content-Encoding">>;
  process(p, 'content-encoding', Bin) ->
      {EncodingBin, Rest} = sip_binary:parse_token(Bin),
      Encoding = sip_binary:binary_to_existing_atom(sip_binary:to_lower(EncodingBin)),
      parse_list('content-encoding', Encoding, Rest);
  
  process(f, 'content-encoding', Encoding) ->
      sip_binary:any_to_binary(Encoding);
  
  %% 20.13 Content-Language
  %% http://tools.ietf.org/html/rfc3261#section-20.13
  