diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/tfstats/textfile.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/tfstats/textfile.cpp')
| -rw-r--r-- | utils/tfstats/textfile.cpp | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/utils/tfstats/textfile.cpp b/utils/tfstats/textfile.cpp new file mode 100644 index 0000000..e8304fb --- /dev/null +++ b/utils/tfstats/textfile.cpp @@ -0,0 +1,405 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implementation of CTextFile. See TextFile.h for details +// +// $Workfile: $ +// $Date: $ +// +//------------------------------------------------------------------------------------------------------ +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "TFStatsApplication.h" +#include "util.h" +#include "TextFile.h" + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::init +// Purpose: initializes a CTextFile object +// Input: filename - name of the file that this object will represent +// eliminateComments - if true, C++ style comments will not be handed +// back as tokens to the user of this object +// Output: +//------------------------------------------------------------------------------------------------------ +void CTextFile::init(const char* filename,bool eliminateComments) +{ + this->filename=filename; + //only support one push back + fWordPushed=false; + noComments=eliminateComments; + memset(wordBuf,0,BUF_SIZE); + theFile=fopen(filename,"rt"); + + + //three different delim sets + //use this when reading strings + stringDelims="\""; + //use this when reading normal file stuff + normalDelims=" \t{}=\n\r;\""; + //use this when you want to discard a block + blockDelims="}"; + //set to default + delims=normalDelims; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::isDelim +// Purpose: returns true if the given char is in the current delimiter set +// Input: c - the character to test +// Output: Returns true on success, false on failure. +//------------------------------------------------------------------------------------------------------ +bool CTextFile::isDelim(char c) +{ + for (int i=0;delims[i] != 0; i++) + { + if (c==delims[i]) + return true; + } + return false; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::discardBlock +// Purpose: advances the file ptr to the character after the next } +//------------------------------------------------------------------------------------------------------ +void CTextFile::discardBlock() +{ + delims=blockDelims; + getToken(); + delims=normalDelims; + discard("}"); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::getToken +// Purpose: gets and returns the next token in the file +// Output: const char* +//------------------------------------------------------------------------------------------------------ +const char* CTextFile::getToken() +{ + return getToken(wordBuf); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::getToken +// Purpose: gets and returns the next token in the file, with an arbitrary buffer +// Input: outputBuf - the buffer to put the token in +// Output: const char* +//------------------------------------------------------------------------------------------------------ +const char* CTextFile::getToken(char* outputBuf) +{ + if (fWordPushed) + { + fWordPushed=false; + strcpy(outputBuf,wordBuf); + return wordBuf; + } + readToken: + char c=getNextNonWSChar(); + if (!theFile || feof(theFile)) return NULL; + if (isDelim(c) && !(isspace(c))) + { + outputBuf[0]=c; + outputBuf[1]=0; + return outputBuf; + } + + int write=0; + while (!isDelim(c)) + { + if (c=='\\') + { + c=fgetc(theFile); + if (!theFile&& feof(theFile)) + break; + } + + //these are both in the normal delimiter set, so this case won't happen unless we're reading a string + //which is exactly the behaviour we want + if (c=='\n' || c=='\r') + { + outputBuf[write]=0; + g_pApp->fatalError("new line in string constant (or unterminated string constant):\n\"%s\"",outputBuf); + } + outputBuf[write++]=c; + c=fgetc(theFile); + + if (feof(theFile)) + break; + } + + if (theFile && !feof(theFile)) + fseek(theFile,-1,SEEK_CUR); //seek to before the delimiter + + outputBuf[write]=0; + + if (outputBuf[0] == '/' && outputBuf[1] == '/') + { + while (fgetc(theFile)!='\n'); + goto readToken; + } + + return outputBuf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::getNextNonWSChar +// Purpose: gets and returns the next non whitespace character +// Output: char +//------------------------------------------------------------------------------------------------------ +char CTextFile::getNextNonWSChar() +{ + char c; +top: + c=' '; + while (theFile && !feof(theFile) && isspace(c)) + c=fgetc(theFile); + + if (!theFile) return 0; + if (feof(theFile)) return 0; + + if (!noComments) + return c; + + //check for comments + if (c=='/') + { + char c2=fgetc(theFile); + if (c2=='/') //found comment? + { + //discard and start over + getLine(); + goto top; + } + else + { + fseek(theFile,-1,SEEK_CUR); + return c; + } + } + else + { + return c; + } + +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::readString +// Purpose: reads and returns the contents of the file up to the next " +// Output: const char* +//------------------------------------------------------------------------------------------------------ +const char* CTextFile::readString() +{ + if (fWordPushed) + { + fWordPushed=false; + return wordBuf; + } + char c=getNextNonWSChar(); + + if (c=='\"') + { + delims=stringDelims; + getToken(); //handles escaping stuff + delims=normalDelims; + if (wordBuf[0]=='\"' && wordBuf[1]==0) + wordBuf[0]=0; + else + discard("\""); + } + else + { + fseek(theFile,-1,SEEK_CUR); + getToken(); + } + + + return wordBuf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::readString +// Purpose: reads and returns the contents of the file up to the next " +// Output: const char* +//------------------------------------------------------------------------------------------------------ +const char* CTextFile::readString(char* buf) +{ + if (fWordPushed) + { + fWordPushed=false; + strcpy(buf,wordBuf); + return buf; + } + char c=getNextNonWSChar(); + if (eof()) return NULL; + if (c=='\"') + { + delims=stringDelims; + getToken(buf); //handles escaping stuff + delims=normalDelims; + if (buf[0]=='\"' && buf[1]==0) + buf[0]=0; + else + discard("\""); + } + else + { + fseek(theFile,-1,SEEK_CUR); + getToken(buf); + } + + + return buf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::getLine +// Purpose: reads and returns the contents of the file up to the next \r or \n +// Output: const char* +//------------------------------------------------------------------------------------------------------ +const char* CTextFile::getLine() +{ + fgets(wordBuf,BUF_SIZE,theFile); + return wordBuf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::discard +// Purpose: discards the next token, also checks to see if it is the same as the token +// the user of the object was expecting to discard. +// Input: test - the token that is expected to be discarded. +// Output: Returns true on success, false on failure. +//------------------------------------------------------------------------------------------------------ +bool CTextFile::discard(char* test) +{ + if (!theFile || feof(theFile)) + return true; + + char wordBuf2[BUF_SIZE]; + getToken(wordBuf2); + + int result = stricmp(wordBuf2,test); + if (result !=0) + g_pApp->fatalError("While parsing %s, expecting \"%s\", got \"%s\"",filename.c_str(),test,wordBuf2); + + return true; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::peekNext +// Purpose: peeks at the next token. gets then immediately pushes it back +// destroys any pushed back words from before. +// Output: char* +//------------------------------------------------------------------------------------------------------ +char* CTextFile::peekNext() +{ + fpos_t startpos; + fgetpos(theFile,&startpos); + + const char* c=getToken(peekBuf); + if (!c) + return NULL; + //pushBack(c); + fseek(theFile,startpos,SEEK_SET); + return peekBuf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::peekNextString +// Purpose: peeks at the next string. gets then immediately pushes it back +// destroys any pushed back words from before. +// Output: char* +//------------------------------------------------------------------------------------------------------ +char* CTextFile::peekNextString() +{ + if (!theFile) + return NULL; + fpos_t startpos; + fgetpos(theFile,&startpos); + + + const char* c=readString(peekBuf); + if (!c) + return NULL; + //pushBack(c); + fseek(theFile,startpos,SEEK_SET); + return peekBuf; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::pushBack +// Purpose: "pushes" a token back into the stream. Only can have one pushed back +// token at a time. getting a token or peeking will destroy the pushed back token +// Input: pushTok - the token to push back. +//------------------------------------------------------------------------------------------------------ +void CTextFile::pushBack(const char* pushTok) +{ + if (pushTok != wordBuf) + strncpy(wordBuf,pushTok,BUF_SIZE); + fWordPushed=true; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::reset +// Purpose: resets the file ptr to the beginning of the file +//------------------------------------------------------------------------------------------------------ +void CTextFile::reset() +{ + fseek(theFile,0,SEEK_SET); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CTextFile::~CTextFile +// Purpose: destructor +//------------------------------------------------------------------------------------------------------ +CTextFile::~CTextFile() +{ + if (theFile) + fclose(theFile); +#ifndef WIN32 + chmod(filename.c_str(),PERMIT); +#endif + +} + + + +bool CTextFile::eof() +{ + bool retval=false; + + //test current pos first + retval = (!theFile || feof(theFile)); + if (retval) + return true; + + //now see if only whitespace is left + + fpos_t beforecheck; + fgetpos(theFile,&beforecheck); + char c=getNextNonWSChar(); + + retval = (!theFile || feof(theFile)); + + fseek(theFile,beforecheck,SEEK_SET); + return retval; +} + + +int CTextFile::readInt() +{ + readString(); + return atoi(wordBuf); +} + +unsigned long CTextFile::readULong() +{ + readString(); + return strtoul(wordBuf,NULL,10); +}
\ No newline at end of file |