⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
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 + -