SF | Создание Ini файла

ANZR

Известный
Автор темы
168
104
Ох блять, чет я седня дохуя любопытный
Мне нужно создать ini файл для сохранения в них настроек плагина, но загвоздка в том, что перерыв все, я не смог найти нормального варианта сохранения и чтения файла
Если вы знаете способ работы с ini - прошу, пишите сюда
Заранее спасибо​
 
Решение
Делал class лично для себя, для облегчения работы с mINI. Не нужно быть ♂dungeon master♂ чтобы разобраться в его работе, но для настоящих ♂boss of the gym♂ оставил пример по работе с ним.
CConfig.h:
#pragma once
// #include <Windows.h>
#include <iostream>

class CConfig {
public:
    // Инициализация класса
    void Init(std::string iniName);

    /////////// read ///////////

    // Возращает число
    int GetInt(std::string stKey1, std::string stKey2);
    // Возращает дробное число
    float GetFloat(std::string stKey1, std::string stKey2);
    // Возращает true или false
    bool GetBool(std::string stKey1, std::string stKey2);

    // Возращает std::string
    std::string GetString(std::string stKey1, std::string...
У

Удалённый пользователь 123482

Гость

gaZmanoV

Участник
31
3
Делал class лично для себя, для облегчения работы с mINI. Не нужно быть ♂dungeon master♂ чтобы разобраться в его работе, но для настоящих ♂boss of the gym♂ оставил пример по работе с ним.
CConfig.h:
#pragma once
// #include <Windows.h>
#include <iostream>

class CConfig {
public:
    // Инициализация класса
    void Init(std::string iniName);

    /////////// read ///////////

    // Возращает число
    int GetInt(std::string stKey1, std::string stKey2);
    // Возращает дробное число
    float GetFloat(std::string stKey1, std::string stKey2);
    // Возращает true или false
    bool GetBool(std::string stKey1, std::string stKey2);

    // Возращает std::string
    std::string GetString(std::string stKey1, std::string stKey2);
    // Возращает const char*
    const char* GetConstChar(std::string stKey1, std::string stKey2);
    // Возращает char
    char GetChar(std::string stKey1, std::string stKey2);


    /////////// write ///////////

    // Записывает число в ini файл
    void WriteInt(std::string stKey1, std::string stKey2, int iInt);
    // Записывает дробное число в ini файл
    void WriteFloat(std::string stKey1, std::string stKey2, float fFloat);
    // Записывает true или false в ini файл
    void WriteBool(std::string stKey1, std::string stKey2, bool bBool);

    // Записывает std::string в ini файл
    void WriteString(std::string stKey1, std::string stKey2, std::string stString);
    // Записывает const char* в ini файл
    void WriteString(std::string stKey1, std::string stKey2, const char* cnhString);
    // Записывает char в ini файл
    void WriteString(std::string stKey1, std::string stKey2, char chString);
private:
    // Сохраняет ini структуру в файл
    void Save();
    // Загружает ini структуру в переменную
    void Refresh();
};

CConfig.cpp:
#include "CConfig.h"
#include "ini.h"

std::string stIniNameFile;
mINI::INIStructure ini;

void CConfig::Init(std::string iniName) {
    stIniNameFile = iniName;
    this->Refresh();
}

/////// private ////////

void CConfig::Refresh() {
    mINI::INIFile fileInstance(stIniNameFile);
    fileInstance.read(ini);
}

void CConfig::Save() {
    mINI::INIFile fileInstance(stIniNameFile);
    fileInstance.write(ini);
}

/////// public ////////

/////// read ///////

int CConfig::GetInt(std::string stKey1, std::string stKey2) {
    this->Refresh();

    int iReturnInteger = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%d", &iReturnInteger);
  
    if (iErrorCode != EOF && iErrorCode != NULL)
        return iReturnInteger;

    return -1;
}

float CConfig::GetFloat(std::string stKey1, std::string stKey2) {
    this->Refresh();

    float fReturnFloat = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%f", &fReturnFloat);
  
    if (iErrorCode != EOF && iErrorCode != NULL)
        return fReturnFloat;
      
    return -1;
}

bool CConfig::GetBool(std::string stKey1, std::string stKey2) {
    this->Refresh();

    int iReturnBool = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%d", &iReturnBool);
  
    if (iErrorCode != EOF && iErrorCode != NULL)
        if (iReturnBool == 1) return true;
      
    return false;
}

std::string CConfig::GetString(std::string stKey1, std::string stKey2) {
    this->Refresh();

    return ini[stKey1][stKey2];
}

const char* CConfig::GetConstChar(std::string stKey1, std::string stKey2) {
    this->Refresh();

    return ini[stKey1][stKey2].c_str();
}

char CConfig::GetChar(std::string stKey1, std::string stKey2) {
    this->Refresh();
    std::string stGetString = ini[stKey1][stKey2];

    char *chReturnChar;
    strcpy(chReturnChar, stGetString.c_str());

    return *chReturnChar;
}

/////// write ///////
#include <string>

void CConfig::WriteInt(std::string stKey1, std::string stKey2, int iInt) {
    ini[stKey1][stKey2] = std::to_string(iInt);
    this->Save();
}

void CConfig::WriteFloat(std::string stKey1, std::string stKey2, float fFloat) {
    ini[stKey1][stKey2] = std::to_string(fFloat);
    this->Save();
}

void CConfig::WriteBool(std::string stKey1, std::string stKey2, bool bBool) {
    if (bBool)
        ini[stKey1][stKey2] = std::to_string(1);
    else
        ini[stKey1][stKey2] = std::to_string(0);

    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, std::string stString) {
    ini[stKey1][stKey2] = stString;
    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, const char* cnhString) {
    ini[stKey1][stKey2] = cnhString;
    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, char chString) {
    ini[stKey1][stKey2] = chString;
    this->Save();
}

ini.h:
/*
* The MIT License (MIT)
* Copyright (c) 2018 Danijel Durakovic
*
* 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.
*
*/

///////////////////////////////////////////////////////////////////////////////
//
//  /mINI/ v0.9.7
//  An INI file reader and writer for the modern age.
//
///////////////////////////////////////////////////////////////////////////////
//
//  A tiny utility library for manipulating INI files with a straightforward
//  API and a minimal footprint. It conforms to the (somewhat) standard INI
//  format - sections and keys are case insensitive and all leading and
//  trailing whitespace is ignored. Comments are lines that begin with a
//  semicolon. Trailing comments are allowed on section lines.
//
//  Files are read on demand, upon which data is kept in memory and the file
//  is closed. This utility supports lazy writing, which only writes changes
//  and updates to a file and preserves custom formatting and comments. A lazy
//  write invoked by a write() call will read the output file, find what
//  changes have been made and update the file accordingly. If you only need to
//  generate files, use generate() instead. Section and key order is preserved
//  on read, write and insert.
//
///////////////////////////////////////////////////////////////////////////////
//
//  /* BASIC USAGE EXAMPLE: */
//
//  /* read from file */
//  mINI::INIFile file("myfile.ini");
//  mINI::INIStructure ini;
//  file.read(ini);
//
//  /* read value; gets a reference to actual value in the structure.
//     if key or section don't exist, a new empty value will be created */
//  std::string& value = ini["section"]["key"];
//
//  /* read value safely; gets a copy of value in the structure.
//     does not alter the structure */
//  std::string value = ini.get("section").get("key");
//
//  /* set or update values */
//  ini["section"]["key"] = "value";
//
//  /* set multiple values */
//  ini["section2"].set({
//      {"key1", "value1"},
//      {"key2", "value2"}
//  });
//
//  /* write updates back to file, preserving comments and formatting */
//  file.write(ini);
//
//  /* or generate a file (overwrites the original) */
//  file.generate(ini);
//
///////////////////////////////////////////////////////////////////////////////
//
//  Long live the INI file!!!
//
///////////////////////////////////////////////////////////////////////////////

#ifndef MINI_INI_H_
#define MINI_INI_H_

#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <unordered_map>
#include <vector>
#include <memory>
#include <fstream>
#include <sys/stat.h>

namespace mINI
{
    namespace INIStringUtil
    {
        const std::string whitespaceDelimiters = " \t\n\r\f\v";
        inline void trim(std::string& str)
        {
            str.erase(str.find_last_not_of(whitespaceDelimiters) + 1);
            str.erase(0, str.find_first_not_of(whitespaceDelimiters));
        }
#ifndef MINI_CASE_SENSITIVE
        inline void toLower(std::string& str)
        {
            std::transform(str.begin(), str.end(), str.begin(), ::tolower);
        }
#endif
        inline void replace(std::string& str, std::string const& a, std::string const& b)
        {
            if (!a.empty())
            {
                std::size_t pos = 0;
                while ((pos = str.find(a, pos)) != std::string::npos)
                {
                    str.replace(pos, a.size(), b);
                    pos += b.size();
                }
            }
        }
#ifdef _WIN32
        const std::string endl = "\r\n";
#else
        const std::string endl = "\n";
#endif
    };

    template<typename T>
    class INIMap
    {
    private:
        using T_DataIndexMap = std::unordered_map<std::string, std::size_t>;
        using T_DataItem = std::pair<std::string, T>;
        using T_DataContainer = std::vector<T_DataItem>;
        using T_MultiArgs = typename std::vector<std::pair<std::string, T>>;

        T_DataIndexMap dataIndexMap;
        T_DataContainer data;

        inline std::size_t setEmpty(std::string& key)
        {
            std::size_t index = data.size();
            dataIndexMap[key] = index;
            data.emplace_back(key, T());
            return index;
        }

    public:
        using const_iterator = typename T_DataContainer::const_iterator;

        INIMap() { }

        INIMap(INIMap const& other)
        {
            std::size_t data_size = other.data.size();
            for (std::size_t i = 0; i < data_size; ++i)
            {
                auto const& key = other.data[i].first;
                auto const& obj = other.data[i].second;
                data.emplace_back(key, obj);
            }
            dataIndexMap = T_DataIndexMap(other.dataIndexMap);
        }

        T& operator[](std::string key)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            bool hasIt = (it != dataIndexMap.end());
            std::size_t index = (hasIt) ? it->second : setEmpty(key);
            return data[index].second;
        }
        T get(std::string key) const
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it == dataIndexMap.end())
            {
                return T();
            }
            return T(data[it->second].second);
        }
        bool has(std::string key) const
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            return (dataIndexMap.count(key) == 1);
        }
        void set(std::string key, T obj)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it != dataIndexMap.end())
            {
                data[it->second].second = obj;
            }
            else
            {
                dataIndexMap[key] = data.size();
                data.emplace_back(key, obj);
            }
        }
        void set(T_MultiArgs const& multiArgs)
        {
            for (auto const& it : multiArgs)
            {
                auto const& key = it.first;
                auto const& obj = it.second;
                set(key, obj);
            }
        }
        bool remove(std::string key)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it != dataIndexMap.end())
            {
                std::size_t index = it->second;
                data.erase(data.begin() + index);
                dataIndexMap.erase(it);
                for (auto& it2 : dataIndexMap)
                {
                    auto& vi = it2.second;
                    if (vi > index)
                    {
                        vi--;
                    }
                }
                return true;
            }
            return false;
        }
        void clear()
        {
            data.clear();
            dataIndexMap.clear();
        }
        std::size_t size() const
        {
            return data.size();
        }
        const_iterator begin() const { return data.begin(); }
        const_iterator end() const { return data.end(); }
    };

    using INIStructure = INIMap<INIMap<std::string>>;

    namespace INIParser
    {
        using T_ParseValues = std::pair<std::string, std::string>;

        enum class PDataType : char
        {
            PDATA_NONE,
            PDATA_COMMENT,
            PDATA_SECTION,
            PDATA_KEYVALUE,
            PDATA_UNKNOWN
        };

        inline PDataType parseLine(std::string line, T_ParseValues& parseData)
        {
            parseData.first.clear();
            parseData.second.clear();
            INIStringUtil::trim(line);
            if (line.empty())
            {
                return PDataType::PDATA_NONE;
            }
            char firstCharacter = line[0];
            if (firstCharacter == ';')
            {
                return PDataType::PDATA_COMMENT;
            }
            if (firstCharacter == '[')
            {
                auto commentAt = line.find_first_of(';');
                if (commentAt != std::string::npos)
                {
                    line = line.substr(0, commentAt);
                }
                auto closingBracketAt = line.find_last_of(']');
                if (closingBracketAt != std::string::npos)
                {
                    auto section = line.substr(1, closingBracketAt - 1);
                    INIStringUtil::trim(section);
                    parseData.first = section;
                    return PDataType::PDATA_SECTION;
                }
            }
            auto lineNorm = line;
            INIStringUtil::replace(lineNorm, "\\=", "  ");
            auto equalsAt = lineNorm.find_first_of('=');
            if (equalsAt != std::string::npos)
            {
                auto key = line.substr(0, equalsAt);
                INIStringUtil::trim(key);
                INIStringUtil::replace(key, "\\=", "=");
                auto value = line.substr(equalsAt + 1);
                INIStringUtil::trim(value);
                parseData.first = key;
                parseData.second = value;
                return PDataType::PDATA_KEYVALUE;
            }
            return PDataType::PDATA_UNKNOWN;
        }
    };

    class INIReader
    {
    public:
        using T_LineData = std::vector<std::string>;
        using T_LineDataPtr = std::shared_ptr<T_LineData>;

    private:
        std::ifstream fileReadStream;
        T_LineDataPtr lineData;

        T_LineData readFile()
        {
            std::string fileContents;
            fileReadStream.seekg(0, std::ios::end);
            fileContents.resize(fileReadStream.tellg());
            fileReadStream.seekg(0, std::ios::beg);
            std::size_t fileSize = fileContents.size();
            fileReadStream.read(&fileContents[0], fileSize);
            fileReadStream.close();
            T_LineData output;
            if (fileSize == 0)
            {
                return output;
            }
            std::string buffer;
            buffer.reserve(50);
            for (std::size_t i = 0; i < fileSize; ++i)
            {
                char& c = fileContents[i];
                if (c == '\n')
                {
                    output.emplace_back(buffer);
                    buffer.clear();
                    continue;
                }
                if (c != '\0' && c != '\r')
                {
                    buffer += c;
                }
            }
            output.emplace_back(buffer);
            return output;
        }

    public:
        INIReader(std::string const& filename, bool keepLineData = false)
        {
            fileReadStream.open(filename, std::ios::in | std::ios::binary);
            if (keepLineData)
            {
                lineData = std::make_shared<T_LineData>();
            }
        }
        ~INIReader() { }

        bool operator>>(INIStructure& data)
        {
            if (!fileReadStream.is_open())
            {
                return false;
            }
            T_LineData fileLines = readFile();
            std::string section;
            bool inSection = false;
            INIParser::T_ParseValues parseData;
            for (auto const& line : fileLines)
            {
                auto parseResult = INIParser::parseLine(line, parseData);
                if (parseResult == INIParser::PDataType::PDATA_SECTION)
                {
                    inSection = true;
                    data[section = parseData.first];
                }
                else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE)
                {
                    auto const& key = parseData.first;
                    auto const& value = parseData.second;
                    data[section][key] = value;
                }
                if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN)
                {
                    if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection)
                    {
                        continue;
                    }
                    lineData->emplace_back(line);
                }
            }
            return true;
        }
        T_LineDataPtr getLines()
        {
            return lineData;
        }
    };

    class INIGenerator
    {
    private:
        std::ofstream fileWriteStream;

    public:
        bool prettyPrint = false;

        INIGenerator(std::string const& filename)
        {
            fileWriteStream.open(filename, std::ios::out | std::ios::binary);
        }
        ~INIGenerator() { }

        bool operator<<(INIStructure const& data)
        {
            if (!fileWriteStream.is_open())
            {
                return false;
            }
            if (!data.size())
            {
                return true;
            }
            auto it = data.begin();
            for (;;)
            {
                auto const& section = it->first;
                auto const& collection = it->second;
                fileWriteStream
                    << "["
                    << section
                    << "]";
                if (collection.size())
                {
                    fileWriteStream << INIStringUtil::endl;
                    auto it2 = collection.begin();
                    for (;;)
                    {
                        auto key = it2->first;
                        INIStringUtil::replace(key, "=", "\\=");
                        auto value = it2->second;
                        INIStringUtil::trim(value);
                        fileWriteStream
                            << key
                            << ((prettyPrint) ? " = " : "=")
                            << value;
                        if (++it2 == collection.end())
                        {
                            break;
                        }
                        fileWriteStream << INIStringUtil::endl;
                    }
                }
                if (++it == data.end())
                {
                    break;
                }
                fileWriteStream << INIStringUtil::endl;
                if (prettyPrint)
                {
                    fileWriteStream << INIStringUtil::endl;
                }
            }
            return true;
        }
    };

    class INIWriter
    {
    private:
        using T_LineData = std::vector<std::string>;
        using T_LineDataPtr = std::shared_ptr<T_LineData>;

        std::string filename;

        T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original)
        {
            T_LineData output;
            INIParser::T_ParseValues parseData;
            std::string sectionCurrent;
            bool parsingSection = false;
            bool continueToNextSection = false;
            bool discardNextEmpty = false;
            bool writeNewKeys = false;
            std::size_t lastKeyLine = 0;
            for (auto line = lineData->begin(); line != lineData->end(); ++line)
            {
                if (!writeNewKeys)
                {
                    auto parseResult = INIParser::parseLine(*line, parseData);
                    if (parseResult == INIParser::PDataType::PDATA_SECTION)
                    {
                        if (parsingSection)
                        {
                            writeNewKeys = true;
                            parsingSection = false;
                            --line;
                            continue;
                        }
                        sectionCurrent = parseData.first;
                        if (data.has(sectionCurrent))
                        {
                            parsingSection = true;
                            continueToNextSection = false;
                            discardNextEmpty = false;
                            output.emplace_back(*line);
                            lastKeyLine = output.size();
                        }
                        else
                        {
                            continueToNextSection = true;
                            discardNextEmpty = true;
                            continue;
                        }
                    }
                    else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE)
                    {
                        if (continueToNextSection)
                        {
                            continue;
                        }
                        if (data.has(sectionCurrent))
                        {
                            auto& collection = data[sectionCurrent];
                            auto const& key = parseData.first;
                            auto const& value = parseData.second;
                            if (collection.has(key))
                            {
                                auto outputValue = collection[key];
                                if (value == outputValue)
                                {
                                    output.emplace_back(*line);
                                }
                                else
                                {
                                    INIStringUtil::trim(outputValue);
                                    auto lineNorm = *line;
                                    INIStringUtil::replace(lineNorm, "\\=", "  ");
                                    auto equalsAt = lineNorm.find_first_of('=');
                                    auto valueAt = lineNorm.find_first_not_of(
                                        INIStringUtil::whitespaceDelimiters,
                                        equalsAt + 1
                                    );
                                    std::string outputLine = line->substr(0, valueAt);
                                    if (prettyPrint && equalsAt + 1 == valueAt)
                                    {
                                        outputLine += " ";
                                    }
                                    outputLine += outputValue;
                                    output.emplace_back(outputLine);
                                }
                                lastKeyLine = output.size();
                            }
                        }
                    }
                    else
                    {
                        if (discardNextEmpty && line->empty())
                        {
                            discardNextEmpty = false;
                        }
                        else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN)
                        {
                            output.emplace_back(*line);
                        }
                    }
                }
                if (writeNewKeys || std::next(line) == lineData->end())
                {
                    T_LineData linesToAdd;
                    if (data.has(sectionCurrent) && original.has(sectionCurrent))
                    {
                        auto const& collection = data[sectionCurrent];
                        auto const& collectionOriginal = original[sectionCurrent];
                        for (auto const& it : collection)
                        {
                            auto key = it.first;
                            if (collectionOriginal.has(key))
                            {
                                continue;
                            }
                            auto value = it.second;
                            INIStringUtil::replace(key, "=", "\\=");
                            INIStringUtil::trim(value);
                            linesToAdd.emplace_back(
                                key + ((prettyPrint) ? " = " : "=") + value
                            );
                        }
                    }
                    if (!linesToAdd.empty())
                    {
                        output.insert(
                            output.begin() + lastKeyLine,
                            linesToAdd.begin(),
                            linesToAdd.end()
                        );
                    }
                    if (writeNewKeys)
                    {
                        writeNewKeys = false;
                        --line;
                    }
                }
            }
            for (auto const& it : data)
            {
                auto const& section = it.first;
                if (original.has(section))
                {
                    continue;
                }
                if (prettyPrint && output.size() > 0 && !output.back().empty())
                {
                    output.emplace_back();
                }
                output.emplace_back("[" + section + "]");
                auto const& collection = it.second;
                for (auto const& it2 : collection)
                {
                    auto key = it2.first;
                    auto value = it2.second;
                    INIStringUtil::replace(key, "=", "\\=");
                    INIStringUtil::trim(value);
                    output.emplace_back(
                        key + ((prettyPrint) ? " = " : "=") + value
                    );
                }
            }
            return output;
        }

    public:
        bool prettyPrint = false;

        INIWriter(std::string const& filename)
        : filename(filename)
        {
        }
        ~INIWriter() { }

        bool operator<<(INIStructure& data)
        {
            struct stat buf;
            bool fileExists = (stat(filename.c_str(), &buf) == 0);
            if (!fileExists)
            {
                INIGenerator generator(filename);
                generator.prettyPrint = prettyPrint;
                return generator << data;
            }
            INIStructure originalData;
            T_LineDataPtr lineData;
            bool readSuccess = false;
            {
                INIReader reader(filename, true);
                if ((readSuccess = reader >> originalData))
                {
                    lineData = reader.getLines();
                }
            }
            if (!readSuccess)
            {
                return false;
            }
            T_LineData output = getLazyOutput(lineData, data, originalData);
            std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
            if (fileWriteStream.is_open())
            {
                if (output.size())
                {
                    auto line = output.begin();
                    for (;;)
                    {
                        fileWriteStream << *line;
                        if (++line == output.end())
                        {
                            break;
                        }
                        fileWriteStream << INIStringUtil::endl;
                    }
                }
                return true;
            }
            return false;
        }
    };

    class INIFile
    {
    private:
        std::string filename;

    public:
        INIFile(std::string const& filename)
        : filename(filename)
        { }

        ~INIFile() { }

        bool read(INIStructure& data) const
        {
            if (data.size())
            {
                data.clear();
            }
            if (filename.empty())
            {
                return false;
            }
            INIReader reader(filename);
            return reader >> data;
        }
        bool generate(INIStructure const& data, bool pretty = false) const
        {
            if (filename.empty())
            {
                return false;
            }
            INIGenerator generator(filename);
            generator.prettyPrint = pretty;
            return generator << data;
        }
        bool write(INIStructure& data, bool pretty = false) const
        {
            if (filename.empty())
            {
                return false;
            }
            INIWriter writer(filename);
            writer.prettyPrint = pretty;
            return writer << data;
        }
    };
}

#endif // MINI_INI_H_
DLLMain.cpp:
#include "DLLMain.hpp"

CConfig* pConfig;

int WINAPI vExample(void* p)
{
    /*
         Вроде бы, если ini файла нет, то он создаться сам. (но это не точно)
         Полный путь до ini файла вписывать не нужно, а можно просто вписать имя.

         Лучше использовать не ini файл, а реестр.
         Его можно взять тута - https://github.com/KiN4StAt/BulletTracer/tree/master/fast
    */
    pConfig->Init("Example.ini");
    std::cout << "bState = ";
    if (pConfig->GetBool("MAIN", "bState"))
        std::cout << "true" << std::endl;
    else
        std::cout << "false" << std::endl;

    // Далее я думаю ты и сам поймёшь.
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(vExample), hModule, 0, nullptr);
        break;
    }
    }

    return TRUE;
}

DLLMain.hpp:
#include <Windows.h>
#include "CConfig.h"

extern CConfig* pConfig;


Example.ini:
[MAIN]
bState = "1"
 
Последнее редактирование:
  • Bug
Реакции: sc6ut

MeG@LaDo[N] ^_^

Известный
280
316
Делал class лично для себя, для облегчения работы с mINI. Не нужно быть ♂dungeon master♂ чтобы разобраться в его работе, но для настоящих ♂boss of the gym♂ оставил пример по работе с ним.
CConfig.h:
#pragma once
// #include <Windows.h>
#include <iostream>

class CConfig {
public:
    // Инициализация класса
    void Init(std::string iniName);

    /////////// read ///////////

    // Возращает число
    int GetInt(std::string stKey1, std::string stKey2);
    // Возращает дробное число
    float GetFloat(std::string stKey1, std::string stKey2);
    // Возращает true или false
    bool GetBool(std::string stKey1, std::string stKey2);

    // Возращает std::string
    std::string GetString(std::string stKey1, std::string stKey2);
    // Возращает const char*
    const char* GetConstChar(std::string stKey1, std::string stKey2);
    // Возращает char
    char GetChar(std::string stKey1, std::string stKey2);


    /////////// write ///////////

    // Записывает число в ini файл
    void WriteInt(std::string stKey1, std::string stKey2, int iInt);
    // Записывает дробное число в ini файл
    void WriteFloat(std::string stKey1, std::string stKey2, float fFloat);
    // Записывает true или false в ini файл
    void WriteBool(std::string stKey1, std::string stKey2, bool bBool);

    // Записывает std::string в ini файл
    void WriteString(std::string stKey1, std::string stKey2, std::string stString);
    // Записывает const char* в ini файл
    void WriteString(std::string stKey1, std::string stKey2, const char* cnhString);
    // Записывает char в ini файл
    void WriteString(std::string stKey1, std::string stKey2, char chString);
private:
    // Сохраняет ini структуру в файл
    void Save();
    // Загружает ini структуру в переменную
    void Refresh();
};

CConfig.cpp:
#include "CConfig.h"
#include "ini.h"

std::string stIniNameFile;
mINI::INIStructure ini;

void CConfig::Init(std::string iniName) {
    stIniNameFile = iniName;
    this->Refresh();
}

/////// private ////////

void CConfig::Refresh() {
    mINI::INIFile fileInstance(stIniNameFile);
    fileInstance.read(ini);
}

void CConfig::Save() {
    mINI::INIFile fileInstance(stIniNameFile);
    fileInstance.write(ini);
}

/////// public ////////

/////// read ///////

int CConfig::GetInt(std::string stKey1, std::string stKey2) {
    this->Refresh();

    int iReturnInteger = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%d", &iReturnInteger);
 
    if (iErrorCode != EOF && iErrorCode != NULL)
        return iReturnInteger;

    return -1;
}

float CConfig::GetFloat(std::string stKey1, std::string stKey2) {
    this->Refresh();

    float fReturnFloat = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%f", &fReturnFloat);
 
    if (iErrorCode != EOF && iErrorCode != NULL)
        return fReturnFloat;
     
    return -1;
}

bool CConfig::GetBool(std::string stKey1, std::string stKey2) {
    this->Refresh();

    int iReturnBool = NULL;
    int iErrorCode = sscanf(ini[stKey1][stKey2].c_str(), "%d", &iReturnBool);
 
    if (iErrorCode != EOF && iErrorCode != NULL)
        if (iReturnBool == 1) return true;
     
    return false;
}

std::string CConfig::GetString(std::string stKey1, std::string stKey2) {
    this->Refresh();

    return ini[stKey1][stKey2];
}

const char* CConfig::GetConstChar(std::string stKey1, std::string stKey2) {
    this->Refresh();

    return ini[stKey1][stKey2].c_str();
}

char CConfig::GetChar(std::string stKey1, std::string stKey2) {
    this->Refresh();
    std::string stGetString = ini[stKey1][stKey2];

    char *chReturnChar;
    strcpy(chReturnChar, stGetString.c_str());

    return *chReturnChar;
}

/////// write ///////
#include <string>

void CConfig::WriteInt(std::string stKey1, std::string stKey2, int iInt) {
    ini[stKey1][stKey2] = std::to_string(iInt);
    this->Save();
}

void CConfig::WriteFloat(std::string stKey1, std::string stKey2, float fFloat) {
    ini[stKey1][stKey2] = std::to_string(fFloat);
    this->Save();
}

void CConfig::WriteBool(std::string stKey1, std::string stKey2, bool bBool) {
    if (bBool)
        ini[stKey1][stKey2] = std::to_string(1);
    else
        ini[stKey1][stKey2] = std::to_string(0);

    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, std::string stString) {
    ini[stKey1][stKey2] = stString;
    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, const char* cnhString) {
    ini[stKey1][stKey2] = cnhString;
    this->Save();
}

void CConfig::WriteString(std::string stKey1, std::string stKey2, char chString) {
    ini[stKey1][stKey2] = chString;
    this->Save();
}

ini.h:
/*
* The MIT License (MIT)
* Copyright (c) 2018 Danijel Durakovic
*
* 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.
*
*/

///////////////////////////////////////////////////////////////////////////////
//
//  /mINI/ v0.9.7
//  An INI file reader and writer for the modern age.
//
///////////////////////////////////////////////////////////////////////////////
//
//  A tiny utility library for manipulating INI files with a straightforward
//  API and a minimal footprint. It conforms to the (somewhat) standard INI
//  format - sections and keys are case insensitive and all leading and
//  trailing whitespace is ignored. Comments are lines that begin with a
//  semicolon. Trailing comments are allowed on section lines.
//
//  Files are read on demand, upon which data is kept in memory and the file
//  is closed. This utility supports lazy writing, which only writes changes
//  and updates to a file and preserves custom formatting and comments. A lazy
//  write invoked by a write() call will read the output file, find what
//  changes have been made and update the file accordingly. If you only need to
//  generate files, use generate() instead. Section and key order is preserved
//  on read, write and insert.
//
///////////////////////////////////////////////////////////////////////////////
//
//  /* BASIC USAGE EXAMPLE: */
//
//  /* read from file */
//  mINI::INIFile file("myfile.ini");
//  mINI::INIStructure ini;
//  file.read(ini);
//
//  /* read value; gets a reference to actual value in the structure.
//     if key or section don't exist, a new empty value will be created */
//  std::string& value = ini["section"]["key"];
//
//  /* read value safely; gets a copy of value in the structure.
//     does not alter the structure */
//  std::string value = ini.get("section").get("key");
//
//  /* set or update values */
//  ini["section"]["key"] = "value";
//
//  /* set multiple values */
//  ini["section2"].set({
//      {"key1", "value1"},
//      {"key2", "value2"}
//  });
//
//  /* write updates back to file, preserving comments and formatting */
//  file.write(ini);
//
//  /* or generate a file (overwrites the original) */
//  file.generate(ini);
//
///////////////////////////////////////////////////////////////////////////////
//
//  Long live the INI file!!!
//
///////////////////////////////////////////////////////////////////////////////

#ifndef MINI_INI_H_
#define MINI_INI_H_

#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <unordered_map>
#include <vector>
#include <memory>
#include <fstream>
#include <sys/stat.h>

namespace mINI
{
    namespace INIStringUtil
    {
        const std::string whitespaceDelimiters = " \t\n\r\f\v";
        inline void trim(std::string& str)
        {
            str.erase(str.find_last_not_of(whitespaceDelimiters) + 1);
            str.erase(0, str.find_first_not_of(whitespaceDelimiters));
        }
#ifndef MINI_CASE_SENSITIVE
        inline void toLower(std::string& str)
        {
            std::transform(str.begin(), str.end(), str.begin(), ::tolower);
        }
#endif
        inline void replace(std::string& str, std::string const& a, std::string const& b)
        {
            if (!a.empty())
            {
                std::size_t pos = 0;
                while ((pos = str.find(a, pos)) != std::string::npos)
                {
                    str.replace(pos, a.size(), b);
                    pos += b.size();
                }
            }
        }
#ifdef _WIN32
        const std::string endl = "\r\n";
#else
        const std::string endl = "\n";
#endif
    };

    template<typename T>
    class INIMap
    {
    private:
        using T_DataIndexMap = std::unordered_map<std::string, std::size_t>;
        using T_DataItem = std::pair<std::string, T>;
        using T_DataContainer = std::vector<T_DataItem>;
        using T_MultiArgs = typename std::vector<std::pair<std::string, T>>;

        T_DataIndexMap dataIndexMap;
        T_DataContainer data;

        inline std::size_t setEmpty(std::string& key)
        {
            std::size_t index = data.size();
            dataIndexMap[key] = index;
            data.emplace_back(key, T());
            return index;
        }

    public:
        using const_iterator = typename T_DataContainer::const_iterator;

        INIMap() { }

        INIMap(INIMap const& other)
        {
            std::size_t data_size = other.data.size();
            for (std::size_t i = 0; i < data_size; ++i)
            {
                auto const& key = other.data[i].first;
                auto const& obj = other.data[i].second;
                data.emplace_back(key, obj);
            }
            dataIndexMap = T_DataIndexMap(other.dataIndexMap);
        }

        T& operator[](std::string key)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            bool hasIt = (it != dataIndexMap.end());
            std::size_t index = (hasIt) ? it->second : setEmpty(key);
            return data[index].second;
        }
        T get(std::string key) const
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it == dataIndexMap.end())
            {
                return T();
            }
            return T(data[it->second].second);
        }
        bool has(std::string key) const
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            return (dataIndexMap.count(key) == 1);
        }
        void set(std::string key, T obj)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it != dataIndexMap.end())
            {
                data[it->second].second = obj;
            }
            else
            {
                dataIndexMap[key] = data.size();
                data.emplace_back(key, obj);
            }
        }
        void set(T_MultiArgs const& multiArgs)
        {
            for (auto const& it : multiArgs)
            {
                auto const& key = it.first;
                auto const& obj = it.second;
                set(key, obj);
            }
        }
        bool remove(std::string key)
        {
            INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
            INIStringUtil::toLower(key);
#endif
            auto it = dataIndexMap.find(key);
            if (it != dataIndexMap.end())
            {
                std::size_t index = it->second;
                data.erase(data.begin() + index);
                dataIndexMap.erase(it);
                for (auto& it2 : dataIndexMap)
                {
                    auto& vi = it2.second;
                    if (vi > index)
                    {
                        vi--;
                    }
                }
                return true;
            }
            return false;
        }
        void clear()
        {
            data.clear();
            dataIndexMap.clear();
        }
        std::size_t size() const
        {
            return data.size();
        }
        const_iterator begin() const { return data.begin(); }
        const_iterator end() const { return data.end(); }
    };

    using INIStructure = INIMap<INIMap<std::string>>;

    namespace INIParser
    {
        using T_ParseValues = std::pair<std::string, std::string>;

        enum class PDataType : char
        {
            PDATA_NONE,
            PDATA_COMMENT,
            PDATA_SECTION,
            PDATA_KEYVALUE,
            PDATA_UNKNOWN
        };

        inline PDataType parseLine(std::string line, T_ParseValues& parseData)
        {
            parseData.first.clear();
            parseData.second.clear();
            INIStringUtil::trim(line);
            if (line.empty())
            {
                return PDataType::PDATA_NONE;
            }
            char firstCharacter = line[0];
            if (firstCharacter == ';')
            {
                return PDataType::PDATA_COMMENT;
            }
            if (firstCharacter == '[')
            {
                auto commentAt = line.find_first_of(';');
                if (commentAt != std::string::npos)
                {
                    line = line.substr(0, commentAt);
                }
                auto closingBracketAt = line.find_last_of(']');
                if (closingBracketAt != std::string::npos)
                {
                    auto section = line.substr(1, closingBracketAt - 1);
                    INIStringUtil::trim(section);
                    parseData.first = section;
                    return PDataType::PDATA_SECTION;
                }
            }
            auto lineNorm = line;
            INIStringUtil::replace(lineNorm, "\\=", "  ");
            auto equalsAt = lineNorm.find_first_of('=');
            if (equalsAt != std::string::npos)
            {
                auto key = line.substr(0, equalsAt);
                INIStringUtil::trim(key);
                INIStringUtil::replace(key, "\\=", "=");
                auto value = line.substr(equalsAt + 1);
                INIStringUtil::trim(value);
                parseData.first = key;
                parseData.second = value;
                return PDataType::PDATA_KEYVALUE;
            }
            return PDataType::PDATA_UNKNOWN;
        }
    };

    class INIReader
    {
    public:
        using T_LineData = std::vector<std::string>;
        using T_LineDataPtr = std::shared_ptr<T_LineData>;

    private:
        std::ifstream fileReadStream;
        T_LineDataPtr lineData;

        T_LineData readFile()
        {
            std::string fileContents;
            fileReadStream.seekg(0, std::ios::end);
            fileContents.resize(fileReadStream.tellg());
            fileReadStream.seekg(0, std::ios::beg);
            std::size_t fileSize = fileContents.size();
            fileReadStream.read(&fileContents[0], fileSize);
            fileReadStream.close();
            T_LineData output;
            if (fileSize == 0)
            {
                return output;
            }
            std::string buffer;
            buffer.reserve(50);
            for (std::size_t i = 0; i < fileSize; ++i)
            {
                char& c = fileContents[i];
                if (c == '\n')
                {
                    output.emplace_back(buffer);
                    buffer.clear();
                    continue;
                }
                if (c != '\0' && c != '\r')
                {
                    buffer += c;
                }
            }
            output.emplace_back(buffer);
            return output;
        }

    public:
        INIReader(std::string const& filename, bool keepLineData = false)
        {
            fileReadStream.open(filename, std::ios::in | std::ios::binary);
            if (keepLineData)
            {
                lineData = std::make_shared<T_LineData>();
            }
        }
        ~INIReader() { }

        bool operator>>(INIStructure& data)
        {
            if (!fileReadStream.is_open())
            {
                return false;
            }
            T_LineData fileLines = readFile();
            std::string section;
            bool inSection = false;
            INIParser::T_ParseValues parseData;
            for (auto const& line : fileLines)
            {
                auto parseResult = INIParser::parseLine(line, parseData);
                if (parseResult == INIParser::PDataType::PDATA_SECTION)
                {
                    inSection = true;
                    data[section = parseData.first];
                }
                else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE)
                {
                    auto const& key = parseData.first;
                    auto const& value = parseData.second;
                    data[section][key] = value;
                }
                if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN)
                {
                    if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection)
                    {
                        continue;
                    }
                    lineData->emplace_back(line);
                }
            }
            return true;
        }
        T_LineDataPtr getLines()
        {
            return lineData;
        }
    };

    class INIGenerator
    {
    private:
        std::ofstream fileWriteStream;

    public:
        bool prettyPrint = false;

        INIGenerator(std::string const& filename)
        {
            fileWriteStream.open(filename, std::ios::out | std::ios::binary);
        }
        ~INIGenerator() { }

        bool operator<<(INIStructure const& data)
        {
            if (!fileWriteStream.is_open())
            {
                return false;
            }
            if (!data.size())
            {
                return true;
            }
            auto it = data.begin();
            for (;;)
            {
                auto const& section = it->first;
                auto const& collection = it->second;
                fileWriteStream
                    << "["
                    << section
                    << "]";
                if (collection.size())
                {
                    fileWriteStream << INIStringUtil::endl;
                    auto it2 = collection.begin();
                    for (;;)
                    {
                        auto key = it2->first;
                        INIStringUtil::replace(key, "=", "\\=");
                        auto value = it2->second;
                        INIStringUtil::trim(value);
                        fileWriteStream
                            << key
                            << ((prettyPrint) ? " = " : "=")
                            << value;
                        if (++it2 == collection.end())
                        {
                            break;
                        }
                        fileWriteStream << INIStringUtil::endl;
                    }
                }
                if (++it == data.end())
                {
                    break;
                }
                fileWriteStream << INIStringUtil::endl;
                if (prettyPrint)
                {
                    fileWriteStream << INIStringUtil::endl;
                }
            }
            return true;
        }
    };

    class INIWriter
    {
    private:
        using T_LineData = std::vector<std::string>;
        using T_LineDataPtr = std::shared_ptr<T_LineData>;

        std::string filename;

        T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original)
        {
            T_LineData output;
            INIParser::T_ParseValues parseData;
            std::string sectionCurrent;
            bool parsingSection = false;
            bool continueToNextSection = false;
            bool discardNextEmpty = false;
            bool writeNewKeys = false;
            std::size_t lastKeyLine = 0;
            for (auto line = lineData->begin(); line != lineData->end(); ++line)
            {
                if (!writeNewKeys)
                {
                    auto parseResult = INIParser::parseLine(*line, parseData);
                    if (parseResult == INIParser::PDataType::PDATA_SECTION)
                    {
                        if (parsingSection)
                        {
                            writeNewKeys = true;
                            parsingSection = false;
                            --line;
                            continue;
                        }
                        sectionCurrent = parseData.first;
                        if (data.has(sectionCurrent))
                        {
                            parsingSection = true;
                            continueToNextSection = false;
                            discardNextEmpty = false;
                            output.emplace_back(*line);
                            lastKeyLine = output.size();
                        }
                        else
                        {
                            continueToNextSection = true;
                            discardNextEmpty = true;
                            continue;
                        }
                    }
                    else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE)
                    {
                        if (continueToNextSection)
                        {
                            continue;
                        }
                        if (data.has(sectionCurrent))
                        {
                            auto& collection = data[sectionCurrent];
                            auto const& key = parseData.first;
                            auto const& value = parseData.second;
                            if (collection.has(key))
                            {
                                auto outputValue = collection[key];
                                if (value == outputValue)
                                {
                                    output.emplace_back(*line);
                                }
                                else
                                {
                                    INIStringUtil::trim(outputValue);
                                    auto lineNorm = *line;
                                    INIStringUtil::replace(lineNorm, "\\=", "  ");
                                    auto equalsAt = lineNorm.find_first_of('=');
                                    auto valueAt = lineNorm.find_first_not_of(
                                        INIStringUtil::whitespaceDelimiters,
                                        equalsAt + 1
                                    );
                                    std::string outputLine = line->substr(0, valueAt);
                                    if (prettyPrint && equalsAt + 1 == valueAt)
                                    {
                                        outputLine += " ";
                                    }
                                    outputLine += outputValue;
                                    output.emplace_back(outputLine);
                                }
                                lastKeyLine = output.size();
                            }
                        }
                    }
                    else
                    {
                        if (discardNextEmpty && line->empty())
                        {
                            discardNextEmpty = false;
                        }
                        else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN)
                        {
                            output.emplace_back(*line);
                        }
                    }
                }
                if (writeNewKeys || std::next(line) == lineData->end())
                {
                    T_LineData linesToAdd;
                    if (data.has(sectionCurrent) && original.has(sectionCurrent))
                    {
                        auto const& collection = data[sectionCurrent];
                        auto const& collectionOriginal = original[sectionCurrent];
                        for (auto const& it : collection)
                        {
                            auto key = it.first;
                            if (collectionOriginal.has(key))
                            {
                                continue;
                            }
                            auto value = it.second;
                            INIStringUtil::replace(key, "=", "\\=");
                            INIStringUtil::trim(value);
                            linesToAdd.emplace_back(
                                key + ((prettyPrint) ? " = " : "=") + value
                            );
                        }
                    }
                    if (!linesToAdd.empty())
                    {
                        output.insert(
                            output.begin() + lastKeyLine,
                            linesToAdd.begin(),
                            linesToAdd.end()
                        );
                    }
                    if (writeNewKeys)
                    {
                        writeNewKeys = false;
                        --line;
                    }
                }
            }
            for (auto const& it : data)
            {
                auto const& section = it.first;
                if (original.has(section))
                {
                    continue;
                }
                if (prettyPrint && output.size() > 0 && !output.back().empty())
                {
                    output.emplace_back();
                }
                output.emplace_back("[" + section + "]");
                auto const& collection = it.second;
                for (auto const& it2 : collection)
                {
                    auto key = it2.first;
                    auto value = it2.second;
                    INIStringUtil::replace(key, "=", "\\=");
                    INIStringUtil::trim(value);
                    output.emplace_back(
                        key + ((prettyPrint) ? " = " : "=") + value
                    );
                }
            }
            return output;
        }

    public:
        bool prettyPrint = false;

        INIWriter(std::string const& filename)
        : filename(filename)
        {
        }
        ~INIWriter() { }

        bool operator<<(INIStructure& data)
        {
            struct stat buf;
            bool fileExists = (stat(filename.c_str(), &buf) == 0);
            if (!fileExists)
            {
                INIGenerator generator(filename);
                generator.prettyPrint = prettyPrint;
                return generator << data;
            }
            INIStructure originalData;
            T_LineDataPtr lineData;
            bool readSuccess = false;
            {
                INIReader reader(filename, true);
                if ((readSuccess = reader >> originalData))
                {
                    lineData = reader.getLines();
                }
            }
            if (!readSuccess)
            {
                return false;
            }
            T_LineData output = getLazyOutput(lineData, data, originalData);
            std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
            if (fileWriteStream.is_open())
            {
                if (output.size())
                {
                    auto line = output.begin();
                    for (;;)
                    {
                        fileWriteStream << *line;
                        if (++line == output.end())
                        {
                            break;
                        }
                        fileWriteStream << INIStringUtil::endl;
                    }
                }
                return true;
            }
            return false;
        }
    };

    class INIFile
    {
    private:
        std::string filename;

    public:
        INIFile(std::string const& filename)
        : filename(filename)
        { }

        ~INIFile() { }

        bool read(INIStructure& data) const
        {
            if (data.size())
            {
                data.clear();
            }
            if (filename.empty())
            {
                return false;
            }
            INIReader reader(filename);
            return reader >> data;
        }
        bool generate(INIStructure const& data, bool pretty = false) const
        {
            if (filename.empty())
            {
                return false;
            }
            INIGenerator generator(filename);
            generator.prettyPrint = pretty;
            return generator << data;
        }
        bool write(INIStructure& data, bool pretty = false) const
        {
            if (filename.empty())
            {
                return false;
            }
            INIWriter writer(filename);
            writer.prettyPrint = pretty;
            return writer << data;
        }
    };
}

#endif // MINI_INI_H_
DLLMain.cpp:
#include "DLLMain.hpp"

CConfig* pConfig;

int WINAPI vExample(void* p)
{
    /*
         Вроде бы, если ini файла нет, то он создаться сам. (но это не точно)
         Полный путь до ini файла вписывать не нужно, а можно просто вписать имя.

         Лучше использовать не ini файл, а реестр.
         Его можно взять тута - https://github.com/KiN4StAt/BulletTracer/tree/master/fast
    */
    pConfig->Init("Example.ini");
    std::cout << "bState = ";
    if (pConfig->GetBool("MAIN", "bState"))
        std::cout << "true" << std::endl;
    else
        std::cout << "false" << std::endl;

    // Далее я думаю ты и сам поймёшь.
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(vExample), hModule, 0, nullptr);
        break;
    }
    }

    return TRUE;
}

DLLMain.hpp:
#include <Windows.h>
#include "CConfig.h"

extern CConfig* pConfig;


Example.ini:
[MAIN]
bState = "1"

pMozze скинул выше вариант,и без лишних марок​

 

gaZmanoV

Участник
31
3

pMozze скинул выше вариант,и без лишних марок​

Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
 
Последнее редактирование:

ANZR

Известный
Автор темы
168
104
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
Ну твой вариант лучше тем, что ты можешь получить разные типы данных с ini файла. На том примере, что мне скинули первом, мне пришлось изрядно повозиться, чтоб получить булево значение, но все таки все работает
Также, можешь получить значение ключа без указателей, как в первом варианте
Тут да, с тобой соглашусь, но для меня было приятностью просто посидеть и поразмыслить о том, как все работает
За пример спасибо, в дальнейших проектах буду юзать твой вариант
Пока обойдусь тем, что мне сначала скинули
 

sc6ut

неизвестный
Модератор
382
1,075
Последнее редактирование:
  • Нравится
Реакции: gaZmanoV

Dark_Knight

Me, me and me.
Друг
4,062
2,077

MeG@LaDo[N] ^_^

Известный
280
316
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
пиздец ты мне тут расписал.А если нужен пример то вот
1616952039050.png

1616952075734.png
 
Последнее редактирование:
  • Bug
Реакции: Dark_Knight

Dark_Knight

Me, me and me.
Друг
4,062
2,077

sc6ut

неизвестный
Модератор
382
1,075
а вот как именно true и false
читать
C++:
bool IniFile::getBool( const std::string &section, const std::string &key ) const {
    if ( !this->fileExists() ) return false;
    char string[0x1000];
    if ( GetPrivateProfileString( section.c_str(), key.c_str(), NULL, string, 0x1000, this->_iniFilePath.c_str() ) )
        return 0 == _strcmpi( string, "true" );
    return false;
}
писать
C++:
void IniFile::setBool( const std::string &section, const std::string &key, const bool value ) const {
    if ( !this->fileExists() ) this->createFile();
    WritePrivateProfileString( section.c_str(), key.c_str(), ( value ? "true" : "false" ), this->_iniFilePath.c_str() );
}
 
Последнее редактирование:
  • Нравится
Реакции: MeG@LaDo[N] ^_^

ANZR

Известный
Автор темы
168
104
читать
C++:
bool IniFile::getBool( const std::string &section, const std::string &key ) const {
    if ( !this->fileExists() ) return false;
    char string[0x1000];
    if ( GetPrivateProfileString( section.c_str(), key.c_str(), NULL, string, 0x1000, this->_ini_file_path.c_str() ) )
        return 0 == _strcmpi( string, "true" );
    return false;
}
писать
C++:
void IniFile::setBool( const std::string &section, const std::string &key, const bool value ) const {
    if ( !this->fileExists() ) this->createFile();
    WritePrivateProfileString( section.c_str(), key.c_str(), ( value ? "true" : "false" ), this->_ini_file_path.c_str() );
}
Во бля, за _strcmpi отдельная благодарочка
Чет я запамятовал за эту функцию