diff options
Diffstat (limited to 'src/gen_adldata/ini/ini_processing.cpp')
-rw-r--r-- | src/gen_adldata/ini/ini_processing.cpp | 1385 |
1 files changed, 0 insertions, 1385 deletions
diff --git a/src/gen_adldata/ini/ini_processing.cpp b/src/gen_adldata/ini/ini_processing.cpp deleted file mode 100644 index 2f15821..0000000 --- a/src/gen_adldata/ini/ini_processing.cpp +++ /dev/null @@ -1,1385 +0,0 @@ -/* -INI Processor - a small library which allows you parsing INI-files - -Copyright (c) 2017 Vitaliy Novichkov <admin@wohlnet.ru> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -*/ - -//#define USE_FILE_MAPPER - -/* Stop parsing on first error (default is to keep parsing). */ -//#define INI_STOP_ON_FIRST_ERROR - -#include "ini_processing.h" -#include <cstdio> -#include <cstring> -#include <cstdlib> -#include <clocale> -#include <sstream> -#include <algorithm> -#include <assert.h> -#ifdef _WIN32 -#include <windows.h> -#endif - -#ifdef USE_FILE_MAPPER -/*****Replace this with right path to file mapper class*****/ -#include "../fileMapper/file_mapper.h" -#endif - -static const unsigned char utfbom[3] = {0xEF, 0xBB, 0xBF}; - -enum { Space = 0x01, Special = 0x02, INIParamEq = 0x04 }; - -static const unsigned char charTraits[256] = -{ - // Space: '\t', '\n', '\r', ' ' - // Special: '\n', '\r', '"', ';', '=', '\\' - // INIParamEq: ':', '=' - - 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, Space | Special, 0, 0, Space | Special, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, 0, Special, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, INIParamEq, - Special, 0, Special | INIParamEq, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#if 0//for speed comparison who faster - macro or inline function. Seems speeds are same -#define IS_SPACE(c) (charTraits[static_cast<unsigned char>(c)] & Space) -#define IS_SPECIAL(c) (charTraits[static_cast<unsigned char>(c)] & Special) -#define IS_INIEQUAL(c) (charTraits[static_cast<unsigned char>(c)] & INIParamEq) -#else -inline unsigned char IS_SPACE(char &c) -{ - return (charTraits[static_cast<unsigned char>(c)] & Space); -} -inline unsigned char IS_SPECIAL(char &c) -{ - return (charTraits[static_cast<unsigned char>(c)] & Special); -} -inline unsigned char IS_INIEQUAL(char &c) -{ - return (charTraits[static_cast<unsigned char>(c)] & INIParamEq); -} -#endif - -/* Strip whitespace chars off end of given string, in place. Return s. */ -inline char *rstrip(char *s) -{ - char *p = s + strlen(s); - - while(p > s && IS_SPACE(*--p)) - *p = '\0'; - - return s; -} - -/* Return pointer to first non-whitespace char in given string. */ -inline char *lskip(char *s) -{ - while(*s && IS_SPACE(*s)) - s++; - - return reinterpret_cast<char *>(s); -} - -inline char *lrtrim(char *s) -{ - while(*s && IS_SPACE(*s)) - s++; - - char *p = s + strlen(s); - - while(p > s && IS_SPACE(*--p)) - *p = '\0'; - - return s; -} - -/* Return pointer to first char c or ';' comment in given string, or pointer to - null at end of string if neither found. ';' must be prefixed by a whitespace - character to register as a comment. */ -inline char *find_char_or_comment(char *s, char c) -{ - unsigned char was_whitespace = 0; - - while(*s && *s != c && !(was_whitespace && *s == ';')) - { - was_whitespace = IS_SPACE(*s); - s++; - } - - return s; -} - -inline char *find_inieq_or_comment(char *s) -{ - unsigned char was_whitespace = 0; - - while(*s && (!IS_INIEQUAL(*s)) && !(was_whitespace && *s == ';')) - { - was_whitespace = IS_SPACE(*s); - s++; - } - - return s; -} - -inline char *removeQuotes(char *begin, char *end) -{ - if((*begin == '\0') || (begin == end)) - return begin; - - if((*begin == '"') && (begin + 1 != end)) - begin++; - else - return begin; - - if(*(end - 1) == '"') - *(end - 1) = '\0'; - - return begin; -} - -inline char *unescapeString(char* str) -{ - char *src, *dst; - src = str; - dst = str; - while(*src) - { - if(*src == '\\') - { - src++; - switch(*src) - { - case 'n': *dst = '\n'; break; - case 'r': *dst = '\r'; break; - case 't': *dst = '\t'; break; - default: *dst = *src; break; - } - } - else - if(src != dst) - { - *dst = *src; - } - src++; dst++; - } - *dst = '\0'; - return str; -} - -//Remove comment line from a tail of value -inline void skipcomment(char *value) -{ - unsigned char quoteDepth = 0; - - while(*value) - { - if(quoteDepth > 0) - { - if(*value == '\\') - { - value++; - continue; - } - - if(*value == '"') - --quoteDepth; - } - else if(*value == '"') - ++quoteDepth; - - if((quoteDepth == 0) && (*value == ';')) - { - *value = '\0'; - break; - } - - value++; - } -} - -inline bool memfgets(char *&line, char *data, char *&pos, char *end) -{ - line = pos; - - while(pos != end) - { - if(*pos == '\n') - { - if((pos > data) && (*(pos - 1) == '\r')) - *((pos++) - 1) = '\0';//Support CRLF too - else - *(pos++) = '\0'; - - break; - } - - ++pos; - } - - return (pos != line); - //EOF is a moment when position wasn't changed. - //If do check "pos != end", will be an inability to read last line. - //this logic allows detect true EOF when line is really eof -} - -/* See documentation in header file. */ -bool IniProcessing::parseHelper(char *data, size_t size) -{ - char *section = nullptr; - #if defined(INI_ALLOW_MULTILINE) - char *prev_name = nullptr; - #endif - char *start; - char *end; - char *name; - char *value; - int lineno = 0; - int error = 0; - char *line; - char *pos_end = data + size; - char *pos_cur = data; - params::IniKeys *recentKeys = nullptr; - - /* Scan through file line by line */ - //while (fgets(line, INI_MAX_LINE, file) != NULL) - while(memfgets(line, data, pos_cur, pos_end)) - { - lineno++; - start = line; - - if((lineno == 1) && (size >= 3) && (memcmp(start, utfbom, 3) == 0)) - start += 3; - - start = lrtrim(start); - - if(!*start)//if empty line - skip it away! - continue; - - switch(*start) - { - case ';': - case '#': - //if (*start == ';' || *start == '#') { - // /* Per Python ConfigParser, allow '#' comments at start of line */ - //} - continue; - - case '[': - { - /* A "[section]" line */ - end = find_char_or_comment(start + 1, ']'); - - if(*end == ']') - { - *end = '\0'; - section = start + 1; - //#if defined(INI_ALLOW_MULTILINE) - // prev_name = nullptr; - //#endif - recentKeys = &m_params.iniData[section]; - } - else if(!error) - { - /* No ']' found on section line */ - m_params.errorCode = ERR_SECTION_SYNTAX; - error = lineno; - } - } - break; - - default: - { - /* Not a comment, must be a name[=:]value pair */ - end = find_inieq_or_comment(start); - - if(IS_INIEQUAL(*end)) - { - *end = '\0'; - name = rstrip(start); - value = lskip(end + 1); - end = find_char_or_comment(value, '\0'); - - #ifndef CASE_SENSITIVE_KEYS - for(char *iter = name; *iter != '\0'; ++iter) - *iter = (char)tolower(*iter); - #endif - - if(*end == ';') - *end = '\0'; - - rstrip(value); - { - char *v = value; - skipcomment(v); - v = rstrip(v); - - if(!recentKeys) - recentKeys = &m_params.iniData["General"]; - - #ifdef INIDEBUG - printf("-> [%s]; %s = %s\n", section, name, v); - #endif - (*recentKeys)[name] = unescapeString( removeQuotes(v, v + strlen(v)) ); - } - } - else if(!error) - { - /* No '=' or ':' found on name[=:]value line */ - m_params.errorCode = ERR_KEY_SYNTAX; - error = lineno; - } - - break; - } - }//switch(*start) - - #if defined(INI_STOP_ON_FIRST_ERROR) - - if(error) - break; - - #endif - } - - m_params.lineWithError = error; - return (error == 0); -} - -/* See documentation in header file. */ -bool IniProcessing::parseFile(const char *filename) -{ - bool valid = true; - char *tmp = nullptr; - #ifdef USE_FILE_MAPPER - //By mystical reasons, reading whole file form fread() is faster than mapper :-P - PGE_FileMapper file(filename); - - if(!file.data) - { - m_params.errorCode = ERR_NOFILE; - return -1; - } - - tmp = reinterpret_cast<char *>(malloc(static_cast<size_t>(file.size + 1))); - - if(!tmp) - { - m_params.errorCode = ERR_NO_MEMORY; - return false; - } - - memcpy(tmp, file.data, static_cast<size_t>(file.size)); - *(tmp + file.size) = '\0';//null terminate last line - valid = ini_parse_file(tmp, static_cast<size_t>(file.size)); - #else - #ifdef _WIN32 - //Convert UTF8 file path into UTF16 to support non-ASCII paths on Windows - std::wstring dest; - dest.resize(std::strlen(filename)); - int newSize = MultiByteToWideChar(CP_UTF8, - 0, - filename, - dest.size(), - (wchar_t *)dest.c_str(), - dest.size()); - dest.resize(newSize); - FILE *cFile = _wfopen(dest.c_str(), L"rb"); - #else - FILE *cFile = fopen(filename, "rb"); - #endif - - if(!cFile) - { - m_params.errorCode = ERR_NOFILE; - return false; - } - - fseek(cFile, 0, SEEK_END); - ssize_t size = static_cast<ssize_t>(ftell(cFile)); - if(size < 0) - { - m_params.errorCode = ERR_KEY_SYNTAX; - fclose(cFile); - return false; - } - fseek(cFile, 0, SEEK_SET); - tmp = reinterpret_cast<char *>(malloc(static_cast<size_t>(size + 1))); - if(!tmp) - { - fclose(cFile); - m_params.errorCode = ERR_NO_MEMORY; - return false; - } - - if(fread(tmp, 1, static_cast<size_t>(size), cFile) != static_cast<size_t>(size)) - valid = false; - - fclose(cFile); - if(valid) - { - *(tmp + size) = '\0';//null terminate last line - try - { - valid = parseHelper(tmp, static_cast<size_t>(size)); - } - catch(...) - { - valid = false; - m_params.errorCode = ERR_SECTION_SYNTAX; - } - } - #endif - - free(tmp); - return valid; -} - -bool IniProcessing::parseMemory(char *mem, size_t size) -{ - bool valid = true; - char *tmp = nullptr; - tmp = reinterpret_cast<char *>(malloc(size + 1)); - - if(!tmp) - { - m_params.errorCode = ERR_NO_MEMORY; - return false; - } - - memcpy(tmp, mem, static_cast<size_t>(size)); - *(tmp + size) = '\0';//null terminate last line - valid = parseHelper(tmp, size); - free(tmp); - return valid; -} - - -IniProcessing::IniProcessing() : - m_params{"", false, -1, ERR_OK, false, params::IniSections(), nullptr, ""} -{} - -IniProcessing::IniProcessing(const char *iniFileName, int) : - m_params{iniFileName, false, -1, ERR_OK, false, params::IniSections(), nullptr, ""} -{ - open(iniFileName); -} - -IniProcessing::IniProcessing(const std::string &iniFileName, int) : - m_params{iniFileName, false, -1, ERR_OK, false, params::IniSections(), nullptr, ""} -{ - open(iniFileName); -} - -#ifdef INI_PROCESSING_ALLOW_QT_TYPES -IniProcessing::IniProcessing(const QString &iniFileName, int) : - m_params{iniFileName.toStdString(), false, -1, ERR_OK, false, params::IniSections(), nullptr, ""} -{ - open(m_params.filePath); -} -#endif - -IniProcessing::IniProcessing(char *memory, size_t size): - m_params{"", false, -1, ERR_OK, false, params::IniSections(), nullptr, ""} -{ - openMem(memory, size); -} - -IniProcessing::IniProcessing(const IniProcessing &ip) : - m_params(ip.m_params) -{} - -bool IniProcessing::open(const std::string &iniFileName) -{ - std::setlocale(LC_NUMERIC, "C"); - - if(!iniFileName.empty()) - { - close(); - m_params.errorCode = ERR_OK; - m_params.filePath = iniFileName; - bool res = parseFile(m_params.filePath.c_str()); - #ifdef INIDEBUG - - if(res) - printf("\n==========WOOHOO!!!==============\n\n"); - else - printf("\n==========OOOUCH!!!==============\n\n"); - - #endif - m_params.opened = res; - return res; - } - - m_params.errorCode = ERR_NOFILE; - return false; -} - -bool IniProcessing::openMem(char *memory, size_t size) -{ - std::setlocale(LC_NUMERIC, "C"); - - if((memory != nullptr) && (size > 0)) - { - close(); - m_params.errorCode = ERR_OK; - m_params.filePath.clear(); - bool res = parseMemory(memory, size); - m_params.opened = res; - return res; - } - - m_params.errorCode = ERR_NOFILE; - return false; -} - -void IniProcessing::close() -{ - m_params.errorCode = ERR_OK; - m_params.iniData.clear(); - m_params.opened = false; - m_params.lineWithError = -1; -} - -IniProcessing::ErrCode IniProcessing::lastError() -{ - return m_params.errorCode; -} - -int IniProcessing::lineWithError() -{ - return m_params.lineWithError; -} - -bool IniProcessing::isOpened() -{ - return m_params.opened; -} - -bool IniProcessing::beginGroup(const std::string &groupName) -{ - //Keep the group name. If not exist, will be created on value write - m_params.currentGroupName = groupName; - - params::IniSections::iterator e = m_params.iniData.find(groupName); - - if(e == m_params.iniData.end()) - return false; - - params::IniKeys &k = e->second; - m_params.currentGroup = &k; - return true; -} - -bool IniProcessing::contains(const std::string &groupName) -{ - if(!m_params.opened) - return false; - - params::IniSections::iterator e = m_params.iniData.find(groupName); - return (e != m_params.iniData.end()); -} - -std::string IniProcessing::fileName() -{ - return m_params.filePath; -} - -std::string IniProcessing::group() -{ - return m_params.currentGroupName; -} - -std::vector<std::string> IniProcessing::childGroups() -{ - std::vector<std::string> groups; - groups.reserve(m_params.iniData.size()); - for(params::IniSections::iterator e = m_params.iniData.begin(); - e != m_params.iniData.end(); - e++) - { - groups.push_back(e->first); - } - return groups; -} - -bool IniProcessing::hasKey(const std::string &keyName) -{ - if(!m_params.opened) - return false; - - if(!m_params.currentGroup) - return false; - - params::IniKeys::iterator e = m_params.currentGroup->find(keyName); - return (e != m_params.currentGroup->end()); -} - -std::vector<std::string> IniProcessing::allKeys() -{ - std::vector<std::string> keys; - if(!m_params.opened) - return keys; - if(!m_params.currentGroup) - return keys; - - keys.reserve(m_params.currentGroup->size()); - - for(params::IniKeys::iterator it = m_params.currentGroup->begin(); - it != m_params.currentGroup->end(); - it++) - { - keys.push_back( it->first ); - } - - return keys; -} - -void IniProcessing::endGroup() -{ - m_params.currentGroup = nullptr; - m_params.currentGroupName.clear(); -} - -void IniProcessing::read(const char *key, bool &dest, bool defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - std::string &k = e->second; - size_t i = 0; - size_t ss = std::min(static_cast<size_t>(4ul), k.size()); - char buff[4] = {0, 0, 0, 0}; - const char *pbufi = k.c_str(); - char *pbuff = buff; - - for(; i < ss; i++) - (*pbuff++) = static_cast<char>(std::tolower(*pbufi++)); - - if(ss < 4) - { - if(ss == 0) - { - dest = false; - return; - } - - if(ss == 1) - { - dest = (buff[0] == '1'); - return; - } - - bool isNum = true; - isNum &= std::isdigit(buff[i]) || (buff[i] == '-') || (buff[i] == '+'); - - for(size_t i = 1; i < ss; i++) - isNum &= std::isdigit(buff[i]); - - if(isNum) - { - long num = std::strtol(buff, 0, 0); - dest = num != 0l; - return; - } - else - { - dest = (std::memcmp(buff, "yes", 3) == 0) || - (std::memcmp(buff, "on", 2) == 0); - return; - } - } - - if(std::memcmp(buff, "true", 4) == 0) - { - dest = true; - return; - } - - try - { - long num = std::strtol(buff, 0, 0); - dest = num != 0l; - return; - } - catch(...) - { - dest = false; - return; - } -} - -void IniProcessing::read(const char *key, unsigned char &dest, unsigned char defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - std::string &k = e->second; - - if(k.size() >= 1) - dest = static_cast<unsigned char>(k[0]); - else - dest = defVal; -} - -void IniProcessing::read(const char *key, char &dest, char defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - std::string &k = e->second; - - if(k.size() >= 1) - dest = k[0]; - else - dest = defVal; -} - -void IniProcessing::read(const char *key, unsigned short &dest, unsigned short defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = static_cast<unsigned short>(std::strtoul(e->second.c_str(), nullptr, 0)); -} - -void IniProcessing::read(const char *key, short &dest, short defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = static_cast<short>(std::strtol(e->second.c_str(), nullptr, 0)); -} - -void IniProcessing::read(const char *key, unsigned int &dest, unsigned int defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = static_cast<unsigned int>(std::strtoul(e->second.c_str(), nullptr, 0)); -} - -void IniProcessing::read(const char *key, int &dest, int defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = static_cast<int>(std::strtol(e->second.c_str(), nullptr, 0)); -} - -void IniProcessing::read(const char *key, unsigned long &dest, unsigned long defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = std::strtoul(e->second.c_str(), nullptr, 0); -} - -void IniProcessing::read(const char *key, long &dest, long defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = std::strtol(e->second.c_str(), nullptr, 0); -} - -void IniProcessing::read(const char *key, unsigned long long &dest, unsigned long long defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = std::strtoull(e->second.c_str(), nullptr, 0); -} - -void IniProcessing::read(const char *key, long long &dest, long long defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = std::strtoll(e->second.c_str(), nullptr, 0); -} - -void IniProcessing::read(const char *key, float &dest, float defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - if(!ok) - { - dest = defVal; - return; - } - dest = std::strtof(e->second.c_str(), nullptr); -} - -void IniProcessing::read(const char *key, double &dest, double defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - dest = std::strtod(e->second.c_str(), nullptr); -} - -void IniProcessing::read(const char *key, long double &dest, long double defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - if(!ok) - { - dest = defVal; - return; - } - dest = std::strtold(e->second.c_str(), nullptr); -} - -void IniProcessing::read(const char *key, std::string &dest, const std::string &defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = e->second; -} - -#ifdef INI_PROCESSING_ALLOW_QT_TYPES -void IniProcessing::read(const char *key, QString &dest, const QString &defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - dest = QString::fromStdString(e->second); -} -#endif - -template<class TList> -inline void StrToNumVectorHelper(const std::string &source, TList &dest, const typename TList::value_type &def) -{ - typedef typename TList::value_type T; - dest.clear(); - - if(!source.empty()) - { - std::stringstream ss(source); - std::string item; - while(std::getline(ss, item, ',')) - { - std::remove(item.begin(), item.end(), ' '); - try - { - if(std::is_same<T, int>::value || - std::is_same<T, long>::value || - std::is_same<T, short>::value) - dest.push_back(static_cast<T>(std::strtol(item.c_str(), NULL, 0))); - else if(std::is_same<T, unsigned int>::value || - std::is_same<T, unsigned long>::value || - std::is_same<T, unsigned short>::value) - dest.push_back(static_cast<T>(std::strtoul(item.c_str(), NULL, 0))); - else if(std::is_same<T, float>::value) - dest.push_back(std::strtof(item.c_str(), NULL)); - else - dest.push_back(std::strtod(item.c_str(), NULL)); - } - catch(...) - { - dest.pop_back(); - } - } - - if(dest.empty()) - dest.push_back(def); - } - else - dest.push_back(def); -} - -template<class TList, typename T> -void readNumArrHelper(IniProcessing *self, const char *key, TList &dest, const TList &defVal) -{ - bool ok = false; - IniProcessing::params::IniKeys::iterator e = self->readHelper(key, ok); - - if(!ok) - { - dest = defVal; - return; - } - - StrToNumVectorHelper(e->second, dest, static_cast<T>(0)); -} - -void IniProcessing::read(const char *key, std::vector<unsigned short> &dest, const std::vector<unsigned short> &defVal) -{ - readNumArrHelper<std::vector<unsigned short>, unsigned short>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<short> &dest, const std::vector<short> &defVal) -{ - readNumArrHelper<std::vector<short>, short>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<unsigned int> &dest, const std::vector<unsigned int> &defVal) -{ - readNumArrHelper<std::vector<unsigned int>, unsigned int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<int> &dest, const std::vector<int> &defVal) -{ - readNumArrHelper<std::vector<int>, int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<unsigned long> &dest, const std::vector<unsigned long> &defVal) -{ - readNumArrHelper<std::vector<unsigned long>, unsigned long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<long> &dest, const std::vector<long> &defVal) -{ - readNumArrHelper<std::vector<long>, long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<unsigned long long> &dest, const std::vector<unsigned long long> &defVal) -{ - readNumArrHelper<std::vector<unsigned long long>, unsigned long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<long long> &dest, const std::vector<long long> &defVal) -{ - readNumArrHelper<std::vector<long long>, long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<float> &dest, const std::vector<float> &defVal) -{ - readNumArrHelper<std::vector<float>, float>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, std::vector<double> &dest, const std::vector<double> &defVal) -{ - readNumArrHelper<std::vector<double>, double>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, std::vector<long double> &dest, const std::vector<long double> &defVal) -{ - readNumArrHelper<std::vector<long double>, long double>(this, key, dest, defVal); -} - -#ifdef INI_PROCESSING_ALLOW_QT_TYPES -void IniProcessing::read(const char *key, QList<short> &dest, const QList<short> &defVal) -{ - readNumArrHelper<QList<short>, short>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, QList<unsigned short> &dest, const QList<unsigned short> &defVal) -{ - readNumArrHelper<QList<unsigned short>, unsigned short>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, QList<int> &dest, const QList<int> &defVal) -{ - readNumArrHelper<QList<int>, int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<unsigned int> &dest, const QList<unsigned int> &defVal) -{ - readNumArrHelper<QList<unsigned int>, unsigned int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<long> &dest, const QList<long> &defVal) -{ - readNumArrHelper<QList<long>, long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<unsigned long> &dest, const QList<unsigned long> &defVal) -{ - readNumArrHelper<QList<unsigned long>, unsigned long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<long long> &dest, const QList<long long> &defVal) -{ - readNumArrHelper<QList<long long>, long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<unsigned long long> &dest, const QList<unsigned long long> &defVal) -{ - readNumArrHelper<QList<unsigned long long>, unsigned long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<float> &dest, const QList<float> &defVal) -{ - readNumArrHelper<QList<float>, float>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QList<double> &dest, const QList<double> &defVal) -{ - readNumArrHelper<QList<double>, double>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, QList<long double> &dest, const QList<long double> &defVal) -{ - readNumArrHelper<QList<long double>, long double>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, QVector<short> &dest, const QVector<short> &defVal) -{ - readNumArrHelper<QVector<short>, short>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<unsigned short> &dest, const QVector<unsigned short> &defVal) -{ - readNumArrHelper<QVector<unsigned short>, unsigned short>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<int> &dest, const QVector<int> &defVal) -{ - readNumArrHelper<QVector<int>, int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<unsigned int> &dest, const QVector<unsigned int> &defVal) -{ - readNumArrHelper<QVector<unsigned int>, unsigned int>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<long> &dest, const QVector<long> &defVal) -{ - readNumArrHelper<QVector<long>, long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<unsigned long> &dest, const QVector<unsigned long> &defVal) -{ - readNumArrHelper<QVector<unsigned long>, unsigned long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<long long> &dest, const QVector<long long> &defVal) -{ - readNumArrHelper<QVector<long long>, long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<unsigned long long> &dest, const QVector<unsigned long long> &defVal) -{ - readNumArrHelper<QVector<unsigned long long>, unsigned long long>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<float> &dest, const QVector<float> &defVal) -{ - readNumArrHelper<QVector<float>, float>(this, key, dest, defVal); -} -void IniProcessing::read(const char *key, QVector<double> &dest, const QVector<double> &defVal) -{ - readNumArrHelper<QVector<double>, double>(this, key, dest, defVal); -} - -void IniProcessing::read(const char *key, QVector<long double> &dest, const QVector<long double> &defVal) -{ - readNumArrHelper<QVector<long double>, long double>(this, key, dest, defVal); -} -#endif - -IniProcessingVariant IniProcessing::value(const char *key, const IniProcessingVariant &defVal) -{ - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - - if(!ok) - return defVal; - - std::string &k = e->second; - return IniProcessingVariant(&k); -} - -void IniProcessing::writeIniParam(const char *key, const std::string &value) -{ - if(m_params.currentGroupName.empty()) - return; - - bool ok = false; - params::IniKeys::iterator e = readHelper(key, ok); - if(ok) - { - e->second = value; - } - else - { - if(!m_params.currentGroup) - { - m_params.iniData.insert({m_params.currentGroupName, params::IniKeys()}); - m_params.currentGroup = &m_params.iniData[m_params.currentGroupName]; - } - m_params.currentGroup->insert({std::string(key), value}); - //Mark as opened - m_params.opened = true; - } -} - -void IniProcessing::setValue(const char *key, unsigned short value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, short value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, unsigned int value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, int value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, unsigned long value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, long value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, unsigned long long value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, long long value) -{ - writeIniParam(key, std::to_string(value)); -} - -void IniProcessing::setValue(const char *key, float value) -{ - writeIniParam(key, IniProcessing::to_string_with_precision(value)); -} - -void IniProcessing::setValue(const char *key, double value) -{ - writeIniParam(key, IniProcessing::to_string_with_precision(value)); -} - -void IniProcessing::setValue(const char *key, long double value) -{ - writeIniParam(key, IniProcessing::to_string_with_precision(value)); -} - -void IniProcessing::setValue(const char *key, const char *value) -{ - writeIniParam(key, value); -} - -void IniProcessing::setValue(const char *key, const std::string &value) -{ - writeIniParam(key, value); -} - -#ifdef INI_PROCESSING_ALLOW_QT_TYPES -void IniProcessing::setValue(const char *key, const QString &value) -{ - writeIniParam(key, value.toStdString()); -} -#endif - -static inline bool isFloatValue(const std::string &str) -{ - enum State - { - ST_SIGN = 0, - ST_DOT, - ST_EXPONENT, - ST_EXPONENT_SIGN, - ST_TAIL - } st = ST_SIGN; - - for(const char &c : str) - { - if(!isdigit(c)) - { - switch(st) - { - case ST_SIGN: - if(c != '-') - return false; - st = ST_DOT; - continue; - case ST_DOT: - if(c != '.') - return false; - else - if((c == 'E') || (c == 'e')) - st = ST_EXPONENT_SIGN; - else - st = ST_EXPONENT; - continue; - case ST_EXPONENT: - if((c != 'E') && (c != 'e')) - return false; - st = ST_EXPONENT_SIGN; - continue; - case ST_EXPONENT_SIGN: - if(c != '-') - return false; - st = ST_TAIL; - continue; - case ST_TAIL: - return false; - } - return false; - } - else - { - if(st == ST_SIGN) - st = ST_DOT; - } - } - return true; -} - -bool IniProcessing::writeIniFile() -{ - #ifdef _WIN32 - //Convert UTF8 file path into UTF16 to support non-ASCII paths on Windows - std::wstring dest; - dest.resize(m_params.filePath.size()); - int newSize = MultiByteToWideChar(CP_UTF8, - 0, - m_params.filePath.c_str(), - dest.size(), - (wchar_t *)dest.c_str(), - dest.size()); - dest.resize(newSize); - FILE *cFile = _wfopen(dest.c_str(), L"wb"); - #else - FILE *cFile = fopen(m_params.filePath.c_str(), "wb"); - #endif - if(!cFile) - return false; - - for(params::IniSections::iterator group = m_params.iniData.begin(); - group != m_params.iniData.end(); - group++) - { - fprintf(cFile, "[%s]\n", group->first.c_str()); - for(params::IniKeys::iterator key = group->second.begin(); - key != group->second.end(); - key++) - { - if(isFloatValue(key->second)) - { - //Store as-is without quoting - fprintf(cFile, "%s = %s\n", key->first.c_str(), key->second.c_str()); - } - else - { - //Set escape quotes and put the string with a quotes - std::string &s = key->second; - std::string escaped; - escaped.reserve(s.length() * 2); - for(char &c : s) - { - switch(c) - { - case '\n': escaped += "\\n"; break; - case '\r': escaped += "\\r"; break; - case '\t': escaped += "\\t"; break; - default: - if((c == '\\') || (c == '"')) - escaped.push_back('\\'); - escaped.push_back(c); - } - } - fprintf(cFile, "%s = \"%s\"\n", key->first.c_str(), escaped.c_str()); - } - } - fprintf(cFile, "\n"); - fflush(cFile); - } - fclose(cFile); - return true; -} - |