//------------------------------------------------------------------------------
// module fileutil.h version 2.0b(english) //
// //
// utility functions to read values/strings from a stream. you can //
// realize format-sensitive reading without the "always read a whoole //
// line" concept. //
// //
// copyright (c) 1998-2003 by Lars Haendel //
// home: www.newty.de //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 2 of the License. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program; if not, write to the Free Software //
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
// //
//------------------------------------------------------------------------------
#ifndef FILEUTIL_H
#define FILEUTIL_H
//----------------------------------------------------------------------------------------------------------------------
#include <iostream> // due to ifstream ...
#include <fstream>
#include <ctype> // isspace()
#include <limits> // INT_MAX
#include "util.h" // define of MaxBits
// exception codes
#define UnexpectedEndl (int) 42 // encountered unexpected end of line (endl)
#define UnexpectedEOF (int) 43 // " " end of file (EOF)
#define NoEndlFound (int) 44 // an endl was expected but not found
#define IllegalCharacter (int) 45 // encountered illegal character
#define NoWhitespace (int) 46 // no whitespace after value
#define KeyNotFound (int) 47
#define BoolReadFailed (int) 48
#define ValueMissing (int) 49 // string/value missing in ReadKey...() functions
#define ErrReadingBits (int) 50
#define UnterminatedBits (int) 51
#define PATH_DELIMITER '\\' // path delimiter in filenames (windows '\\' (backslash), Linux '/' (slash))
#define COMPL_PATH_DELIMITER '/' //
#ifdef BUILDER
using namespace std;
#endif
//----------------------------------------------------------------------------------------------------------------------
// error handling
const char* GetLastError(const int& errNo); // get error description
char& GetIllegalCharacter();
const char* GetLastKey();
//----------------------------------------------------------------------------------------------------------------------
// filename and string manipulations
void ExchangeExt(char*const& szFilename, const char*const& szExtension); // exchange a filename's extension
void EnsurePathDelimiter(char*const& szPath); // ensure path delimiter at end
void CorrectPathDelimiter(char*const& szFilename); // replace wrong path delimiter by correct one
void ExtractPath(char*const& szDir, const char*const& szFilename); // extract path
void PrefixPath(char*const& szFilename, const char*const& szDir); // prepend path if necessary
bool CheckName(const char*const& szName); // check for valid filename without(!) path and extension
int SizeOfString (const char*const& szString);
const char* FlagToString (const int& flag, const bool& f_LeftAlign=false);
const char* GetPrefixedPath (const char*const& szFilename, const char*const& szDir);
//int CountLinesEx (ifstream& file);
int SearchKey (ifstream& file, const char*const& szKey, const int& maxLines=INT_MAX, const char& delimiter=EOF);
int ReadKeyBool (ifstream& file, const char*const& szKey, const int defaultValue=-1, const int& maxLines=INT_MAX);
bool ReadKeyString(ifstream& file, const char*const& szKey, char* szString, const int& size, const int& maxLines=INT_MAX);
void ReadBits (ifstream& file, int& value, const int& nBits=MaxBits);
/**********************************************************************************************************************/
// functions skipws()/skipwsEx() and wrappers
// functions to remove whitespaces out of an ifstream returning the number of encountered endl's
// the extended version also removes all comments
int skipws (ifstream& file);
int skipwsEx(ifstream& file);
// wrapper for the two functions above which are throwing an exception depending on the number of
// encountered endl's
int skipwsEndl (ifstream& file); // use skipws() throwing exception if no endl occurs
void skipwsNoEndl (ifstream& file); // " " " " " an " "
int skipwsExEndl (ifstream& file); // like above but use skipwsEx()
void skipwsExNoEndl(ifstream& file); // " " " " "
/**********************************************************************************************************************/
// "read"-functions
// reading a string from an ifstream. All whitespaces, comments and the delimiter
// terminate the string. The delimiter is left in the stream and is returned.
char ReadString(ifstream& file, char* szString, const int& size, const char& delimiter=' ');
/*******************************************************************************************************************/
// functions reads an object of type T from an ifstream throwing an exception if the
// reading causes a failstate of the stream. note: the '>>' operator skips whitespaces like
// endl's. thus if you track the actual line-number in the file don't forget to call
// skipws()/skipwsEx() before.
void ReadFailed(ifstream& file); // utility function - private :-))
template <class T> T Read(ifstream& file, const T)
{
file.clear(); // reset stream state
T value;
file >> value; // try to read from stream
if(file.fail()!=0) // examine in case of a failstate
ReadFailed(file);
// check if the next character after the value is a ws or a comment ...
if(!isspace(file.peek()) && !IsComment((char) file.peek()))
{
GetIllegalCharacter() = (char) file.peek(); // set as "illegal character"
throw NoWhitespace; // ... otherwise: throw exception
}
return value;
};
/*******************************************************************************************************************/
// wrapper: read a value and throw an exception if an endl occurs
template < class T > T ReadExpNoEndl(ifstream& file, T value)
{
skipwsNoEndl(file);
return Read(file, value);
};
/*******************************************************************************************************************/
// search stream for string <key> followed by a '=' and read following value. If read fails
// throw an exception. Return default value if key is not found.
template < class T > T ReadKeyValue(ifstream& file, const char* szKey, const T defaultValue,
const int& maxLines=INT_MAX)
{
file.clear();
streampos curPos = file.tellg(); // preserve actual stream position
try{
SearchKey(file, szKey, maxLines, '['); // search key
} catch(int errNo) { goto __ReturnDefault__; }
if(file.get()!='=') // if next character is not '=' -> return default value
goto __ReturnDefault__;
if(skipws(file)!=0)
throw ValueMissing;
T value;
try{
value=Read(file, defaultValue); // read
} catch(int errNo) { file.seekg(curPos); throw errNo; }
file.seekg(curPos); // restore stream position
return value;
__ReturnDefault__:
file.seekg(curPos); // restore stream position
return defaultValue;
};
#endif