MoochoPack: Miscellaneous Utilities for MOOCHO Version of the Day
OptionsFromStreamPack_OptionsFromStream.cpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00005 //                  Copyright (2003) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include <string>
00030 #include <ostream>
00031 #include <istream>
00032 
00033 #include "OptionsFromStreamPack_OptionsFromStream.hpp"
00034 #include "InputStreamHelperPack_EatInputComment.hpp"
00035 #include "Teuchos_TestForException.hpp"
00036 
00037 // Define this if you want to debug the parser
00038 //#define PRINT_OPTIONS_FROM_STREAM_TRACE
00039 
00040 namespace {
00041 
00042 // Remove white space from beginning and end.
00043 inline
00044 void clip_ws( std::string* str ) {
00045   // Remove the first non ' ' characters
00046   {
00047     std::string::iterator itr;
00048     for( itr = str->begin(); itr != str->end(); ++itr )
00049       if( *itr != ' ' ) break;
00050     str->erase( str->begin(), itr ); 
00051   }
00052   // Remove the last non ' ' characters
00053   {
00054     std::string::iterator itr;
00055     for( itr = str->end() - 1; itr > str->begin() - 1; --itr )
00056       if( *itr != ' ' ) break;
00057     str->erase( itr + 1, str->end() ); 
00058   }
00059 }
00060 
00061 } // end namespace
00062 
00063 namespace OptionsFromStreamPack {
00064 
00065 namespace OptionsFromStreamUtilityPack {
00066 
00067 // class OptionsGroup
00068 
00069 std::string OptionsGroup::option_does_not_exist_;
00070 
00071 } // end namespace OptionsFromStreamUtilityPack
00072 
00073 // class OptionsFromStream
00074 
00075 OptionsFromStream::options_group_t
00076 OptionsFromStream::options_group( const std::string& options_group_name )
00077 {
00078   options_group_map_t::iterator itr = options_group_map_.find( options_group_name );
00079   if( itr != options_group_map_.end() ) {
00080     (*itr).second.second.set(true); // flag that we have accessed this options group
00081     return options_group_t(&(*itr).second.first);
00082   }
00083   return options_group_t(NULL);
00084 }
00085 
00086 const OptionsFromStream::options_group_t
00087 OptionsFromStream::options_group( const std::string& options_group_name ) const
00088 {
00089   options_group_map_t::const_iterator itr = options_group_map_.find( options_group_name );
00090   if( itr != options_group_map_.end() ) {
00091     const_cast<false_bool_t&>((*itr).second.second).set(true); // flag that we have accessed this options group
00092     return options_group_t(const_cast<option_to_value_map_t*>(&(*itr).second.first));
00093   }
00094   return options_group_t(NULL);
00095 }
00096 
00097 void OptionsFromStream::reset_unaccessed_options_groups()
00098 {
00099   for( iterator og_itr = begin() ; og_itr != end(); ++og_itr ) {
00100     (*og_itr).second.second.set(false); // rest to not accessed yet.
00101   }
00102 }
00103 
00104 void OptionsFromStream::print_unaccessed_options_groups( std::ostream& out ) const
00105 {
00106   const_iterator og_itr = begin();
00107   for( ; og_itr != end(); ++og_itr ) {
00108     if( (*og_itr).second.second == false ) // if options group was not accessed
00109       out << "options_group " << options_group_name( og_itr ) << " {}\n";
00110   }
00111 }
00112 
00113 void OptionsFromStream::read_options( std::istream& in )
00114 {
00115   using std::getline;
00116   
00117   using InputStreamHelperPack::eat_comment_lines;
00118 
00119   std::string curr_word;
00120 
00121   if(!in)
00122     return; // No options to read!
00123 
00124 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00125   std::cout << "\n*** Entering OptionsFromStream::read_options(...)!\n\n";
00126 #endif
00127 
00128   // Eat words until you get to begin_options.
00129   while( curr_word != "begin_options" && !in.eof() )
00130     in >> curr_word;
00131 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00132   std::cout << "Found begin_options, start parsing options!\n";
00133 #endif
00134   // Loop through each options group.
00135   while( !in.eof() ) {
00136      eat_comment_lines(in,'*');
00137     // read options_group
00138     in >> curr_word;
00139 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00140     std::cout << "\ncurr_word = \""<<curr_word<<"\"\n";
00141 #endif
00142     if( curr_word == "}" ) {
00143 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00144       std::cout << "Found \'}\', Moving on to the next options group or the end!\n";
00145 #endif
00146       break;
00147     }
00148     if( curr_word == "end_options" ) {
00149 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00150       std::cout << "Found \'end_options\', stoping parsing options!\n";
00151 #endif
00152       break;
00153     }
00154     TEST_FOR_EXCEPTION(
00155       curr_word != "options_group", InputStreamError
00156       ,"OptionsFromStream::read_options(...) : "
00157       "Error, curr_word = \'" << curr_word << " != \'options_group\'" );
00158     // read the name of the options group up to {
00159     std::getline(in,curr_word,'{');
00160     clip_ws( &curr_word );
00161     const std::string optgroup_name = curr_word;
00162 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00163     std::cout << "\noptgroup_name = \"" << optgroup_name << "\"\n";
00164 #endif
00165     // Access the options and values map for this options group.
00166     option_to_value_map_t& optval = options_group_map_[optgroup_name].first;
00167     // Grap all of the options for this options group
00168      eat_comment_lines(in,'*');
00169     std::string optgroup_options;
00170     getline(in,optgroup_options,'}');
00171 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00172     std::cout << "optgroup_options = \"" << optgroup_options << "\"\n";
00173 #endif
00174     std::istringstream optgroup_options_in(optgroup_options);
00175     // Loop through and add the options.
00176     while(true) {
00177       eat_comment_lines(optgroup_options_in,'*');
00178       // Get an option and its value
00179       std::string option_and_value;
00180       getline(optgroup_options_in,option_and_value,';');
00181       // Note: above If ';' is missing it will take the rest of the string to
00182       // the end of '}' for the end of the options group.  These means that if
00183       // there is no comments after the last option=value pair then the last
00184       // semicolon is optional!  This turns out to work nicely for the
00185       // CommandLineOptionsFromStreamProcessor class so this is good behavior!
00186       clip_ws(&option_and_value);
00187 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00188       std::cout << "  option_and_value = \"" << option_and_value << "\"\n";
00189 #endif
00190       if(!option_and_value.length())
00191         break;
00192       // Process the option and value
00193       const std::string::size_type equal_idx = option_and_value.find('=',0);
00194       TEST_FOR_EXCEPTION(
00195         equal_idx==std::string::npos, std::logic_error,
00196         "Error, for the option group \"" << optgroup_name << "\""
00197         << " the option value string \"" << option_and_value << "\" is missing the \"=\" separator!"
00198         );
00199       std::string option = option_and_value.substr(0,equal_idx);
00200       std::string value = option_and_value.substr(equal_idx+1);
00201       clip_ws(&option);
00202       clip_ws(&value);
00203 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00204       std::cout << "    option = \"" << option << "\"\n";
00205       std::cout << "    value  = \"" << value << "\"\n";
00206 #endif
00207       optval[option] = value;
00208     }
00209   }
00210 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00211   std::cout << "\n*** Leaving OptionsFromStream::read_options(...)!\n\n";
00212 #endif
00213 }
00214 
00215 void OptionsFromStream::print_options( std::ostream& out ) const {
00216   out << "\nbegin_options\n";
00217   const_iterator og_itr = begin();
00218   for( ; og_itr != end(); ++og_itr ) {
00219     const options_group_t optgrp = OptionsFromStreamPack::options_group( og_itr );
00220     options_group_t::const_iterator itr = optgrp.begin();
00221     if(itr == optgrp.end()) continue;
00222     out << "\noptions_group " << options_group_name( og_itr ) << " {\n";
00223     for( ; itr != optgrp.end(); ++itr ) {
00224       const std::string
00225         &name  = option_name(itr),
00226         &value = option_value(itr);
00227       out << "    " << name << " = " << value << ";\n";
00228     }
00229     out << "}\n";
00230   }
00231   out << "\nend_options\n\n";
00232 }
00233 
00234 } // end namespace OptionsFromStreamPack
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends