| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- #include "IniFile.h"
- #include "FileService.h"
- //---------------------------------------------------------------------------------------------
- //IniFile
- //---------------------------------------------------------------------------------------------
- IniFile::IniFile(const char * _path, bool _isReadOnly, const char * _cppFileName, long _cppFileLine)
- {
- path = _path;
- parser.fileName = path;
- isChangeData = false;
- isReadOnly = _isReadOnly;
- lockRelease = false;
- #ifndef STOP_DEBUG
- cppFileName = _cppFileName;
- cppFileLine = _cppFileLine;
- #endif
- }
- IniFile::~IniFile()
- {
- }
- //Прочитать файл
- bool IniFile::Open(IFileService_DFOpenMode mode)
- {
- Assert(isReadOnly);
- IDataFile * file = FileService::object->OpenDataFile(path, mode, _FL_);
- if(file)
- {
- dword size = file->Size();
- void * ptr = parser.Reserved(size);
- if(file->Read(ptr, size) != size)
- {
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't read from ini file \"%s\" [read only mode] (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- return false;
- }
- file->Release();
- }else{
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't open ini file \"%s\" [read only mode] (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- return false;
- }
- parser.Parse();
- return true;
- }
- #ifndef _XBOX
- //Открыть файл
- bool IniFile::Open(IFileService_OpenMode mode)
- {
- Assert(!isReadOnly);
- IFile * file = FileService::object->OpenFile(path, mode, _FL_);
- if(file)
- {
- dword size = file->Size();
- void * ptr = parser.Reserved(size);
- if(file->Read(ptr, size) != size)
- {
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't read from ini file \"%s\" [editable mode] (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- return false;
- }
- file->Release();
- }else{
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't open ini file \"%s\" [editable mode] (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- return false;
- }
- if(mode == file_open_existing_for_read)
- {
- isReadOnly = true;
- }
- parser.Parse();
- return true;
- }
- #endif
- //Закрыть файл сообщив об ошибке
- void IniFile::ErrorRelease()
- {
- #ifndef STOP_DEBUG
- api->Error("FileService error: IIniFile file \"%s\" not release (file: %s, line %i)", path.c_str(), cppFileName, cppFileLine);
- #endif
- delete this;
- }
- //Блокировать возможность удалить файл
- void IniFile::LockRelease(bool isLock)
- {
- lockRelease = isLock;
- }
- //Закрыть файл
- void IniFile::Release()
- {
- if(lockRelease)
- {
- return;
- }
- if(!isReadOnly)
- {
- Flush();
- }
- SingleExClassThread(FileService::object)
- FileService::object->DeleteIniFile(this);
- delete this;
- }
- //Поулчить путь до файла
- const char * IniFile::GetPath() const
- {
- return path;
- }
- //Получить список секций
- void IniFile::GetSections(array<string> & sections)
- {
- sections.DelAll();
- parser.GetSections(sections);
- }
- //Добавить секцию
- void IniFile::AddSection(const char * section)
- {
- Assert(!isReadOnly);
- parser.AddSection(section);
- isChangeData = true;
- }
- //Удалить секцию с ключами
- void IniFile::DelSection(const char * section)
- {
- Assert(!isReadOnly);
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- if(sectionIndex >= 0)
- {
- parser.DelSection(sectionIndex);
- isChangeData = true;
- }
- }
- //Проверить наличие секции
- bool IniFile::IsSectionCreated(const char * section)
- {
- return (parser.FindSection(section) >= 0);
- }
- //Получить количество ключей
- dword IniFile::GetKeysCount(const char * section, const char * name)
- {
- //Подготовим имя ключа
- if(!name || !name[0]) return 0;
- long nameLen = strlen(name);
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- //Перебираем все одноимённые ключи в секции
- for(long keyIndex = -1, count = 0; true; count++)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) break;
- }
- return count;
- }
- //Проверить наличие ключа в секции
- bool IniFile::IsKeyCreated(const char * section, const char * name, long index)
- {
- if(!name || !name[0]) return false;
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- if(sectionIndex < 0)
- {
- return false;
- }
- long nameLen = strlen(name);
- return (parser.FindKey(sectionIndex, name, nameLen, index) >= 0);
- }
- //Удалить ключ
- void IniFile::DelKey(const char * section, const char * name, long index)
- {
- Assert(!isReadOnly);
- if(!name || !name[0]) return;
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- if(sectionIndex < 0)
- {
- return;
- }
- long nameLen = strlen(name);
- for(long keyIndex = -1; true; index--)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) break;
- if(index <= 0)
- {
- parser.DelKey(keyIndex);
- isChangeData = true;
- }
- }
- }
- //Установить значение ключа как строку
- void IniFile::SetString(const char * section, const char * name, const char * value, long index)
- {
- Assert(!isReadOnly);
- //Подготовим имя ключа
- if(!name || !name[0]) return;
- long nameLen = strlen(name);
- //Находим индекс секции}
- long sectionIndex = parser.AddSection(section);
- Assert(sectionIndex >= 0);
- //Ищим ключ
- for(long keyIndex = -1; true; index--)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0)
- {
- isChangeData = true;
- if(index <= 0)
- {
- keyIndex = parser.AddKey(sectionIndex, name, value);
- return;
- }else{
- keyIndex = parser.AddKey(sectionIndex, name, "");
- }
- }
- if(index <= 0)
- {
- isChangeData = true;
- parser.SetKey(keyIndex, value);
- return;
- }
- }
- }
- //Получить значение ключа как строку
- const char * IniFile::GetString(const char * section, const char * name, const char * defValue, long index)
- {
- if(!name || !name[0]) return defValue;
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- if(sectionIndex < 0)
- {
- return defValue;
- }
- //Ищим ключ
- long nameLen = strlen(name);
- for(long keyIndex = -1; true; index--)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0)
- {
- return defValue;
- }
- if(index <= 0)
- {
- return parser.GetKey(keyIndex);
- }
- }
- return defValue;
- }
- //Получить все значения ключа как строки
- void IniFile::GetStrings(const char * section, const char * name, array<string> & value)
- {
- value.DelAll();
- //Подготовим имя ключа
- if(!name || !name[0]) return;
- long nameLen = strlen(name);
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- //Перебираем все одноимённые ключи в секции
- long keyIndex = -1;
- while(true)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) return;
- value.Add(parser.GetKey(keyIndex));
- }
- }
- //Установить значение ключа как long
- void IniFile::SetLong(const char * section, const char * name, long value, long index)
- {
- char buf[128];
- crt_snprintf(buf, sizeof(buf), "%i", value);
- SetString(section, name, buf, index);
- }
- //Получить значение ключа как long
- long IniFile::GetLong(const char * section, const char * name, long defValue, long index)
- {
- const char * v = GetString(section, name, null, index);
- if(!v) return defValue;
- char * stop;
- return strtol(v, &stop, 10);
- }
- //Получить все значения ключа как long
- void IniFile::GetLongs(const char * section, const char * name, array<long> & value)
- {
- //Подготовим имя ключа
- if(!name || !name[0]) return;
- long nameLen = strlen(name);
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- //Перебираем все одноимённые ключи в секции
- long keyIndex = -1;
- while(true)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) return;
- const char * v = parser.GetKey(keyIndex);
- char * stop;
- long vl = strtol(v, &stop, 10);
- value.Add(vl);
- }
- }
- //Установить значение ключа как float
- void IniFile::SetFloat(const char * section, const char * name, float value, long index)
- {
- SetDouble(section, name, value, index);
- }
- //Получить значение ключа как float
- float IniFile::GetFloat(const char * section, const char * name, float defValue, long index)
- {
- return (float)GetDouble(section, name, defValue, index);
- }
- //Получить все значения ключа как float
- void IniFile::GetFloats(const char * section, const char * name, array<float> & value)
- {
- value.DelAll();
- //Подготовим имя ключа
- if(!name || !name[0]) return;
- long nameLen = strlen(name);
-
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- //Перебираем все одноимённые ключи в секции
- long keyIndex = -1;
- while(true)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) return;
- const char * v = parser.GetKey(keyIndex);
- char * stop;
- float vl = (float)strtod(v, &stop);
- value.Add(vl);
- }
- }
- //Установить значение ключа как double
- void IniFile::SetDouble(const char * section, const char * name, double value, long index)
- {
- char buf[128];
- crt_snprintf(buf, sizeof(buf), "%f", value);
- SetString(section, name, buf, index);
- }
- //Получить значение ключа как double
- double IniFile::GetDouble(const char * section, const char * name, double defValue, long index)
- {
- const char * v = GetString(section, name, null, index);
- if(!v) return defValue;
- char * stop;
- return strtod(v, &stop);
- }
- //Получить все значения ключа как double
- void IniFile::GetDoubles(const char * section, const char * name, array<double> & value)
- {
- value.DelAll();
- //Подготовим имя ключа
- if(!name || !name[0]) return;
- long nameLen = strlen(name);
- //Находим индекс секции
- long sectionIndex = parser.FindSection(section);
- //Перебираем все одноимённые ключи в секции
- long keyIndex = -1;
- while(true)
- {
- keyIndex = parser.FindKey(sectionIndex, name, nameLen, keyIndex);
- if(keyIndex < 0) return;
- const char * v = parser.GetKey(keyIndex);
- char * stop;
- double vl = strtod(v, &stop);
- value.Add(vl);
- }
- }
- //Сохранить изменения на диск немедленно
- void IniFile::Flush()
- {
- #ifndef _XBOX
- Assert(!isReadOnly);
- dword size = 0;
- const void * data = parser.GetBuffer(size);
- IFile * file = FileService::object->OpenFile(path, file_create_always, _FL_);
- if(file)
- {
- if(file->Write(data, size) != size)
- {
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't write to file \"%s\" (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- }
- file->Release();
- }else{
- #ifndef STOP_DEBUG
- api->Error("FileService error: Can't open to write ini file \"%s\" (file: %s, line: %i -> IniFile::Flush)", path.c_str(), cppFileName, cppFileLine);
- #endif
- }
- #endif
- }
|