anchor.diff:  %%%===================================================================
   %%% Helpers
   %%%===================================================================
  --spec prepare_parser(#parser{}) -> {ok, #parser{}}.
  -prepare_parser(#parser{type = single_doc} = Parser) ->
  -    {ok,Parser};
  -prepare_parser(#parser{type = multiple_docs} = Parser) ->
  -    %% open fake stream tag and discard events
  -    %% use random bytes to reduce probability of closing the tag by user
  -    <<I:128/integer>> = crypto:rand_bytes(16),
  -    Tag = list_to_binary(erlang:integer_to_list(I,16)),
  -    {ok, NewParser, _ } = parse(Parser, <<"<_",Tag/binary,">">>),
  -    {ok, NewParser}.
   
  --spec parse_events(list(), list(), list()) -> {list(xmlstreamelement()), list()}.
  -parse_events([], Stack, Acc) ->
  +-spec parse_events(list(), list(), list(), boolean()) -> {list(xmlstreamelement()), list()}.
  +parse_events([], Stack, Acc, _InfiniteStream) ->
       {lists:reverse(Acc), Stack};
  -parse_events([{xml_element_start, Name, NSs, Attrs} | Rest], [], Acc) ->
  +parse_events([{xml_element_start, Name, NSs, Attrs} | Rest], [], Acc, false) ->
       NewAttrs = nss_to_fake_attrs(NSs, []) ++ Attrs,
       parse_events(Rest, [#xmlel{name = Name, attrs = NewAttrs}],
  -                 [#xmlstreamstart{name = Name, attrs = NewAttrs} | Acc]);
  -parse_events([{xml_element_start, Name, NSs, Attrs} | Rest], Stack, Acc) ->
  +                 [#xmlstreamstart{name = Name, attrs = NewAttrs} | Acc], false);
  +parse_events([{xml_element_start, Name, NSs, Attrs} | Rest], Stack, Acc, InfiniteStream) ->
       NewAttrs = nss_to_fake_attrs(NSs, []) ++ Attrs,
  -    parse_events(Rest, [#xmlel{name = Name, attrs = NewAttrs} | Stack], Acc);
  -parse_events([{xml_element_end, Name} | Rest], [#xmlel{name = Name}], Acc) ->
  -    parse_events(Rest, [], [#xmlstreamend{name = Name} | Acc]);
  -parse_events([{xml_element_end, Name} | Rest], [#xmlel{name = Name} = Element, Top], Acc) ->
  -    parse_events(Rest, [Top], [xml_element(Element) | Acc]);
  -parse_events([{xml_element_end, _Name} | Rest], [Element, Parent | Stack], Acc) ->
  +    parse_events(Rest, [#xmlel{name = Name, attrs = NewAttrs} | Stack], Acc, InfiniteStream);
  +parse_events([{xml_element_end, Name} | Rest], [#xmlel{name = Name}], Acc, false) ->
  +    parse_events(Rest, [], [#xmlstreamend{name = Name} | Acc], false);
  +parse_events([{xml_element_end, Name} | Rest], [#xmlel{name = Name} = Element, Top], Acc, InfiniteStream) ->
  +    parse_events(Rest, [Top], [xml_element(Element) | Acc], InfiniteStream);
  +parse_events([{xml_element_end, _Name} | Rest], [Element, Parent | Stack], Acc, InfiniteStream) ->
       NewElement = Element#xmlel{children = lists:reverse(Element#xmlel.children)},
       NewParent = Parent#xmlel{children = [NewElement | Parent#xmlel.children]},
  -    parse_events(Rest, [NewParent | Stack], Acc);
  -parse_events([{xml_cdata, _CData} | Rest], [Top], Acc) ->
  -    parse_events(Rest, [Top], Acc);
  -parse_events([{xml_cdata, CData} | Rest], [#xmlel{children = [#xmlcdata{content = Content} |
  -                                                                   RestChildren]} = XML | Stack], Acc) ->
  +    parse_events(Rest, [NewParent | Stack], Acc, InfiniteStream);
  +parse_events([{xml_cdata, _CData} | Rest], [Top], Acc, InfiniteStream) ->
  +    parse_events(Rest, [Top], Acc, InfiniteStream);
  +parse_events([{xml_cdata, CData} | Rest],
  +             [#xmlel{children = [#xmlcdata{content = Content} | RestChildren]} = XML | Stack],
  +             Acc, InfiniteStream) ->
       NewChildren = [#xmlcdata{content = list_to_binary([Content, CData])} | RestChildren],
  -    parse_events(Rest, [XML#xmlel{children = NewChildren} | Stack], Acc);
  -parse_events([{xml_cdata, CData} | Rest], [Element | Stack], Acc) ->
  +    parse_events(Rest, [XML#xmlel{children = NewChildren} | Stack], Acc, InfiniteStream);
  +parse_events([{xml_cdata, CData} | Rest], [Element | Stack], Acc, InfiniteStream) ->
       NewChildren = [#xmlcdata{content = CData} | Element#xmlel.children],
  -    parse_events(Rest, [Element#xmlel{children = NewChildren} | Stack], Acc).
  +    parse_events(Rest, [Element#xmlel{children = NewChildren} | Stack], Acc, InfiniteStream).
   
   -spec xml_element(#xmlel{}) -> #xmlel{}.
   xml_element(#xmlel{children = Children} = Element) ->
  
positive.code:          parse/2,
           reset_parser/1,
           free_parser/1]).
  -export_type([parser/0]).
  -export_type([parser_type/0]).
  
  %% single_doc - the old way one document: <stream:stream> ..... </stream:stream>
  %% multiple_docs - xmpp over websockets(IETF 89) replaces <stream:..> tags with
  %% <open/> <close/>. As a result we have a stream of multiple xml documents instead of one document.
  %% This type of parser can handle that stream.
  %% see: http://datatracker.ietf.org/doc/draft-ietf-xmpp-websocket/?include_text=1
  -type parser_type() :: single_doc | multiple_docs.
  
  -record(parser, {
          event_parser,
          type,
          stack = []
  }).
  
  -type parser() :: #parser{}.
  
  
negative.code: 
  -spec parse(parser(), binary()) ->
          {ok, parser(), [xmlstreamelement()]} | {error, {string(), binary()}}.
  parse(#parser{event_parser = EventParser, stack = OldStack, config = Config} = Parser, Input) ->
      case exml_event:parse(EventParser, Input) of
          {ok, Events} ->
              {Elements, NewStack} = parse_events(Events, OldStack, [],
                                                  Config#config.infinite_stream),
              NewParser = if
                              NewStack =:= [] andalso Config#config.autoreset ->
                                  reset_parser(Parser);
                              true ->
                                  Parser
                          end,
              {ok, NewParser#parser{stack=NewStack}, Elements};
          {error, Msg} ->
              {error, {Msg, Input}}
      end.
  
  -spec reset_parser(parser()) -> {ok, parser()} | {error, any()}.
  reset_parser(#parser{event_parser = EventParser, config = Config}) ->
      try
          exml_event:reset_parser(EventParser),
          %% drop all the state except event_parser
          {ok, #parser{event_parser = EventParser, config = Config}}
      catch
          E:R ->
              {error, {E, R}}
  