mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
Optimized ConfigParser. Reduced processing time on startup and on refreshing.
This commit is contained in:
parent
c7f9293e9c
commit
4389edb8c1
@ -58,16 +58,17 @@ CConfigParser::~CConfigParser()
|
|||||||
**
|
**
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow)
|
void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow, LPCTSTR config)
|
||||||
{
|
{
|
||||||
m_Filename = filename;
|
m_Filename = filename;
|
||||||
|
|
||||||
m_BuiltInVariables.clear();
|
m_BuiltInVariables.clear();
|
||||||
m_Variables.clear();
|
m_Variables.clear();
|
||||||
m_Measures.clear();
|
m_Measures.clear();
|
||||||
m_Keys.clear();
|
|
||||||
m_Values.clear();
|
m_Values.clear();
|
||||||
m_Sections.clear();
|
m_Sections.clear();
|
||||||
|
m_FoundSections.clear();
|
||||||
|
m_ListVariables.clear();
|
||||||
|
|
||||||
// Set the built-in variables. Do this before the ini file is read so that the paths can be used with @include
|
// Set the built-in variables. Do this before the ini file is read so that the paths can be used with @include
|
||||||
SetBuiltInVariables(pRainmeter, meterWindow);
|
SetBuiltInVariables(pRainmeter, meterWindow);
|
||||||
@ -76,8 +77,10 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW
|
|||||||
std::vector<std::wstring> iniFileMappings;
|
std::vector<std::wstring> iniFileMappings;
|
||||||
CSystem::GetIniFileMappingList(iniFileMappings);
|
CSystem::GetIniFileMappingList(iniFileMappings);
|
||||||
|
|
||||||
ReadIniFile(iniFileMappings, m_Filename);
|
ReadIniFile(iniFileMappings, m_Filename, config);
|
||||||
ReadVariables();
|
ReadVariables();
|
||||||
|
|
||||||
|
std::unordered_set<std::wstring>().swap(m_FoundSections); // clear and minimize
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -130,11 +133,9 @@ void CConfigParser::SetBuiltInVariables(CRainmeter* pRainmeter, CMeterWindow* me
|
|||||||
*/
|
*/
|
||||||
void CConfigParser::ReadVariables()
|
void CConfigParser::ReadVariables()
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> listVariables = GetKeys(L"Variables");
|
for (size_t i = 0, isize = m_ListVariables.size(); i < isize; ++i)
|
||||||
|
|
||||||
for (size_t i = 0, isize = listVariables.size(); i < isize; ++i)
|
|
||||||
{
|
{
|
||||||
SetVariable(listVariables[i], ReadString(L"Variables", listVariables[i].c_str(), L"", false));
|
SetVariable(m_ListVariables[i], ReadString(L"Variables", m_ListVariables[i].c_str(), L"", false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,7 +1033,7 @@ RECT CConfigParser::ParseRECT(LPCTSTR string)
|
|||||||
**
|
**
|
||||||
** \param iniFile The ini file to be read.
|
** \param iniFile The ini file to be read.
|
||||||
*/
|
*/
|
||||||
void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& iniFile, int depth)
|
void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& iniFile, LPCTSTR config, int depth)
|
||||||
{
|
{
|
||||||
if (depth > 100) // Is 100 enough to assume the include loop never ends?
|
if (depth > 100) // Is 100 enough to assume the include loop never ends?
|
||||||
{
|
{
|
||||||
@ -1062,15 +1063,19 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all the sections (i.e. different meters)
|
// Get all the sections (i.e. different meters)
|
||||||
|
std::list<std::wstring> sections;
|
||||||
WCHAR* items = new WCHAR[MAX_LINE_LENGTH];
|
WCHAR* items = new WCHAR[MAX_LINE_LENGTH];
|
||||||
int size = MAX_LINE_LENGTH;
|
DWORD size = MAX_LINE_LENGTH;
|
||||||
|
WCHAR* pos = NULL;
|
||||||
WCHAR* epos = NULL;
|
WCHAR* epos = NULL;
|
||||||
|
|
||||||
|
if (config == NULL)
|
||||||
|
{
|
||||||
// Get all the sections
|
// Get all the sections
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
items[0] = 0;
|
items[0] = 0;
|
||||||
int res = GetPrivateProfileString( NULL, NULL, NULL, items, size, iniRead.c_str());
|
DWORD res = GetPrivateProfileString(NULL, NULL, NULL, items, size, iniRead.c_str());
|
||||||
if (res == 0) // File not found
|
if (res == 0) // File not found
|
||||||
{
|
{
|
||||||
delete [] items;
|
delete [] items;
|
||||||
@ -1089,38 +1094,52 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the sections
|
// Read the sections
|
||||||
std::list<std::wstring> sections;
|
pos = items;
|
||||||
WCHAR* pos = items;
|
|
||||||
while (pos < epos)
|
while (pos < epos)
|
||||||
{
|
{
|
||||||
if (*pos)
|
if (*pos)
|
||||||
{
|
{
|
||||||
std::wstring strTmp = StrToLower(pos);
|
std::wstring strTmp = StrToLower(pos);
|
||||||
if (m_Keys.find(strTmp) == m_Keys.end())
|
if (m_FoundSections.find(strTmp) == m_FoundSections.end())
|
||||||
{
|
{
|
||||||
m_Keys[strTmp] = std::vector<std::wstring>();
|
m_FoundSections.insert(strTmp);
|
||||||
m_Sections.push_back(pos);
|
m_Sections.push_back(pos);
|
||||||
}
|
}
|
||||||
sections.push_back(pos);
|
sections.push_back(pos);
|
||||||
pos += wcslen(pos) + 1;
|
pos += strTmp.size() + 1;
|
||||||
}
|
}
|
||||||
else // Empty string
|
else // Empty string
|
||||||
{
|
{
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Special case: Read only "Rainmeter" and specified section from "Rainmeter.ini"
|
||||||
|
sections.push_back(L"Rainmeter");
|
||||||
|
sections.push_back(config);
|
||||||
|
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
m_Sections.push_back(L"Rainmeter");
|
||||||
|
m_Sections.push_back(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Read the keys and values
|
// Read the keys and values
|
||||||
int bufferSize = MAX_LINE_LENGTH;
|
DWORD bufferSize = MAX_LINE_LENGTH;
|
||||||
WCHAR* buffer = new WCHAR[bufferSize];
|
WCHAR* buffer = new WCHAR[bufferSize];
|
||||||
|
|
||||||
std::list<std::wstring>::const_iterator iter = sections.begin();
|
std::list<std::wstring>::const_iterator iter = sections.begin();
|
||||||
for ( ; iter != sections.end(); ++iter)
|
for ( ; iter != sections.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
bool isVariables = (_wcsicmp((*iter).c_str(), L"Variables") == 0);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
items[0] = 0;
|
items[0] = 0;
|
||||||
int res = GetPrivateProfileString((*iter).c_str(), NULL, NULL, items, size, iniRead.c_str());
|
DWORD res = GetPrivateProfileString((*iter).c_str(), NULL, NULL, items, size, iniRead.c_str());
|
||||||
if (res < size - 2) // Fits in the buffer
|
if (res < size - 2) // Fits in the buffer
|
||||||
{
|
{
|
||||||
epos = items + res;
|
epos = items + res;
|
||||||
@ -1137,12 +1156,10 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
{
|
{
|
||||||
if (*pos)
|
if (*pos)
|
||||||
{
|
{
|
||||||
std::wstring strKey = pos;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
int res = GetPrivateProfileString((*iter).c_str(), strKey.c_str(), L"", buffer, bufferSize, iniRead.c_str());
|
DWORD res = GetPrivateProfileString((*iter).c_str(), pos, L"", buffer, bufferSize, iniRead.c_str());
|
||||||
if (res < bufferSize - 2) break; // Fits in the buffer
|
if (res < bufferSize - 2) break; // Fits in the buffer
|
||||||
|
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
@ -1150,7 +1167,7 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
buffer = new WCHAR[bufferSize];
|
buffer = new WCHAR[bufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_wcsnicmp(strKey.c_str(), L"@include", 8) == 0)
|
if (_wcsnicmp(pos, L"@include", 8) == 0)
|
||||||
{
|
{
|
||||||
std::wstring strIncludeFile = buffer;
|
std::wstring strIncludeFile = buffer;
|
||||||
ReadVariables();
|
ReadVariables();
|
||||||
@ -1159,13 +1176,13 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
(strIncludeFile.length() < 2 || (strIncludeFile[0] != L'\\' && strIncludeFile[0] != L'/') || (strIncludeFile[1] != L'\\' && strIncludeFile[1] != L'/')))
|
(strIncludeFile.length() < 2 || (strIncludeFile[0] != L'\\' && strIncludeFile[0] != L'/') || (strIncludeFile[1] != L'\\' && strIncludeFile[1] != L'/')))
|
||||||
{
|
{
|
||||||
// It's a relative path so add the current path as a prefix
|
// It's a relative path so add the current path as a prefix
|
||||||
strIncludeFile = CRainmeter::ExtractPath(iniFile) + strIncludeFile;
|
strIncludeFile.insert(0, CRainmeter::ExtractPath(iniFile));
|
||||||
}
|
}
|
||||||
ReadIniFile(iniFileMappings, strIncludeFile, depth + 1);
|
ReadIniFile(iniFileMappings, strIncludeFile, config, depth + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetValue((*iter), strKey, buffer);
|
SetValue((*iter), pos, buffer, isVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += wcslen(pos) + 1;
|
pos += wcslen(pos) + 1;
|
||||||
@ -1189,18 +1206,16 @@ void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings
|
|||||||
** \param strKey The name of the key.
|
** \param strKey The name of the key.
|
||||||
** \param strValue The value for the key.
|
** \param strValue The value for the key.
|
||||||
*/
|
*/
|
||||||
void CConfigParser::SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue)
|
void CConfigParser::SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue, bool isVariables)
|
||||||
{
|
{
|
||||||
// LogWithArgs(LOG_DEBUG, L"[%s] %s=%s (size: %i)", strSection.c_str(), strKey.c_str(), strValue.c_str(), (int)m_Values.size());
|
// LogWithArgs(LOG_DEBUG, L"[%s] %s=%s (size: %i)", strSection.c_str(), strKey.c_str(), strValue.c_str(), (int)m_Values.size());
|
||||||
|
|
||||||
std::wstring strTmpSection = StrToLower(strSection);
|
std::wstring strTmpSection = StrToLower(strSection);
|
||||||
std::wstring strTmpKey = StrToLower(strKey);
|
std::wstring strTmpKey = StrToLower(strKey);
|
||||||
|
|
||||||
std::unordered_map<std::wstring, std::vector<std::wstring> >::iterator iter = m_Keys.find(strTmpSection);
|
if (isVariables)
|
||||||
if (iter != m_Keys.end())
|
|
||||||
{
|
{
|
||||||
std::vector<std::wstring>& array = (*iter).second;
|
m_ListVariables.push_back(strTmpKey);
|
||||||
array.push_back(strTmpKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strTmpSection += L"::";
|
strTmpSection += L"::";
|
||||||
@ -1230,21 +1245,3 @@ const std::wstring& CConfigParser::GetValue(const std::wstring& strSection, cons
|
|||||||
|
|
||||||
return strDefault;
|
return strDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
** Returns a list of keys under the given section.
|
|
||||||
**
|
|
||||||
** \param strSection The name of the section.
|
|
||||||
** \return A list of keys under the given section.
|
|
||||||
*/
|
|
||||||
std::vector<std::wstring> CConfigParser::GetKeys(const std::wstring& strSection)
|
|
||||||
{
|
|
||||||
std::unordered_map<std::wstring, std::vector<std::wstring> >::const_iterator iter = m_Keys.find(StrToLower(strSection));
|
|
||||||
if (iter != m_Keys.end())
|
|
||||||
{
|
|
||||||
return (*iter).second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::vector<std::wstring>();
|
|
||||||
}
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <gdiplus.h>
|
#include <gdiplus.h>
|
||||||
@ -39,7 +40,7 @@ public:
|
|||||||
CConfigParser();
|
CConfigParser();
|
||||||
~CConfigParser();
|
~CConfigParser();
|
||||||
|
|
||||||
void Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow = NULL);
|
void Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow = NULL, LPCTSTR config = NULL);
|
||||||
void AddMeasure(CMeasure* pMeasure);
|
void AddMeasure(CMeasure* pMeasure);
|
||||||
|
|
||||||
void SetVariable(const std::wstring& strVariable, const std::wstring& strValue) { SetVariable(m_Variables, strVariable, strValue); }
|
void SetVariable(const std::wstring& strVariable, const std::wstring& strValue) { SetVariable(m_Variables, strVariable, strValue); }
|
||||||
@ -91,10 +92,9 @@ private:
|
|||||||
|
|
||||||
CMeasure* GetMeasure(const std::wstring& name);
|
CMeasure* GetMeasure(const std::wstring& name);
|
||||||
|
|
||||||
void ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& strFileName, int depth = 0);
|
void ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& strFileName, LPCTSTR config = NULL, int depth = 0);
|
||||||
void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue);
|
void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue, bool isVariables);
|
||||||
const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault);
|
const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault);
|
||||||
std::vector<std::wstring> GetKeys(const std::wstring& strSection);
|
|
||||||
|
|
||||||
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
|
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
|
||||||
|
|
||||||
@ -104,6 +104,7 @@ private:
|
|||||||
static void SetMonitorVariable(const std::wstring& strVariable, const std::wstring& strValue) { SetVariable(c_MonitorVariables, strVariable, strValue); }
|
static void SetMonitorVariable(const std::wstring& strVariable, const std::wstring& strValue) { SetVariable(c_MonitorVariables, strVariable, strValue); }
|
||||||
|
|
||||||
static std::wstring StrToLower(const std::wstring& str) { std::wstring strTmp(str); std::transform(strTmp.begin(), strTmp.end(), strTmp.begin(), ::towlower); return strTmp; }
|
static std::wstring StrToLower(const std::wstring& str) { std::wstring strTmp(str); std::transform(strTmp.begin(), strTmp.end(), strTmp.begin(), ::towlower); return strTmp; }
|
||||||
|
static std::wstring StrToLower(const WCHAR* str) { std::wstring strTmp(str); std::transform(strTmp.begin(), strTmp.end(), strTmp.begin(), ::towlower); return strTmp; }
|
||||||
|
|
||||||
std::wstring m_Filename;
|
std::wstring m_Filename;
|
||||||
|
|
||||||
@ -117,7 +118,8 @@ private:
|
|||||||
bool m_LastDefaultUsed;
|
bool m_LastDefaultUsed;
|
||||||
|
|
||||||
std::vector<std::wstring> m_Sections; // The sections must be an ordered array
|
std::vector<std::wstring> m_Sections; // The sections must be an ordered array
|
||||||
std::unordered_map<std::wstring, std::vector<std::wstring> > m_Keys;
|
std::unordered_set<std::wstring> m_FoundSections;
|
||||||
|
std::vector<std::wstring> m_ListVariables;
|
||||||
std::unordered_map<std::wstring, std::wstring> m_Values;
|
std::unordered_map<std::wstring, std::wstring> m_Values;
|
||||||
|
|
||||||
std::unordered_map<std::wstring, std::wstring> m_BuiltInVariables; // Built-in variables
|
std::unordered_map<std::wstring, std::wstring> m_BuiltInVariables; // Built-in variables
|
||||||
|
@ -1778,7 +1778,7 @@ void CMeterWindow::ReadConfig()
|
|||||||
m_ConfigGroup = L"";
|
m_ConfigGroup = L"";
|
||||||
|
|
||||||
CConfigParser parser;
|
CConfigParser parser;
|
||||||
parser.Initialize(iniFile.c_str(), m_Rainmeter);
|
parser.Initialize(iniFile.c_str(), m_Rainmeter, NULL, m_SkinName.c_str());
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user