mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
152 lines
4.3 KiB
C++
152 lines
4.3 KiB
C++
#include "IniConfig.hpp"
|
||
|
||
static bool __slash = false;
|
||
|
||
// Изменяет значение флага в соответствии с установленными правилами, указывает,
|
||
// что делать с текущим символом/буфером
|
||
void Rule(int& flags, int cur, bool& skip, bool& complete)
|
||
{
|
||
complete = false;
|
||
skip = false;
|
||
|
||
bool string = flags / 1000 % 10 == 1;
|
||
|
||
if (cur == '\\')
|
||
{
|
||
__slash = true;
|
||
skip = true;
|
||
return;
|
||
}
|
||
|
||
if (cur == '\"' && !__slash)
|
||
{
|
||
skip = (!string ? true : complete = true);
|
||
flags = (!string ? 1000 : 0) + flags % 1000;
|
||
return;
|
||
}
|
||
else if (cur == '\"' && __slash)
|
||
return;
|
||
|
||
if (cur == '[' && __slash) return;
|
||
if (cur == ']' && __slash) return;
|
||
if (cur == ',' && __slash) return;
|
||
if (cur == '=' && __slash) return;
|
||
|
||
if (cur == ' ' && !string) { skip = true; return; }
|
||
if (cur == '\t' && !string) { skip = true; return; }
|
||
if (cur == '\n' && string) { skip = true; return; }
|
||
|
||
if (flags == 10 && cur == '[' ) { flags = 100; skip = true; return; }
|
||
if (flags == 100 && cur != ']' ) { return; }
|
||
if (flags == 10 && cur != '=' ) { return; }
|
||
if (flags == 0 && cur != '[' ) { skip = true; return; }
|
||
if (flags != 1 && cur == '\n') { skip = true; return; }
|
||
if (flags == 0 && cur == '[' ) { flags = 100; skip = true; }
|
||
if (flags == 100 && cur == ']' ) { complete = true; skip = true; flags = 10; }
|
||
if (flags == 10 && cur == '=' ) { complete = true; skip = true; flags = 1; }
|
||
if (flags == 1 && cur == ',' ) { complete = true; skip = true; flags = 1; }
|
||
if (flags == 1 && cur == '\n') { complete = true; flags = 10; }
|
||
}
|
||
|
||
// Загружает INI-структуру из файла. При возникновении ошибки возвращает false
|
||
// file - файл для загрузки
|
||
bool IniFile::Load(const String& file, int charset)
|
||
{
|
||
FileIn in;
|
||
if (!in.Open(file)) return false;
|
||
bool r = Load(in, charset);
|
||
in.Close();
|
||
return r;
|
||
}
|
||
|
||
// Загружает INI-структуру из потока. При возникновении ошибки возвращает false
|
||
// s - поток для загрузки
|
||
bool IniFile::Load(Stream& s, int charset)
|
||
{
|
||
Content.Clear();
|
||
|
||
int sIndex = -1;
|
||
int nIndex = -1;
|
||
|
||
String buffer;
|
||
bool complete;
|
||
bool skip;
|
||
int last;
|
||
int flags = 0;
|
||
String line;
|
||
|
||
while(!s.IsEof())
|
||
{
|
||
line = ::ToCharset(CHARSET_DEFAULT, s.GetLine(), charset);
|
||
line << '\n';
|
||
|
||
for (int i = 0; i < line.GetCount(); ++i)
|
||
{
|
||
int c = line[i];
|
||
|
||
bool lastSplash = __slash;
|
||
last = flags % 1000;
|
||
Rule(flags, c, skip, complete);
|
||
|
||
if (!__slash)
|
||
if (!skip)
|
||
if (c != '\n' && c != '\r' && c != '\"') buffer << (char)c;
|
||
|
||
if (lastSplash && __slash)
|
||
{
|
||
if (c == '\"') { buffer << '\"'; __slash = false; }
|
||
else if (c == '[') { buffer << '['; __slash = false; }
|
||
else if (c == ']') { buffer << ']'; __slash = false; }
|
||
else if (c == '=') { buffer << '='; __slash = false; }
|
||
else if (c == ',') { buffer << ','; __slash = false; }
|
||
else { buffer << '\\'; __slash = false; }
|
||
}
|
||
|
||
if (complete && !buffer.IsEmpty())
|
||
{
|
||
if (last == 100)
|
||
{
|
||
sIndex++;
|
||
nIndex = -1;
|
||
Content.Add(IniConvert(buffer, false));
|
||
}
|
||
|
||
if (last == 10)
|
||
{
|
||
nIndex++;
|
||
Content[sIndex].Content.Add(IniConvert(buffer, false));
|
||
}
|
||
|
||
if (last == 1)
|
||
Content[sIndex].Content[nIndex].Content.Add(IniConvert(buffer, false));
|
||
|
||
buffer.Clear();
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// Возвращает массив с перечислением всех секций файла
|
||
Vector<String> IniFile::EnumSections()
|
||
{
|
||
Vector<String> result;
|
||
for (int i = 0; i < Content.GetCount(); ++i)
|
||
result << Content[i].GetText();
|
||
return result;
|
||
}
|
||
|
||
// Возвращает массив с перечислением всех ключей определенной секции файла
|
||
// s - секция для поиска ключей
|
||
Vector<String> IniFile::EnumNames(const String& s)
|
||
{
|
||
Vector<String> result;
|
||
for (int i = 0; i < Content.GetCount(); ++i)
|
||
if (s == Content[i].GetText())
|
||
{
|
||
for (int j = 0; j < Content[i].Content.GetCount(); ++j)
|
||
result << Content[i].Content[j].GetText();
|
||
}
|
||
return result;
|
||
}
|