📄 config.cpp
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.com>
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; either version 2
of the License, or (at your option) any later version.
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.
*/
//---------------------------------------------------------------------------
#include <windows.h>
#pragma hdrstop
#include <stdio.h>
#include <list>
#include "Config.h"
//---------------------------------------------------------------------------
#ifdef CONFIG_STREAM_METHODS
#pragma package(smart_init)
#endif // CONFIG_STREAM_METHODS
namespace KCeasyEngine {
using std::list;
// comparison by pos functor for sections
class TFileConfigSectionSort : public std::binary_function<TFileConfigSection const&,TFileConfigSection const&,bool>
{
public:
bool operator()(TFileConfigSection const& a, TFileConfigSection const& b) const
{ return a.Pos < b.Pos; }
};
// comparison by pos functor for values
class TFileConfigValueSort : public std::binary_function<TFileConfigValue const&,TFileConfigValue const&,bool>
{
public:
bool operator()(TFileConfigValue const& a, TFileConfigValue const& b) const
{ return a.Pos < b.Pos; }
};
// class TFileConfig
// public
TFileConfig::TFileConfig()
: DefaultConfResId(0)
{
LastFileWriteTime.dwLowDateTime = LastFileWriteTime.dwHighDateTime = 0;
}
TFileConfig::TFileConfig(const string& NFilePath)
: FilePath(NFilePath),
DefaultConfResId(0)
{
LastFileWriteTime.dwLowDateTime = LastFileWriteTime.dwHighDateTime = 0;
}
TFileConfig::~TFileConfig()
{
}
bool TFileConfig::Load(bool ForceReload, bool LoadDefaults)
{
HANDLE hFile;
FILETIME ft;
// only load if file time has changed or ForceReload is true
if((hFile = CreateFile(FilePath.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL)) != INVALID_HANDLE_VALUE) {
ft.dwLowDateTime = LastFileWriteTime.dwLowDateTime;
ft.dwHighDateTime = LastFileWriteTime.dwHighDateTime;
if(GetFileTime(hFile,NULL,NULL,&LastFileWriteTime)) {
if(ft.dwLowDateTime == LastFileWriteTime.dwLowDateTime &&
ft.dwHighDateTime == LastFileWriteTime.dwHighDateTime &&
!ForceReload)
{
CloseHandle(hFile);
return true; // return true if no file change
}
}
CloseHandle(hFile);
}
// slurp config file
bool LoadSucceeded = false;
FILE *fp;
char buf[1024*16];
int len;
string Data;
Sections.clear();
if((fp = fopen(FilePath.c_str(),"rb")) != NULL) {
while((len = fread(buf, 1, sizeof(buf), fp)) > 0)
Data.append(buf,len);
fclose(fp);
// parse data
if(ParseString(Data))
LoadSucceeded = true;
else
Sections.clear();
}
// Load default settings if any were specified. Since our parser only adds
// values if they are not already there this will not modify the the
// settings loaded above.
if(LoadDefaults && DefaultConfResId != 0) {
HRSRC hResInfo;
if((hResInfo = FindResource(NULL,MAKEINTRESOURCE(DefaultConfResId),RT_RCDATA)) != NULL) {
HGLOBAL hResData;
if((hResData = LoadResource(NULL,hResInfo)) != NULL) {
char* ResStr;
if((ResStr = (char*)LockResource(hResData)) != NULL) {
unsigned int Size = SizeofResource(NULL,hResInfo);
Data.assign(ResStr,Size);
// parse default config
ParseString(Data);
}
}
}
}
return LoadSucceeded;
}
bool TFileConfig::Save()
{
FILE *fp;
list<TFileConfigSection> SecList;
// sort sections by position in file
for(map<string,TFileConfigSection>::iterator itr = Sections.begin(); itr != Sections.end(); ++itr) {
SecList.push_front((*itr).second);
SecList.front().Name = (*itr).first;
}
SecList.sort(TFileConfigSectionSort());
if((fp = fopen(FilePath.c_str(),"wb")) == NULL)
return false;
// loop through sections
for(list<TFileConfigSection>::iterator si=SecList.begin(); si!=SecList.end(); ++si) {
if((*si).Name == "")
continue;
// write section description
fprintf(fp, "%s",(*si).Descr.c_str());
// write section header
fprintf(fp, "[%s]\r\n",(*si).Name.c_str());
list<TFileConfigValue> ValList;
// sort values by position in file
for(map<string,TFileConfigValue>::iterator itr = (*si).Values.begin(); itr != (*si).Values.end(); ++itr) {
ValList.push_front((*itr).second);
ValList.front().Name = (*itr).first;
}
ValList.sort(TFileConfigValueSort());
// loop through name/key pairs
for(list<TFileConfigValue>::iterator vi=ValList.begin(); vi!=ValList.end(); ++vi) {
if((*vi).Name == "")
continue;
// write comments
fprintf(fp, "%s",(*vi).Descr.c_str());
// write key/value
fprintf(fp, "%s = %s\r\n",(*vi).Name.c_str(),(*vi).Value);
}
}
fclose(fp);
return true;
}
bool TFileConfig::ValueExists(const char* Key)
{
map<string,TFileConfigSection>::iterator si;
if((si = Sections.find(SectionFromKey(Key))) != Sections.end())
return (*si).second.Values.find(NameFromKey(Key)) != (*si).second.Values.end();
return false;
}
const string& TFileConfig::GetValue(const char* Key)
{
map<string,TFileConfigSection>::iterator si;
map<string,TFileConfigValue>::iterator vi;
if((si = Sections.find(SectionFromKey(Key))) != Sections.end())
if((vi = (*si).second.Values.find(NameFromKey(Key))) != (*si).second.Values.end())
return (*vi).second.Value;
return EmptyString;
}
int TFileConfig::GetValueInt(const char* Key)
{
return atoi(GetValue(Key).c_str());
}
void TFileConfig::SetValue(const char* Key, const char* Value)
{
#if 0
// WARNING: Does not set section.Name and value.Name for new values. This
// means that new values set here will not be saved!
Sections[SectionFromKey(Key)].Values[NameFromKey(Key)].Value = Value;
#else
map<string,TFileConfigSection>::iterator si;
map<string,TFileConfigValue>::iterator vi;
string Section = SectionFromKey(Key);
string Name = NameFromKey(Key);
if((si = Sections.find(Section)) == Sections.end()) {
// create new section
si = Sections.insert(map<string,TFileConfigSection>::value_type(Section,TFileConfigSection(Section,Sections.size()))).first;
}
if((vi = (*si).second.Values.find(Name)) != (*si).second.Values.end()) {
(*vi).second.Value = Value;
} else {
// create new value
(*si).second.Values.insert(map<string,TFileConfigValue>::value_type(Name,TFileConfigValue(Name,Value,(*si).second.Values.size()))).first;
}
#endif
}
void TFileConfig::SetValueInt(const char* Key, int Value)
{
char buf[33];
SetValue(Key,itoa(Value,buf,10));
}
bool TFileConfig::RemoveValue(const char* Key)
{
map<string,TFileConfigSection>::iterator si;
map<string,TFileConfigValue>::iterator vi;
if((si = Sections.find(SectionFromKey(Key))) != Sections.end()) {
if((vi = (*si).second.Values.find(NameFromKey(Key))) != (*si).second.Values.end()) {
(*si).second.Values.erase(vi);
// remove section if empty
if((*si).second.Values.empty())
Sections.erase(si);
return true;
}
}
return false;
}
bool TFileConfig::RemoveSection(const char* Section)
{
map<string,TFileConfigSection>::iterator si;
if((si = Sections.find(Section)) != Sections.end()) {
Sections.erase(si);
return true;
}
return false;
}
list<string> TFileConfig::GetSections()
{
map<string,TFileConfigSection>::iterator si;
list<string> SecList;
for(si=Sections.begin();si!=Sections.end();++si)
SecList.push_back((*si).first);
return SecList;
}
list<string> TFileConfig::GetNames(const char* Section)
{
map<string,TFileConfigSection>::iterator si;
map<string,TFileConfigValue>::iterator vi;
list<string> NameList;
if((si = Sections.find(Section)) != Sections.end()) {
// loop through name/key pairs
for(vi=(*si).second.Values.begin(); vi!=(*si).second.Values.end(); ++vi) {
NameList.push_back((*vi).first);
}
}
return NameList;
}
#ifdef CONFIG_STREAM_METHODS
bool TFileConfig::SetValueStream(const char* Key, TStream* Stream)
{
if(!Stream->Size)
return false;
unsigned char* Decoded = new unsigned char[Stream->Size];
try {
Stream->Seek(0,soFromBeginning);
Stream->ReadBuffer(Decoded,Stream->Size);
}
catch(EWriteError&) {
delete[] Decoded;
return false;
}
char *Encoded = Base64Encode(Decoded, Stream->Size);
SetValue(Key,Encoded);
delete[] Decoded;
delete[] Encoded;
return true;
}
bool TFileConfig::GetValueStream(const char* Key, TStream* Stream)
{
string Encoded = GetValue(Key);
if(Encoded.empty())
return false;
int DecodedLen;
unsigned char *Decoded = Base64Decode(Encoded.c_str(),&DecodedLen);
if(!DecodedLen || !Decoded)
return false;
try {
// Stream->Seek(0,soFromBeginning);
Stream->Size = 0;
Stream->WriteBuffer(Decoded,DecodedLen);
Stream->Seek(0,soFromBeginning);
}
catch(EReadError&) {
delete[] Decoded;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -