/*************************************************** Created by: Venkat on Mon Aug 15 10:33:23 CDT 2005 Modified : Purpose : ****************************************************/ #include "eff_utils/Efficiency.hpp" #include "eff_utils/EffExceptions.hpp" #include #include using namespace std; using namespace eff_utils; Efficiency::Efficiency(istream &fstr, const EffInfo* request){ MakeEfficiency( fstr, request);} Efficiency::Efficiency() { _isValid = false; } bool Efficiency::MakeEfficiency(istream& fstr, const EffInfo* request){ if(!EffParse(fstr, request)) return false; else return true; } Efficiency::~Efficiency(){;} void Efficiency::doStream( ostream & os) const { // first dump efficiency info os << _spec; // now dump the efficiency values themselvs stream( os ); } bool Efficiency::Tokenize(const string& str, std::string & key, vector& tokens, const string& delimiters) { int nfound = 0; if(str.empty()) return false; // Skip delimiters at beginning string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first non-delimiter string::size_type pos = str.find_first_of(delimiters, lastPos); bool first = true; while (string::npos != pos || string::npos != lastPos) { ++nfound; std::string tmp = str.substr(lastPos, pos - lastPos); if( first ) { key = tmp; first = false; } else { // Found a token, add it to the vector. tokens.push_back(tmp); } // Skip delimiters. lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } if(nfound == 0) return false; else return true; } bool Efficiency::isRequestInFile(istream& fp, const EffInfo* request) { int counter = 0 ; bool endOfObject = false ; // true after filling one EffInfo object while(fp && fp.good()) { vector tokens; std::string str; std::string key; getline(fp,str); // Tokenize is used to break the input line into a series of "words", the first of which is the "keyword". The fourth parameter to this call // is the set of delimeters for defining word boundaries bool goodTokens = Tokenize(str, key, tokens, "\t\r\n: "); if(!goodTokens) continue ; if( ParseInputLine( key, tokens)) { endOfObject = true ; continue ; } if (endOfObject) { if(*request == _spec) return true ; Clear() ; endOfObject = false ; } _spec.ParseInputLine( key, tokens); } if(*request == _spec) return true ; return false ; } bool Efficiency::EffParse(istream& fp, const EffInfo* request) { // read in one Efficiency object from the input stream bool endOfObject = false ; // true after filling one EffInfo object while(fp && fp.good()) { vector tokens; std::string str; std::string key; std::streampos savePoint = fp.tellg(); getline(fp,str); // Tokenize is used to break the input line into a series of "words", the first of which is the "keyword". The fourth parameter to this call // is the set of delimeters for defining word boundaries bool goodTokens = Tokenize(str, key, tokens, "\t\r\n: "); if(!goodTokens) continue ; // ParseInputLine is implemented by the derived class. It returns true if the derived class found a key which it recongnised // thus endOfObject is set to true the first time a key is found belonging to the derived class. if( ParseInputLine( key, tokens)) { // cout << " --- Find endofObject" << endl; endOfObject = true ; continue ; } else { // cout << " - EffParse str: " << str << endl; // cout << " - key: " << key << endl; // cout << " - tokens: "; // for( int itok = 0 ; itok < tokens.size() ; itok++ ) // cout << tokens[itok] << " - "; // cout << endl; } // this section can only be reached if the key was not recongnised by the derived class if (endOfObject) { // cout << "nlenle " << endl; // so we can only get into here when we find the first line with a key not // recognised by the derived class after a block of lines (1 or more) which *were* recognised by the // derived class. bool reqFound = false; if( request ) { if( request->Contains(_spec) ) reqFound = true; } else { reqFound = true; } if( reqFound ) { // does the specification of the efficiency match what we requested? _isValid = doValidateInput(); // is it valid? if( _isValid ) { // now we need to put the current line back into the buffer in case the controller of the stream (most likely EffTool) wants to make // a new Efficiency object to continue parsing the input stream to look for further instances of matching efficiencies! fp.seekg( savePoint ); } return _isValid ; // } // if it matched the request but was invalid then we return false... if it doesn't match then we keep processing here. // by wiping the contents and continuing with the current line Clear() ; endOfObject = false ; } // current line was not processed by the derived class so its most likely metadata rather than the efficiency data itself and thus belongs in the spec. _spec.ParseInputLine( key, tokens); } // if we got to the end of the stream without finding a file. throw an exception here. if(request && !request->Contains(_spec)) throw EffRequestNotFoundInFile() ; _isValid = doValidateInput(); return _isValid; } bool Efficiency::doValidateInput() const { bool valid = true; // first make sure all the things needed to define an arbitrary efficiency have been defined // now allow derived class to check for what it requires if( valid ) valid = valid && ValidateInput(); return valid; }