From aafef187ef856a36c3f8e599afea2dee44f08904 Mon Sep 17 00:00:00 2001 From: faketruth Date: Mon, 3 Oct 2011 19:25:04 +0000 Subject: Source for additional projects -jsoncpp -lua -tolua++ -WebServer -zlib -iniFile git-svn-id: http://mc-server.googlecode.com/svn/trunk@4 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- iniFile/iniFile.cpp | 507 ++++++++++++++++++++++++++++++++++++++++++++++++++++ iniFile/iniFile.h | 184 +++++++++++++++++++ 2 files changed, 691 insertions(+) create mode 100644 iniFile/iniFile.cpp create mode 100644 iniFile/iniFile.h (limited to 'iniFile') diff --git a/iniFile/iniFile.cpp b/iniFile/iniFile.cpp new file mode 100644 index 000000000..76e64ff37 --- /dev/null +++ b/iniFile/iniFile.cpp @@ -0,0 +1,507 @@ +// IniFile.cpp: Implementation of the CIniFile class. +// Written by: Adam Clauss +// Email: cabadam@houston.rr.com +// You may use this class/code as you wish in your programs. Feel free to distribute it, and +// email suggested changes to me. +// +// Rewritten by: Shane Hill +// Date: 21/08/2001 +// Email: Shane.Hill@dsto.defence.gov.au +// Reason: Remove dependancy on MFC. Code should compile on any +// platform. +////////////////////////////////////////////////////////////////////// + +/* + !! MODIFIED BY FAKETRUTH !! +*/ + +// C++ Includes +#include +#include +#include + +using namespace std; + +// C Includes +#include +#include +#include + +// Local Includes +#include "iniFile.h" + +#if defined(WIN32) +#define iniEOL endl +#else +#define iniEOL '\r' << endl +#endif + +#ifndef _WIN32 +#define sprintf_s(buffer, buffer_size, stringbuffer, ...) (sprintf(buffer, stringbuffer, __VA_ARGS__)) +#define vsprintf_s(buffer, stringbuffer, ...) (vsprintf(buffer, stringbuffer, __VA_ARGS__)) +#define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__)) +#endif + +cIniFile::cIniFile( const string iniPath) +{ + Path( iniPath); + caseInsensitive = true; +} + +bool cIniFile::ReadFile() +{ + // Normally you would use ifstream, but the SGI CC compiler has + // a few bugs with ifstream. So ... fstream used. + fstream f; + string line; + string keyname, valuename, value; + string::size_type pLeft, pRight; + + f.open( path.c_str(), ios::in); + if ( f.fail()) + return false; + + while( getline( f, line)) { + // To be compatible with Win32, check for existence of '\r'. + // Win32 files have the '\r' and Unix files don't at the end of a line. + // Note that the '\r' will be written to INI files from + // Unix so that the created INI file can be read under Win32 + // without change. + unsigned int lineLength = line.length(); + if(lineLength == 0) continue; + if ( line[lineLength - 1] == '\r') + line = line.substr( 0, lineLength - 1); + + if ( line.length()) { + // Check that the user hasn't opened a binary file by checking the first + // character of each line! + if ( !isprint( line[0])) { + printf( "Failing on char %d\n", line[0]); + f.close(); + return false; + } + if (( pLeft = line.find_first_of(";#[=")) != string::npos) { + switch ( line[pLeft]) { + case '[': + if ((pRight = line.find_last_of("]")) != string::npos && + pRight > pLeft) { + keyname = line.substr( pLeft + 1, pRight - pLeft - 1); + AddKeyName( keyname); + } + break; + + case '=': + valuename = line.substr( 0, pLeft); + value = line.substr( pLeft + 1); + SetValue( keyname, valuename, value); + break; + + case ';': + case '#': + if ( !names.size()) + HeaderComment( line.substr( pLeft + 1)); + else + KeyComment( keyname, line.substr( pLeft + 1)); + break; + } + } + } + } + + f.close(); + if ( names.size()) + return true; + return false; +} + +bool cIniFile::WriteFile() +{ + unsigned commentID, keyID, valueID; + // Normally you would use ofstream, but the SGI CC compiler has + // a few bugs with ofstream. So ... fstream used. + fstream f; + + f.open( path.c_str(), ios::out); + if ( f.fail()) + return false; + + // Write header comments. + for ( commentID = 0; commentID < comments.size(); ++commentID) + f << ';' << comments[commentID] << iniEOL; + if ( comments.size()) + f << iniEOL; + + // Write keys and values. + for ( keyID = 0; keyID < keys.size(); ++keyID) { + f << '[' << names[keyID] << ']' << iniEOL; + // Comments. + for ( commentID = 0; commentID < keys[keyID].comments.size(); ++commentID) + f << ';' << keys[keyID].comments[commentID] << iniEOL; + // Values. + for ( valueID = 0; valueID < keys[keyID].names.size(); ++valueID) + f << keys[keyID].names[valueID] << '=' << keys[keyID].values[valueID] << iniEOL; + f << iniEOL; + } + f.close(); + + return true; +} + +long cIniFile::FindKey( const string & keyname) const +{ + for ( unsigned keyID = 0; keyID < names.size(); ++keyID) + if ( CheckCase( names[keyID]) == CheckCase( keyname)) + return long(keyID); + return noID; +} + +long cIniFile::FindValue( unsigned const keyID, const string & valuename) const +{ + if ( !keys.size() || keyID >= keys.size()) + return noID; + + for ( unsigned valueID = 0; valueID < keys[keyID].names.size(); ++valueID) + if ( CheckCase( keys[keyID].names[valueID]) == CheckCase( valuename)) + return long(valueID); + return noID; +} + +unsigned cIniFile::AddKeyName( const string & keyname) +{ + names.resize( names.size() + 1, keyname); + keys.resize( keys.size() + 1); + return names.size() - 1; +} + +string cIniFile::KeyName( unsigned const keyID) const +{ + if ( keyID < names.size()) + return names[keyID]; + else + return ""; +} + +unsigned cIniFile::NumValues( unsigned const keyID) +{ + if ( keyID < keys.size()) + return keys[keyID].names.size(); + return 0; +} + +unsigned cIniFile::NumValues( const string & keyname) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return 0; + return keys[keyID].names.size(); +} + +string cIniFile::ValueName( unsigned const keyID, unsigned const valueID) const +{ + if ( keyID < keys.size() && valueID < keys[keyID].names.size()) + return keys[keyID].names[valueID]; + return ""; +} + +string cIniFile::ValueName( const string & keyname, unsigned const valueID) const +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return ""; + return ValueName( keyID, valueID); +} + +bool cIniFile::SetValue( unsigned const keyID, unsigned const valueID, const string & value) +{ + if ( keyID < keys.size() && valueID < keys[keyID].names.size()) + keys[keyID].values[valueID] = value; + + return false; +} + +bool cIniFile::SetValue( const string & keyname, const string & valuename, const string & value, bool const create) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) { + if ( create) + keyID = long( AddKeyName( keyname)); + else + return false; + } + + long valueID = FindValue( unsigned(keyID), valuename); + if ( valueID == noID) { + if ( !create) + return false; + keys[keyID].names.resize( keys[keyID].names.size() + 1, valuename); + keys[keyID].values.resize( keys[keyID].values.size() + 1, value); + } else + { + if(!create) + keys[keyID].values[valueID] = value; + else + { + keys[keyID].names.resize( keys[keyID].names.size() + 1, valuename); + keys[keyID].values.resize( keys[keyID].values.size() + 1, value); + } + } + + return true; +} + +bool cIniFile::SetValueI( const string & keyname, const string & valuename, int const value, bool const create) +{ + char svalue[MAX_VALUEDATA]; + + sprintf_s( svalue, MAX_VALUEDATA, "%d", value); + return SetValue( keyname, valuename, svalue, create); +} + +bool cIniFile::SetValueF( const string & keyname, const string & valuename, double const value, bool const create) +{ + char svalue[MAX_VALUEDATA]; + + sprintf_s( svalue, MAX_VALUEDATA, "%f", value); + return SetValue( keyname, valuename, svalue, create); +} + +bool cIniFile::SetValueV( const string & keyname, const string & valuename, char *format, ...) +{ + va_list args; + char value[MAX_VALUEDATA]; + + va_start( args, format); + vsprintf_s( value, format, args); + va_end( args); + return SetValue( keyname, valuename, value ); +} + +string cIniFile::GetValue( unsigned const keyID, unsigned const valueID, const string & defValue) const +{ + if ( keyID < keys.size() && valueID < keys[keyID].names.size()) + return keys[keyID].values[valueID]; + return defValue; +} + +string cIniFile::GetValue( const string & keyname, const string & valuename, const string & defValue) const +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return defValue; + + long valueID = FindValue( unsigned(keyID), valuename); + if ( valueID == noID) + return defValue; + + return keys[keyID].values[valueID]; +} + +int cIniFile::GetValueI(const string & keyname, const string & valuename, int const defValue) const +{ + char svalue[MAX_VALUEDATA]; + + sprintf_s( svalue, MAX_VALUEDATA, "%d", defValue); + return atoi( GetValue( keyname, valuename, svalue).c_str()); +} + +double cIniFile::GetValueF(const string & keyname, const string & valuename, double const defValue) const +{ + char svalue[MAX_VALUEDATA]; + + sprintf_s( svalue, MAX_VALUEDATA, "%f", defValue); + return atof( GetValue( keyname, valuename, svalue).c_str()); +} + +// 16 variables may be a bit of over kill, but hey, it's only code. +unsigned cIniFile::GetValueV( const string & keyname, const string & valuename, char *format, + void *v1, void *v2, void *v3, void *v4, + void *v5, void *v6, void *v7, void *v8, + void *v9, void *v10, void *v11, void *v12, + void *v13, void *v14, void *v15, void *v16) +{ + string value; + // va_list args; + unsigned nVals; + + + value = GetValue( keyname, valuename); + if ( !value.length()) + return false; + // Why is there not vsscanf() function. Linux man pages say that there is + // but no compiler I've seen has it defined. Bummer! + // + // va_start( args, format); + // nVals = vsscanf( value.c_str(), format, args); + // va_end( args); + + nVals = sscanf_s( value.c_str(), format, + v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16); + + return nVals; +} + +bool cIniFile::DeleteValue( const string & keyname, const string & valuename) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return false; + + long valueID = FindValue( unsigned(keyID), valuename); + if ( valueID == noID) + return false; + + // This looks strange, but is neccessary. + vector::iterator npos = keys[keyID].names.begin() + valueID; + vector::iterator vpos = keys[keyID].values.begin() + valueID; + keys[keyID].names.erase( npos, npos + 1); + keys[keyID].values.erase( vpos, vpos + 1); + + return true; +} + +bool cIniFile::DeleteKey( const string & keyname) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return false; + + // Now hopefully this destroys the vector lists within keys. + // Looking at source, this should be the case using the destructor. + // If not, I may have to do it explicitly. Memory leak check should tell. + // memleak_test.cpp shows that the following not required. + //keys[keyID].names.clear(); + //keys[keyID].values.clear(); + + vector::iterator npos = names.begin() + keyID; + vector::iterator kpos = keys.begin() + keyID; + names.erase( npos, npos + 1); + keys.erase( kpos, kpos + 1); + + return true; +} + +void cIniFile::Erase() +{ + // This loop not needed. The vector<> destructor seems to do + // all the work itself. memleak_test.cpp shows this. + //for ( unsigned i = 0; i < keys.size(); ++i) { + // keys[i].names.clear(); + // keys[i].values.clear(); + //} + names.clear(); + keys.clear(); + comments.clear(); +} + +void cIniFile::HeaderComment( const string & comment) +{ + comments.resize( comments.size() + 1, comment); +} + +string cIniFile::HeaderComment( unsigned const commentID) const +{ + if ( commentID < comments.size()) + return comments[commentID]; + return ""; +} + +bool cIniFile::DeleteHeaderComment( unsigned commentID) +{ + if ( commentID < comments.size()) { + vector::iterator cpos = comments.begin() + commentID; + comments.erase( cpos, cpos + 1); + return true; + } + return false; +} + +unsigned cIniFile::NumKeyComments( unsigned const keyID) const +{ + if ( keyID < keys.size()) + return keys[keyID].comments.size(); + return 0; +} + +unsigned cIniFile::NumKeyComments( const string & keyname) const +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return 0; + return keys[keyID].comments.size(); +} + +bool cIniFile::KeyComment( unsigned const keyID, const string & comment) +{ + if ( keyID < keys.size()) { + keys[keyID].comments.resize( keys[keyID].comments.size() + 1, comment); + return true; + } + return false; +} + +bool cIniFile::KeyComment( const string & keyname, const string & comment) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return false; + return KeyComment( unsigned(keyID), comment); +} + +string cIniFile::KeyComment( unsigned const keyID, unsigned const commentID) const +{ + if ( keyID < keys.size() && commentID < keys[keyID].comments.size()) + return keys[keyID].comments[commentID]; + return ""; +} + +string cIniFile::KeyComment( const string & keyname, unsigned const commentID) const +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return ""; + return KeyComment( unsigned(keyID), commentID); +} + +bool cIniFile::DeleteKeyComment( unsigned const keyID, unsigned const commentID) +{ + if ( keyID < keys.size() && commentID < keys[keyID].comments.size()) { + vector::iterator cpos = keys[keyID].comments.begin() + commentID; + keys[keyID].comments.erase( cpos, cpos + 1); + return true; + } + return false; +} + +bool cIniFile::DeleteKeyComment( const string & keyname, unsigned const commentID) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return false; + return DeleteKeyComment( unsigned(keyID), commentID); +} + +bool cIniFile::DeleteKeyComments( unsigned const keyID) +{ + if ( keyID < keys.size()) { + keys[keyID].comments.clear(); + return true; + } + return false; +} + +bool cIniFile::DeleteKeyComments( const string & keyname) +{ + long keyID = FindKey( keyname); + if ( keyID == noID) + return false; + return DeleteKeyComments( unsigned(keyID)); +} + +string cIniFile::CheckCase( string s) const +{ + if ( caseInsensitive) + for ( string::size_type i = 0; i < s.length(); ++i) + s[i] = (char)tolower(s[i]); + return s; +} diff --git a/iniFile/iniFile.h b/iniFile/iniFile.h new file mode 100644 index 000000000..c23c0369f --- /dev/null +++ b/iniFile/iniFile.h @@ -0,0 +1,184 @@ +// IniFile.cpp: Implementation of the CIniFile class. +// Written by: Adam Clauss +// Email: cabadam@tamu.edu +// You may use this class/code as you wish in your programs. Feel free to distribute it, and +// email suggested changes to me. +// +// Rewritten by: Shane Hill +// Date: 21/08/2001 +// Email: Shane.Hill@dsto.defence.gov.au +// Reason: Remove dependancy on MFC. Code should compile on any +// platform. Tested on Windows/Linux/Irix +////////////////////////////////////////////////////////////////////// + +/* + !! MODIFIED BY FAKETRUTH !! +*/ + +#ifndef CIniFile_H +#define CIniFile_H + +// C++ Includes +#include +#include + +// C Includes +#include + +#define MAX_KEYNAME 128 +#define MAX_VALUENAME 128 +#define MAX_VALUEDATA 2048 + +class cIniFile //tolua_export +{ //tolua_export +private: + bool caseInsensitive; + std::string path; + struct key { + std::vector names; + std::vector values; + std::vector comments; + }; + std::vector keys; + std::vector names; + std::vector comments; + std::string CheckCase( std::string s) const; + +public: + enum errors{ noID = -1}; + cIniFile( const std::string iniPath = ""); //tolua_export + virtual ~cIniFile() {} + + // Sets whether or not keynames and valuenames should be case sensitive. + // The default is case insensitive. + void CaseSensitive() {caseInsensitive = false;} //tolua_export + void CaseInsensitive() {caseInsensitive = true;} //tolua_export + + // Sets path of ini file to read and write from. + void Path(const std::string & newPath) {path = newPath;} //tolua_export + std::string Path() const {return path;} //tolua_export + void SetPath(const std::string & newPath) {Path( newPath);} //tolua_export + + // Reads ini file specified using path. + // Returns true if successful, false otherwise. + bool ReadFile(); //tolua_export + + // Writes data stored in class to ini file. + bool WriteFile(); //tolua_export + + // Deletes all stored ini data. + void Erase(); //tolua_export + void Clear() {Erase();} //tolua_export + void Reset() {Erase();} //tolua_export + + // Returns index of specified key, or noID if not found. + long FindKey( const std::string & keyname) const; //tolua_export + + // Returns index of specified value, in the specified key, or noID if not found. + long FindValue( const unsigned keyID, const std::string & valuename) const; //tolua_export + + // Returns number of keys currently in the ini. + unsigned NumKeys() const {return names.size();} //tolua_export + unsigned GetNumKeys() const {return NumKeys();} //tolua_export + + // Add a key name. + unsigned AddKeyName( const std::string & keyname); //tolua_export + + // Returns key names by index. + std::string KeyName( const unsigned keyID) const; //tolua_export + std::string GetKeyName( const unsigned keyID) const {return KeyName(keyID);} //tolua_export + + // Returns number of values stored for specified key. + unsigned NumValues( const std::string & keyname); //tolua_export + unsigned GetNumValues( const std::string & keyname) {return NumValues( keyname);} //tolua_export + unsigned NumValues( const unsigned keyID); //tolua_export + unsigned GetNumValues( const unsigned keyID) {return NumValues( keyID);} //tolua_export + + // Returns value name by index for a given keyname or keyID. + std::string ValueName( const std::string & keyname, const unsigned valueID) const; //tolua_export + std::string GetValueName( const std::string & keyname, const unsigned valueID) const { //tolua_export + return ValueName( keyname, valueID); + } //tolua_export + std::string ValueName( const unsigned keyID, const unsigned valueID) const; //tolua_export + std::string GetValueName( const unsigned keyID, const unsigned valueID) const { //tolua_export + return ValueName( keyID, valueID); + } //tolua_export + + // Gets value of [keyname] valuename =. + // Overloaded to return string, int, and double. + // Returns defValue if key/value not found. + std::string GetValue( const std::string & keyname, const std::string & valuename, const std::string & defValue = "") const; //tolua_export + std::string GetValue( const unsigned keyID, const unsigned valueID, const std::string & defValue = "") const; //tolua_export + int GetValueI( const std::string & keyname, const std::string & valuename, const int defValue = 0) const; //tolua_export + bool GetValueB( const std::string & keyname, const std::string & valuename, const bool defValue = false) const { //tolua_export + return ( GetValueI( keyname, valuename, int( defValue)) > 0); + } //tolua_export + double GetValueF( const std::string & keyname, const std::string & valuename, const double defValue = 0.0) const; //tolua_export + // This is a variable length formatted GetValue routine. All these voids + // are required because there is no vsscanf() like there is a vsprintf(). + // Only a maximum of 8 variable can be read. + unsigned GetValueV( const std::string & keyname, const std::string & valuename, char *format, + void *v1 = 0, void *v2 = 0, void *v3 = 0, void *v4 = 0, + void *v5 = 0, void *v6 = 0, void *v7 = 0, void *v8 = 0, + void *v9 = 0, void *v10 = 0, void *v11 = 0, void *v12 = 0, + void *v13 = 0, void *v14 = 0, void *v15 = 0, void *v16 = 0); + + // Sets value of [keyname] valuename =. + // Specify the optional paramter as false (0) if you do not want it to create + // the key if it doesn't exist. Returns true if data entered, false otherwise. + // Overloaded to accept string, int, and double. + bool SetValue( const unsigned keyID, const unsigned valueID, const std::string & value); //tolua_export + bool SetValue( const std::string & keyname, const std::string & valuename, const std::string & value, const bool create = true); //tolua_export + bool SetValueI( const std::string & keyname, const std::string & valuename, const int value, const bool create = true); //tolua_export + bool SetValueB( const std::string & keyname, const std::string & valuename, const bool value, const bool create = true) { //tolua_export + return SetValueI( keyname, valuename, int(value), create); + } //tolua_export + bool SetValueF( const std::string & keyname, const std::string & valuename, const double value, const bool create = true); //tolua_export + bool SetValueV( const std::string & keyname, const std::string & valuename, char *format, ...); + + // Deletes specified value. + // Returns true if value existed and deleted, false otherwise. + bool DeleteValue( const std::string & keyname, const std::string & valuename); //tolua_export + + // Deletes specified key and all values contained within. + // Returns true if key existed and deleted, false otherwise. + bool DeleteKey(const std::string & keyname); //tolua_export + + // Header comment functions. + // Header comments are those comments before the first key. + // + // Number of header comments. + unsigned NumHeaderComments() {return comments.size();} //tolua_export + // Add a header comment. + void HeaderComment( const std::string & comment); //tolua_export + // Return a header comment. + std::string HeaderComment( const unsigned commentID) const; //tolua_export + // Delete a header comment. + bool DeleteHeaderComment( unsigned commentID); //tolua_export + // Delete all header comments. + void DeleteHeaderComments() {comments.clear();} //tolua_export + + // Key comment functions. + // Key comments are those comments within a key. Any comments + // defined within value names will be added to this list. Therefore, + // these comments will be moved to the top of the key definition when + // the CIniFile::WriteFile() is called. + // + // Number of key comments. + unsigned NumKeyComments( const unsigned keyID) const; //tolua_export + unsigned NumKeyComments( const std::string & keyname) const; //tolua_export + // Add a key comment. + bool KeyComment( const unsigned keyID, const std::string & comment); //tolua_export + bool KeyComment( const std::string & keyname, const std::string & comment); //tolua_export + // Return a key comment. + std::string KeyComment( const unsigned keyID, const unsigned commentID) const; //tolua_export + std::string KeyComment( const std::string & keyname, const unsigned commentID) const; //tolua_export + // Delete a key comment. + bool DeleteKeyComment( const unsigned keyID, const unsigned commentID); //tolua_export + bool DeleteKeyComment( const std::string & keyname, const unsigned commentID); //tolua_export + // Delete all comments for a key. + bool DeleteKeyComments( const unsigned keyID); //tolua_export + bool DeleteKeyComments( const std::string & keyname); //tolua_export +}; //tolua_export + +#endif -- cgit v1.2.3