contrib/mul/mbl/mbl_parse_sequence.h
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_parse_sequence.h
00002 #ifndef mbl_parse_sequence_h_
00003 #define mbl_parse_sequence_h_
00004 //:
00005 // \file
00006 // \author Ian Scott
00007 // \date  7-Aug-2007
00008 // \brief Load a sequence of PODs/objects from a config file.
00009 
00010 #include <vcl_algorithm.h>
00011 #include <vcl_istream.h>
00012 #include <vcl_iterator.h>
00013 #include <mbl/mbl_exception.h>
00014 
00015 //: Read a sequence of PODs from a stream.
00016 // This function will read through a stream, and store the text found to a string.
00017 // The function terminates correctly when it finds a matched closing brace,
00018 // Alternatively, if there was no opening brace, it will terminate at the end of a stream.
00019 // Other conditions will cause an exception to be thrown, and the stream's fail bit to be set
00020 //
00021 // \throws mbl_exception_parse_error if unrecoverable parse error.
00022 //
00023 // \verbatim
00024 // Example:
00025 // vcl_vector<unsigned> v;
00026 // mbl_parse_sequence(vcl_cin, vcl_back_inserter(v), unsigned());
00027 // \endverbatim
00028 template <class ITER, class T>
00029 inline void mbl_parse_sequence(vcl_istream &afs, ITER insert_iter, T /*dummy*/)
00030 {
00031   // Can't use iterator_traits<ITER>::value_type to infer T,
00032   // because output_iterators may not have a useful value_type
00033   // and are defined by the standard to have value_type void,
00034   // See http://www.adras.com/Why-no-std-back-insert-iterator-value-type.t2639-153.html
00035 
00036   if (!afs) return;
00037   char brace1, brace2;
00038   afs >> vcl_ws >> brace1;
00039   if (afs.eof()) return;
00040 
00041   if ( brace1 == '{')
00042   {
00043     vcl_copy(vcl_istream_iterator<T>(afs),
00044              vcl_istream_iterator<T>(), insert_iter);
00045 
00046     if (afs.fail())
00047       afs.clear();
00048 
00049     afs >> vcl_ws >> brace2;
00050     if (!afs || brace2 != '}')
00051     {
00052       afs.putback(brace2);
00053       afs.clear(vcl_ios::failbit); // Set a recoverable IO error on stream
00054       throw mbl_exception_parse_error(
00055         "mbl_parse_sequence failed to find closing brace.");
00056     }
00057   }
00058   else
00059   {
00060     afs.putback(brace1);
00061 
00062     vcl_copy(vcl_istream_iterator<T>(afs),
00063              vcl_istream_iterator<T>(), insert_iter);
00064 
00065     if (afs.fail())
00066       afs.clear();
00067 
00068     char c;
00069     afs >> c;
00070     if (!(!afs))
00071     {
00072       afs.putback(c);
00073       afs.clear(vcl_ios::failbit);
00074 
00075       throw mbl_exception_parse_error(
00076         "mbl_parse_sequence failed to find EOF.");
00077     }
00078     afs.clear(vcl_ios::eofbit);
00079   }
00080 }
00081 
00082 #endif // mbl_parse_sequence_h_