📄 config.cxx
字号:
/*
* config.cxx
*
* System/application configuration class implementation
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: config.cxx,v $
* Revision 1.20 1998/12/16 12:40:41 robertj
* Fixed bug where .ini file is not written when service run as a daemon.
*
* Revision 1.19 1998/12/16 09:57:37 robertj
* Fixed bug in writing .ini file, not truncating file when shrinking.
*
* Revision 1.18 1998/11/30 21:51:41 robertj
* New directory structure.
*
* Revision 1.17 1998/11/03 02:30:38 robertj
* Fixed emeory leak of environment.
*
* Revision 1.16 1998/09/24 04:12:11 robertj
* Added open software license.
*
*/
#define _CONFIG_CXX
#pragma implementation "config.h"
#include <ptlib.h>
#include "../common/pconfig.cxx"
#define SYS_CONFIG_NAME "pwlib"
#define APP_CONFIG_DIR ".pwlib_config/"
#define SYS_CONFIG_DIR "/usr/local/pwlib/"
#define EXTENSION ".ini"
#define ENVIRONMENT_CONFIG_STR "/\~~environment~~\/"
//
// a single key/value pair
//
PDECLARE_CLASS (PXConfigValue, PCaselessString)
public:
PXConfigValue(const PString & theKey, const PString & theValue = "")
: PCaselessString(theKey), value(theValue) { }
PString GetValue() const { return value; }
void SetValue(const PString & theValue) { value = theValue; }
protected:
PString value;
};
//
// a list of key/value pairs
//
PLIST (PXConfigSectionList, PXConfigValue);
//
// a list of key value pairs, with a section name
//
PDECLARE_CLASS(PXConfigSection, PCaselessString)
public:
PXConfigSection(const PCaselessString & theName)
: PCaselessString(theName) { list.AllowDeleteObjects(); }
PXConfigSectionList & GetList() { return list; }
protected:
PXConfigSectionList list;
};
//
// a list of sections
//
PDECLARE_LIST(PXConfig, PXConfigSection)
public:
PXConfig(int i = 0);
void Wait() { mutex.Wait(); }
void Signal() { mutex.Signal(); }
BOOL ReadFromFile (const PFilePath & filename);
void ReadFromEnvironment (char **envp);
BOOL WriteToFile(const PFilePath & filename);
BOOL Flush(const PFilePath & filename, BOOL force);
void SetDirty() { dirty = TRUE; }
BOOL AddInstance();
BOOL RemoveInstance(const PFilePath & filename);
protected:
int instanceCount;
PMutex mutex;
BOOL dirty;
BOOL saveOnExit;
};
//
// a dictionary of configurations, keyed by filename
//
PDECLARE_DICTIONARY(PXConfigDictionary, PFilePath, PXConfig)
public:
PXConfigDictionary(int dummy);
~PXConfigDictionary();
PXConfig * GetFileConfigInstance(const PFilePath & key, const PFilePath & readKey);
PXConfig * GetEnvironmentInstance();
void RemoveInstance(PXConfig * instance);
void WriteChangedInstances(BOOL force);
protected:
PMutex mutex;
PXConfig * environmentInstance;
PThread * writeThread;
PSyncPointAck stopConfigWriteThread;
};
PDECLARE_CLASS(PXConfigWriteThread, PThread)
public:
PXConfigWriteThread(PSyncPointAck & stop);
~PXConfigWriteThread();
void Main();
private:
PSyncPointAck & stop;
};
PXConfigDictionary * configDict;
#define new PNEW
//////////////////////////////////////////////////////
void PProcess::CreateConfigFilesDictionary()
{
configFiles = new PXConfigDictionary(0);
}
PXConfigWriteThread::PXConfigWriteThread(PSyncPointAck & s)
: PThread(10000, AutoDeleteThread),
stop(s)
{
Resume();
}
PXConfigWriteThread::~PXConfigWriteThread()
{
stop.Acknowledge();
}
void PXConfigWriteThread::Main()
{
while (!stop.Wait(30000)) // if stop.Wait() returns TRUE, we are shutting down
configDict->WriteChangedInstances(FALSE); // check dictionary for items that need writing
configDict->WriteChangedInstances(TRUE);
}
PXConfig::PXConfig(int)
{
// make sure content gets removed
AllowDeleteObjects();
// no instances, initially
instanceCount = 0;
// we start off clean
dirty = FALSE;
// normally save on exit (except for environment configs)
saveOnExit = TRUE;
}
BOOL PXConfig::AddInstance()
{
mutex.Wait();
BOOL stat = instanceCount++ == 0;
mutex.Signal();
return stat;
}
BOOL PXConfig::RemoveInstance(const PFilePath & /*filename*/)
{
mutex.Wait();
PAssert(instanceCount != 0, "PConfig instance count dec past zero");
BOOL stat = --instanceCount == 0;
/*
this code required if no write thread used
if (stat && saveOnExit && dirty) {
WriteToFile(filename);
dirty = FALSE;
}
*/
mutex.Signal();
return stat;
}
BOOL PXConfig::Flush(const PFilePath & filename, BOOL force)
{
mutex.Wait();
BOOL stat = instanceCount == 0;
if ((force || (instanceCount == 0)) && saveOnExit && dirty) {
if (instanceCount != 0)
PProcess::PXShowSystemWarning(2000, "Flush of config with non-zero instance");
WriteToFile(filename);
dirty = FALSE;
}
mutex.Signal();
return stat;
}
BOOL PXConfig::WriteToFile(const PFilePath & filename)
{
// make sure the directory that the file is to be written into exists
PDirectory dir = filename.GetDirectory();
if (!dir.Exists() && !dir.Create(
PFileInfo::UserExecute |
PFileInfo::UserWrite |
PFileInfo::UserRead)) {
PProcess::PXShowSystemWarning(2000, "Cannot create PWLIB config dir");
return FALSE;
}
PTextFile file;
if (!file.Open(filename, PFile::WriteOnly)) {
PProcess::PXShowSystemWarning(2001, "Cannot create PWLIB config file");
return FALSE;
}
for (PINDEX i = 0; i < GetSize(); i++) {
PXConfigSectionList & section = (*this)[i].GetList();
file << "[" << (*this)[i] << "]" << endl;
for (PINDEX j = 0; j < section.GetSize(); j++) {
PXConfigValue & value = section[j];
file << value << "=" << value.GetValue() << endl;
}
file << endl;
}
file.flush();
file.SetLength(file.GetPosition());
return TRUE;
}
BOOL PXConfig::ReadFromFile (const PFilePath & filename)
{
PINDEX len;
PString line;
// clear out all information
RemoveAll();
// attempt to open file
PTextFile file;
if (!file.Open(filename, PFile::ReadOnly))
return FALSE;
PXConfigSection * currentSection = NULL;
// read lines in the file
while (file.ReadLine(line)) {
line = line.Trim();
if ((len = line.GetLength()) > 0) {
// ignore comments and blank lines
char ch = line[0];
if ((len > 0) && (ch != ';') && (ch != '#')) {
if (ch == '[') {
PCaselessString sectionName = (line.Mid(1,len-(line[len-1]==']'?2:1))).Trim();
PINDEX index;
if ((index = GetValuesIndex(sectionName)) != P_MAX_INDEX)
currentSection = &(*this )[index];
else {
currentSection = new PXConfigSection(sectionName);
Append(currentSection);
}
} else if (currentSection != NULL) {
PINDEX equals = line.Find('=');
if (equals > 0) {
PString keyStr = line.Left(equals).Trim();
PString valStr = line.Right(len - equals - 1).Trim();
PXConfigValue * value = new PXConfigValue(keyStr, valStr);
currentSection->GetList().Append(value);
}
}
}
}
}
// close the file and return
file.Close();
return TRUE;
}
void PXConfig::ReadFromEnvironment (char **envp)
{
// clear out all information
RemoveAll();
PXConfigSection * currentSection = new PXConfigSection("Options");
Append(currentSection);
while (*envp != NULL && **envp != '\0') {
PString line(*envp);
PINDEX equals = line.Find('=');
if (equals > 0) {
PXConfigValue * value = new PXConfigValue(line.Left(equals), line.Right(line.GetLength() - equals - 1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -