The
      x::mime::header_iter
      template instantiates an output iterator that takes the output sequence
      from x::mime::bodystart_iter.
      The template parameter is another output iterator class, over an
      int output sequence.
      Instantiated by create(), the constructor takes
      an instance of the output iterator class, which ends up iterating over
      the output sequence that
      x::mime::header_iter
      received, and
      x::mime::header_iter
      adds additional values into the output sequence:
    
	  The name of each header gets preceded by an
	  x::mime::header_name_start and followed by an
	  x::mime::header_name_end.
	
	  The contents of each header gets preceded by an
	  x::mime::header_contents_start and followed by
	  an
	  x::mime::header_contents_end.
	  x::mime::header_name_start and 
	  x::mime::header_name_end are always followed by
	  x::mime::header_contents_start and
	  x::mime::header_contents_end, but
	  x::mime::header_contents_start does not
	  immediately follow a
	  x::mime::header_name_end.
	
	  The portion of the output sequence delimited by
	  x::mime::header_contents_start and
	  x::mime::header_contents_end excludes the
	  colon and whitespace that separates the header name from its
	  contents.
	  x::mime::header_iter does not
	  remove values from the output sequence it receives, it only adds
	  these additional values.
	
	  For multiline header contents, the sequence delimited by an
	  x::mime::header_contents_start and an
	  x::mime::header_contents_end has
	  additional
	  x::mime::header_fold_start and an
	  x::mime::header_fold_end values that
	  delimiter the start and the end of the newline and leading spaces
	  on the continued header line. For the purpose of parsing the
	  headers contents, the output sequence between and including
	  x::mime::header_fold_start and
	  x::mime::header_fold_end is logically
	  equivalent to a single space character (as already mentioned,
	  x::mime::header_iter does not
	  remove values from the output sequence it receives, it only adds
	  dditional values).
	
	  After
	  x::mime::header_iter iterates over a
	  x::mime::body_start,
	  the
	  x::mime::header_iter passes it, and the
	  rest of the output sequence, with no further parsing or action.
	
#include <x/mime/newlineiter.H> #include <x/mime/bodystartiter.H> #include <x/mime/headeriter.H> #include <map> #include <iterator> #include <iostream> class headercollector : public std::iterator<std::output_iterator_tag, void, void, void, void> { public: std::multimap<std::string, std::string> *h; std::string name; bool seen_contents_start; bool in_header_name; bool in_newline; bool in_fold; std::multimap<std::string, std::string>::iterator value; headercollector(std::multimap<std::string, std::string> *hArg) : h(hArg), in_header_name(false), seen_contents_start(false) { } void operator=(int c) { switch (c) { case x::mime::header_name_start: name.clear(); in_header_name=true; return; case x::mime::header_name_end: value=h->insert(std::make_pair(name, "")); in_header_name=false; return; case x::mime::header_contents_start: seen_contents_start=true; in_newline=false; in_fold=false; return; case x::mime::header_contents_end: seen_contents_start=false; return; case x::mime::header_fold_start: in_fold=true; return; case x::mime::header_fold_end: in_fold=false; value->second.push_back(' '); return; case x::mime::newline_start: in_newline=true; return; case x::mime::newline_end: in_newline=false; return; } if (!x::mime::nontoken(c)) return; if (in_header_name) { name.push_back(c); return; } if (!seen_contents_start || in_fold || in_newline) return; value->second.push_back(c); } headercollector &operator*() { return *this; } headercollector &operator++() { return *this; } headercollector &operator++(int) { return *this; } }; int main() { std::multimap<std::string, std::string> h; typedef x::mime::header_iter<headercollector> header_iter_t; typedef x::mime::bodystart_iter<header_iter_t> bodystart_iter_t; typedef x::mime::newline_iter<bodystart_iter_t> newline_iter_t; auto iter=std::copy(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>(), newline_iter_t::create (bodystart_iter_t::create (header_iter_t::create(&h)))); iter.get()->eof(); for (const auto &c:h) { std::cout << "Header: " << c.first << ", value: " << c.second << std::endl; } return 0; }
      This example constructs a simple output iterator that receives
      the output sequence from a
      x::mime::header_iter, collects all headers
      in a std::multimap, then shows them:
    
      
$ cat headeriter.txt
Mime-Version: 1.0
Subject: subject line
   folded header
test
$ ./headeriter <headeriter.txt
Header: Mime-Version, value: 1.0
Header: Subject, value: subject line folded header
    x::mime::header_collector
	x::mime::header_collector
	implements a basic output iterator that turns the output sequence
	from a
	x::mime::header_iter into calls to a lambda
	or a functor:
      
#include <x/mime/newlineiter.H> #include <x/mime/bodystartiter.H> #include <x/mime/headeriter.H> #include <x/mime/headercollector.H> #include <map> #include <iterator> #include <iostream> int main() { typedef x::mime::header_iter<x::mime::header_collector> header_iter_t; typedef x::mime::bodystart_iter<header_iter_t> bodystart_iter_t; typedef x::mime::newline_iter<bodystart_iter_t> newline_iter_t; auto iter=std::copy(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>(), newline_iter_t::create (bodystart_iter_t::create (header_iter_t::create (x::mime::header_collector::create ([] (const std::string &name, const std::string &name_lc, const std::string &value) { std::cout << "Header: " << name << ", value: " << value << std::endl; }))))); iter.get()->eof(); return 0; }
This produces the same results as the previous example, with two small, but important, differences.
	    x::mime::header_collector::create()
	    instantiates an output iterator over the sequence from
	    x::mime::header_iter, and calls the
	    lambda or the functor that's passed to
	    create(). The functor/lambda
	    gets invoked with three parameters: the header name,
	    the header name converted to lowercase, and the contents of
	    the header.
	  
	    x::mime::header_collector
	    does not store the headers from the MIME object it iterates over
	    into a container of any kind. The functor/lambda gets invoked
	    as soon as the entire header name
	    and contents get iterated over.