📄 chxliteprefs.cpp
字号:
#include "chxliteprefs.h"#include "hlxclib/fcntl.h"#include "chxdataf.h"#include "hxslist.h"#include "hxstring.h"#include "hxdir.h"#include "hxccf.h"#include "ihxpckts.h"#include <ctype.h>#include "hlxclib/stdlib.h"#include "pathutil.h"#include "hxthread.h"BEGIN_INTERFACE_LIST(CHXLitePrefs) INTERFACE_LIST_ENTRY_SIMPLE(IHXPreferences) INTERFACE_LIST_ENTRY_SIMPLE(IHXPreferences3)END_INTERFACE_LIST// for keeping track of a pref valueclass Pref{public: Pref(const char* pStr): m_bChanged(FALSE), m_strValue(pStr){} BOOL HasChanged() const { return m_bChanged;} void SetChanged(BOOL bChanged) { m_bChanged = bChanged;} void SetValue(const char* pStr) { m_strValue = pStr;} const char* Buffer() const { return m_strValue;} UINT32 Size() const {return m_strValue.GetLength() + 1;}private: BOOL m_bChanged; CHXString m_strValue;};// helpers local to this modulenamespace LitePrefs{void ClearPrefs(CHXMapStringToOb* pPrefs);CHXDataFile* OpenPrefFile(const char* pPath, UINT16 mode);HX_RESULT WritePrefFile(const char* pPath, CHXStringList& shadows, const CHXMapStringToOb& prefs);HX_RESULT WritePrefs(const CHXMapStringToOb* pPrefs, const char* pPath);HX_RESULT ReadPrefs(const char* pPath, CHXMapStringToOb* pPrefs);HX_RESULT ParsePrefs(CHXDataFile* pFile, CHXMapStringToOb* pPrefs, CHXStringList* pShadows);HX_RESULT StorePref(CHXMapStringToOb* pPrefs, const char* pName, const char* pValue, BOOL bChanged = TRUE);HX_RESULT RetrievePref(IHXCommonClassFactory* pFactory, const CHXMapStringToOb* pPrefs, const char* pName, REF(IHXBuffer*) pValue);void FindNewOrAlteredPrefs(const CHXMapStringToOb& memPrefs, const CHXMapStringToOb& origPrefs, CHXMapStringToOb& prefsOut);BOOL SkipToken(char*& pos, INT32& nCount, char term);BOOL ParseToken(char*& pos, INT32& nCount, char term, CHXString& token);CHXString GetBasePath(const CHXString& strPath);}//// get base path part of full filename path (strip off filename)//inlineCHXString LitePrefs::GetBasePath(const CHXString& strPath){ CHXString strBase; INT32 idxSep = strPath.ReverseFind(OS_SEPARATOR_CHAR); if( idxSep != -1 ) { strBase = strPath.Left(idxSep + 1); } return strBase;}//// go through current prefs (in memory) and determine which entries// are: a) set in a shadow but now have a different value; or b) not// in a shadow to begin with//inline voidLitePrefs::FindNewOrAlteredPrefs(const CHXMapStringToOb& memPrefs, const CHXMapStringToOb& origPrefs, CHXMapStringToOb& prefsOut){ // for each current pref setting (cast away const to work around deficiency in map inteface)... CHXMapStringToOb& memPrefs_ = (CHXMapStringToOb&)memPrefs; CHXMapStringToOb::Iterator iterEnd = memPrefs_.End(); for(CHXMapStringToOb::Iterator iter = memPrefs_.Begin(); iter != iterEnd; ++iter) { Pref* pPref = (Pref*)*iter; const char* pKey = iter.get_key(); HX_ASSERT(pPref); HX_ASSERT(pKey); // transfer this pref if is new or altered if( pPref->HasChanged() || (0 != origPrefs.Lookup(pKey)) ) { prefsOut.SetAt(pKey, pPref); } }}//// Prefs are read from primary file, then shadows. Settings in primary file override// those in shadows (which are essentially defaults). Therefore the first value that // is found for a given pref is the value that remains in effect.//HX_RESULT LitePrefs::ReadPrefs(const char* pPath, CHXMapStringToOb* pPrefs){ HX_RESULT res = HXR_FAIL; CHXDataFile* pFile = LitePrefs::OpenPrefFile(pPath, O_RDONLY); if (pFile) { CHXStringList shadows; res = LitePrefs::ParsePrefs(pFile, pPrefs, &shadows); pFile->Close(); // use base path from current pref file to locate regerenced shadow file CHXString strBase = LitePrefs::GetBasePath(pPath); LISTPOSITION i = shadows.GetHeadPosition(); while(i) { const CHXString& strShadowFile = *((CHXString*) shadows.GetNext(i)); CHXString strPath = HXPathUtil::CombinePath(strBase, strShadowFile); res = LitePrefs::ReadPrefs(strPath, pPrefs); } HX_DELETE(pFile); } return res;}// helperCHXDataFile*LitePrefs::OpenPrefFile(const char* pPath, UINT16 mode){ CHXDataFile* pFile = CHXDataFile::Construct(); if (pFile) { HX_RESULT res = pFile->Open(pPath, mode, TRUE); if (FAILED(res)) { HX_DELETE(pFile); } } return pFile;}//// write out the given file in our pref file format//HX_RESULTLitePrefs::WritePrefFile(const char* pPath, CHXStringList& shadows, const CHXMapStringToOb& prefs){ HX_RESULT hr = HXR_FAIL; CHXDataFile* pFile = LitePrefs::OpenPrefFile(pPath, O_WRONLY | O_CREAT | O_TRUNC); if (pFile) { // // write the shadow pref file references // LISTPOSITION j = shadows.GetHeadPosition(); while(j) { const CHXString& fileName = *((CHXString*) shadows.GetNext(j)); // format shadow, write to file pFile->Write("[", 1); pFile->Write(fileName, fileName.GetLength()); pFile->Write("]\n", 2); } // // write out preference name/value entries // // cast away const to work around deficiency in map interface... CHXMapStringToOb& prefs_ = (CHXMapStringToOb&)prefs; CHXMapStringToOb::Iterator iterEnd = prefs_.End(); for(CHXMapStringToOb::Iterator iter = prefs_.Begin(); iter != iterEnd; ++iter) { const char* pPrefKey = iter.get_key(); Pref* pPref = (Pref*)*iter; pFile->Write(pPrefKey, strlen(pPrefKey)); pFile->Write("=", 1); if (pPref->Size() > 1) { // don't write the null terminator pFile->Write(pPref->Buffer(), pPref->Size()-1); } pFile->Write("\n", 1); } HX_DELETE(pFile); hr = HXR_OK; } return hr;}HX_RESULTLitePrefs::WritePrefs(const CHXMapStringToOb* pPrefs, const char* pPath){ HX_RESULT res = HXR_FAIL; CHXDataFile* pFile = LitePrefs::OpenPrefFile(pPath, O_RDONLY); if (pFile) { // read current preference settings from files CHXStringList shadows; CHXMapStringToOb origPrefs; res = LitePrefs::ParsePrefs(pFile, &origPrefs, &shadows); HX_DELETE(pFile); if (SUCCEEDED(res)) { // determine altered or new preferences CHXMapStringToOb newPrefs; FindNewOrAlteredPrefs(*pPrefs, origPrefs, newPrefs); // write out the prefs with our up-to-date values LitePrefs::WritePrefFile(pPath, shadows, newPrefs); } LitePrefs::ClearPrefs(&origPrefs); } return res;}HX_RESULT LitePrefs::StorePref(CHXMapStringToOb* pPrefs, const char* pName, const char* pValue, BOOL bChanged){ Pref* pPref = NULL; if (pPrefs->Lookup(pName, (void*&)pPref)) { // update existing pref pPref->SetValue(pValue); } else { // create and add new pref pPref = new Pref(pValue); if(!pPref) { return HXR_OUTOFMEMORY; } pPrefs->SetAt(pName, pPref); } pPref->SetChanged(bChanged); return HXR_OK;}HX_RESULTLitePrefs::ParsePrefs(CHXDataFile* pFile, CHXMapStringToOb* pPrefs, CHXStringList* pShadows){ HX_ASSERT(pFile && pPrefs && pShadows); #define BUF_SZ 0x0400 // read file in 1k chunks ParseState eState = eParsingWhiteSpace; INT32 nCount = 0; CHXString strBuf; char* pos = 0; char* buf = strBuf.GetBuffer(BUF_SZ); CHXString sName; CHXString sValue; for (;;) { // read more data if (nCount == 0) { nCount = (INT32)pFile->Read(buf, BUF_SZ); if (nCount <= 0) { // end of file break; } pos = buf; } switch(eState) { case eParsingValue: { if (LitePrefs::ParseToken(pos, nCount, '\n', sValue)) { eState = eParsingWhiteSpace; // don't add this name value if name already exists in prefs if(0 == pPrefs->Lookup(sName)) { HX_RESULT res = LitePrefs::StorePref(pPrefs, sName, sValue, FALSE); if (FAILED(res)) { return res; } } sName.Empty(); sValue.Empty(); } } break; case eParsingComment: { // skip to end of line if (LitePrefs::SkipToken(pos, nCount, '\n')) { eState = eParsingWhiteSpace; } } break; case eParsingName: { // name is everything up to '=' if (LitePrefs::ParseToken(pos, nCount, '=', sName)) { eState = eParsingValue; } } break; case eParsingShadow: { // shadow reference is everything up to closing ']' if (LitePrefs::ParseToken(pos, nCount, ']', sName)) { eState = eParsingComment; // queue this up for parsing pShadows->AddTailString(sName); sName.Empty(); } } break; case eParsingWhiteSpace: { // we're looking for something to parse switch (*pos) { case '[': { eState = eParsingShadow; } break; case '#': case ';':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -