📄 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.22 2000/05/25 12:10:06 robertj * Added PConfig::HasKey() function to determine if value actually set. * * Revision 1.21 2000/05/02 08:30:26 craigs * Removed "memory leaks" caused by brain-dead GNU linker * * 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, NoAutoDeleteThread), stop(s){ Resume();}PXConfigWriteThread::~PXConfigWriteThread(){}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); stop.Acknowledge();}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)); currentSection->GetList().Append(value); } envp++; } // can't save environment configs saveOnExit = FALSE;}static BOOL LocateFile(const PString & baseName,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -