当前位置: 首页 > news >正文

Win32 / C++ ini配置文件解析类(支持简易加解密)

Win32 api 的 ini 读写每次都是解析整个文件, 如果需要大量操作, 那么性能将会比较差, 于是实现了一个ini解析类,  支持自适应 utf-8, utf16, ansi 编码, 此外, 也可以简单进行数据加解密, 如果不想让比尔看到明文配置的话.

CIniHelperX.h

#pragma once

#include <string>
#include <tchar.h>
#include <vector>
#include <windows.h>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

using _tstring_list = std::vector<_tstring>;

typedef struct _INI_CFG_VALUE
{
    _tstring ValueName;             // 值名
    _tstring ValueNameRaw;          // 原始值名
    _tstring ValueData;             // 值数据
    _tstring ValueDataRaw;          // 原始值数据
    _tstring_list ValueComment;     // 注释

    _INI_CFG_VALUE(const _tstring& name = _T(""), const _tstring& content = _T(""), const std::vector<_tstring>& comment = {})
        :
        ValueName(name),
        ValueData(content),
        ValueComment(comment)
    {

    }

    bool operator == (const _INI_CFG_VALUE& r) const
    {
        return this->ValueName == r.ValueName;
    }

}INI_CFG_VALUE;

using INI_VALUE_LIST = std::vector<INI_CFG_VALUE>;

typedef struct _INI_CFG_SECTION
{
    _tstring SectionName;           // 值名
    _tstring SrctionNameRaw;        // 原始值名
    _tstring_list SectionComment;   // 注释
    INI_VALUE_LIST ValueList;       // 值列表

    _INI_CFG_SECTION(const _tstring& name = _T(""), const INI_VALUE_LIST& value = {}, const std::vector<_tstring>& comment = {})
        :
        SectionName(name),
        ValueList(value),
        SectionComment(comment)
    {

    }

    bool operator == (const _INI_CFG_SECTION& r) const
    {
        return this->SectionName == r.SectionName;
    }

}INI_CFG_SECTION;

using INI_SECTION_LIST = std::vector<INI_CFG_SECTION>;

// 文本编码
enum eTextEncoding
{
    eTextAuto,              // 自动识别
    eTextAnsi,              // Ansi编码
    eTextUtf8,              // UTF-8
    eTextUtf8BOM,           // UTF-8 带字节序
    eTextUtf16LEBOM,        // UTF16 小端字节序
    eTextUtf16BEBOM         // UTF16 大端字节序
};

// Ini配置辅助类
class CIniHelperX
{
public:

    CIniHelperX(const _tstring& strPath = _T(""), bool fLoad = true, bool fAutoSave = false, bool fEncrypt = false);
    ~CIniHelperX();

    // 加载
    bool Load();
    bool LoadFromFile(const _tstring& strFileName);

    // 保存
    bool Save(eTextEncoding enc = eTextEncoding::eTextAuto);
    bool SaveToFile(const _tstring& strFileName, eTextEncoding enc = eTextEncoding::eTextAuto);

    // 清空
    void Clear();

    // 是否自动加密
    bool IsEncrypt() const;

    // 设置自动加密
    void SetEncrypt(bool fEnable = true);

    // 是否自动保存
    bool IsAutoSave() const;

    // 设置自动保存
    void SetAutoSave(bool fEnable = true);

    // 从数据加载
    bool LoadFromData(LPCVOID lpData, DWORD nSize);

    // 读写字符串
    _tstring GetString(const _tstring& strSec, const _tstring& strKey, const _tstring& strDefault = _T("")) const;
    bool SetString(const _tstring& strSec, const _tstring& strKey, const _tstring& strVal);

    // 读写布尔值
    bool GetBool(const _tstring& strSec, const _tstring& strKey, bool fDefault = false) const;
    bool SetBool(const _tstring& strSec, const _tstring& strKey, bool fValue);

    // 读写整数
    int64_t GetInt(const _tstring& strSec, const _tstring& strKey, int64_t dwDefault = 0, int radix = 10) const;
    bool SetInt(const _tstring& strSec, const _tstring& strKey, int64_t dwNumber, int radix = 10);

    // 读写浮点数
    double GetFloat(const _tstring& strSec, const _tstring& strKey, double dDefault = 0.0f) const;
    bool SetFloat(const _tstring& strSec, const _tstring& strKey, double dNumber);

    // 删除配置节
    bool DeleteSection(const _tstring& strSec);

    // 删除配置值
    bool DeleteValue(const _tstring& strSec, const _tstring& strKey = _T(""));

    // 导出文本
    std::wstring DumpWStr() const;
    std::string DumpAStr() const;
    std::string DumpU8Str() const;
    _tstring Dump() const;

    // 数据是否加密
    virtual bool IsEncrypted(const uint8_t* pData, size_t nSize);

    // 获取加密后数据
    virtual std::vector<uint8_t> GetEncryptData(const uint8_t* pData, size_t nSize);

    // 获取解密后数据
    virtual std::vector<uint8_t> GetDecryptData(const uint8_t* pData, size_t nSize);

private:

    std::vector<_tstring> SplitStringLine(const _tstring& str);
    _tstring _GetTextList(const std::vector<_tstring>& strList) const;
    bool _Parse(const _tstring& strCfg);
    _tstring _Dump(const INI_SECTION_LIST& mapData) const;

private:
    INI_SECTION_LIST m_SectionList;         // 节列表
    _tstring m_strFilePath;                 // 文件路径
    _tstring m_strCRLF;                     // 转行控制符
    std::vector<_tstring> EndTextList;      // 末尾文本
    eTextEncoding m_TextEncoding;           // 文本编码
    bool m_fAutoSave;                       // 自动保存(启用后设置数值时转储到文件)
    bool m_fEncrypt;                        // 加解密
};

CIniHelperX.cpp

#include "CIniHelperX.h"
#include <windows.h>
#include <strsafe.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

#define FROFILE_EXTERN_NAME                     _T(".ini")

// UTF-8 Byte count table
unsigned char g_utf8_bytes_count_table[0x100] = {
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
    0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
    0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
    0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x00,0x00,
};

// UTF-8 Data mask table
unsigned char g_utf8_data_mask_table[0x100] = {
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
    0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
    0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
    0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,
};

#define CRC32_POLY          (0xEDB88320L)           // CRC32标准
#define CRC32_TABLE_SIZE    (256)                   // CRC查询表大小
#define CRC32_BLOCK_SIZE    (1024 * 1024 * 64)      // CRC缓冲块大小

#define ENCRYPTED_ID        (0x20250325)            // 加密文件标识

#define _count_of(_array) (sizeof(_array) / sizeof(_array[0]))

typedef struct _INI_ENCRYPTED_HEADER
{
    uint32_t   magic;       // 加密文件标识
    uint32_t   crc_data;    // 加密后数据校验码
    uint32_t   crc_raw;     // 加密前数据校验码
    uint32_t   data_size;   // 数据大小
    uint8_t    data[0];     // 数据起始
}INI_ENCRYPTED_HEADER, * PINI_ENCRYPTED_HEADER;

static uint32_t g_Crc32Table[CRC32_TABLE_SIZE] = { 0 }; // CRC查询表
static bool g_bInitFlag = false;                        // CRC查询表初始化标记

static void _InitCrc32Table(void);
static uint32_t GetCrc32(const uint8_t* lpData, size_t byteSize);
static uint32_t GetCrc32Data(uint32_t crcInit, const uint8_t* lpData, size_t byteSize);

uint32_t GetCrc32Value(const void* lpData, size_t nSize)
{
    if (!g_bInitFlag)
    {
        _InitCrc32Table();
        g_bInitFlag = true;
    }

    return GetCrc32((uint8_t*)lpData, nSize);
}

uint32_t GetPartCrc32(uint32_t crcInit, const void* lpData, size_t byteSize)
{
    if (0 == byteSize)
    {
        return crcInit;
    }

    if (!g_bInitFlag)
    {
        _InitCrc32Table();
        g_bInitFlag = true;
    }

    return GetCrc32Data(crcInit, (uint8_t*)lpData, byteSize);
}

void _InitCrc32Table(void)
{
    for (uint32_t i = 0; i < _count_of(g_Crc32Table); i++)
    {
        uint32_t crc = i;
        for (int j = 0; j < 8; j++)
        {
            if (crc & 0x00000001L)
                crc = (crc >> 1) ^ CRC32_POLY;
            else
                crc = crc >> 1;
        }
        g_Crc32Table[i] = crc;
    }
}

uint32_t GetCrc32(const uint8_t* lpData, size_t byteSize)
{
    uint32_t dwCrc32 = 0;
    size_t nBlockSize = byteSize > CRC32_BLOCK_SIZE ? CRC32_BLOCK_SIZE : byteSize;
    uint8_t* lpBase = (uint8_t*)lpData;

    while (byteSize > 0)
    {
        dwCrc32 = GetCrc32Data(dwCrc32, lpBase, nBlockSize);
        lpBase += nBlockSize;
        byteSize -= nBlockSize;

        nBlockSize = byteSize > CRC32_BLOCK_SIZE ? CRC32_BLOCK_SIZE : byteSize;
    }

    return dwCrc32;
}

uint32_t GetCrc32Data(uint32_t crcInit, const uint8_t* lpData, size_t byteSize)
{
    uint32_t crc = crcInit ^ 0xffffffff;

    while (byteSize--)
    {
        crc = (crc >> 8) ^ g_Crc32Table[(crc & 0xff) ^ *lpData++];
    }

    return crc ^ 0xffffffff;
}

std::string _WStrToMultiStr(UINT CodePage, const std::wstring& str)
{
    int cbMultiByte = ::WideCharToMultiByte(CodePage, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
    std::string strResult(cbMultiByte, 0);
    size_t nConverted = ::WideCharToMultiByte(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size(), NULL, NULL);
    strResult.resize(nConverted);
    return strResult;
}

std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str)
{
    int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
    std::wstring strResult(cchWideChar, 0);
    size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());
    strResult.resize(nConverted);
    return strResult;
}

std::string WStrToAStr(const std::wstring& str)
{
    return _WStrToMultiStr(CP_ACP, str);
}

std::string WStrToU8Str(const std::wstring& str)
{
    return _WStrToMultiStr(CP_UTF8, str);
}

_tstring WStrToTStr(const std::wstring& str)
{
#ifdef _UNICODE
    return str;
#else
    return _WStrToMultiStr(CP_ACP, str);
#endif
}

std::wstring AStrToWStr(const std::string& str)
{
    return _MultiStrToWStr(CP_ACP, str);
}

std::string AStrToU8Str(const std::string& str)
{
    return WStrToU8Str(AStrToWStr(str));
}

_tstring AStrToTStr(const std::string& str)
{
#ifdef _UNICODE
    return _MultiStrToWStr(CP_ACP, str);
#else
    return str;
#endif
}

std::wstring U8StrToWStr(const std::string& str)
{
    return _MultiStrToWStr(CP_UTF8, str);
}

std::string U8StrToAStr(const std::string& str)
{
    return WStrToAStr(U8StrToWStr(str));
}

_tstring U8StrToTStr(const std::string& str)
{
#ifdef _UNICODE
    return _MultiStrToWStr(CP_UTF8, str);
#else
    return WStrToAStr(U8StrToWStr(str));
#endif
}

std::string TStrToAStr(const _tstring& str)
{
#ifdef _UNICODE
    return _WStrToMultiStr(CP_ACP, str);
#else
    return str;
#endif
}

std::wstring TStrToWStr(const _tstring& str)
{
#ifdef _UNICODE
    return str;
#else
    return AStrToWStr(str);
#endif
}

std::string TStrToU8Str(const _tstring& str)
{
#ifdef _UNICODE
    return WStrToU8Str(str);
#else
    return WStrToU8Str(AStrToWStr(str));
#endif
}

_tstring GetCurrentModulePath()
{
    TCHAR szCurPath[MAX_PATH] = { 0 };
    ::GetModuleFileName(NULL, szCurPath, _countof(szCurPath));

    _tstring strDir = szCurPath;
    return strDir;
}

_tstring GetCurrentModuleDir()
{
    _tstring strDir = GetCurrentModulePath();
    strDir.resize(strDir.find_last_of(_T('\\')));
    return strDir;
}

_tstring GetCurrentModuleName(bool bHasExt/* = false*/)
{
    _tstring strDir = GetCurrentModulePath();
    size_t nIndex = strDir.find_last_of(_T('\\'));
    if (nIndex != _tstring::npos)
    {
        strDir = strDir.substr(nIndex + 1);
    }

    if (!bHasExt)
    {
        nIndex = strDir.find_last_of(_T('.'));
        if (nIndex != _tstring::npos)
        {
            strDir.resize(nIndex);
        }
    }

    return strDir;
}

_tstring GetFileDir(const _tstring& strPath)
{
    _tstring strDir = strPath;
    for (auto& ch : strDir)
    {
        if (_T('/') == ch)
        {
            ch = _T('\\');
        }
    }

    _tstring strResult;
    size_t nIndex = strDir.find_last_of(_T('\\'));
    if (nIndex != _tstring::npos)
    {
        strResult = strDir.substr(0, nIndex);
    }

    return strResult;
}

bool IsDirectory(const _tstring& strPath)
{
    DWORD dwAttr = ::GetFileAttributes(strPath.c_str());
    if (INVALID_FILE_ATTRIBUTES == dwAttr)
    {
        return false;
    }

    return FILE_ATTRIBUTE_DIRECTORY == (FILE_ATTRIBUTE_DIRECTORY & dwAttr);
}

bool CreateDir(const _tstring& strPath)
{
    _tstring strDriver;              //驱动器号, 如 D:
    _tstring strSubPath = strPath;   //路径, 如 Test\1\2\3

    if (strPath.empty())
    {
        return false;
    }

    //获取盘符
    do
    {
        size_t nFindIndex = strPath.find_first_of(':');  //检查是否有驱动器号
        if (nFindIndex == _tstring::npos)
        {
            break;
        }

        strDriver = strPath.substr(0, nFindIndex + 1); //得到驱动器号, 如 D:
        nFindIndex = strPath.find(_T("\\"), nFindIndex);
        if (nFindIndex == _tstring::npos)
        {
            break;
        }

        strSubPath = strPath.substr(nFindIndex + 1); //得到路径, 如 Test\1\2\3
    } while (false);

    _tstring strDestDir;
    size_t nFindBegin = 0;
    size_t nFindIndex = 0;
    do
    {
        nFindIndex = strSubPath.find(_T("\\"), nFindBegin);
        if (nFindIndex != _tstring::npos)
        {
            strDestDir = strSubPath.substr(0, nFindIndex);
            nFindBegin = nFindIndex + 1;
        }
        else
        {
            strDestDir = strSubPath;
        }

        if (!strDriver.empty())
        {
            strDestDir = strDriver + _T("\\") + strDestDir;
        }

        if (!::CreateDirectory(strDestDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != ::GetLastError())
        {
            return false;
        }

    } while (nFindIndex != _tstring::npos);

    return true;
}

int GetUtf8Count(const void* data_ptr, size_t size/* = -1*/)
{
    const uint8_t* data_pos = (const uint8_t*)data_ptr;
    size_t size_count = size;
    uint32_t code_point = 0;
    int32_t byte_count = 0;
    int32_t char_count = 0;
    bool result_flag = true;

    while ((0 != *data_pos) && (0 != size_count))
    {
        uint8_t ch = *data_pos;

        // ASCII 范围
        if (ch < 0x7F)
        {
            code_point = ch;
            char_count++;
        }
        else
        {
            if (0 == byte_count)
            {
                code_point = 0;
                if (ch >= 0xC0)
                {
                    // 获取字符编码字节数
                    byte_count = g_utf8_bytes_count_table[ch];

                    // 获取首字节码点
                    code_point = ch & g_utf8_data_mask_table[ch];

                    if (0 == byte_count)
                    {
                        result_flag = false;
                        break;
                    }

                    byte_count--;
                }
                else
                {
                    result_flag = false;
                    break;
                }
            }
            else
            {
                // 非首字节码点字节掩码检查
                if (0x80 != (ch & 0xC0))
                {
                    result_flag = false;
                    break;
                }

                // 码点组合
                code_point = code_point << 6;
                code_point |= ch & 0x3F;

                byte_count--;

                // 统计字符计数, 忽略字节顺序标记(BOM)
                if ((0 == byte_count) && (0xFEFF != code_point))
                {
                    char_count++;
                }
            }
        }

        data_pos++;

        if (-1 != size_count)
        {
            size_count--;
        }
    }

    if (!result_flag)
    {
        return -1;
    }

    return char_count;
}

int32_t GetUtf16Count(const void* data_ptr, size_t size/* = -1*/, bool* big_endian_ptr = nullptr)
{
    const uint16_t* data_pos = (const uint16_t*)data_ptr;
    size_t size_count = size;
    uint32_t code_point = 0;
    uint16_t code_point_high = 0;
    uint16_t code_point_low = 0;
    uint16_t code_point_tmp = 0;
    int32_t byte_count = 0;
    int32_t char_count = 0;
    bool big_endian_flag = false;
    bool little_endian_flag = false;
    bool result_flag = true;

    if (-1 != size_count)
    {
        if ((size_count < 2) || (0 != (size_count % 2)))
        {
            return -1;
        }
    }

    while ((0 != *data_pos) && (0 != size_count))
    {
        code_point_tmp = *data_pos;

        // 检查字节序
        if (0xFFFE == code_point_tmp || 0xFEFF == code_point_tmp)
        {
            if (0 == byte_count)
            {
                // 小端序
                if (0xFFFE == code_point_tmp)
                {
                    big_endian_flag = true;
                }

                // 大端序
                if (0xFEFF == code_point_tmp)
                {
                    little_endian_flag = true;
                }
            }
            else
            {
                result_flag = false;
                break;
            }

            // 不可能同时存在小端序和大端序
            if (big_endian_flag && little_endian_flag)
            {
                result_flag = false;
                break;
            }

            data_pos++;

            if (-1 != size_count)
            {
                size_count -= 2;
            }

            continue;
        }

        //字节序转换
        if (big_endian_flag)
        {
            code_point_tmp = ((code_point_tmp >> 8) | (code_point_tmp << 8));
        }

        // 代理区检查
        if (!(code_point_tmp >= 0xD800 && code_point_tmp <= 0xDFFF))
        {
            if (code_point_high > 0)
            {
                result_flag = false;
                break;
            }

            code_point = code_point_tmp;
            char_count++;
        }
        else
        {
            if (0 == byte_count)
            {
                // 高位代理(高10位)
                if (code_point_tmp >= 0xD800 && code_point_tmp <= 0xDBFF)
                {
                    code_point_high = (code_point_tmp - 0xD800);
                    byte_count = 1;
                }
                else
                {
                    result_flag = false;
                    break;
                }
            }
            else
            {
                if (1 == byte_count)
                {
                    // 低位代理(低10位)
                    if ((code_point_tmp >= 0xDC00) && (code_point_tmp <= 0xDFFF))
                    {
                        code_point_low = (code_point_tmp - 0xDC00);
                        code_point = 0x10000 + ((uint32_t)code_point_high << 10 | code_point_low);
                        code_point_low = 0;
                        code_point_high = 0;
                    }
                    else
                    {
                        result_flag = false;
                        break;
                    }
                }

                byte_count--;

                if (0 == byte_count)
                {
                    char_count++;
                }
            }
        }

        data_pos++;

        if (-1 != size_count)
        {
            size_count -= 2;
        }
    }

    if (!result_flag)
    {
        return -1;
    }

    if (big_endian_ptr)
    {
        *big_endian_ptr = big_endian_flag;
    }

    return char_count;
}

CIniHelperX::CIniHelperX(const _tstring& strPath/* = _T("")*/, bool fLoad/* = true*/, bool fAutoSave/* = false*/, bool fEncrypt/* = true*/)
    :
    m_strFilePath(GetCurrentModuleDir()),
    m_fAutoSave(fAutoSave),
    m_fEncrypt(fEncrypt),
    m_strCRLF(_T("\r\n")),
    m_TextEncoding(eTextEncoding::eTextUtf8)
{
    m_strFilePath += _T("\\");
    m_strFilePath += GetCurrentModuleName(false);
    m_strFilePath += FROFILE_EXTERN_NAME;

    if (!strPath.empty())
    {
        if (::PathIsRelative(strPath.c_str()))
        {
            m_strFilePath = GetCurrentModuleDir();
            m_strFilePath += _T("\\");
            m_strFilePath += strPath;
        }
        else
        {
            m_strFilePath = strPath;
        }
    }

    if (fLoad)
    {
        Load();
    }
}

CIniHelperX::~CIniHelperX()
{

}

bool CIniHelperX::LoadFromFile(const _tstring& strFileName)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    bool bSuccess = true;

    _tstring strFilePath = strFileName;
    if (strFileName.empty())
    {
        strFilePath += GetCurrentModuleDir();
        strFilePath += _T("\\");
        strFilePath += GetCurrentModuleName(false);
        strFilePath += FROFILE_EXTERN_NAME;
    }

    hFile = ::CreateFile(strFilePath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (INVALID_HANDLE_VALUE == hFile)
    {
        return false;
    }

    m_SectionList.clear();
    LPBYTE lpData = nullptr;
    // 读取文本
    do
    {
        LARGE_INTEGER liSize = { 0 };
        if (!::GetFileSizeEx(hFile, &liSize))
        {
            break;
        }

        lpData = (LPBYTE)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)liSize.QuadPart + 2);
        if (nullptr == lpData)
        {
            break;
        }

        DWORD nBytesToRead = 0;
        if (!::ReadFile(hFile, (LPVOID)lpData, liSize.LowPart, &nBytesToRead, NULL))
        {
            break;
        }

        bSuccess = LoadFromData(lpData, liSize.LowPart);

    } while (false);

    if (nullptr != lpData)
    {
        ::HeapFree(::GetProcessHeap(), 0, (LPVOID)lpData);
    }

    if (INVALID_HANDLE_VALUE != hFile)
    {
        ::CloseHandle(hFile);
    }

    return bSuccess;
}

bool CIniHelperX::Load()
{
    return LoadFromFile(m_strFilePath);
}

bool CIniHelperX::Save(eTextEncoding enc/* = eTextEncoding::eAuto*/)
{
    return SaveToFile(m_strFilePath, enc);
}

void CIniHelperX::Clear()
{
    m_SectionList.clear();
}

bool CIniHelperX::SaveToFile(const _tstring& strFileName, eTextEncoding enc/* = eTextEncoding::eAuto*/)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    bool bSuccess = true;

    _tstring strFilePath = strFileName;
    if (strFileName.empty())
    {
        strFilePath += GetCurrentModuleDir();
        strFilePath += _T("\\");
        strFilePath += GetCurrentModuleName(false);
        strFilePath += FROFILE_EXTERN_NAME;
    }

    do
    {
        std::string strMulBytes;
        std::wstring strWideBytes;
        bool fWideByte = false;

        _tstring strDirectory = GetFileDir(strFilePath);
        if (!IsDirectory(strDirectory))
        {
            CreateDir(strDirectory);
        }

        hFile = ::CreateFile(strFilePath.c_str(),
            GENERIC_WRITE,
            FILE_SHARE_READ,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (INVALID_HANDLE_VALUE == hFile)
        {
            return false;
        }

        if (enc == eTextEncoding::eTextAuto)
        {
            enc = m_TextEncoding;
        }

        if (enc == eTextEncoding::eTextAnsi)
        {
            _tstring strDump = _Dump(m_SectionList);
            strMulBytes += TStrToAStr(strDump);
        }
        else if (enc == eTextEncoding::eTextUtf8)
        {
            _tstring strDump = _Dump(m_SectionList);
            strMulBytes += TStrToU8Str(strDump);
        }
        else if (enc == eTextEncoding::eTextUtf8BOM)
        {
            strMulBytes = "\xEF\xBB\xBF";
            _tstring strDump = _Dump(m_SectionList);
            strMulBytes += TStrToU8Str(strDump);
        }
        else if (enc == eTextEncoding::eTextUtf16LEBOM)
        {
            strWideBytes += wchar_t(0xFEFF);
            _tstring strDump = _Dump(m_SectionList);
            strWideBytes += TStrToWStr(strDump);
            fWideByte = true;
        }
        else if (enc == eTextEncoding::eTextUtf16BEBOM)
        {
            strWideBytes += wchar_t(0xFEFF);
            _tstring strDump = _Dump(m_SectionList);
            strWideBytes += TStrToWStr(strDump);
            fWideByte = true;

            for (auto& ch : strWideBytes)
            {
                ch = ((ch & 0x00FF) << 8) | ((ch & 0xFF00) >> 8);
            }
        }

        if (m_fEncrypt)
        {
            if (fWideByte)
            {
                std::vector<uint8_t> vData = GetEncryptData((uint8_t*)strWideBytes.c_str(), strWideBytes.size() * sizeof(wchar_t));
                bSuccess = ::WriteFile(hFile, vData.data(), vData.size(), nullptr, nullptr);
            }
            else
            {
                std::vector<uint8_t> vData = GetEncryptData((uint8_t*)strMulBytes.c_str(), strMulBytes.size());
                bSuccess = ::WriteFile(hFile, vData.data(), vData.size(), nullptr, nullptr);
            }

            if (!bSuccess)
            {
                break;
            }
        }
        else
        {
            if (fWideByte)
            {
                bSuccess = ::WriteFile(hFile, strWideBytes.data(), strWideBytes.size() * sizeof(wchar_t), nullptr, nullptr);
            }
            else
            {
                bSuccess = ::WriteFile(hFile, strMulBytes.data(), strMulBytes.size(), nullptr, nullptr);
            }

            if (!bSuccess)
            {
                break;
            }
        }

    } while (false);

    if (INVALID_HANDLE_VALUE != hFile)
    {
        ::CloseHandle(hFile);
    }

    return bSuccess;
}

bool CIniHelperX::LoadFromData(LPCVOID lpData, DWORD nSize)
{
    _tstring strContent;
    std::vector<uint8_t> DecryptData;
    uint8_t* pBytesData = (uint8_t*)lpData;
    size_t nDataSize = nSize;
    bool fBigEndian = false;

    if (IsEncrypted((uint8_t*)pBytesData, nSize))
    {
        DecryptData = GetDecryptData((uint8_t*)pBytesData, nDataSize);
        pBytesData = DecryptData.data();
        nDataSize = DecryptData.size();
    }

    // 编码自动转换
    if (GetUtf8Count(pBytesData, nDataSize) >= 0)
    {
        // UTF8 -> UTF16
        std::string strUtf8((const char*)pBytesData, nDataSize);

        m_TextEncoding = eTextEncoding::eTextUtf8;

        // 去除字节序标识
        while (strUtf8.size() >= 3 && (0xEF == (uint8_t)strUtf8[0] && 0xBB == (uint8_t)strUtf8[1] && 0xBF == (uint8_t)strUtf8[2]))
        {
            m_TextEncoding = eTextEncoding::eTextUtf8BOM;
            strUtf8 = strUtf8.substr(3);
        }

        strContent = U8StrToTStr(strUtf8);
    }
    else if (GetUtf16Count(pBytesData, nDataSize, &fBigEndian) >= 0)
    {
        // UTF16 -> Text
        std::wstring strUtf16((const wchar_t*)pBytesData, nDataSize / sizeof(wchar_t));

        m_TextEncoding = eTextEncoding::eTextUtf16LEBOM;
        if (fBigEndian)
        {
            m_TextEncoding = eTextEncoding::eTextUtf16BEBOM;
        }

        if (eTextEncoding::eTextUtf16BEBOM == m_TextEncoding)
        {
            for (auto& ch : strUtf16)
            {
                ch = ((ch & 0x00FF) << 8) | ((ch & 0xFF00) >> 8);
            }
        }

        // 去除字节序标识
        while (!strUtf16.empty() && 0xFEFF == strUtf16[0])
        {
            strUtf16 = strUtf16.substr(1);
        }

        strContent = WStrToTStr(strUtf16);
    }
    else
    {
        m_TextEncoding = eTextEncoding::eTextAnsi;
        std::string strAnsi((const char*)pBytesData, nDataSize);
        strContent = AStrToTStr(strAnsi);
    }

    // 去除字节序标识
    while (!strContent.empty() && 0xFEFF == strContent[0])
    {
        strContent = strContent.substr(1);
    }

    if (!strContent.empty())
    {
        _Parse(strContent);
    }

    return true;
}

std::wstring CIniHelperX::DumpWStr() const
{
    return TStrToWStr(_Dump(m_SectionList));
}

std::string CIniHelperX::DumpAStr() const
{
    return TStrToAStr(_Dump(m_SectionList));
}

std::string CIniHelperX::DumpU8Str() const
{
    return TStrToU8Str(_Dump(m_SectionList));
}

_tstring CIniHelperX::Dump() const
{
    return _Dump(m_SectionList);
}

bool CIniHelperX::IsEncrypt() const
{
    return m_fEncrypt;
}

void CIniHelperX::SetEncrypt(bool fEnable/* = true*/)
{
    m_fEncrypt = fEnable;
}

bool CIniHelperX::IsAutoSave() const
{
    return m_fAutoSave;
}

void CIniHelperX::SetAutoSave(bool fEnable/* = true*/)
{
    m_fAutoSave = fEnable;
}

std::vector<_tstring> CIniHelperX::SplitStringLine(const _tstring& str)
{
    std::vector<_tstring> splitOut;
    m_strCRLF = _T("\r\n");

    if (_tstring::npos != str.find(_T("\r\n")))
    {
        m_strCRLF = _T("\r\n");
    }
    else if (_tstring::npos != str.find(_T("\r")))
    {
        m_strCRLF = _T("\r");
    }
    else if (_tstring::npos != str.find(_T("\n")))
    {
        m_strCRLF = _T("\n");
    }

    size_t iStart = 0;
    size_t iEnd = 0;

    while (_tstring::npos != (iEnd = str.find(m_strCRLF, iEnd)))
    {
        _tstring strLine = str.substr(iStart, iEnd - iStart);
        splitOut.push_back(strLine);
        iEnd += m_strCRLF.size();
        iStart = iEnd;
    }

    if (iStart != iEnd)
    {
        _tstring strLine = str.substr(iStart, iEnd - iStart);
        if (!strLine.empty() && _T('\r') == strLine.back())
        {
            strLine.resize(strLine.size() - 1);
        }

        splitOut.push_back(strLine);
    }

    return splitOut;
}

bool _IsSection(const _tstring& strContent)
{
    if (strContent.empty())
    {
        return false;
    }

    if (((_T('[') == strContent.front() && _T(']') == strContent.back())))
    {
        return true;
    }

    return false;
}

bool _IsComment(const _tstring& strContent)
{
    if (strContent.empty())
    {
        return false;
    }

    if (((_T('#') == strContent[0] || _T(';') == strContent[0])))
    {
        return true;
    }

    return false;
}

_tstring RemoveStringSpaces(_tstring& strValue, bool fLeft, bool fRight)
{
    LPCTSTR lpBegin = strValue.data();
    LPCTSTR lpEnd = strValue.data() + strValue.size();

    if (fLeft)
    {
        while (lpBegin < lpEnd)
        {
            if (_T(' ') == *lpBegin)
            {
                lpBegin++;
            }
            else
            {
                break;
            }
        }
    }

    if (fRight)
    {
        while (lpEnd > lpBegin)
        {
            if (_T(' ') == *(lpEnd - 1))
            {
                lpEnd--;
            }
            else
            {
                break;
            }
        }
    }

    return _tstring(lpBegin, lpEnd - lpBegin);
}

bool CIniHelperX::_Parse(const _tstring& strCfg)
{
    INI_CFG_SECTION iniAppInfo;
    _tstring strSection;
    std::vector<_tstring> vTestLine = SplitStringLine(strCfg);
    std::vector<_tstring> vComment;

    for (auto& item : vTestLine)
    {
        //查找到配置节
        if (_IsSection(item))
        {
            //插入节配置
            if (!strSection.empty())
            {
                iniAppInfo.SectionName = strSection;
                m_SectionList.push_back(iniAppInfo);
                iniAppInfo.ValueList.clear();
            }
            strSection = item.substr(1, item.size() - 2);

            iniAppInfo.SectionName = RemoveStringSpaces(strSection, true, true);
            iniAppInfo.SrctionNameRaw = strSection;
            iniAppInfo.SectionComment = vComment;
            vComment.clear();
        }
        else
        {
            auto itFind = item.find(_T("="));

            // 过滤注释
            if (_tstring::npos == itFind || item.empty() || _IsComment(item))
            {
                vComment.push_back(item);
                continue;
            }

            // 获取原始值名和值数据
            _tstring strRawName = item.substr(0, itFind);
            _tstring strRawValue = item.substr(itFind + 1);

            // 移除值名前后空格
            _tstring strName = RemoveStringSpaces(strRawName, true, true);

            // 移除数据前面空格
            _tstring strValue = RemoveStringSpaces(strRawValue, true, true);

            // 移除值数据前后引号
            if (strValue.size() >= 2)
            {
                // 移除值数据前后单引号
                if (_T('\'') == strValue.front() && _T('\'') == strValue.back())
                {
                    strValue = strValue.substr(1, strValue.size() - 2);
                }
                // 移除值数据前后双引号
                else if (_T('\"') == strValue.front() && _T('\"') == strValue.back())
                {
                    strValue = strValue.substr(1, strValue.size() - 2);
                }
            }

            INI_CFG_VALUE info(strName, strValue, vComment);
            info.ValueNameRaw = strRawName;
            info.ValueDataRaw = strRawValue;
            iniAppInfo.ValueList.push_back(info);
            vComment.clear();
        }
    }

    //插入节配置
    if (!strSection.empty())
    {
        m_SectionList.push_back(iniAppInfo);
    }

    EndTextList = vComment;

    return true;
}

_tstring CIniHelperX::_GetTextList(const std::vector<_tstring>& strList) const
{
    _tstring strResult;
    size_t nCount = strList.size();
    for (const auto& item : strList)
    {
        nCount--;
        if (item.empty() && nCount > 0)
        {
            strResult += m_strCRLF;
        }
        else
        {
            strResult += item;
            if (nCount > 0)
            {
                strResult += m_strCRLF;
            }
        }
    }

    return strResult;
}

_tstring CIniHelperX::_Dump(const INI_SECTION_LIST& mapData) const
{
    std::vector<_tstring> vOutput;

    size_t nCount = 0;
    for (const auto& section : mapData)
    {
        // 节注释
        nCount += section.SectionComment.size();

        // 节名
        nCount++;

        for (const auto& value : section.ValueList)
        {
            // 值注释
            nCount += value.ValueComment.size();

            // 值名 = 值数据
            nCount++;
        }
    }
    nCount += EndTextList.size();

    vOutput.reserve(nCount);

    for (const auto& section : mapData)
    {
        // 节注释
        vOutput.insert(vOutput.end(), section.SectionComment.begin(), section.SectionComment.end());

        // 节名
        vOutput.emplace_back(_T("[") + section.SrctionNameRaw + _T("]"));

        // 值列表
        for (const auto& value : section.ValueList)
        {
            // 值注释
            vOutput.insert(vOutput.end(), value.ValueComment.begin(), value.ValueComment.end());

            // 值名 = 值数据
            vOutput.emplace_back(value.ValueNameRaw + _T("=") + value.ValueDataRaw);
        }
    }
    vOutput.insert(vOutput.end(), EndTextList.begin(), EndTextList.end());

    return _GetTextList(vOutput);
}

_tstring CIniHelperX::GetString(const _tstring& strSec, const _tstring& strKey, const _tstring& strDefault/* = _T("")*/) const
{
    _tstring strText = strDefault;

    auto itSec = std::find(m_SectionList.begin(), m_SectionList.end(), strSec);
    if (itSec != m_SectionList.end())
    {
        auto itValue = std::find(itSec->ValueList.begin(), itSec->ValueList.end(), strKey);
        if (itValue != itSec->ValueList.end())
        {
            strText = itValue->ValueData;
        }
    }

    return strText;
}

bool CIniHelperX::SetString(const _tstring& strSec, const _tstring& strKey, const _tstring& strVal)
{
    auto itSec = std::find(m_SectionList.begin(), m_SectionList.end(), strSec);
    if (itSec != m_SectionList.end())
    {
        auto itValue = std::find(itSec->ValueList.begin(), itSec->ValueList.end(), strKey);
        if (itValue != itSec->ValueList.end())
        {
            itValue->ValueData = strVal;
            itValue->ValueDataRaw = strVal;
        }
        else
        {
            // 修改值, 原始值名与原始值数据也需要修改
            INI_CFG_VALUE value(strKey, strVal);
            value.ValueNameRaw = strKey;
            value.ValueDataRaw = strVal;

            itSec->ValueList.push_back(value);
        }
    }
    else
    {
        // 修改值, 原始值名与原始值数据也需要修改
        INI_CFG_VALUE value(strKey, strVal);
        value.ValueNameRaw = strKey;
        value.ValueDataRaw = strVal;

        // 修改节, 原始节名也需要修改
        INI_CFG_SECTION info(strSec, { value }, {});
        info.SrctionNameRaw = strSec;

        m_SectionList.push_back(info);
    }

    if (m_fAutoSave)
    {
        Save();
    }

    return true;
}

bool CIniHelperX::GetBool(const _tstring& strSec, const _tstring& strKey, bool fDefault/* = false*/) const
{
    return 0 == _tcsicmp(GetString(strSec, strKey, fDefault ? _T("true") : _T("false")).c_str(), _T("true"));
}

bool CIniHelperX::SetBool(const _tstring& strSec, const _tstring& strKey, bool fValue)
{
    return SetString(strSec, strKey, fValue ? _T("true") : _T("false"));
}

int64_t CIniHelperX::GetInt(const _tstring& strSec, const _tstring& strKey, int64_t dwDefault/* = 0*/, int radix/* = 10*/) const
{
    TCHAR szBuf[MAX_PATH] = { 0 };
    ::_i64tot_s(dwDefault, szBuf, _countof(szBuf), radix);
    return(::_tcstoll(GetString(strSec, strKey, szBuf).c_str(), nullptr, radix));
}

bool CIniHelperX::SetInt(const _tstring& strSec, const _tstring& strKey, int64_t dwNumber, int radix/* = 10*/)
{
    TCHAR szBuf[MAX_PATH] = { 0 };
    ::_i64tot_s(dwNumber, szBuf, _countof(szBuf), radix);
    return SetString(strSec, strKey, szBuf);
}

double CIniHelperX::GetFloat(const _tstring& strSec, const _tstring& strKey, double dDefault/* = 0.0f*/) const
{
    TCHAR szBuf[MAX_PATH] = { 0 };
    ::_stprintf_s(szBuf, _countof(szBuf), _T("%g"), dDefault);
    return(::_tcstod(GetString(strSec, strKey, szBuf).c_str(), nullptr));
}

bool CIniHelperX::SetFloat(const _tstring& strSec, const _tstring& strKey, double dNumber)
{
    TCHAR szBuf[MAX_PATH] = { 0 };
    ::_stprintf_s(szBuf, _countof(szBuf), _T("%g"), dNumber);
    return SetString(strSec, strKey, szBuf);
}

bool CIniHelperX::DeleteSection(const _tstring& strSec)
{
    auto itSec = std::find(m_SectionList.begin(), m_SectionList.end(), strSec);
    if (itSec == m_SectionList.end())
    {
        return false;
    }

    m_SectionList.erase(itSec);
    return true;
}

bool CIniHelperX::DeleteValue(const _tstring& strSec, const _tstring& strKey/* = _T("")*/)
{
    auto itSec = std::find(m_SectionList.begin(), m_SectionList.end(), strSec);
    if (itSec == m_SectionList.end())
    {
        return false;
    }

    auto itValue = std::find(itSec->ValueList.begin(), itSec->ValueList.end(), strKey);
    if (itValue == itSec->ValueList.end())
    {
        return false;
    }

    itSec->ValueList.erase(itValue);
    return true;
}

bool CIniHelperX::IsEncrypted(const uint8_t* pData, size_t nSize)
{
    bool fResult = false;

    do
    {
        PINI_ENCRYPTED_HEADER pEnc = (PINI_ENCRYPTED_HEADER)pData;
        if (nSize < sizeof(INI_ENCRYPTED_HEADER))
        {
            break;
        }

        // 检查标识
        if (ENCRYPTED_ID != pEnc->magic)
        {
            break;
        }

        // 检查大小
        if (pEnc->data_size + sizeof(INI_ENCRYPTED_HEADER) != nSize)
        {
            break;
        }

        if (pEnc->crc_data != GetCrc32Value(pEnc->data, pEnc->data_size))
        {
            break;
        }

        fResult = true;

    } while (false);

    return fResult;
}

std::vector<uint8_t> CIniHelperX::GetEncryptData(const uint8_t* pData, size_t nSize)
{
    std::vector<uint8_t> reault;

    do
    {
        if (!pData || (0 == nSize))
        {
            break;
        }

        // 检查是否已经加密过
        if (IsEncrypted(pData, nSize))
        {
            reault.resize(nSize);
            memcpy(reault.data(), pData, nSize);
            return reault;
        }

        // 加密数据
        INI_ENCRYPTED_HEADER ide = { 0 };
        ide.magic = ENCRYPTED_ID;
        ide.data_size = nSize;

        reault.resize(sizeof(INI_ENCRYPTED_HEADER) + nSize);
        PINI_ENCRYPTED_HEADER pEnc = (PINI_ENCRYPTED_HEADER)reault.data();
        memcpy(pEnc, &ide, sizeof(INI_ENCRYPTED_HEADER));
        memcpy(pEnc->data, pData, nSize);

        // 计算加密前数据校验和
        pEnc->crc_raw = GetCrc32Value(pEnc->data, pEnc->data_size);

        // 加密数据
        uint8_t* pBytesData = pEnc->data;
        size_t nBytesSize = pEnc->data_size;
        for (size_t i = 0; i < nBytesSize; i++)
        {
            pBytesData[i] = (pBytesData[i] ^ (uint8_t)(0x80 + i)) + i;
        }

        // 计算加密后数据校验和
        pEnc->crc_data = GetCrc32Value(pEnc->data, pEnc->data_size);

    } while (false);

    return reault;
}

std::vector<uint8_t> CIniHelperX::GetDecryptData(const uint8_t* pData, size_t nSize)
{
    std::vector<uint8_t> reault;

    do
    {
        if (!pData || (0 == nSize))
        {
            break;
        }

        PINI_ENCRYPTED_HEADER pEnc = (PINI_ENCRYPTED_HEADER)pData;
        if (nSize < sizeof(INI_ENCRYPTED_HEADER))
        {
            break;
        }

        // 检查标识
        if (ENCRYPTED_ID != pEnc->magic)
        {
            break;
        }

        // 检查大小
        if (pEnc->data_size + sizeof(INI_ENCRYPTED_HEADER) != nSize)
        {
            break;
        }

        std::vector<uint8_t> vDataBuf(pEnc->data_size);
        memcpy(vDataBuf.data(), pEnc->data, pEnc->data_size);
        uint8_t* pBytesData = vDataBuf.data();
        size_t nBytesSize = vDataBuf.size();

        // 检查加密后数据校验和
        if (pEnc->crc_data != GetCrc32Value(pBytesData, nBytesSize))
        {
            break;
        }

        // 解密数据
        for (size_t i = 0; i < nBytesSize; i++)
        {
            pBytesData[i] = (pBytesData[i] - i) ^ (uint8_t)(0x80 + i);
        }

        // 检查解密后数据校验和
        if (pEnc->crc_raw != GetCrc32Value(pBytesData, nBytesSize))
        {
            break;
        }

        reault = std::move(vDataBuf);

    } while (false);

    return reault;
}

main.cpp

#include <locale.h>
#include <tchar.h>
#include "Win32Utils/CIniHelperX.h"

int _tmain(int argc, LPCTSTR argv[])
{
    setlocale(LC_ALL, "");

    CIniHelperX obj;

    obj.SetString(_T("config"), _T("name"), _T("FlameCyclone"));
    obj.SetInt(_T("config"), _T("age"), 30);
    obj.SetFloat(_T("config"), _T("float"), 3.141592653589793);
    obj.Save();

    obj.SetEncrypt(true);
    obj.SaveToFile(_T("Encrypt.ini"));

    return 0;
}

 

相关文章:

  • 线性代数核心概念与NumPy科学计算实战全解析
  • 鸿蒙学习笔记(1)-文件解读、编写程序、生命周期
  • 汽车高级驾驶辅助系统应用存储MRAM
  • 边缘计算场景下的分布式推理系统架构设计
  • MySQL索引优化最佳实践
  • Python 3.8 Requests 爬虫教程(2025最新版)
  • 递归进阶(用递归改造循环11~20)(1082、1265、1395、1083、1066、1782、1783、1784、1008、1224)
  • 树的深度优先(DFS)和广度优先(BFS)算法
  • Nginx相关漏洞解析
  • Redis 版本演进及主要新特性
  • 常见框架漏洞攻略-Spring篇
  • 拓扑排序(算法基础)
  • 针对信息化软硬件设备:常用询价网站是否够用
  • 【Unity3D脚本与系统设计6】鼠标触摸超时待机实现
  • 全排列 | 下一个排列
  • CSS3学习教程,从入门到精通,CSS3 浮动与清除浮动语法知识点及案例代码(14)
  • 计算机二级:文件操作
  • C语言部分代码
  • 深入理解指针(2)(C语言版)
  • MySQL基本函数
  • 网站备案号被注销什么原因/广州seo网站管理
  • 中国十大货源批发网站/网络运营
  • 广州市企业网站建设/seo zac
  • asp.net建网站/大数据网站
  • 想在微信公众号上做网站链接/自媒体论坛交流推荐
  • 动物摄影网站/百度认证证书