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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include <string>
00043 #include <ostream>
00044 #include <istream>
00045 
00046 #include "OptionsFromStreamPack_OptionsFromStream.hpp"
00047 #include "InputStreamHelperPack_EatInputComment.hpp"
00048 #include "Teuchos_Assert.hpp"
00049 
00050 // Define this if you want to debug the parser
00051 //#define PRINT_OPTIONS_FROM_STREAM_TRACE
00052 
00053 namespace {
00054 
00055 // Remove white space from beginning and end.
00056 inline
00057 void clip_ws( std::string* str ) {
00058   // Remove the first non ' ' characters
00059   {
00060     std::string::iterator itr;
00061     for( itr = str->begin(); itr != str->end(); ++itr )
00062       if( *itr != ' ' ) break;
00063     str->erase( str->begin(), itr ); 
00064   }
00065   // Remove the last non ' ' characters
00066   {
00067     std::string::iterator itr;
00068     for( itr = str->end() - 1; itr > str->begin() - 1; --itr )
00069       if( *itr != ' ' ) break;
00070     str->erase( itr + 1, str->end() ); 
00071   }
00072 }
00073 
00074 } // end namespace
00075 
00076 namespace OptionsFromStreamPack {
00077 
00078 namespace OptionsFromStreamUtilityPack {
00079 
00080 // class OptionsGroup
00081 
00082 std::string OptionsGroup::option_does_not_exist_;
00083 
00084 } // end namespace OptionsFromStreamUtilityPack
00085 
00086 // class OptionsFromStream
00087 
00088 OptionsFromStream::options_group_t
00089 OptionsFromStream::options_group( const std::string& options_group_name )
00090 {
00091   options_group_map_t::iterator itr = options_group_map_.find( options_group_name );
00092   if( itr != options_group_map_.end() ) {
00093     (*itr).second.second.set(true); // flag that we have accessed this options group
00094     return options_group_t(&(*itr).second.first);
00095   }
00096   return options_group_t(NULL);
00097 }
00098 
00099 const OptionsFromStream::options_group_t
00100 OptionsFromStream::options_group( const std::string& options_group_name ) const
00101 {
00102   options_group_map_t::const_iterator itr = options_group_map_.find( options_group_name );
00103   if( itr != options_group_map_.end() ) {
00104     const_cast<false_bool_t&>((*itr).second.second).set(true); // flag that we have accessed this options group
00105     return options_group_t(const_cast<option_to_value_map_t*>(&(*itr).second.first));
00106   }
00107   return options_group_t(NULL);
00108 }
00109 
00110 void OptionsFromStream::reset_unaccessed_options_groups()
00111 {
00112   for( iterator og_itr = begin() ; og_itr != end(); ++og_itr ) {
00113     (*og_itr).second.second.set(false); // rest to not accessed yet.
00114   }
00115 }
00116 
00117 void OptionsFromStream::print_unaccessed_options_groups( std::ostream& out ) const
00118 {
00119   const_iterator og_itr = begin();
00120   for( ; og_itr != end(); ++og_itr ) {
00121     if( (*og_itr).second.second == false ) // if options group was not accessed
00122       out << "options_group " << options_group_name( og_itr ) << " {}\n";
00123   }
00124 }
00125 
00126 void OptionsFromStream::read_options( std::istream& in )
00127 {
00128   using std::getline;
00129   
00130   using InputStreamHelperPack::eat_comment_lines;
00131 
00132   std::string curr_word;
00133 
00134   if(!in)
00135     return; // No options to read!
00136 
00137 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00138   std::cout << "\n*** Entering OptionsFromStream::read_options(...)!\n\n";
00139 #endif
00140 
00141   // Eat words until you get to begin_options.
00142   while( curr_word != "begin_options" && !in.eof() )
00143     in >> curr_word;
00144 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00145   std::cout << "Found begin_options, start parsing options!\n";
00146 #endif
00147   // Loop through each options group.
00148   while( !in.eof() ) {
00149      eat_comment_lines(in,'*');
00150     // read options_group
00151     in >> curr_word;
00152 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00153     std::cout << "\ncurr_word = \""<<curr_word<<"\"\n";
00154 #endif
00155     if( curr_word == "}" ) {
00156 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00157       std::cout << "Found \'}\', Moving on to the next options group or the end!\n";
00158 #endif
00159       break;
00160     }
00161     if( curr_word == "end_options" ) {
00162 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00163       std::cout << "Found \'end_options\', stoping parsing options!\n";
00164 #endif
00165       break;
00166     }
00167     TEUCHOS_TEST_FOR_EXCEPTION(
00168       curr_word != "options_group", InputStreamError
00169       ,"OptionsFromStream::read_options(...) : "
00170       "Error, curr_word = \'" << curr_word << " != \'options_group\'" );
00171     // read the name of the options group up to {
00172     std::getline(in,curr_word,'{');
00173     clip_ws( &curr_word );
00174     const std::string optgroup_name = curr_word;
00175 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00176     std::cout << "\noptgroup_name = \"" << optgroup_name << "\"\n";
00177 #endif
00178     // Access the options and values map for this options group.
00179     option_to_value_map_t& optval = options_group_map_[optgroup_name].first;
00180     // Grap all of the options for this options group
00181      eat_comment_lines(in,'*');
00182     std::string optgroup_options;
00183     getline(in,optgroup_options,'}');
00184 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00185     std::cout << "optgroup_options = \"" << optgroup_options << "\"\n";
00186 #endif
00187     std::istringstream optgroup_options_in(optgroup_options);
00188     // Loop through and add the options.
00189     while(true) {
00190       eat_comment_lines(optgroup_options_in,'*');
00191       // Get an option and its value
00192       std::string option_and_value;
00193       getline(optgroup_options_in,option_and_value,';');
00194       // Note: above If ';' is missing it will take the rest of the string to
00195       // the end of '}' for the end of the options group.  These means that if
00196       // there is no comments after the last option=value pair then the last
00197       // semicolon is optional!  This turns out to work nicely for the
00198       // CommandLineOptionsFromStreamProcessor class so this is good behavior!
00199       clip_ws(&option_and_value);
00200 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00201       std::cout << "  option_and_value = \"" << option_and_value << "\"\n";
00202 #endif
00203       if(!option_and_value.length())
00204         break;
00205       // Process the option and value
00206       const std::string::size_type equal_idx = option_and_value.find('=',0);
00207       TEUCHOS_TEST_FOR_EXCEPTION(
00208         equal_idx==std::string::npos, std::logic_error,
00209         "Error, for the option group \"" << optgroup_name << "\""
00210         << " the option value string \"" << option_and_value << "\" is missing the \"=\" separator!"
00211         );
00212       std::string option = option_and_value.substr(0,equal_idx);
00213       std::string value = option_and_value.substr(equal_idx+1);
00214       clip_ws(&option);
00215       clip_ws(&value);
00216 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00217       std::cout << "    option = \"" << option << "\"\n";
00218       std::cout << "    value  = \"" << value << "\"\n";
00219 #endif
00220       optval[option] = value;
00221     }
00222   }
00223 #ifdef PRINT_OPTIONS_FROM_STREAM_TRACE
00224   std::cout << "\n*** Leaving OptionsFromStream::read_options(...)!\n\n";
00225 #endif
00226 }
00227 
00228 void OptionsFromStream::print_options( std::ostream& out ) const {
00229   out << "\nbegin_options\n";
00230   const_iterator og_itr = begin();
00231   for( ; og_itr != end(); ++og_itr ) {
00232     const options_group_t optgrp = OptionsFromStreamPack::options_group( og_itr );
00233     options_group_t::const_iterator itr = optgrp.begin();
00234     if(itr == optgrp.end()) continue;
00235     out << "\noptions_group " << options_group_name( og_itr ) << " {\n";
00236     for( ; itr != optgrp.end(); ++itr ) {
00237       const std::string
00238         &name  = option_name(itr),
00239         &value = option_value(itr);
00240       out << "    " << name << " = " << value << ";\n";
00241     }
00242     out << "}\n";
00243   }
00244   out << "\nend_options\n\n";
00245 }
00246 
00247 } // end namespace OptionsFromStreamPack
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends