📄 settings.cpp
字号:
// Settings.cpp: implementation of the CSettings class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Settings.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPtrList CIniFileList::m_IniFileList;
CIniFileData* CIniFileList::m_pCurDataFile;
CIniFileList CSettings::m_IniList;
void SortStringList(CStringList* pList)
{
CStringList SortedList;
for (POSITION pos = pList->GetHeadPosition(); pos != NULL;)
{
CString strItem = pList->GetNext(pos);
//
// Look for the proper place to insert this item.
//
if (SortedList.IsEmpty())
{
SortedList.AddTail(strItem);
}
else
{
BOOL bInserted = FALSE;
for (POSITION srt = SortedList.GetHeadPosition(); srt != NULL;)
{
CString strSort = SortedList.GetAt(srt);
if (strSort.CompareNoCase(strItem) > 0)
{
SortedList.InsertBefore(srt, strItem);
bInserted = TRUE;
break;
}
SortedList.GetNext(srt);
}
if (!bInserted)
{
SortedList.AddTail(strItem);
}
}
}
#if DEBUG_SORT
for (POSITION srt = SortedList.GetHeadPosition(); srt != NULL;)
{
CString strSort = SortedList.GetNext(srt);
OutputDebugString(strSort+"\n");
}
#endif
pList->RemoveAll();
pList->AddTail(&SortedList);
}
BOOL CIniFileList::AddIniFile(CString strFileName)
{
BOOL bAlreadyLoaded = FALSE;
POSITION pos;
for (pos = m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pIni = (CIniFileData*)m_IniFileList.GetNext(pos);
if (pIni->GetFileName() == strFileName)
{
// This ini file has already been loaded.
bAlreadyLoaded = TRUE;
break;
}
}
if (!bAlreadyLoaded)
{
CIniFileData* pIni = new CIniFileData(strFileName);
m_IniFileList.AddTail(pIni);
}
return true;
}
CIniFileData* CIniFileList::GetFile(CString strFileName)
{
POSITION pos;
for (pos = m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pIni = (CIniFileData*)m_IniFileList.GetNext(pos);
if (pIni->GetFileName() == strFileName)
{
return pIni;
}
}
return NULL;
}
CIniFileList::~CIniFileList()
{
POSITION pos;
for (pos = m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pIni = (CIniFileData*)m_IniFileList.GetNext(pos);
delete pIni;
}
m_IniFileList.RemoveAll();
}
BOOL CIniFileList::Toss(CString strFileName)
{
BOOL bResult = FALSE;
POSITION pos;
for (pos = m_IniFileList.GetHeadPosition(); pos != NULL;)
{
POSITION del = pos;
CIniFileData* pIni = (CIniFileData*)m_IniFileList.GetNext(pos);
if (pIni->GetFileName() == strFileName)
{
m_IniFileList.RemoveAt(del);
delete pIni;
bResult = TRUE;
break;
}
}
return bResult;
}
CIniFileData::CIniFileData(CString strFileName)
{
m_strFileName = strFileName;
// Load the ini file data from the disk file...
CStdioFile File;
CIniFileSection* pSect;
if (File.Open(m_strFileName, CFile::modeRead))
{
CString strIn;
while (File.ReadString(strIn))
{
strIn.TrimLeft();
strIn.TrimRight();
if (strIn.IsEmpty())
{
continue;
}
else if (strIn[0] == ';')
{
continue;
}
else if (strIn[0] == '[')
{
// Beginning of a new section
strIn.TrimLeft('[');
strIn.TrimRight(']');
pSect = new CIniFileSection;
m_SectionList.AddTail(strIn);
CIniFileSection* pTmp;
if (m_SectionMap.Lookup(strIn, (void *&) pTmp))
{
#ifdef _DEBUG
CString strMsg;
strMsg.Format("Duplicate section found!\n\nFile: %s\nSection: %s\n\nOnly first section is parsed.",
m_strFileName, strIn);
AfxMessageBox(strMsg);
// Duplicate sections should not exist.
#endif
delete pTmp;
}
m_SectionMap.SetAt(strIn, (void *)pSect);
}
else
{
CString strKey = strIn.Left(strIn.Find("="));
CString strVal = strIn.Right(strIn.GetLength()-strKey.GetLength()-1);
strKey.TrimLeft();
strKey.TrimRight();
strVal.TrimLeft();
strVal.TrimRight();
if (!strVal.IsEmpty() && strVal[0]=='=')
{
int i = 5;
}
pSect->AddKeyVal(strKey, strVal);
}
}
}
}
BOOL CIniFileData::WriteIniFile(BOOL bEliminate)
{
CStdioFile File;
while (!File.Open(m_strFileName, CFile::modeWrite|CFile::modeCreate))
{
#ifdef _DEBUG
CString strMsg;
CString strTmp;
strMsg += "File could not be opened for writing!\n";
strTmp.Format("File: %s\n\n", m_strFileName);
strMsg += strTmp;
strMsg += "Please correct this situation before continuing.";
if (AfxMessageBox(strMsg, MB_RETRYCANCEL) == IDCANCEL)
return FALSE;
#endif
}
POSITION pos;
CString strDumped = "The following sections were eliminated\n";
strDumped += "becuase they are no longer referenced:\n\n";
int nElimCount = 0;
SortStringList(&m_SectionList);
for (pos = m_SectionList.GetHeadPosition(); pos != NULL;)
{
CIniFileSection* pSect;
CString strKey;
CString strVal;
CString strOut;
strKey = m_SectionList.GetNext(pos);
m_SectionMap.Lookup(strKey, (void *&)pSect);
if (bEliminate && pSect->m_bReferenced == FALSE)
{
// The caller has ask that unreferenced sections be
// eliminated from the ini file and this section has
// not been referenced, so skip it.
strDumped += strKey + "\n";
nElimCount++;
continue;
}
if (!pSect->m_KeyList.IsEmpty())
{
strOut.Format("[%s]\n", strKey);
File.WriteString(strOut);
POSITION key;
if (pSect->m_bSortKeys == TRUE)
{
SortStringList(&(pSect->m_KeyList));
}
for (key = pSect->m_KeyList.GetHeadPosition(); key != NULL;)
{
strKey = pSect->m_KeyList.GetNext(key);
pSect->m_ValueMap.Lookup(strKey, strVal);
strOut.Format("%s=%s\n",strKey, strVal);
File.WriteString(strOut);
}
File.WriteString("\n");
}
}
File.Close();
return true;
}
CIniFileData::~CIniFileData()
{
POSITION pos;
for (pos = m_SectionMap.GetStartPosition(); pos != NULL;)
{
CIniFileSection* pSect;
CString strKey;
m_SectionMap.GetNextAssoc(pos, strKey, (void *&)pSect);
delete pSect;
}
m_SectionMap.RemoveAll();
m_SectionList.RemoveAll();
}
CString CIniFileData::GetFileName()
{
return m_strFileName;
}
void CIniFileData::SetFileName(CString strNewName)
{
m_strFileName = strNewName;
}
CIniFileSection* CIniFileData::GetSection(CString strSection)
{
CIniFileSection* pSect = NULL;
m_SectionMap.Lookup(strSection, (void *&)pSect);
if (pSect != NULL)
{
pSect->SetReferenced();
}
return pSect;
}
CIniFileSection* CIniFileData::AddSection(CString strSection, CString strAddAfter)
{
CIniFileSection* pSect = new CIniFileSection;
pSect->SetReferenced();
POSITION insert;
if (strAddAfter.IsEmpty())
{
insert = m_SectionList.GetTailPosition();
}
else
{
insert = m_SectionList.Find(strAddAfter);
if (insert == NULL)
{
insert = m_SectionList.GetTailPosition();
}
}
m_SectionList.InsertAfter(insert, strSection);
m_SectionMap.SetAt(strSection, pSect);
return pSect;
}
CIniFileSection::CIniFileSection()
{
// Default to FALSE, won't be set to true until
// the section is referenced.
m_bReferenced = FALSE;
m_bSortKeys = FALSE;
}
void CIniFileSection::SetReferenced(BOOL bReferenced)
{
m_bReferenced = bReferenced;
}
CIniFileSection::~CIniFileSection()
{
m_KeyList.RemoveAll();
m_ValueMap.RemoveAll();
}
void CIniFileSection::AddKeyVal(CString strKey, CString strVal)
{
m_KeyList.AddTail(strKey);
m_ValueMap.SetAt(strKey, strVal);
}
CSettings::CSettings(LPCSTR lpszIniFile)
{
CString strPath;
CString strFile;
m_strIniFile = lpszIniFile;
m_strSection.Empty();
m_IniList.AddIniFile(lpszIniFile);
m_CurKeyPos = NULL;
m_bAlertNotFound = TRUE;
}
BOOL CSettings::ChangeIniFileName(CString strOldName, CString strNewName)
{
POSITION pos;
for (pos = m_IniList.m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pData = (CIniFileData*) m_IniList.m_IniFileList.GetNext(pos);
if (pData->GetFileName() == strOldName)
{
pData->SetFileName(strNewName);
break;
}
}
return TRUE;
}
BOOL CSettings::SaveIniFile(CString strFileName, BOOL bEliminate, BOOL bToss)
{
POSITION pos;
for (pos = m_IniList.m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pData = (CIniFileData*) m_IniList.m_IniFileList.GetNext(pos);
if (pData->GetFileName() == strFileName)
{
pData->WriteIniFile(bEliminate);
}
}
if (bToss)
{
m_IniList.Toss(strFileName);
}
return TRUE;
}
void CSettings::UnloadAllData()
{
POSITION pos;
for (pos = m_IniList.m_IniFileList.GetHeadPosition(); pos != NULL;)
{
CIniFileData* pData = (CIniFileData*) m_IniList.m_IniFileList.GetNext(pos);
delete pData;
}
m_IniList.m_IniFileList.RemoveAll();
}
CSettings::CSettings()
{
m_strIniFile.Empty();
m_strSection.Empty();
m_CurKeyPos = NULL;
m_bAlertNotFound = TRUE;
}
CSettings::~CSettings()
{
}
//----------------------------------------------------------------
// Get all of the section names
//----------------------------------------------------------------
BOOL CSettings::EnumSectionNames()
{
m_pNextString = NULL;
m_pKeyList = m_IniList.GetFile(m_strIniFile)->GetSectionList();
m_CurKeyPos = m_pKeyList->GetHeadPosition();
m_pValMap = NULL;
return true;
}
//----------------------------------------------------------------
// Get all of the keys in the specified section section names
// params:
// lpszSection : name of the section
//----------------------------------------------------------------
int CSettings::EnumKeyNames(LPCSTR lpszSection, BOOL bAddSection)
{
if (m_strIniFile.IsEmpty()) return 0;
m_pCurSect = NULL;
m_pKeyList=NULL;
m_CurKeyPos = NULL;
m_pValMap = NULL;
int nResult = 0;
CIniFileData* pData = m_IniList.GetFile(m_strIniFile);
ASSERT(pData!=NULL);
CIniFileSection* pSect = pData->GetSection(lpszSection);
if (pSect == NULL && bAddSection)
{
// Add new section
pSect = pData->AddSection(lpszSection);
}
m_pCurSect = pSect;
if (pSect != NULL)
{
CStringList* pList = pSect->GetKeyList();
if (pList != NULL)
{
m_pKeyList = pList;
m_pValMap = &pSect->m_ValueMap;
m_CurKeyPos = m_pKeyList->GetHeadPosition();
if (m_pKeyList->IsEmpty())
nResult = 0;
else
nResult = m_pKeyList->GetCount();
}
}
return nResult;
}
int CSettings::PrepareKeys(CStringList* pFileList, LPCSTR lpszSection, BOOL bAddSection, BOOL bReload)
{
int nResult = 0;
for (POSITION pos = pFileList->GetHeadPosition(); pos != NULL;)
{
nResult = PrepareKeys(pFileList->GetNext(pos), lpszSection, bAddSection, bReload);
if (nResult != 0)
{
break;
}
}
return nResult;
}
int CSettings::PrepareKeys(LPCSTR lpszIniFile, LPCSTR lpszSection, BOOL bAddSection, BOOL bReload)
{
CString strFile;
strFile = lpszIniFile;
m_strIniFile = strFile;
m_strSection = lpszSection;
if (bReload)
{
m_IniList.Toss(lpszIniFile);
}
m_IniList.AddIniFile(lpszIniFile);
return EnumKeyNames(m_strSection, bAddSection);
}
int CSettings::ResetKeys(LPCSTR lpszIniFile, LPCSTR lpszSection, BOOL bSortKeys)
{
int nResult = PrepareKeys(lpszIniFile, lpszSection, TRUE);
if (m_pCurSect)
{
m_pCurSect->m_bSortKeys = bSortKeys;
}
DeleteSection();
return nResult;
}
//----------------------------------------------------------------
// Get the next key name or section name,
// used to enumerate through all key or sections names.
// return : false if no more names.
//----------------------------------------------------------------
BOOL CSettings::GetNext()
{
if (m_CurKeyPos == NULL)
{
return FALSE;
}
else
{
m_CurKey = m_pKeyList->GetNext(m_CurKeyPos);
if (m_pValMap)
{
m_pValMap->Lookup(m_CurKey, m_CurVal);
}
return TRUE;
}
}
CString CSettings::GetName()
{
return m_CurKey;
}
BOOL CSettings::GetKeyVal(CString& strKey, CString &strValue)
{
strKey = m_CurKey;
strValue = m_CurVal;
return TRUE;
}
BOOL CSettings::GetKeyVal(CString& strKey, int &nValue)
{
strKey = m_CurKey;
nValue = atoi(m_CurVal);
return TRUE;
}
BOOL CSettings::GetValue(LPCSTR pszKey, int &nValue)
{
const int nDefault = 0x80000000;
BOOL bReturn = FALSE;
if (m_pValMap)
{
CString strVal;
if (bReturn = (m_pValMap->Lookup(pszKey, strVal)!=0))
{
nValue = atoi(strVal);
}
}
AlertUserNotFound(bReturn, pszKey);
return bReturn;
}
BOOL CSettings::GetValue(LPCSTR pszKey, unsigned int &nValue)
{
const unsigned int nDefault = 0x80000000;
BOOL bReturn = FALSE;
if (m_pValMap)
{
CString strVal;
if (bReturn = (m_pValMap->Lookup(pszKey, strVal)!=0))
{
nValue = (unsigned int) atoi(strVal);
}
}
AlertUserNotFound(bReturn, pszKey);
return bReturn;
}
BOOL CSettings::GetValue(LPCSTR pszKey, CString &strValue)
{
BOOL bReturn = FALSE;
if (m_pValMap)
{
CString strTmp;
if (bReturn = (m_pValMap->Lookup(pszKey, strTmp)!=0))
{
strValue = strTmp;
}
}
AlertUserNotFound(bReturn, pszKey);
return bReturn;
}
BOOL CSettings::SetValue(LPCSTR pszKey, int nValue)
{
if (m_pCurSect)
{
// See if this key already exist. If so replace it, if not
// add a new key.
CString strVal;
if (!m_pCurSect->m_ValueMap.Lookup(pszKey, strVal))
{
m_pCurSect->m_KeyList.AddTail(pszKey);
}
strVal.Format("%d", nValue);
m_pCurSect->m_ValueMap.SetAt(pszKey, strVal);
return TRUE;
}
return FALSE;
}
BOOL CSettings::SetValue(LPCSTR pszKey, CString strValue)
{
if (m_pCurSect)
{
// See if this key already exist. If so replace it, if not
// add a new key.
CString strVal;
if (!m_pCurSect->m_ValueMap.Lookup(pszKey, strVal))
{
m_pCurSect->m_KeyList.AddTail(pszKey);
}
m_pCurSect->m_ValueMap.SetAt(pszKey, strValue);
}
return FALSE;
}
void CSettings::DeleteSection()
{
if (m_pCurSect)
{
m_pCurSect->m_KeyList.RemoveAll();
m_pCurSect->m_ValueMap.RemoveAll();
}
}
void CSettings::AlertUserNotFound(BOOL bReturn, LPCSTR pszKey)
{
if (!bReturn && m_bAlertNotFound)
{
#ifdef _DEBUG
CString strMsg;
strMsg.Format("Key <%s> not found!\nSettings File: %s\nSection: %s",
pszKey, m_strIniFile, m_strSection);
strMsg += "\nPress YES to see future messages while parsing this\n";
strMsg += "section, or NO to ignore any more messages.\n";
int nBut = AfxMessageBox(strMsg, MB_YESNO);
if (nBut == IDNO)
{
m_bAlertNotFound = FALSE;
}
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -