contrib/mul/mbl/mbl_parse_int_list.h
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_parse_int_list.h
00002 #ifndef mbl_parse_int_list_h_
00003 #define mbl_parse_int_list_h_
00004 //:
00005 // \file
00006 // \author Ian Scott
00007 // \date  7-Aug-2007
00008 // \brief Load an int_list of PODs/objects from a config file.
00009 
00010 #include <mbl/mbl_exception.h>
00011 #include <vcl_istream.h>
00012 #include <vcl_cctype.h>
00013 
00014 //: Read a list of integers from a stream.
00015 // This integer list should be space-separated.
00016 // Lists of the form "{ 1 2 5 : 10 }" a la matlab are accepted. Note that "a : b"
00017 // will include b rather than following normal C++ convention.
00018 // Failed parsing will cause an exception to be thrown, and the stream's fail bit to be set
00019 //
00020 // \throws mbl_exception_parse_error if unrecoverable parse error.
00021 //
00022 // \verbatim
00023 // Example:
00024 // vcl_vector<unsigned> v;
00025 // mbl_parse_int_list(vcl_cin, vcl_back_inserter(v), unsigned());
00026 // \endverbatim
00027 template <class ITER, class T>
00028 inline void mbl_parse_int_list(vcl_istream &afs, ITER insert_iter, T)
00029 {
00030   if (!afs) return;
00031 
00032   char c;
00033   afs >> vcl_ws >> c;
00034   if (!afs) return;
00035 
00036   bool openbrace = false;
00037 
00038   if (c == '{')
00039     openbrace = true;
00040   else
00041     afs.putback(c);
00042 
00043 
00044   while (true)
00045   {
00046     char c;
00047     afs >> vcl_ws >> c;
00048     if (afs.eof() || (c =='}' && openbrace))
00049     {
00050       afs.clear();
00051       return;
00052     }
00053     else if (!afs)
00054     {
00055       afs.clear(vcl_ios::failbit);
00056       mbl_exception_warning(mbl_exception_parse_error(
00057         "mbl_parse_int_list: Unknown stream failure") );
00058       return;
00059     }
00060 
00061     else if (! (vcl_isdigit(c) || c== '-') )
00062     {
00063       afs.clear(vcl_ios::failbit);
00064       mbl_exception_warning(mbl_exception_parse_error(
00065         vcl_string("mbl_parse_int_list: unexpected character '") + c + "'") );
00066       return;
00067     }
00068 
00069 
00070     afs.putback(c);
00071     T current;
00072     afs >> current >> vcl_ws >> c;
00073     if (afs.eof() && openbrace)
00074     {
00075       afs.clear(vcl_ios::failbit);
00076       mbl_exception_warning(mbl_exception_parse_error(
00077         "mbl_parse_int_list: unexpected EOF" ) );
00078       return;
00079     }
00080 
00081     if (afs.eof() || (c =='}' && openbrace) )
00082     {
00083       *insert_iter++ = current;
00084       afs.clear();
00085       return;
00086     }
00087     else if (!afs)
00088     {
00089       mbl_exception_warning(mbl_exception_parse_error(
00090         "mbl_parse_int_list: non-integer detected") );
00091       return;
00092     }
00093     else if (vcl_isdigit(c) || c== '-')
00094     {
00095       afs.putback(c);
00096       *insert_iter++ = current;
00097       continue;
00098     }
00099     else if (c!=':')
00100     {
00101       afs.clear(vcl_ios::failbit);
00102       mbl_exception_warning(mbl_exception_parse_error(
00103         vcl_string("mbl_parse_int_list: unexpected character '") + c + "'") );
00104       return;
00105     }
00106     else
00107     {
00108       T last;
00109       afs >> vcl_ws >> last;
00110       if (afs.eof())
00111       {
00112         mbl_exception_warning(mbl_exception_parse_error(
00113           "mbl_parse_int_list: unexpected EOF") );
00114         return;
00115       }
00116       if (!afs)
00117       {
00118         mbl_exception_warning(mbl_exception_parse_error(
00119           "mbl_parse_int_list: Unknown stream error") );
00120         return;
00121       }
00122 
00123       if (current > last)
00124       {
00125         // Count down to last
00126         // Note: Do in two steps to avoid -- problems when last==0
00127         while (current > last)
00128           *insert_iter++ = current--;
00129 
00130         *insert_iter++ = last;
00131 #if 0
00132         afs.clear(vcl_ios::failbit);
00133         mbl_exception_warning(mbl_exception_parse_error(
00134           vcl_string("mbl_parse_int_list: unbounded sequence") ));
00135         return;
00136 #endif
00137       }
00138       else
00139       {
00140         // Count up to last
00141         while (current <= last)
00142           *insert_iter++ = current++;
00143       }
00144     }
00145   }
00146 }
00147 
00148 #endif // mbl_parse_int_list_h_