///////////////////////////////////////////////////////////////////////////// // // // Parser class // // // // Burkhard Militzer Urbana 4-1-99 // // based on earlier version by John Shumway // // // ///////////////////////////////////////////////////////////////////////////// #ifndef _PARSER_ #define _PARSER_ #include #include #include using namespace std; #include "Array.h" class FileBuffer { FILE * file; char * buffer; size_t size; size_t sizeRead; size_t marker; public: FileBuffer(const string & fileName, const size_t size_=10*1024*1024):size(size_) { buffer = new char[size]; file = fopen(fileName.c_str(),"r"); if (file==NULL) error("Error opening file:",fileName); if (Read()==false) error("Could not read any lines after opening",fileName); } ~FileBuffer() { delete[] buffer; Close(); } bool Read() { sizeRead = fread(buffer,sizeof(char),size,file); marker = 0; if (sizeRead==0) { Close(); return false; } return true; } size_t FindNextBreak(const size_t i) { // returns 'size' if nothing is found const char delimiter = '\n'; size_t j; for(j=i; j0; } } } bool Status() { return (sizeRead>0); // return (file != NULL); } void Close() { if (file) fclose(file); } }; class Parser { // #define USE_FILE_BUFFER const string filename; #ifndef USE_FILE_BUFFER ifstream ifs; istream& is; #else FileBuffer fileBuffer; #endif Array1 words; string line; bool ignoreComments; bool ignoreEmptyLines; int nLinesRead; int nNonEmptyLinesRead; static const int notFound = -1; public: Parser(const string & fn): filename(fn), #ifndef USE_FILE_BUFFER ifs(fn.c_str()), is(ifs), #else fileBuffer(fn), #endif ignoreComments(true), ignoreEmptyLines(true), nLinesRead(0), nNonEmptyLinesRead(0) { #ifndef USE_FILE_BUFFER if (!is) error("Parser: could not open file",filename); #endif } #ifndef USE_FILE_BUFFER Parser(istream& is_): is(is_), ignoreComments(true), ignoreEmptyLines(true), nLinesRead(0), nNonEmptyLinesRead(0) {} void PutLineBackIntoStream() { is.putback('\n'); for(int i=line.length()-1; i>=0; i--) { is.putback(line[i]); } } #endif bool Status() { #ifndef USE_FILE_BUFFER return (bool) is; #else return fileBuffer.Status(); #endif } void Close() { #ifndef USE_FILE_BUFFER if (ifs) ifs.close(); #else fileBuffer.Close(); #endif } bool GetLine() { // no splitting into words -- added 01/14/13 #ifndef USE_FILE_BUFFER getline(is, line); return (bool) is; #else return fileBuffer.GetLine(line); #endif } void GetLineSavely() { GetLineSafely(); } void GetLineSafely() { if (!GetLine()) error("Parser encountered unexpected end of file"); } bool FindInLine(const string & s) const { return (line.find(s)!=line.npos); } int PositionInLine(const string & s) const { for(int i=0; i GetCurrentArrayOfWord() const { return words; } //Return the number of words in the current line ("words"). //Return the number of words in the current line ("words"). int GetNWords() const { return words.Size(); }; int GetLineNumber() const { return nLinesRead; } int GetNumberOfNonEmptyLines() const { return nNonEmptyLinesRead; } //Return a word as a string, int, or double. (no some error checking done) const string& GetString(int i=0) const; const string& GetNameString(int i=0) const; const string GetStringLowerCase(int i=0) const; const string GetNameStringLowerCase(int i=0) const; const string GetStringUpperCase(int i=0) const; const string GetNameStringUpperCase(int i=0) const; int GetInt(const int i=0) const; double GetDouble(const int i=0) const; bool GetIntSafely(const int i, int & x) const; bool GetDoubleSafely(const int i, double & x) const; int GetLastInt() const { return GetInt(GetNWords()-1); } double GetLastDouble() const { return GetDouble(GetNWords()-1); } int GetIntFollowingString(const string & s, const int offset=0, const bool printError=true) const; double GetDoubleFollowingString(const string & s, const int offset=0, const bool printError=true) const; int GetNumberOfDoublesFollowingString(const string & s) const; void Get(int & i, const int n) const { i=GetInt(n); } void Get(double & d, const int n) const { d=GetDouble(n); } void Get(string & s, const int n) const { s=GetString(n); } void SetIgnoreComments() { ignoreComments=true; } void UnSetIgnoreComments() { ignoreComments=false; } void SetIgnoreEmptyLines() { ignoreEmptyLines=true; } void UnSetIgnoreEmptyLines() { ignoreEmptyLines=false; } void ProcessKeyword(const string & keyword, const int n); void ProcessKeyword(const string & keyword); void ProcessLine(const int n); void SplitLine() { words.Clear(); istringstream line_stream(line); string word; line_stream >> word; while (word.length()!=0 && line_stream) { words.PushBack(word); // Write2(words.size(),words[words.size()-1]); line_stream >> word; } } void SplitXMLLine(); void SplitXMLWord(string & w); int FindKeywordInLine(const string & key); int FindKeywordInLineSafely(const string & key); double GetDoubleAfterKeyword(const string & key); // similar to GetIntFollowingString() above int GetIntAfterKeyword(const string & key); bool GetDoubleAfterKeywordSafely(const string & key, double & x); // return true if keyword was found and x was set bool GetIntAfterKeywordSafely(const string & key, int & x); // return true if keyword was found and x was set // void PutLineBack() { // depricated // PutLineBackIntoStream(); // } void PutLineBackIntoParser(const Array1 & line); string GetFileName() const { return filename; } bool IsStringInLine(const string & s) const { // 's' may contain spaces while keywords do not return (line.find(s)!=line.npos); } private: void CheckNotNumber(const string & s) const; static bool IsInt(const string & s) { const string intChars(" +-0123456789"); string::size_type j=s.find_first_not_of(intChars); return (j == string::npos); } static bool IsDouble(const string & s) { // see also Standard.h const string doubleChars(" +-0123456789.edDE"); string::size_type j=s.find_first_not_of(doubleChars); return (j == string::npos); } }; #endif // _PARSER_