mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
Organized the project files.
And also fixed some bugs.
This commit is contained in:
170
desktopini/desktopini.vcxproj
Normal file
170
desktopini/desktopini.vcxproj
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>desktopini</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalDependencies>shlwapi.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalDependencies>shlwapi.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="filepath.h" />
|
||||
<ClInclude Include="initfile.h" />
|
||||
<ClInclude Include="module.h" />
|
||||
<ClInclude Include="nstring.h" />
|
||||
<ClInclude Include="raii.h" />
|
||||
<ClInclude Include="strcmp.h" />
|
||||
<ClInclude Include="strcode.h" />
|
||||
<ClInclude Include="syncutil.h" />
|
||||
<ClInclude Include="typestrans.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
54
desktopini/desktopini.vcxproj.filters
Normal file
54
desktopini/desktopini.vcxproj.filters
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="filepath.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="initfile.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="module.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nstring.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="raii.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strcmp.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strcode.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="syncutil.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="typestrans.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
871
desktopini/filepath.h
Normal file
871
desktopini/filepath.h
Normal file
@@ -0,0 +1,871 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <shlwapi.h>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include "strcmp.h"
|
||||
#include "version.h"
|
||||
#include "module.h"
|
||||
typedef version S_VERSION;
|
||||
template <typename T> constexpr T Max (T l, T r) { return l > r ? l : r; }
|
||||
template <typename T> constexpr T Max (T l, T m, T r) { return Max (Max (l, r), m); }
|
||||
template <typename T> constexpr T Max (T l, T ml, T mr, T r) { return Max (Max (l, ml), Max (mr, r)); }
|
||||
template <typename CharT> std::basic_string <CharT> replace_substring
|
||||
(
|
||||
const std::basic_string <CharT> &str,
|
||||
const std::basic_string <CharT> &from,
|
||||
const std::basic_string <CharT> &to
|
||||
)
|
||||
{
|
||||
if (from.empty ()) return str;
|
||||
std::basic_string <CharT> result;
|
||||
size_t pos = 0;
|
||||
size_t start_pos;
|
||||
while ((start_pos = str.find (from, pos)) != std::basic_string<CharT>::npos)
|
||||
{
|
||||
result.append (str, pos, start_pos - pos);
|
||||
result.append (to);
|
||||
pos = start_pos + from.length ();
|
||||
}
|
||||
result.append (str, pos, str.length () - pos);
|
||||
return result;
|
||||
}
|
||||
std::string GetProgramRootDirectoryA (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
char path [MAX_PATH];
|
||||
if (GetModuleFileNameA (hModule, path, MAX_PATH))
|
||||
{
|
||||
std::string dir (path);
|
||||
size_t pos = dir.find_last_of ("\\/");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
dir = dir.substr (0, pos);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
std::wstring GetProgramRootDirectoryW (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
wchar_t path [MAX_PATH];
|
||||
if (GetModuleFileNameW (hModule, path, MAX_PATH))
|
||||
{
|
||||
std::wstring dir (path);
|
||||
size_t pos = dir.find_last_of (L"\\/");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
dir = dir.substr (0, pos);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
std::string EnsureTrailingSlash (const std::string &path)
|
||||
{
|
||||
if (path.empty ()) return path; // 空路径直接返回
|
||||
|
||||
char lastChar = path.back ();
|
||||
if (lastChar == '\\' || lastChar == '/')
|
||||
return path; // 已有分隔符,直接返回
|
||||
// 根据系统或原路径格式添加适当的分隔符
|
||||
char separator = (path.find ('/') != std::string::npos) ? '/' : '\\';
|
||||
return path + separator;
|
||||
}
|
||||
std::wstring EnsureTrailingSlash (const std::wstring &path)
|
||||
{
|
||||
if (path.empty ()) return path;
|
||||
|
||||
wchar_t lastChar = path.back ();
|
||||
if (lastChar == L'\\' || lastChar == L'/')
|
||||
return path;
|
||||
|
||||
wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\';
|
||||
return path + separator;
|
||||
}
|
||||
bool IsFileExistsW (LPCWSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsFileExistsA (LPCSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesA (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
|
||||
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
|
||||
bool IsFileExists (const std::string &filePath) { return IsFileExistsA (filePath.c_str ()); }
|
||||
bool IsFileExists (const std::wstring &filePath) { return IsFileExistsW (filePath.c_str ()); }
|
||||
bool IsDirectoryExistsA (LPCSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesA (path);
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsDirectoryExistsW (LPCWSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW (path);
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsDirectoryExists (const std::string &path) { return IsDirectoryExistsA (path.c_str ()); }
|
||||
bool IsDirectoryExists (const std::wstring &path) { return IsDirectoryExistsW (path.c_str ()); }
|
||||
bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); }
|
||||
bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); }
|
||||
bool IsPathExistsW (LPCWSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
|
||||
}
|
||||
bool IsPathExistsA (LPCSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesA (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
|
||||
}
|
||||
bool IsPathExists (const std::string &path) { return IsPathExistsA (path.c_str ()); }
|
||||
bool IsPathExists (const std::wstring &path) { return IsPathExistsW (path.c_str ()); }
|
||||
bool IsPathExists (LPCSTR path) { return IsPathExistsA (path); }
|
||||
bool IsPathExists (LPCWSTR path) { return IsPathExistsW (path); }
|
||||
std::string NormalizePath (const std::string &path)
|
||||
{
|
||||
if (!path.empty () && path.back () == '\\')
|
||||
return path.substr (0, path.size () - 1);
|
||||
return path.c_str ();
|
||||
}
|
||||
std::wstring NormalizePath (const std::wstring &path)
|
||||
{
|
||||
if (!path.empty () && path.back () == L'\\')
|
||||
return path.substr (0, path.size () - 1);
|
||||
return path.c_str ();
|
||||
}
|
||||
std::vector <std::string> EnumSubdirectories (const std::string &directory, bool includeParentPath)
|
||||
{
|
||||
std::vector<std::string> subdirs;
|
||||
std::string normPath = NormalizePath (directory);
|
||||
std::string searchPath = normPath + "\\*";
|
||||
WIN32_FIND_DATAA findData;
|
||||
HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
|
||||
do
|
||||
{
|
||||
// 过滤 "." 和 ".."
|
||||
if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0)
|
||||
continue;
|
||||
// 判断是否为目录
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (includeParentPath)
|
||||
subdirs.push_back (normPath + "\\" + findData.cFileName);
|
||||
else
|
||||
subdirs.push_back (findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileA (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
return subdirs;
|
||||
}
|
||||
std::vector <std::wstring> EnumSubdirectories (const std::wstring &directory, bool includeParentPath)
|
||||
{
|
||||
std::vector<std::wstring> subdirs;
|
||||
std::wstring normPath = NormalizePath (directory);
|
||||
std::wstring searchPath = normPath + L"\\*";
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
|
||||
do
|
||||
{
|
||||
if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0)
|
||||
continue;
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (includeParentPath)
|
||||
subdirs.push_back (normPath + L"\\" + findData.cFileName);
|
||||
else
|
||||
subdirs.push_back (findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
return subdirs;
|
||||
}
|
||||
std::string GetCurrentProgramPathA (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
std::vector <CHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameA (hModule, nullptr, 0)) + 1);
|
||||
GetModuleFileNameA (hModule, buf.data (), buf.capacity ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetCurrentProgramPathW (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameW (hModule, nullptr, 0)) + 1);
|
||||
GetModuleFileNameW (hModule, buf.data (), buf.capacity ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::string GetCurrentProgramNameA (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameA (GetCurrentProgramPathA (hModule).c_str ()); }
|
||||
std::wstring GetCurrentProgramNameW (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameW (GetCurrentProgramPathW (hModule).c_str ()); }
|
||||
S_VERSION GetExeFileVersion (LPCSTR lpszFilePath)
|
||||
{
|
||||
S_VERSION ver (0);
|
||||
DWORD dummy;
|
||||
DWORD size = GetFileVersionInfoSizeA (lpszFilePath, &dummy);
|
||||
std::vector <BYTE> pVersionInfo (size);
|
||||
if (!GetFileVersionInfoA (lpszFilePath, 0, size, pVersionInfo.data ()))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
VS_FIXEDFILEINFO* pFileInfo = nullptr;
|
||||
UINT len = 0;
|
||||
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
if (len == 0 || pFileInfo == nullptr)
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
ver = S_VERSION (
|
||||
HIWORD (pFileInfo->dwFileVersionMS),
|
||||
LOWORD (pFileInfo->dwFileVersionMS),
|
||||
HIWORD (pFileInfo->dwFileVersionLS),
|
||||
LOWORD (pFileInfo->dwFileVersionLS)
|
||||
);
|
||||
return ver;
|
||||
}
|
||||
S_VERSION GetExeFileVersion (LPCWSTR lpswFilePath)
|
||||
{
|
||||
S_VERSION ver (0);
|
||||
DWORD dummy;
|
||||
DWORD size = GetFileVersionInfoSizeW (lpswFilePath, &dummy);
|
||||
std::vector <BYTE> pVersionInfo (size);
|
||||
if (!GetFileVersionInfoW (lpswFilePath, 0, size, pVersionInfo.data ()))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
VS_FIXEDFILEINFO* pFileInfo = nullptr;
|
||||
UINT len = 0;
|
||||
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
if (len == 0 || pFileInfo == nullptr)
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
ver = S_VERSION (
|
||||
HIWORD (pFileInfo->dwFileVersionMS),
|
||||
LOWORD (pFileInfo->dwFileVersionMS),
|
||||
HIWORD (pFileInfo->dwFileVersionLS),
|
||||
LOWORD (pFileInfo->dwFileVersionLS)
|
||||
);
|
||||
return ver;
|
||||
}
|
||||
S_VERSION GetExeFileVersion (std::wstring objswFilePath)
|
||||
{
|
||||
return GetExeFileVersion (objswFilePath.c_str ());
|
||||
}
|
||||
S_VERSION GetExeFileVersion (std::string objszFilePath)
|
||||
{
|
||||
return GetExeFileVersion (objszFilePath.c_str ());
|
||||
}
|
||||
// 设置当前进程的环境变量RunPath和ProgramPath
|
||||
void SetupInstanceEnvironment (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
// 设置RunPath为当前工作目录(无结尾反斜杠)
|
||||
std::vector <WCHAR> currentDir (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
|
||||
DWORD len = GetCurrentDirectoryW (currentDir.capacity (), currentDir.data ());
|
||||
if (len > 0)
|
||||
{
|
||||
std::wstring runPath (currentDir.data ());
|
||||
if (!runPath.empty () && (runPath.back () == L'\\' || runPath.back () == L'/'))
|
||||
{
|
||||
runPath.pop_back ();
|
||||
}
|
||||
SetEnvironmentVariableW (L"RunPath", runPath.c_str ());
|
||||
}
|
||||
// 设置ProgramPath为程序所在目录(无结尾反斜杠)
|
||||
std::vector <WCHAR> modulePath (Max <size_t> (GetModuleFileNameW (hModule, nullptr, 0), MAX_PATH) + 1);
|
||||
len = GetModuleFileNameW (hModule, modulePath.data (), MAX_PATH);
|
||||
if (len > 0 && len < MAX_PATH)
|
||||
{
|
||||
wchar_t* lastSlash = wcsrchr (modulePath.data (), L'\\');
|
||||
if (!lastSlash) lastSlash = wcsrchr (modulePath.data (), L'/');
|
||||
if (lastSlash) *lastSlash = L'\0';
|
||||
std::wstring programPath (modulePath.data ());
|
||||
if (!programPath.empty () && (programPath.back () == L'\\' || programPath.back () == L'/'))
|
||||
{
|
||||
programPath.pop_back ();
|
||||
}
|
||||
SetEnvironmentVariableW (L"ProgramPath", programPath.c_str ());
|
||||
}
|
||||
}
|
||||
// 处理宽字符串环境变量展开
|
||||
std::wstring ProcessEnvVars (const std::wstring &input)
|
||||
{
|
||||
DWORD requiredSize = ExpandEnvironmentStringsW (input.c_str (), nullptr, 0);
|
||||
if (requiredSize == 0) return input;
|
||||
std::wstring buffer (requiredSize, L'\0');
|
||||
if (!ExpandEnvironmentStringsW (input.c_str (), &buffer [0], requiredSize))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
buffer.resize (requiredSize - 1); // 去除终止空字符
|
||||
return buffer.c_str ();
|
||||
}
|
||||
std::wstring ProcessEnvVars (LPCWSTR input)
|
||||
{
|
||||
return ProcessEnvVars (std::wstring (input));
|
||||
}
|
||||
// 处理ANSI字符串环境变量展开
|
||||
std::string ProcessEnvVars (const std::string &input)
|
||||
{
|
||||
DWORD requiredSize = ExpandEnvironmentStringsA (input.c_str (), nullptr, 0);
|
||||
if (requiredSize == 0) return input;
|
||||
std::string buffer (requiredSize, '\0');
|
||||
if (!ExpandEnvironmentStringsA (input.c_str (), &buffer [0], requiredSize))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
buffer.resize (requiredSize - 1); // 去除终止空字符
|
||||
return buffer.c_str ();
|
||||
}
|
||||
std::string ProcessEnvVars (LPCSTR input)
|
||||
{
|
||||
return ProcessEnvVars (std::string (input));
|
||||
}
|
||||
std::string GetCurrentDirectoryA ()
|
||||
{
|
||||
std::vector <CHAR> buf (Max <size_t> (GetCurrentDirectoryA (0, nullptr), MAX_PATH) + 1);
|
||||
GetCurrentDirectoryA (buf.size (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetCurrentDirectoryW ()
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
|
||||
GetCurrentDirectoryW (buf.size (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetFileDirectoryW (const std::wstring &filePath)
|
||||
{
|
||||
std::vector <WCHAR> buf (filePath.capacity () + 1);
|
||||
lstrcpyW (buf.data (), filePath.c_str ());
|
||||
PathRemoveFileSpecW (buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::string GetFileDirectoryA (const std::string &filePath)
|
||||
{
|
||||
std::vector <CHAR> buf (filePath.capacity () + 1);
|
||||
lstrcpyA (buf.data (), filePath.c_str ());
|
||||
PathRemoveFileSpecA (buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter,
|
||||
std::vector <std::wstring> &outFiles, bool recursive = false)
|
||||
{
|
||||
std::wstring searchPath = directory;
|
||||
if (!searchPath.empty () && searchPath.back () != L'\\')
|
||||
{
|
||||
searchPath += L'\\';
|
||||
}
|
||||
searchPath += filter;
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do {
|
||||
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
outFiles.push_back (directory + L"\\" + findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
}
|
||||
if (recursive) {
|
||||
std::wstring subDirSearchPath = directory + L"\\*";
|
||||
hFind = FindFirstFileW (subDirSearchPath.c_str (), &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do {
|
||||
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
wcscmp (findData.cFileName, L".") != 0 && wcscmp (findData.cFileName, L"..") != 0)
|
||||
{
|
||||
EnumerateFilesW (directory + L"\\" + findData.cFileName, filter, outFiles, true);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
}
|
||||
}
|
||||
return outFiles.size ();
|
||||
}
|
||||
// 检查是否为 Windows 设备名(大小写不敏感)
|
||||
bool IsReservedName (const std::wstring &name)
|
||||
{
|
||||
static const wchar_t* reserved [] = {
|
||||
L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", L"COM8", L"COM9",
|
||||
L"LPT1", L"LPT2", L"LPT3", L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9"
|
||||
};
|
||||
std::wstring upperName = StringToUpper (name);
|
||||
for (const auto& res : reserved)
|
||||
{
|
||||
if (upperName == res || (upperName.rfind (res, 0) == 0 && upperName.length () > wcslen (res) && upperName [wcslen (res)] == L'.'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Windows 文件命名规范检查 (Unicode)
|
||||
bool IsValidWindowsNameW (LPCWSTR name)
|
||||
{
|
||||
if (!name || !*name) return false;
|
||||
std::wstring wname (name);
|
||||
if (wname.find_first_of (L"<>:\"/\\|?*") != std::wstring::npos) return false;
|
||||
if (IsReservedName (wname)) return false;
|
||||
if (wname.back () == L' ' || wname.back () == L'.') return false;
|
||||
return true;
|
||||
}
|
||||
// Windows 文件命名规范检查 (ANSI)
|
||||
bool IsValidWindowsNameA (LPCSTR name)
|
||||
{
|
||||
if (!name || !*name) return false;
|
||||
std::string str (name);
|
||||
if (str.find_first_of ("<>:\"/\\|?*") != std::string::npos) return false;
|
||||
|
||||
// 转换 ANSI 到宽字符
|
||||
int len = MultiByteToWideChar (CP_ACP, 0, name, -1, NULL, 0);
|
||||
if (len <= 0) return false;
|
||||
std::wstring wname (len - 1, L'\0');
|
||||
MultiByteToWideChar (CP_ACP, 0, name, -1, &wname [0], len);
|
||||
if (IsReservedName (wname)) return false;
|
||||
if (str.back () == ' ' || str.back () == '.') return false;
|
||||
return true;
|
||||
}
|
||||
bool IsValidWindowsName (LPCSTR name) { return IsValidWindowsNameA (name); }
|
||||
bool IsValidWindowsName (LPCWSTR name) { return IsValidWindowsNameW (name); }
|
||||
bool IsValidWindowsName (const std::wstring &name) { return IsValidWindowsName (name.c_str ()); }
|
||||
bool IsValidWindowsName (const std::string &name) { return IsValidWindowsName (name.c_str ()); }
|
||||
std::wstring GetRootFolderNameFromFilePath (const std::wstring &lpFilePath)
|
||||
{
|
||||
std::vector <WCHAR> szPath (Max <size_t> (lpFilePath.length (), MAX_PATH) + 1);
|
||||
if (!PathCanonicalizeW (szPath.data (), lpFilePath.c_str ())) return L"";
|
||||
if (PathRemoveFileSpecW (szPath.data ()) == FALSE) return L"";
|
||||
LPCWSTR pszFolder = PathFindFileNameW (szPath.data ());
|
||||
if (*pszFolder != L'\0') return std::wstring (pszFolder);
|
||||
WCHAR rootName [3] = {szPath [0], L':', L'\0'};
|
||||
return std::wstring (rootName);
|
||||
}
|
||||
std::wstring GetSafeTimestampForFilename ()
|
||||
{
|
||||
::FILETIME ft;
|
||||
GetSystemTimeAsFileTime (&ft);
|
||||
SYSTEMTIME st;
|
||||
FileTimeToSystemTime (&ft, &st);
|
||||
std::wstringstream wss;
|
||||
wss << std::setfill (L'0')
|
||||
<< st.wYear
|
||||
<< std::setw (2) << st.wMonth
|
||||
<< std::setw (2) << st.wDay << L"_"
|
||||
<< std::setw (2) << st.wHour
|
||||
<< std::setw (2) << st.wMinute
|
||||
<< std::setw (2) << st.wSecond
|
||||
<< std::setw (3) << st.wMilliseconds;
|
||||
return wss.str ();
|
||||
}
|
||||
size_t EnumFiles (
|
||||
const std::wstring &lpDir,
|
||||
const std::wstring &lpFilter,
|
||||
std::vector <std::wstring> &aszOutput,
|
||||
bool bOutputWithPath = false,
|
||||
bool bSortByLetter = false,
|
||||
bool bIncludeSubDir = false
|
||||
) {
|
||||
if (!bIncludeSubDir) aszOutput.clear ();
|
||||
std::vector<std::wstring> filters;
|
||||
size_t start = 0;
|
||||
while (start < lpFilter.length ())
|
||||
{
|
||||
size_t pos = lpFilter.find (L'\\', start);
|
||||
if (pos == std::wstring::npos) pos = lpFilter.length ();
|
||||
filters.emplace_back (lpFilter.substr (start, pos - start));
|
||||
start = pos + 1;
|
||||
}
|
||||
|
||||
std::function <void (const std::wstring &, std::wstring)> enumDir;
|
||||
enumDir = [&] (const std::wstring &physicalPath, std::wstring relativePath)
|
||||
{
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
do {
|
||||
if (wcscmp (ffd.cFileName, L".") == 0 ||
|
||||
wcscmp (ffd.cFileName, L"..") == 0) continue;
|
||||
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
const std::wstring newPhysical = physicalPath + L"\\" + ffd.cFileName;
|
||||
std::wstring newRelative = relativePath;
|
||||
if (isDir) {
|
||||
if (bIncludeSubDir) {
|
||||
newRelative += ffd.cFileName;
|
||||
newRelative += L"\\";
|
||||
enumDir (newPhysical, newRelative);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &filter : filters)
|
||||
{
|
||||
if (PathMatchSpecW (ffd.cFileName, filter.c_str ()))
|
||||
{
|
||||
aszOutput.push_back
|
||||
(
|
||||
bOutputWithPath ? newPhysical : (relativePath + ffd.cFileName)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (FindNextFileW (hFind, &ffd));
|
||||
FindClose (hFind);
|
||||
};
|
||||
enumDir (lpDir, L"");
|
||||
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
|
||||
return aszOutput.size ();
|
||||
}
|
||||
std::wstring GetRelativePath (
|
||||
const std::wstring &pszBaseDir,
|
||||
const std::wstring &pszFullPath,
|
||||
DWORD cchRelative
|
||||
) {
|
||||
std::vector <WCHAR> szBase (Max <size_t> (pszBaseDir.length (), pszFullPath.length (), MAX_PATH) + 1);
|
||||
wcscpy_s (szBase.data (), MAX_PATH, pszBaseDir.c_str ());
|
||||
if (szBase [wcslen (szBase.data ()) - 1] != L'\\')
|
||||
{
|
||||
wcscat_s (szBase.data (), MAX_PATH, L"\\");
|
||||
}
|
||||
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, szBase.size ()) + 1);
|
||||
BOOL res = PathRelativePathToW (
|
||||
buf.data (),
|
||||
szBase.data (),
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
pszFullPath.c_str (),
|
||||
FILE_ATTRIBUTE_NORMAL
|
||||
);
|
||||
if (res) return buf.data ();
|
||||
else return L"";
|
||||
}
|
||||
size_t EnumDirectory (
|
||||
const std::wstring &lpDir,
|
||||
std::vector<std::wstring> &aszOutput,
|
||||
bool bOutputWithPath = false,
|
||||
bool bSortByLetter = false,
|
||||
bool bIncludeSubDir = false
|
||||
) {
|
||||
aszOutput.clear ();
|
||||
std::function <void (const std::wstring &, const std::wstring &)> enumDir;
|
||||
enumDir = [&] (const std::wstring &physicalPath, const std::wstring &relativePath) {
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
do
|
||||
{
|
||||
const std::wstring name = ffd.cFileName;
|
||||
if (name == L"." || name == L"..") continue;
|
||||
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
std::wstring newPhysical = physicalPath + L"\\" + name;
|
||||
std::wstring newRelative = relativePath + name;
|
||||
if (isDir)
|
||||
{
|
||||
if (bIncludeSubDir) enumDir (newPhysical, newRelative + L"\\");
|
||||
if (bOutputWithPath) aszOutput.push_back (newPhysical);
|
||||
else aszOutput.push_back (newRelative);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &ffd));
|
||||
FindClose (hFind);
|
||||
};
|
||||
enumDir (lpDir, L"");
|
||||
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
|
||||
return aszOutput.size ();
|
||||
}
|
||||
|
||||
static DWORD CALLBACK ProgressRoutine (
|
||||
LARGE_INTEGER TotalFileSize,
|
||||
LARGE_INTEGER TotalBytesTransferred,
|
||||
LARGE_INTEGER /*StreamSize*/,
|
||||
LARGE_INTEGER /*StreamBytesTransferred*/,
|
||||
DWORD /*dwStreamNumber*/,
|
||||
DWORD /*dwCallbackReason*/,
|
||||
HANDLE /*hSourceFile*/,
|
||||
HANDLE /*hDestinationFile*/,
|
||||
LPVOID lpData
|
||||
) {
|
||||
auto *pCallback = reinterpret_cast <std::function <void (int)> *> (lpData);
|
||||
if (pCallback && *pCallback)
|
||||
{
|
||||
int progress = static_cast <int> (
|
||||
(TotalBytesTransferred.QuadPart * 100) / TotalFileSize.QuadPart
|
||||
);
|
||||
(*pCallback) (progress);
|
||||
}
|
||||
return PROGRESS_CONTINUE;
|
||||
}
|
||||
bool RenameFileW (
|
||||
const std::wstring &lpSrcPath,
|
||||
const std::wstring &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressW (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameFileA (
|
||||
const std::string &lpSrcPath,
|
||||
const std::string &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressA (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameFileW (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
struct BuildTask
|
||||
{
|
||||
LPWSTR src = nullptr, dest = nullptr;
|
||||
~BuildTask ()
|
||||
{
|
||||
if (src != nullptr)
|
||||
{
|
||||
delete [] src;
|
||||
src = nullptr;
|
||||
}
|
||||
if (dest != nullptr)
|
||||
{
|
||||
delete [] dest;
|
||||
dest = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
BuildTask bt;
|
||||
bt.src = new WCHAR [lpSrcDir.length () + lpSrcName.length () + 2];
|
||||
bt.dest = new WCHAR [lpSrcDir.length () + lpDestName.length () + 2];
|
||||
PathCombineW (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineW (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
|
||||
return RenameFileW (bt.src, bt.dest, fProgress);
|
||||
}
|
||||
bool RenameFileA (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
struct BuildTask
|
||||
{
|
||||
LPSTR src = nullptr, dest = nullptr;
|
||||
~BuildTask ()
|
||||
{
|
||||
if (src != nullptr)
|
||||
{
|
||||
delete [] src;
|
||||
src = nullptr;
|
||||
}
|
||||
if (dest != nullptr)
|
||||
{
|
||||
delete [] dest;
|
||||
dest = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
BuildTask bt;
|
||||
bt.src = new CHAR [lpSrcDir.length () + lpSrcName.length () + 2];
|
||||
bt.dest = new CHAR [lpSrcDir.length () + lpDestName.length () + 2];
|
||||
PathCombineA (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineA (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
|
||||
return RenameFileA (bt.src, bt.dest, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::wstring &lpSrcPath, const std::wstring &lpDestPath, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileW (lpSrcPath, lpDestPath, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::string &lpSrcPath, const std::string &lpDestPath, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileA (lpSrcPath, lpDestPath, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileW (lpSrcDir, lpSrcName, lpDestName, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileA (lpSrcDir, lpSrcName, lpDestName, fProgress);
|
||||
}
|
||||
bool RenameDirectoryW (
|
||||
const std::wstring &lpSrcPath,
|
||||
const std::wstring &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressW (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameDirectoryA (
|
||||
const std::string &lpSrcPath,
|
||||
const std::string &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressA (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameDirectoryW (
|
||||
const std::wstring &lpParentDir,
|
||||
const std::wstring &lpSrcName,
|
||||
const std::wstring &lpDestName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
struct PathBuilder
|
||||
{
|
||||
LPWSTR src = nullptr;
|
||||
LPWSTR dest = nullptr;
|
||||
~PathBuilder ()
|
||||
{
|
||||
delete [] src;
|
||||
delete [] dest;
|
||||
}
|
||||
} pb;
|
||||
pb.src = new WCHAR [lpParentDir.length () + lpSrcName.length () + 2];
|
||||
pb.dest = new WCHAR [lpParentDir.length () + lpDestName.length () + 2];
|
||||
PathCombineW (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineW (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
|
||||
return RenameDirectoryW (pb.src, pb.dest, fProgress);
|
||||
}
|
||||
bool RenameDirectoryA (
|
||||
const std::string &lpParentDir,
|
||||
const std::string &lpSrcName,
|
||||
const std::string &lpDestName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
struct PathBuilder
|
||||
{
|
||||
LPSTR src = nullptr;
|
||||
LPSTR dest = nullptr;
|
||||
~PathBuilder ()
|
||||
{
|
||||
delete [] src;
|
||||
delete [] dest;
|
||||
}
|
||||
} pb;
|
||||
pb.src = new CHAR [lpParentDir.length () + lpSrcName.length () + 2];
|
||||
pb.dest = new CHAR [lpParentDir.length () + lpDestName.length () + 2];
|
||||
PathCombineA (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineA (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
|
||||
return RenameDirectoryA (pb.src, pb.dest, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::wstring &src,
|
||||
const std::wstring &dst,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryW (src, dst, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::string &src,
|
||||
const std::string &dst,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryA (src, dst, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::wstring &parentDir,
|
||||
const std::wstring &srcName,
|
||||
const std::wstring &dstName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryW (parentDir, srcName, dstName, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::string &parentDir,
|
||||
const std::string &srcName,
|
||||
const std::string &dstName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryA (parentDir, srcName, dstName, fProgress);
|
||||
}
|
||||
std::wstring CombinePath (const std::wstring &left, const std::wstring &right)
|
||||
{
|
||||
std::vector <WCHAR> buf (left.capacity () + right.capacity () + 2);
|
||||
PathCombineW (buf.data (), left.c_str (), right.c_str ());
|
||||
return buf.data ();
|
||||
}
|
||||
#ifdef PathCommonPrefix
|
||||
#undef PathCommonPrefix
|
||||
#endif
|
||||
std::wstring PathCommonPrefix (const std::wstring &file1, const std::wstring &file2)
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (file1.capacity (), file2.capacity (), MAX_PATH) + 2);
|
||||
PathCommonPrefixW (file1.c_str (), file2.c_str (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
#undef GetFullPathName
|
||||
std::wstring GetFullPathName (const std::wstring &lpFileName)
|
||||
{
|
||||
if (lpFileName.empty ()) return L"";
|
||||
DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
|
||||
if (length == 0) return L"";
|
||||
std::vector <WCHAR> buffer (length + 1, L'\0');
|
||||
DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
|
||||
if (result == 0) return L"";
|
||||
return std::wstring (buffer.data (), result);
|
||||
}
|
||||
bool PathEquals (const std::wstring &path1, const std::wstring &path2)
|
||||
{
|
||||
size_t maxlen = Max <size_t> (path1.capacity () + 1, path2.capacity () + 1, MAX_PATH);
|
||||
std::vector <WCHAR> buf1 (maxlen), buf2 (maxlen);
|
||||
PathCanonicalizeW (buf1.data (), path1.c_str ());
|
||||
PathCanonicalizeW (buf2.data (), path2.c_str ());
|
||||
return IsNormalizeStringEquals (buf1.data (), buf2.data ());
|
||||
}
|
||||
607
desktopini/initfile.h
Normal file
607
desktopini/initfile.h
Normal file
@@ -0,0 +1,607 @@
|
||||
#pragma once
|
||||
#ifndef _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <cwchar>
|
||||
#include <type_traits>
|
||||
#include "strcode.h"
|
||||
#include "nstring.h"
|
||||
#include "typestrans.h"
|
||||
#ifdef _cplusplus_cli
|
||||
#include "mpstr.h"
|
||||
#endif
|
||||
|
||||
template <typename T> std::wstring TypeToString (T value, const std::wstring &reserve = L"") { return std::to_wstring (value); }
|
||||
template <typename T> std::string TypeToString (T value, const std::string &reserve = "") { return std::to_string (value); }
|
||||
|
||||
std::string GetPrivateProfileStringA (const std::string &filePath, const std::string §ion, const std::string &key, LPCSTR defaultValue = "")
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
GetPrivateProfileStringA (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
|
||||
return buf;
|
||||
}
|
||||
std::wstring GetPrivateProfileStringW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, LPCWSTR defaultValue = L"")
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
GetPrivateProfileStringW (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
|
||||
return buf;
|
||||
}
|
||||
UINT GetPrivateProfileIntA (const std::string &filePath, const std::string §ion, const std::string &key, INT defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntA (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
|
||||
}
|
||||
UINT GetPrivateProfileIntW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, INT defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntW (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
|
||||
}
|
||||
BOOL WritePrivateProfileStringA (const std::string &filePath, const std::string §ion, const std::string &key, const std::string &value)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
|
||||
}
|
||||
BOOL WritePrivateProfileStringW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, const std::wstring &value)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
|
||||
}
|
||||
size_t GetPrivateProfileSectionA (const std::string &filePath, const std::string §ion, std::vector <std::string> &output)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion, std::vector <std::wstring> &output)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionNamesA (const std::string &filePath, std::vector <std::string> &output)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionNamesA (buf, sizeof (buf), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionNamesW (const std::wstring &filePath, std::vector <std::wstring> &output)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionNamesW (buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
bool WritePrivateProfileSectionA (const std::string &filePath, const std::string §ion, const std::vector <std::string> &lines)
|
||||
{
|
||||
std::string buf;
|
||||
for (const auto &line : lines) buf.append (line).push_back ('\0');
|
||||
buf.push_back ('\0');
|
||||
return WritePrivateProfileSectionA (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion, const std::vector <std::wstring> &lines)
|
||||
{
|
||||
std::wstring buf;
|
||||
for (const auto &line : lines) buf.append (line).push_back (L'\0');
|
||||
buf.push_back (L'\0'); // Ë« \0 ½áβ
|
||||
return WritePrivateProfileSectionW (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
|
||||
}
|
||||
bool GetPrivateProfileStructA (const std::string &filePath, const std::string §ion, const std::string &key, void *output, UINT size)
|
||||
{
|
||||
return GetPrivateProfileStructA (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileStructA (const std::string &filePath, const std::string §ion, const std::string &key, void *data, UINT size)
|
||||
{
|
||||
return WritePrivateProfileStructA (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool GetPrivateProfileStructW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, void *output, UINT size)
|
||||
{
|
||||
return GetPrivateProfileStructW (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileStructW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, void *data, UINT size)
|
||||
{
|
||||
return WritePrivateProfileStructW (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
size_t GetPrivateProfileKeysW (const std::wstring &filePath, const std::wstring §ion, std::vector <std::wstring> &keys)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
keys.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR* ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
std::wstring line = ptr;
|
||||
size_t pos = line.find (L'=');
|
||||
if (pos != std::wstring::npos) keys.push_back (line.substr (0, pos));
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return keys.size ();
|
||||
}
|
||||
size_t GetPrivateProfileKeysA (const std::string &filePath, const std::string §ion, std::vector <std::string> &keys)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
|
||||
keys.clear ();
|
||||
if (len == 0)
|
||||
return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
std::string line = ptr;
|
||||
size_t pos = line.find ('=');
|
||||
if (pos != std::string::npos) keys.push_back (line.substr (0, pos));
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return keys.size ();
|
||||
}
|
||||
bool DeletePrivateProfileKeyA (const std::string &filePath, const std::string §ion, const std::string &key)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileKeyW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileSectionA (const std::string &filePath, const std::string §ion)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
|
||||
class initkey
|
||||
{
|
||||
public:
|
||||
using pstring = std::string &;
|
||||
using pwstring = std::wstring &;
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
private:
|
||||
pcwstring filepath;
|
||||
pcwstring section;
|
||||
template <typename T, typename Trans = T, typename Func> T read_t (T defaultvalue, Func process) const
|
||||
{
|
||||
auto res = read_wstring (std::to_wstring ((Trans)defaultvalue));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T> bool write_t (T value) { return write_string (std::to_wstring (value)); }
|
||||
public:
|
||||
std::wstring key;
|
||||
initkey (pcwstring path, pcwstring sect, pcwstring k): filepath (path), section (sect), key (k) {}
|
||||
std::wstring read_wstring (pcwstring defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
|
||||
std::string read_string (pcstring defaultvalue = "") const { return WStringToString (read_wstring (StringToWString (defaultvalue))); }
|
||||
short read_short (short defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
|
||||
unsigned short read_ushort (unsigned short defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
|
||||
int read_int (int defaultvalue = 0) const { return read_t (defaultvalue, _wtoi); }
|
||||
unsigned int read_uint (unsigned int defaultvalue = 0) const { return read_t (defaultvalue, _wtou); }
|
||||
long read_long (long defaultvalue = 0) const { return read_t (defaultvalue, _wtol); }
|
||||
unsigned long read_ulong (unsigned long defaultvalue = 0) const { return read_t (defaultvalue, _wtoul); }
|
||||
long long read_llong (long long defaultvalue = 0) const { return read_t (defaultvalue, _wtoll); }
|
||||
unsigned long long read_ullong (unsigned long long defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
|
||||
float read_float (float defaultvalue = 0) const { return read_t (defaultvalue, _wtof); }
|
||||
double read_double (double defaultvalue = 0) const { return read_t (defaultvalue, _wtod); }
|
||||
bool read_bool (bool defaultvalue = false) const
|
||||
{
|
||||
std::wnstring res = read_wstring (defaultvalue ? L"true" : L"false");
|
||||
if (res.empty ()) return defaultvalue;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return defaultvalue;
|
||||
}
|
||||
int8_t read_i8 (int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (defaultvalue, _wtoi8); }
|
||||
uint8_t read_u8 (uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (defaultvalue, _wtoui8); }
|
||||
int16_t read_i16 (int16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
|
||||
uint16_t read_u16 (uint16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
|
||||
int32_t read_i32 (int32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi32); }
|
||||
uint32_t read_u32 (uint32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui32); }
|
||||
int64_t read_i64 (int64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi64); }
|
||||
uint64_t read_u64 (uint64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
|
||||
bool read_struct (void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (T &structinst) const { return read_struct (&structinst, sizeof (structinst)); }
|
||||
bool write_string (pcwstring value) { return write (value); }
|
||||
bool write_string (pcstring value) { return write (value); }
|
||||
bool write (pcwstring value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write (pcstring value) { return write (StringToWString (value)); }
|
||||
bool write (LPCWSTR value) { return write_string (std::wstring (value ? value : L"")); }
|
||||
bool write (LPCSTR value) { return write_string (value ? value : ""); }
|
||||
bool write (int value) { return write_t (value); }
|
||||
bool write (unsigned int value) { return write_t (value); }
|
||||
bool write (short value) { return write_t (value); }
|
||||
bool write (unsigned short value) { return write_t (value); }
|
||||
bool write (long value) { return write_t (value); }
|
||||
bool write (unsigned long value) { return write_t (value); }
|
||||
bool write (long long value) { return write_t (value); }
|
||||
bool write (unsigned long long value) { return write_t (value); }
|
||||
bool write (int8_t value) { return write_t ((int16_t)value); }
|
||||
bool write (uint8_t value) { return write_t ((uint16_t)value); }
|
||||
bool write (float value) { return write_t (value); }
|
||||
bool write (double value) { return write_t (value); }
|
||||
bool write (bool value) { return write (value ? L"true" : L"false"); }
|
||||
bool write (void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
operator std::wstring () { return read_wstring (); }
|
||||
operator std::string () { return read_string (); }
|
||||
template <typename T> initkey &operator = (T value) { write (value); return *this; }
|
||||
initkey &operator = (const initkey &) = delete;
|
||||
// ɾ³ýÏî
|
||||
bool clear () { return DeletePrivateProfileKeyW (filepath, section, key); }
|
||||
bool empty () const { return read_wstring ().empty (); }
|
||||
#define OPERATOR_TYPE_READ(_type_, _method_) \
|
||||
operator _type_ () { return _method_ (); }
|
||||
OPERATOR_TYPE_READ (int, read_int)
|
||||
OPERATOR_TYPE_READ (unsigned int, read_uint)
|
||||
OPERATOR_TYPE_READ (long, read_long)
|
||||
OPERATOR_TYPE_READ (unsigned long, read_ulong)
|
||||
OPERATOR_TYPE_READ (long long, read_llong)
|
||||
OPERATOR_TYPE_READ (unsigned long long, read_ullong)
|
||||
OPERATOR_TYPE_READ (short, read_short)
|
||||
OPERATOR_TYPE_READ (unsigned short, read_ushort)
|
||||
OPERATOR_TYPE_READ (float, read_float)
|
||||
OPERATOR_TYPE_READ (double, read_double)
|
||||
OPERATOR_TYPE_READ (bool, read_bool)
|
||||
#ifdef OPERATOR_TYPE_READ
|
||||
#undef OPERATOR_TYPE_READ
|
||||
#endif
|
||||
};
|
||||
class initsection
|
||||
{
|
||||
private:
|
||||
const std::wstring &filepath;
|
||||
template <typename T, typename Trans = T, typename CT, typename Func> T read_t (const std::basic_string <CT> &key, T defaultvalue, Func process) const
|
||||
{
|
||||
std::basic_string <CT> temp;
|
||||
auto res = read_string (key, TypeToString ((Trans)defaultvalue, temp));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T, typename CT> bool write_t (const std::basic_string <CT> &key, T value)
|
||||
{
|
||||
std::basic_string <CT> temp;
|
||||
return write_string (key, TypeToString (value, temp));
|
||||
}
|
||||
public:
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
std::wstring section;
|
||||
initsection (const std::wstring &path, const std::wstring §): filepath (path), section (sect) {}
|
||||
size_t keys (std::vector <std::wstring> &output) const { return GetPrivateProfileKeysW (filepath, section, output); }
|
||||
size_t keys (std::vector <std::string> &output) const { return GetPrivateProfileKeysA (WStringToString (filepath), WStringToString (section), output); }
|
||||
bool key_values (const std::vector <std::wstring> &lines) { return WritePrivateProfileSectionW (filepath, section, lines); }
|
||||
bool key_values (const std::vector <std::string> &lines) { return WritePrivateProfileSectionA (WStringToString (filepath), WStringToString (section), lines); }
|
||||
size_t key_values (std::vector <std::wstring> &output) const { return GetPrivateProfileSectionW (filepath, section, output); }
|
||||
size_t key_values (std::vector <std::string> &output) const { return GetPrivateProfileSectionA (WStringToString (filepath), WStringToString (section), output); }
|
||||
std::wstring read_string (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
|
||||
std::string read_string (const std::string &key, const std::string &defaultvalue = "") const { return WStringToString (read_string (StringToWString (key), StringToWString (defaultvalue))); }
|
||||
std::wstring read_wstring (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return read_string (key, defaultvalue); }
|
||||
int read_int (const std::wstring &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi); }
|
||||
int read_int (const std::string &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, atoi); }
|
||||
unsigned int read_uint (const std::wstring &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou); }
|
||||
unsigned int read_uint (const std::string &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, atou); }
|
||||
long read_long (const std::wstring &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtol); }
|
||||
long read_long (const std::string &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, atol); }
|
||||
unsigned long read_ulong (const std::wstring &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoul); }
|
||||
unsigned long read_ulong (const std::string &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, atoul); }
|
||||
long long read_llong (const std::wstring &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoll); }
|
||||
long long read_llong (const std::string &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, atoll); }
|
||||
unsigned long long read_ullong (const std::wstring &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou64); }
|
||||
unsigned long long read_ullong (const std::string &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, atou64); }
|
||||
int8_t read_i8 (const std::wstring &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, _wtoi8); }
|
||||
int8_t read_i8 (const std::string &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, atoi8); }
|
||||
uint8_t read_u8 (const std::wstring &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, _wtoui8); }
|
||||
uint8_t read_u8 (const std::string &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, atoui8); }
|
||||
int16_t read_i16 (const std::wstring &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi16); }
|
||||
int16_t read_i16 (const std::string &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi16); }
|
||||
short read_short (pcwstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
|
||||
short read_short (pcstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
|
||||
unsigned short read_ushort (pcwstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
|
||||
unsigned short read_ushort (pcstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
|
||||
uint16_t read_u16 (const std::wstring &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui16); }
|
||||
uint16_t read_u16 (const std::string &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui16); }
|
||||
int32_t read_i32 (const std::wstring &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi32); }
|
||||
int32_t read_i32 (const std::string &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi32); }
|
||||
uint32_t read_u32 (const std::wstring &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui32); }
|
||||
uint32_t read_u32 (const std::string &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui32); }
|
||||
int64_t read_i64 (const std::wstring &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi64); }
|
||||
int64_t read_i64 (const std::string &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi64); }
|
||||
uint64_t read_u64 (const std::wstring &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
|
||||
uint64_t read_u64 (const std::string &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
|
||||
float read_float (const std::wstring &key, float defaultvalue = 0) const { return read_t (key, defaultvalue, _wtof); }
|
||||
double read_double (const std::wstring &key, double defaultvalue = 0) const { return read_t (key, defaultvalue, _wtod); }
|
||||
bool read_bool (const std::wstring &key, bool defaultvalue = false) const
|
||||
{
|
||||
std::wnstring res = read_string (key, defaultvalue ? L"true" : L"false");
|
||||
if (res.empty ()) return defaultvalue;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return defaultvalue;
|
||||
}
|
||||
bool read_bool (const std::string &key, bool defaultvalue = false) const { return read_bool (StringToWString (key), defaultvalue); }
|
||||
bool read_struct (const std::wstring &key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (const std::wstring &key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
|
||||
bool write_string (const std::wstring &key, const std::wstring &value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write_string (const std::string &key, const std::string &value) { return write_string (StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring key, LPCWSTR value) { return write_string (key, value ? value : L""); }
|
||||
bool write (pcstring key, LPCSTR value) { return write_string (key, value ? value : ""); }
|
||||
bool write (const std::wstring &key, const std::wstring &value) { return write_string (key, value); }
|
||||
bool write (const std::string &key, const std::string &value) { return write_string (key, value); }
|
||||
bool write (pcwstring key, short value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned short value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, int value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned int value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, long long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned long long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, int8_t value) { return write_t (key, (int16_t)value); }
|
||||
bool write (pcwstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
|
||||
bool write (pcwstring key, bool value) { return write (key, value ? L"true" : L"false"); }
|
||||
bool write (pcstring key, short value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned short value) { return write_t (key, value); }
|
||||
bool write (pcstring key, int value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned int value) { return write_t (key, value); }
|
||||
bool write (pcstring key, long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, long long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned long long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, int8_t value) { return write_t (key, (int16_t)value); }
|
||||
bool write (pcstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
|
||||
bool write (pcstring key, bool value) { return write (StringToWString (key), value ? L"true" : L"false"); }
|
||||
bool write (pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
bool write (pcstring key, void *buf, size_t bufsize) { return write (StringToWString (key), buf, bufsize); }
|
||||
initkey operator [] (pcwstring key) { return initkey (filepath, section, key); }
|
||||
initkey operator [] (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
|
||||
std::wstring operator [] (pcwstring key) const { return read_string (key); }
|
||||
std::wstring operator [] (pcstring key) const { return read_string (StringToWString (key)); }
|
||||
bool delete_key (pcwstring key) { return DeletePrivateProfileKeyW (filepath, section, key); }
|
||||
bool delete_key (pcstring key) { return delete_key (StringToWString (key)); }
|
||||
bool clear () { return DeletePrivateProfileSectionW (filepath, section); }
|
||||
initkey get_key (pcwstring key) const { return initkey (filepath, section, key); }
|
||||
initkey get_key (pcwstring key) { return initkey (filepath, section, key); }
|
||||
initkey get_key (pcstring key) const { return initkey (filepath, section, StringToWString (key)); }
|
||||
initkey get_key (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
|
||||
initsection &operator = (const initsection &) = delete;
|
||||
};
|
||||
class initfile
|
||||
{
|
||||
public:
|
||||
using pstring = std::string &;
|
||||
using pwstring = std::wstring &;
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
std::wstring filepath;
|
||||
private:
|
||||
template <typename T, typename TRANS = T, typename FN> T read_t (pcwstring section, pcwstring key, T defaultvalue, FN process) const
|
||||
{
|
||||
auto res = read_wstring (section, key, std::to_wstring ((TRANS)defaultvalue));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T> bool write_t (pcwstring section, pcwstring key, T value) { return write (section, key, std::to_wstring (value)); }
|
||||
public:
|
||||
initfile (const std::wstring &initpath): filepath (initpath) {}
|
||||
size_t sections (std::vector <std::wstring> §) const { return GetPrivateProfileSectionNamesW (filepath, sect); }
|
||||
size_t sections (std::vector <std::string> §) const { return GetPrivateProfileSectionNamesA (WStringToString (filepath), sect); }
|
||||
bool delete_section (pcwstring section) { return DeletePrivateProfileSectionW (filepath, section); }
|
||||
bool delete_section (pcstring section) { return delete_section (StringToWString (section)); }
|
||||
size_t key_values (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileSectionW (filepath, section, keyvalues); }
|
||||
size_t key_values (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileSectionA (WStringToString (filepath), section, keyvalues); }
|
||||
size_t keys (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileKeysW (filepath, section, keyvalues); }
|
||||
size_t keys (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileKeysA (WStringToString (filepath), section, keyvalues); }
|
||||
initsection get_section (pcwstring section) { return initsection (filepath, section); }
|
||||
initsection get_section (pcwstring section) const { return initsection (filepath, section); }
|
||||
std::wstring read_wstring (pcwstring section, pcwstring key, pcwstring dflt = L"") const { return GetPrivateProfileStringW (filepath, section, key, dflt.c_str ()); }
|
||||
std::string read_string (pcwstring section, pcwstring key, pcstring dflt = "") const { return WStringToString (read_wstring (section, key, StringToWString (dflt))); }
|
||||
#define INIT_READ_WARGS(_type_, _dfltvalue_) pcwstring section, pcwstring key, _type_ dflt = _dfltvalue_
|
||||
#define METHOD_INIT_READ(_type_, _typename_, _dfltvalue_, _process_) \
|
||||
_type_ read_##_typename_ (INIT_READ_WARGS (_type_, _dfltvalue_)) const { return read_t (section, key, dflt, _process_); }
|
||||
METHOD_INIT_READ (int, int, 0, _wtoi)
|
||||
METHOD_INIT_READ (unsigned int, uint, 0, _wtou)
|
||||
METHOD_INIT_READ (long, long, 0, _wtol)
|
||||
METHOD_INIT_READ (unsigned long, ulong, 0, _wtoul)
|
||||
METHOD_INIT_READ (long long, llong, 0, _wtoll)
|
||||
METHOD_INIT_READ (unsigned long, ullong, 0, _wtou64)
|
||||
METHOD_INIT_READ (short, short, 0, _wtoi16)
|
||||
METHOD_INIT_READ (unsigned short, ushort, 0, _wtoui16)
|
||||
METHOD_INIT_READ (int16_t, i16, 0, _wtoi16)
|
||||
METHOD_INIT_READ (uint16_t, u16, 0, _wtoui16)
|
||||
METHOD_INIT_READ (int32_t, i32, 0, _wtoi32)
|
||||
METHOD_INIT_READ (uint32_t, u32, 0, _wtoui32)
|
||||
METHOD_INIT_READ (int64_t, i64, 0, _wtoi64)
|
||||
METHOD_INIT_READ (uint64_t, u64, 0, _wtou64)
|
||||
METHOD_INIT_READ (float, float, 0, _wtof)
|
||||
METHOD_INIT_READ (double, double, 0, _wtod)
|
||||
int8_t read_i8 (INIT_READ_WARGS (int8_t, 0)) const { return read_t <int8_t, int16_t> (section, key, dflt, _wtoi8); }
|
||||
uint8_t read_u8 (INIT_READ_WARGS (uint8_t, 0)) const { return read_t <uint8_t, uint16_t> (section, key, dflt, _wtoui8); }
|
||||
bool read_bool (INIT_READ_WARGS (bool, false)) const
|
||||
{
|
||||
std::wnstring res = read_wstring (section, key, dflt ? L"true" : L"false");
|
||||
if (res.empty ()) return dflt;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return dflt;
|
||||
}
|
||||
bool read_struct (pcwstring section, pcwstring key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (pcwstring section, pcwstring key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
|
||||
#ifdef INIT_READ_WARGS
|
||||
#undef INIT_READ_WARGS
|
||||
#endif
|
||||
#ifdef METHOD_INIT_READ
|
||||
#undef METHOD_INIT_READ
|
||||
#endif
|
||||
#define INIT_WRITE_WARGS(_type_) pcwstring section, pcwstring key, _type_ value
|
||||
bool write (INIT_WRITE_WARGS (pcwstring)) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
#define METHOD_INIT_WRITE(_type_) \
|
||||
bool write (INIT_WRITE_WARGS (_type_)) { return write_t (section, key, value); }
|
||||
METHOD_INIT_WRITE (short)
|
||||
METHOD_INIT_WRITE (unsigned short)
|
||||
METHOD_INIT_WRITE (int)
|
||||
METHOD_INIT_WRITE (unsigned int)
|
||||
METHOD_INIT_WRITE (long)
|
||||
METHOD_INIT_WRITE (unsigned long)
|
||||
METHOD_INIT_WRITE (long long)
|
||||
METHOD_INIT_WRITE (unsigned long long)
|
||||
METHOD_INIT_WRITE (float)
|
||||
METHOD_INIT_WRITE (double)
|
||||
bool write (INIT_WRITE_WARGS (bool)) { return write (section, key, value ? L"true" : L"false"); }
|
||||
bool write (INIT_WRITE_WARGS (int8_t)) { return write_t (section, key, (int16_t)value); }
|
||||
bool write (INIT_WRITE_WARGS (uint8_t)) { return write_t (section, key, (uint16_t)value); }
|
||||
bool write (pcwstring section, pcwstring key, LPCWSTR value) { return write (section, key, std::wstring (value ? value : L"")); }
|
||||
bool write (pcstring section, pcstring key, LPCSTR value) { return write (StringToWString (section), StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring section, pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
initsection operator [] (pcwstring section) { return initsection (filepath, section); }
|
||||
initsection operator [] (pcstring section) { return initsection (filepath, StringToWString (section)); }
|
||||
initsection operator [] (pcwstring section) const { return initsection (filepath, section); }
|
||||
initsection operator [] (pcstring section) const { return initsection (filepath, StringToWString (section)); }
|
||||
#ifdef METHOD_INIT_WRITE
|
||||
#undef METHOD_INIT_WRITE
|
||||
#endif
|
||||
#ifdef INIT_WRITE_WARGS
|
||||
#undef INIT_WRITE_WARGS
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
namespace Win32
|
||||
{
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
public ref class Key
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
String ^section = "";
|
||||
String ^key = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; }}
|
||||
property String ^Section { String ^get () { return section; }}
|
||||
property String ^KeyName { String ^get () { return key; }}
|
||||
Key (String ^file, String ^sect, String ^k): filepath (file), section (sect), key (k) {}
|
||||
Object ^Get (Object ^dflt)
|
||||
{
|
||||
auto res = GetPrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key),
|
||||
dflt ? MPStringToStdW (dflt->ToString ()).c_str () : L""
|
||||
);
|
||||
return CStringToMPString (res);
|
||||
}
|
||||
Object ^Get ()
|
||||
{
|
||||
auto res = GetPrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key)
|
||||
);
|
||||
return CStringToMPString (res);
|
||||
}
|
||||
bool Set (Object ^value)
|
||||
{
|
||||
return WritePrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key),
|
||||
MPStringToStdW (value ? value->ToString () : L"")
|
||||
);
|
||||
}
|
||||
property Object ^Value { Object ^get () { return Get (); } void set (Object ^value) { Set (value); } }
|
||||
Key %operator = (Object ^value) { Value = value; return *this; }
|
||||
operator String ^ () { return Value->ToString (); }
|
||||
explicit operator bool ()
|
||||
{
|
||||
auto boolstr = Value->ToString ()->Trim ()->ToLower ();
|
||||
if (boolstr == "true" || boolstr == "zhen" || boolstr == "yes" || boolstr == "Õæ") return true;
|
||||
else if (boolstr == "false" || boolstr == "jia" || boolstr == "no" || boolstr == "¼Ù") return false;
|
||||
else return false;
|
||||
}
|
||||
#define OPERATOR_TRANSITION_DEFINE(type, transfunc, defaultret) \
|
||||
operator type () { try { transfunc (Value->ToString ()); } catch (...) { return defaultret; }}
|
||||
OPERATOR_TRANSITION_DEFINE (int8_t, Convert::ToSByte, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint8_t, Convert::ToByte, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int16_t, Convert::ToInt16, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint16_t, Convert::ToUInt16, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int32_t, Convert::ToInt32, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint32_t, Convert::ToUInt32, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int64_t, Convert::ToInt64, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint64_t, Convert::ToUInt64, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (float, Convert::ToSingle, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (double, Convert::ToDouble, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (System::Decimal, Convert::ToDecimal, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (System::DateTime, Convert::ToDateTime, Convert::ToDateTime (0))
|
||||
#ifdef OPERATOR_TRANSITION_DEFINE
|
||||
#undef OPERATOR_TRANSITION_DEFINE
|
||||
#endif
|
||||
};
|
||||
[ComVisible (true)]
|
||||
public ref class Section
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
String ^section = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; } }
|
||||
property String ^SectionName { String ^get () { return section; } }
|
||||
Section (String ^file, String ^sect): filepath (file), section (sect) {}
|
||||
Key ^GetKey (String ^key) { return gcnew Key (filepath, section, key); }
|
||||
Object ^Get (String ^key, Object ^dflt) { return GetKey (key)->Get (dflt); }
|
||||
Object ^Get (String ^key) { return GetKey (key)->Get (); }
|
||||
bool Set (String ^key, Object ^value) { return GetKey (key)->Set (value); }
|
||||
Key ^operator [] (String ^key) { return GetKey (key); }
|
||||
};
|
||||
[ComVisible (true)]
|
||||
public ref class InitConfig
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; } void set (String ^path) { filepath = path; } }
|
||||
InitConfig (String ^path): filepath (path) {}
|
||||
InitConfig () {}
|
||||
Section ^GetSection (String ^section) { return gcnew Section (filepath, section); }
|
||||
Key ^GetKey (String ^section, String ^key) { return gcnew Key (filepath, section, key); }
|
||||
Object ^Get (String ^section, String ^key, String ^dflt) { return GetKey (section, key)->Get (dflt); }
|
||||
Object ^Get (String ^section, String ^key) { return GetKey (section, key)->Get (); }
|
||||
Section ^Get (String ^section) { return GetSection (section); }
|
||||
bool Set (String ^section, String ^key, String ^value) { return GetKey (section, key)->Set (value); }
|
||||
Section ^operator [] (String ^section) { return GetSection (section); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
158
desktopini/main.cpp
Normal file
158
desktopini/main.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define HMODULE_MODE_EXE
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include "module.h"
|
||||
#include "filepath.h"
|
||||
#include "initfile.h"
|
||||
#include <fstream>
|
||||
|
||||
std::wstring GetWin32ErrorMessage (DWORD err)
|
||||
{
|
||||
if (err == 0) return L"";
|
||||
LPWSTR buffer = nullptr;
|
||||
FormatMessageW (
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
err,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&buffer,
|
||||
0,
|
||||
nullptr
|
||||
);
|
||||
std::wstring msg = buffer ? buffer : L"Unknown error";
|
||||
if (buffer) LocalFree (buffer);
|
||||
return msg;
|
||||
}
|
||||
|
||||
int wmain (int argc, wchar_t** argv)
|
||||
{
|
||||
if (argc <= 1)
|
||||
{
|
||||
std::cout <<
|
||||
"Usage:\n"
|
||||
" desktopini.exe <filepath | dirpath> <section> <key> <value>\n\n"
|
||||
"<filepath>: The tool does not modify the file itself. It writes\n"
|
||||
"information to the desktop.ini file located in the same directory.\n";
|
||||
return 0;
|
||||
}
|
||||
else if (argc < 5)
|
||||
{
|
||||
std::cout << "ERROR: Invalid arguments.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring desktopini;
|
||||
if (IsFileExists (argv [1]))
|
||||
{
|
||||
desktopini = CombinePath (GetFileDirectoryW (argv [1]), L"desktop.ini");
|
||||
std::wcout << L"INFO: Input is a file. Using directory desktop.ini:\n "
|
||||
<< desktopini << L"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
desktopini = CombinePath (argv [1], L"desktop.ini");
|
||||
std::wcout << L"INFO: Input is a directory. Using desktop.ini:\n "
|
||||
<< desktopini << L"\n";
|
||||
}
|
||||
|
||||
std::wstring parent = GetFileDirectoryW (desktopini);
|
||||
|
||||
// Write INI
|
||||
if (!IsFileExists (desktopini))
|
||||
{
|
||||
std::wfstream wfs (desktopini, std::ios::out);
|
||||
wfs << L"";
|
||||
wfs.close ();
|
||||
}
|
||||
initfile dini (desktopini);
|
||||
auto res = dini [argv [2]] [argv [3]].write (argv [4]);
|
||||
if (res)
|
||||
{
|
||||
std::wcout << L"OK: Wrote INI entry ["
|
||||
<< argv [2] << L"] "
|
||||
<< argv [3] << L" = "
|
||||
<< argv [4] << L"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"ERROR: Failed to write to desktop.ini.\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
// desktop.ini attributes
|
||||
DWORD iniattr = GetFileAttributesW (desktopini.c_str ());
|
||||
if (iniattr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"WARNING: Cannot query desktop.ini attributes.\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
iniattr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
if (!(iniattr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)))
|
||||
{
|
||||
if (SetFileAttributesW (
|
||||
desktopini.c_str (),
|
||||
iniattr | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
std::wcout << L"OK: desktop.ini attributes set to HIDDEN | SYSTEM.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Failed to set attributes on desktop.ini.\n"
|
||||
<< L" Path: " << desktopini << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"INFO: desktop.ini already has required attributes.\n";
|
||||
}
|
||||
|
||||
// parent directory attributes
|
||||
DWORD parentattr = GetFileAttributesW (parent.c_str ());
|
||||
if (parentattr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Cannot query parent directory attributes.\n"
|
||||
<< L" Path: " << parent << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 4;
|
||||
}
|
||||
if (!(parentattr & FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
if (SetFileAttributesW (parent.c_str (), parentattr | FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
std::wcout << L"OK: Parent directory marked as SYSTEM.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Failed to set SYSTEM attribute on directory.\n"
|
||||
<< L" Path: " << parent << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"INFO: Parent directory is already SYSTEM.\n";
|
||||
}
|
||||
std::wcout << L"\nSUCCESS: desktop.ini configuration completed successfully.\n";
|
||||
return 0;
|
||||
}
|
||||
51
desktopini/module.h
Normal file
51
desktopini/module.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#ifdef __cplusplus
|
||||
#ifndef GetCurrentModule_bRefDefault
|
||||
// 在 C++ 中,GetCurrentModule 将会启用默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
|
||||
// 用法如:HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
|
||||
#define GetCurrentModule_bRefDefault = FALSE
|
||||
#endif
|
||||
#else
|
||||
#define GetCurrentModule_bRefDefault
|
||||
#endif
|
||||
HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
|
||||
{
|
||||
HMODULE hModule = NULL;
|
||||
if (GetModuleHandleExW (bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
||||
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCWSTR)GetCurrentModule, &hModule))
|
||||
{
|
||||
return hModule;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
HMODULE GetSelfModuleHandle ()
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
return ((::VirtualQuery (GetSelfModuleHandle, &mbi, sizeof (mbi)) != 0)
|
||||
? (HMODULE)mbi.AllocationBase : NULL);
|
||||
}
|
||||
#ifndef GetModuleHandleW_lpModuleNameDefault
|
||||
#define GetModuleHandleW_lpModuleNameDefault NULL
|
||||
#endif
|
||||
#ifndef DEFAULT_HMODULE
|
||||
#ifdef HMODULE_MODE_EXE
|
||||
#define DEFAULT_HMODULE GetModuleHandleW (NULL)
|
||||
#elif defined (HMODULE_MODE_DLL1)
|
||||
#define DEFAULT_HMODULE GetCurrentModule ()
|
||||
#elif defined (HMODULE_MODE_DLL2)
|
||||
#define DEFAULT_HMODULE GetSelfModuleHandle ()
|
||||
#else
|
||||
#define DEFAULT_HMODULE GetModuleHandleW (GetModuleHandleW_lpModuleNameDefault)
|
||||
#endif
|
||||
#endif
|
||||
#undef GetModuleHandleW_lpModuleNameDefault
|
||||
#ifdef __cplusplus
|
||||
#ifndef hModule_DefaultParam
|
||||
// 在 C++ 中,你可以使用此宏“hModule_DefaultParam”来用于给一些函数的形参定义默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
|
||||
// 用法如:std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)。
|
||||
#define hModule_DefaultParam = DEFAULT_HMODULE
|
||||
#endif
|
||||
#else
|
||||
#define hModule_DefaultParam
|
||||
#endif
|
||||
465
desktopini/nstring.h
Normal file
465
desktopini/nstring.h
Normal file
@@ -0,0 +1,465 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <cctype>
|
||||
namespace l0km
|
||||
{
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string<E, TR, AL> toupper (const std::basic_string <E, TR, AL> &src)
|
||||
{
|
||||
std::basic_string <E, TR, AL> dst = src;
|
||||
static const std::locale loc;
|
||||
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
|
||||
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
|
||||
{
|
||||
dst [i] = ctype.toupper (src [i]);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string <E, TR, AL> tolower (const std::basic_string <E, TR, AL> &src)
|
||||
{
|
||||
std::basic_string <E, TR, AL> dst = src;
|
||||
static const std::locale loc;
|
||||
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
|
||||
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
|
||||
{
|
||||
dst [i] = ctype.tolower (src [i]);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
inline char toupper (char ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <char>> (loc).toupper (ch);
|
||||
}
|
||||
inline char tolower (char ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <char>> (loc).tolower (ch);
|
||||
}
|
||||
inline wchar_t toupper (wchar_t ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <wchar_t>> (loc).toupper (ch);
|
||||
}
|
||||
inline wchar_t tolower (wchar_t ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <wchar_t>> (loc).tolower (ch);
|
||||
}
|
||||
inline int toupper (int ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <int>> (loc).toupper (ch);
|
||||
}
|
||||
inline int tolower (int ch)
|
||||
{
|
||||
if (ch < -1) return ch;
|
||||
static const std::locale loc;
|
||||
return std::use_facet <std::ctype <int>> (loc).tolower (ch);
|
||||
}
|
||||
}
|
||||
template <typename ct> bool is_blank (ct &ch)
|
||||
{
|
||||
return ch == ct (' ') || ch == ct ('\t') || ch == ct ('\n');
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> NormalizeString (const std::basic_string <E, TR, AL> &str, bool upper = false, bool includemidblank = false)
|
||||
{
|
||||
typedef std::basic_string <E, TR, AL> string_type;
|
||||
string_type result;
|
||||
if (str.empty ()) return result;
|
||||
auto begin_it = str.begin ();
|
||||
auto end_it = str.end ();
|
||||
while (begin_it != end_it && is_blank (*begin_it)) ++begin_it;
|
||||
while (end_it != begin_it && is_blank (*(end_it - 1))) --end_it;
|
||||
bool in_space = false;
|
||||
for (auto it = begin_it; it != end_it; ++ it)
|
||||
{
|
||||
if (is_blank (*it))
|
||||
{
|
||||
if (includemidblank)
|
||||
{
|
||||
if (!in_space)
|
||||
{
|
||||
result.push_back (E (' '));
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back (*it);
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back (*it);
|
||||
in_space = false;
|
||||
}
|
||||
}
|
||||
if (upper) return l0km::toupper (result);
|
||||
else return l0km::tolower (result);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEquals (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
|
||||
{
|
||||
auto _local_strlen = [] (const E *p) -> size_t {
|
||||
size_t cnt = 0;
|
||||
while (*(p + cnt)) { cnt ++; }
|
||||
return cnt;
|
||||
};
|
||||
const E *pl = l.c_str ();
|
||||
const E *pr = r.c_str ();
|
||||
while (*pl && is_blank (*pl)) ++ pl;
|
||||
while (*pr && is_blank (*pr)) ++ pr;
|
||||
const E *el = l.c_str () + _local_strlen (l.c_str ());
|
||||
const E *er = r.c_str () + _local_strlen (r.c_str ());
|
||||
while (el > pl && is_blank (*(el - 1))) --el;
|
||||
while (er > pr && is_blank (*(er - 1))) --er;
|
||||
while (pl < el && pr < er)
|
||||
{
|
||||
if (includemidblank)
|
||||
{
|
||||
if (is_blank (*pl) && is_blank (*pr))
|
||||
{
|
||||
while (pl < el && is_blank (*pl)) ++pl;
|
||||
while (pr < er && is_blank (*pr)) ++pr;
|
||||
continue;
|
||||
}
|
||||
else if (is_blank (*pl))
|
||||
{
|
||||
while (pl < el && is_blank (*pl)) ++pl;
|
||||
continue;
|
||||
}
|
||||
else if (is_blank (*pr))
|
||||
{
|
||||
while (pr < er && is_blank (*pr)) ++pr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (l0km::tolower (*pl) != l0km::tolower (*pr)) return false;
|
||||
++ pl;
|
||||
++ pr;
|
||||
}
|
||||
while (pl < el && is_blank (*pl)) ++ pl;
|
||||
while (pr < er && is_blank (*pr)) ++ pr;
|
||||
return pl == el && pr == er;
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> int64_t NormalizeStringCompare (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
|
||||
{
|
||||
auto _local_strlen = [] (const E *p) -> size_t {
|
||||
size_t cnt = 0;
|
||||
while (*(p + cnt)) { cnt ++; }
|
||||
return cnt;
|
||||
};
|
||||
const E *pl = l.c_str ();
|
||||
const E *pr = r.c_str ();
|
||||
while (*pl && is_blank (*pl)) ++ pl;
|
||||
while (*pr && is_blank (*pr)) ++ pr;
|
||||
const E *el = l.c_str () + _local_strlen (l.c_str ());
|
||||
const E *er = r.c_str () + _local_strlen (r.c_str ());
|
||||
while (el > pl && is_blank (*(el - 1))) -- el;
|
||||
while (er > pr && is_blank (*(er - 1))) -- er;
|
||||
while (pl < el && pr < er)
|
||||
{
|
||||
if (includemidblank)
|
||||
{
|
||||
if (is_blank (*pl) && is_blank (*pr))
|
||||
{
|
||||
while (pl < el && is_blank (*pl)) ++pl;
|
||||
while (pr < er && is_blank (*pr)) ++pr;
|
||||
continue;
|
||||
}
|
||||
else if (is_blank (*pl))
|
||||
{
|
||||
while (pl < el && is_blank (*pl)) ++pl;
|
||||
continue;
|
||||
}
|
||||
else if (is_blank (*pr))
|
||||
{
|
||||
while (pr < er && is_blank (*pr)) ++pr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
E chl = l0km::tolower (*pl);
|
||||
E chr = l0km::tolower (*pr);
|
||||
if (chl != chr) return (int64_t)chl - (int64_t)chr;
|
||||
++ pl;
|
||||
++ pr;
|
||||
}
|
||||
while (pl < el && is_blank (*pl)) ++ pl;
|
||||
while (pr < er && is_blank (*pr)) ++ pr;
|
||||
if (pl == el && pr == er) return 0;
|
||||
if (pl == el) return -1;
|
||||
if (pr == er) return 1;
|
||||
return (int64_t)l0km::tolower (*pl) - (int64_t)l0km::tolower (*pr);
|
||||
}
|
||||
template <typename CharT> bool IsNormalizeStringEquals (const CharT *l, const CharT *r, bool includemidblank = false)
|
||||
{
|
||||
if (!l || !r) return l == r;
|
||||
auto skip_blank = [] (const CharT *&p)
|
||||
{
|
||||
while (*p && is_blank (*p)) ++ p;
|
||||
};
|
||||
const CharT *p1 = l;
|
||||
const CharT *p2 = r;
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
while (*p1 && *p2)
|
||||
{
|
||||
CharT ch1 = l0km::tolower (*p1);
|
||||
CharT ch2 = l0km::tolower (*p2);
|
||||
if (ch1 != ch2) return false;
|
||||
++ p1;
|
||||
++ p2;
|
||||
if (includemidblank)
|
||||
{
|
||||
if (is_blank (*p1) || is_blank (*p2))
|
||||
{
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
return *p1 == 0 && *p2 == 0;
|
||||
}
|
||||
template <typename CharT> int64_t NormalizeStringCompare (const CharT *l, const CharT *r, bool includemidblank = false)
|
||||
{
|
||||
if (!l || !r) return l ? 1 : (r ? -1 : 0);
|
||||
auto skip_blank = [] (const CharT *&p)
|
||||
{
|
||||
while (*p && is_blank (*p)) ++ p;
|
||||
};
|
||||
const CharT *p1 = l;
|
||||
const CharT *p2 = r;
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
while (*p1 && *p2)
|
||||
{
|
||||
CharT ch1 = l0km::tolower (*p1);
|
||||
CharT ch2 = l0km::tolower (*p2);
|
||||
if (ch1 != ch2) return (ch1 < ch2) ? -1 : 1;
|
||||
++ p1;
|
||||
++ p2;
|
||||
if (includemidblank)
|
||||
{
|
||||
if (is_blank (*p1) || is_blank (*p2))
|
||||
{
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
skip_blank (p1);
|
||||
skip_blank (p2);
|
||||
if (*p1 == 0 && *p2 == 0) return 0;
|
||||
if (*p1 == 0) return -1;
|
||||
return 1;
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEmpty (const std::basic_string <E, TR, AL> &str)
|
||||
{
|
||||
return IsNormalizeStringEquals (str, std::basic_string <E, TR, AL> ());
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> StringTrim (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
|
||||
{
|
||||
typedef std::basic_string <E, TR, AL> string_type;
|
||||
typedef typename string_type::size_type size_type;
|
||||
if (str.empty ()) return string_type ();
|
||||
size_type first = 0;
|
||||
size_type last = str.size ();
|
||||
while (first < last && is_blank (str [first])) ++first;
|
||||
while (last > first && is_blank (str [last - 1])) --last;
|
||||
if (first == last) return string_type ();
|
||||
string_type result;
|
||||
result.reserve (last - first);
|
||||
bool in_space = false;
|
||||
for (size_type i = first; i < last; ++ i)
|
||||
{
|
||||
if (is_blank (str [i]))
|
||||
{
|
||||
if (includemidblank)
|
||||
{
|
||||
if (!in_space)
|
||||
{
|
||||
result.push_back (E (' '));
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back (str [i]);
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back (str [i]);
|
||||
in_space = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits<E>, typename AL = std::allocator <E>> size_t GetNormalizeStringLength (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
|
||||
{
|
||||
typedef typename std::basic_string <E, TR, AL>::size_type size_type;
|
||||
if (str.empty ()) return 0;
|
||||
size_type first = 0, last = str.size ();
|
||||
while (first < last && is_blank (str [first])) ++first;
|
||||
while (last > first && is_blank (str [last - 1])) --last;
|
||||
if (first == last) return 0;
|
||||
size_t length = 0;
|
||||
bool in_space = false;
|
||||
for (size_type i = first; i < last; ++i)
|
||||
{
|
||||
if (is_blank (str [i]))
|
||||
{
|
||||
if (includemidblank)
|
||||
{
|
||||
if (!in_space)
|
||||
{
|
||||
++ length;
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++ length;
|
||||
in_space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++ length;
|
||||
in_space = false;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <typename ct, typename tr = std::char_traits <ct>, typename al = std::allocator <ct>> class basic_nstring: public std::basic_string <ct, tr, al>
|
||||
{
|
||||
bool default_upper = false, default_include_blank_in_str = false;
|
||||
public:
|
||||
using base = std::basic_string <ct, tr, al>;
|
||||
using derive = std::basic_nstring <ct, tr, al>;
|
||||
using typename base::size_type;
|
||||
using typename base::value_type;
|
||||
using base::base;
|
||||
using pstr = ct *;
|
||||
using pcstr = const ct *;
|
||||
basic_nstring (): base (), default_upper (false), default_include_blank_in_str (false) {}
|
||||
basic_nstring (const ct *pStr): base (pStr), default_upper (false), default_include_blank_in_str (false) {}
|
||||
basic_nstring (const base &str): base (str) {}
|
||||
basic_nstring (base &&str): base (std::move (str)) {}
|
||||
basic_nstring (const ct *data, size_type count): base (data, count), default_upper (false), default_include_blank_in_str (false) {}
|
||||
// template <std::size_t N> basic_nstring (const ct (&arr) [N]) : base (arr, N - 1) {}
|
||||
template <typename InputIt> basic_nstring (InputIt first, InputIt last): base (first, last), default_upper (false), default_include_blank_in_str (false) {}
|
||||
bool upper_default () const { return this->default_upper; }
|
||||
bool upper_default (bool value) { return this->default_upper = value; }
|
||||
bool include_blank_in_str_middle () const { return this->default_include_blank_in_str; }
|
||||
bool include_blank_in_str_middle (bool value) { return this->default_include_blank_in_str = value; }
|
||||
base normalize (bool upper, bool includemidblank) const
|
||||
{
|
||||
return NormalizeString <ct, tr, al> (*this, upper, includemidblank);
|
||||
}
|
||||
base normalize (bool upper) const
|
||||
{
|
||||
return this->normalize (upper, default_include_blank_in_str);
|
||||
}
|
||||
base normalize () const { return this->normalize (default_upper); }
|
||||
base upper (bool includemidblank) const
|
||||
{
|
||||
return NormalizeString <ct, tr, al> (*this, true, includemidblank);
|
||||
}
|
||||
base upper () const { return this->upper (default_include_blank_in_str); }
|
||||
base lower (bool includemidblank) const
|
||||
{
|
||||
return NormalizeString <ct, tr, al> (*this, false, includemidblank);
|
||||
}
|
||||
base lower () const { return this->lower (default_include_blank_in_str); }
|
||||
base trim (bool includemidblank) const
|
||||
{
|
||||
return StringTrim <ct, tr, al> (*this, includemidblank);
|
||||
}
|
||||
base trim () const { return this->trim (default_include_blank_in_str); }
|
||||
size_t length (bool includemidblank) const { return GetNormalizeStringLength (*this, includemidblank); }
|
||||
size_t length () const { return length (default_include_blank_in_str); }
|
||||
bool empty () const
|
||||
{
|
||||
return IsNormalizeStringEmpty (*this);
|
||||
}
|
||||
bool equals (const base &another, bool includemidblank) const
|
||||
{
|
||||
return IsNormalizeStringEquals <ct, tr, al> (*this, another, includemidblank);
|
||||
}
|
||||
bool equals (const base &another) const { return equals (another, default_include_blank_in_str); }
|
||||
int64_t compare (const base &another, bool includemidblank) const
|
||||
{
|
||||
return NormalizeStringCompare <ct, tr, al> (*this, another, includemidblank);
|
||||
}
|
||||
int64_t compare (const base &another) const { return compare (another, default_include_blank_in_str); }
|
||||
base &string () { return *this; }
|
||||
base to_string (bool upper, bool includemidblank) const { return this->normalize (upper, includemidblank); }
|
||||
base to_string (bool upper) const { return this->normalize (upper, default_include_blank_in_str); }
|
||||
base to_string () const { return this->normalize (default_upper); }
|
||||
bool operator == (const base &other) const { return equals (other, false); }
|
||||
bool operator != (const base &other) const { return !equals (other, false); }
|
||||
bool operator < (const base &other) const { return compare (other, false) < 0; }
|
||||
bool operator > (const base &other) const { return compare (other, false) > 0; }
|
||||
bool operator <= (const base &other) const { return compare (other, false) <= 0; }
|
||||
bool operator >= (const base &other) const { return compare (other, false) >= 0; }
|
||||
int64_t operator - (const base &other) const { return compare (other, false); }
|
||||
bool operator == (pcstr &other) const { return equals (other, false); }
|
||||
bool operator != (pcstr &other) const { return !equals (other, false); }
|
||||
bool operator < (pcstr &other) const { return compare (other, false) < 0; }
|
||||
bool operator > (pcstr &other) const { return compare (other, false) > 0; }
|
||||
bool operator <= (pcstr &other) const { return compare (other, false) <= 0; }
|
||||
bool operator >= (pcstr &other) const { return compare (other, false) >= 0; }
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static bool equals (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
|
||||
{
|
||||
return IsNormalizeStringEquals <E, TR, AL> (l, r, remove_mid_blank);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static int64_t compare (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
|
||||
{
|
||||
return NormalizeStringCompare <E, TR, AL> (l, r, remove_mid_blank);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static std::basic_string <E, TR, AL> normalize (const std::basic_string <E> &str, bool to_upper = false, bool remove_mid_blank = false)
|
||||
{
|
||||
return NormalizeString <E, TR, AL> (str, to_upper, remove_mid_blank);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static std::basic_string <E, TR, AL> trim (const std::basic_string <E> &str, bool remove_mid_blank = false)
|
||||
{
|
||||
return StringTrim <E, TR, AL> (str, remove_mid_blank);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static size_t length (const std::basic_string <E> &str, bool remove_mid_blank = false)
|
||||
{
|
||||
return GetNormalizeStringLength <E, TR, AL> (str, remove_mid_blank);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static bool empty (const std::basic_string <E> &str)
|
||||
{
|
||||
return IsNormalizeStringEmpty <E, TR, AL> (str);
|
||||
}
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static std::basic_nstring <E, TR, AL> to_nstring (std::basic_string <E> &str) { return std::basic_nstring <E> (str); }
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static std::basic_nstring <E, TR, AL> toupper (const std::basic_nstring <E, TR, AL> &str) { return l0km::toupper (str); }
|
||||
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
|
||||
static std::basic_nstring <E, TR, AL> tolower (const std::basic_nstring <E, TR, AL> &str) { return l0km::tolower (str); }
|
||||
};
|
||||
|
||||
typedef basic_nstring <char> nstring;
|
||||
typedef basic_nstring <wchar_t> wnstring;
|
||||
}
|
||||
10
desktopini/raii.h
Normal file
10
desktopini/raii.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
typedef struct raii
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
raii (std::function <void ()> pFunc = nullptr): endtask (pFunc) {}
|
||||
~raii () { if (endtask) endtask (); }
|
||||
raii (const raii &) = delete;
|
||||
raii (raii &&) = delete;
|
||||
} destruct;
|
||||
154
desktopini/strcmp.h
Normal file
154
desktopini/strcmp.h
Normal file
@@ -0,0 +1,154 @@
|
||||
#pragma once
|
||||
#include <Shlwapi.h>
|
||||
#include "nstring.h"
|
||||
#ifdef __cplusplus
|
||||
#define ptrnull(ptr) (!(ptr))
|
||||
#else
|
||||
#define ptrnull(ptr) ((ptr) == NULL)
|
||||
#endif
|
||||
#define ptrvalid(ptr) (!ptrnull (ptr))
|
||||
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为非空字符串:指针有效且长度大于 0。千万不能是野指针,否则一定会崩溃!
|
||||
#define strvalid(strptr) (ptrvalid (strptr) && *(strptr))
|
||||
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为空字符串:指针为 NULL 或长度为 0。千万不能是野指针,否则一定会崩溃!
|
||||
#define strnull(strptr) (ptrnull (strptr) || !*(strptr))
|
||||
typedef std::wnstring strlabel, StringLabel;
|
||||
std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); }
|
||||
std::string StringTrim (const std::string &str) { return std::nstring::trim (str); }
|
||||
#define StringToUpper l0km::toupper
|
||||
#define StringToLower l0km::tolower
|
||||
int LabelCompare (const std::wstring &l1, const std::wstring &l2)
|
||||
{
|
||||
return std::wnstring::compare (l1, l2);
|
||||
}
|
||||
int LabelCompare (const std::string &l1, const std::string &l2)
|
||||
{
|
||||
return std::nstring::compare (l1, l2);
|
||||
}
|
||||
bool LabelEqual (const std::wstring &l1, const std::wstring &l2)
|
||||
{
|
||||
return std::wnstring::equals (l1, l2);
|
||||
}
|
||||
bool LabelEqual (const std::string &l1, const std::string &l2)
|
||||
{
|
||||
return std::wnstring::equals (l1, l2);
|
||||
}
|
||||
bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); }
|
||||
bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); }
|
||||
#define LabelNoEmpty(_str_) (!LabelEmpty (_str_))
|
||||
int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::string s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
|
||||
if (!found)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return found - text.c_str ();
|
||||
}
|
||||
int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::wstring s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
|
||||
if (!found)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return found - text.c_str ();
|
||||
}
|
||||
bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::string s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
|
||||
if (!found) return false;
|
||||
return true;
|
||||
}
|
||||
bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::wstring s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
|
||||
if (!found) return false;
|
||||
return true;
|
||||
}
|
||||
// 该函数帮助构成 "<str1>\0<str2>\0" 这种字符串,用于通用对话框中的文件框
|
||||
LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize)
|
||||
{
|
||||
if (!dest || !endwith || bufsize == 0)
|
||||
return dest;
|
||||
if (dest [0] == L'\0' && bufsize > 1)
|
||||
{
|
||||
dest [1] = L'\0';
|
||||
}
|
||||
size_t pos = 0;
|
||||
while (pos < bufsize - 1)
|
||||
{
|
||||
if (dest [pos] == L'\0' && dest [pos + 1] == L'\0')
|
||||
{
|
||||
if (dest [0]) pos ++;
|
||||
break;
|
||||
}
|
||||
pos ++;
|
||||
}
|
||||
size_t i = 0;
|
||||
while (pos < bufsize - 1 && endwith [i] != L'\0')
|
||||
{
|
||||
dest [pos ++] = endwith [i ++];
|
||||
}
|
||||
if (pos < bufsize)
|
||||
{
|
||||
dest [pos] = L'\0';
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
// 取文本左边,注意:长度指的是文本字符数,比如“ch”的长度为2
|
||||
std::wstring GetStringLeft (const std::wstring &str, size_t length)
|
||||
{
|
||||
std::vector <WCHAR> buf (length + 1);
|
||||
lstrcpynW (buf.data (), str.c_str (), length + 1);
|
||||
return buf.data ();
|
||||
}
|
||||
// 取文本右边
|
||||
std::wstring GetStringRight (const std::wstring &str, size_t length)
|
||||
{
|
||||
if (length >= str.length ()) return str;
|
||||
return str.substr (str.length () - length, length).c_str ();
|
||||
}
|
||||
33
desktopini/strcode.h
Normal file
33
desktopini/strcode.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP)
|
||||
{
|
||||
if (str.empty ()) return std::wstring ();
|
||||
int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0);
|
||||
if (len == 0) return std::wstring ();
|
||||
std::wstring wstr (len - 1, L'\0');
|
||||
MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len);
|
||||
return wstr;
|
||||
}
|
||||
std::string WStringToString (const std::wstring &wstr, UINT codePage = CP_ACP)
|
||||
{
|
||||
if (wstr.empty ()) return std::string ();
|
||||
int len = WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (len == 0) return std::string ();
|
||||
std::string str (len - 1, '\0');
|
||||
WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, &str [0], len, nullptr, nullptr);
|
||||
return str;
|
||||
}
|
||||
std::string WStringToUtf8 (const std::wstring& ws)
|
||||
{
|
||||
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
|
||||
return conv.to_bytes (ws);
|
||||
}
|
||||
std::wstring Utf8ToWString (const std::string& s)
|
||||
{
|
||||
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
|
||||
return conv.from_bytes (s);
|
||||
}
|
||||
124
desktopini/syncutil.h
Normal file
124
desktopini/syncutil.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION m_csection;
|
||||
public:
|
||||
CriticalSection (DWORD spinCount = 4000) { InitializeCriticalSectionAndSpinCount (&m_csection, spinCount); }
|
||||
CriticalSection (const CriticalSection &) = delete;
|
||||
CriticalSection &operator = (const CriticalSection &) = delete;
|
||||
~CriticalSection () { DeleteCriticalSection (&m_csection); }
|
||||
void Lock () { EnterCriticalSection (&m_csection); }
|
||||
void Unlock () { LeaveCriticalSection (&m_csection); }
|
||||
bool TryLock () { return TryEnterCriticalSection (&m_csection) != 0; }
|
||||
class ScopedLock
|
||||
{
|
||||
public:
|
||||
explicit ScopedLock (CriticalSection &cs): m_cs (cs) { m_cs.Lock (); }
|
||||
~ScopedLock () { m_cs.Unlock (); }
|
||||
ScopedLock (const ScopedLock &) = delete;
|
||||
ScopedLock &operator = (const ScopedLock &) = delete;
|
||||
private:
|
||||
CriticalSection& m_cs;
|
||||
};
|
||||
};
|
||||
|
||||
#define CreateScopedLock(_obj_cs_) CriticalSection::ScopedLock _obj_cs_##sl (_obj_cs_)
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
ref struct TaskStructEvent
|
||||
{
|
||||
typedef array <Object ^> args;
|
||||
typedef void (*eventfunc) (... args ^args);
|
||||
eventfunc post;
|
||||
args ^postargs;
|
||||
public:
|
||||
TaskStructEvent (
|
||||
eventfunc prefunc,
|
||||
args ^preargs,
|
||||
eventfunc postfunc,
|
||||
args ^postargs
|
||||
): post (postfunc), postargs (postargs)
|
||||
{
|
||||
if (prefunc == nullptr) {
|
||||
#pragma message("警告:预处理函数指针为空,可能跳过初始化操作")
|
||||
}
|
||||
if (prefunc)
|
||||
{
|
||||
if (preargs)
|
||||
{
|
||||
#pragma region 参数验证示例
|
||||
/*
|
||||
实际项目中应添加具体类型检查,例如:
|
||||
ValidateArgsType<Button^>(preargs);
|
||||
*/
|
||||
#pragma endregion
|
||||
prefunc (preargs);
|
||||
}
|
||||
else prefunc (gcnew args {});
|
||||
}
|
||||
}
|
||||
~TaskStructEvent ()
|
||||
{
|
||||
if (post == nullptr)
|
||||
{
|
||||
#pragma message("警告:后处理函数指针为空,资源可能无法正确释放")
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (postargs) { post (postargs); }
|
||||
else { post (gcnew args {}); }
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
#pragma message("注意:后处理中的异常需手动处理")
|
||||
}
|
||||
}
|
||||
};
|
||||
#define CreateStructEvent(_varname_taskname_, _func_construct_, _args_construct_, _func_destruct_, _args_destruct_) \
|
||||
TaskStructEvent _varname_taskname_ ( \
|
||||
_func_construct_, \
|
||||
_args_construct_, \
|
||||
_func_destruct_, \
|
||||
_args_destruct_ \
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
template <typename PreCallback, typename PostCallback> class ScopedEvent
|
||||
{
|
||||
public:
|
||||
ScopedEvent (PreCallback &&pre, PostCallback &&post)
|
||||
: m_post (std::forward <PostCallback> (post))
|
||||
{
|
||||
static_assert (
|
||||
std::is_constructible <std::function <void ()>, PreCallback>::value,
|
||||
"预处理回调必须可转换为 void () 类型"
|
||||
);
|
||||
|
||||
if (pre) { pre (); }
|
||||
}
|
||||
~ScopedEvent () noexcept
|
||||
{
|
||||
if (m_post) { m_post (); }
|
||||
}
|
||||
ScopedEvent (const ScopedEvent &) = delete;
|
||||
ScopedEvent &operator = (const ScopedEvent &) = delete;
|
||||
ScopedEvent (ScopedEvent &&) = default;
|
||||
ScopedEvent &operator =(ScopedEvent &&) = default;
|
||||
private:
|
||||
PostCallback m_post;
|
||||
};
|
||||
template <typename PreFunc, typename PostFunc> auto make_scoped_event (PreFunc &&pre, PostFunc &&post)
|
||||
{
|
||||
return ScopedEvent <PreFunc, PostFunc> (
|
||||
std::forward <PreFunc> (pre),
|
||||
std::forward <PostFunc> (post)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
267
desktopini/typestrans.h
Normal file
267
desktopini/typestrans.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#pragma once
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#ifdef __cplusplus
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdbool>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#endif
|
||||
unsigned _wtou (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long _wtoul (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long _wtou64 (const wchar_t *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double _wtod (const wchar_t *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (swscanf (str, L"%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
unsigned atou (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long atoul (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long atou64 (const char *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double atod (const char *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (sscanf (str, "%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
int8_t atoi8 (const char *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return (int8_t)value;
|
||||
}
|
||||
int16_t atoi16 (const char *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return (int16_t)value;
|
||||
}
|
||||
int32_t atoi32 (const char *str)
|
||||
{
|
||||
int32_t value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return value;
|
||||
}
|
||||
uint8_t atoui8 (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return (uint8_t)value;
|
||||
}
|
||||
uint16_t atoui16 (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return (uint16_t)value;
|
||||
}
|
||||
uint32_t atoui32 (const char *str)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return value;
|
||||
}
|
||||
int8_t _wtoi8 (const wchar_t *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return (int8_t)value;
|
||||
}
|
||||
int16_t _wtoi16 (const wchar_t *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return (int16_t)value;
|
||||
}
|
||||
int32_t _wtoi32 (const wchar_t *str)
|
||||
{
|
||||
int32_t value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return value;
|
||||
}
|
||||
uint8_t _wtoui8 (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return (uint8_t)value;
|
||||
}
|
||||
uint16_t _wtoui16 (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return (uint16_t)value;
|
||||
}
|
||||
uint32_t _wtoui32 (const wchar_t *str)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return value;
|
||||
}
|
||||
int64_t atoi64 (const char *str)
|
||||
{
|
||||
int64_t value = 0;
|
||||
if (str) sscanf (str, "%lld", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
|
||||
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
|
||||
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
|
||||
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
|
||||
EXTERN_C bool StringToBoolA (const char *str)
|
||||
{
|
||||
char buf [32] = {0};
|
||||
strcpy (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !strcmp (buf, "true") ||
|
||||
!strcmp (buf, "yes") ||
|
||||
!strcmp (buf, "ok") ||
|
||||
!strcmp (buf, "sure") ||
|
||||
!strcmp (buf, "okay") ||
|
||||
!strcmp (buf, "zhen") ||
|
||||
!strcmp (buf, "真");
|
||||
}
|
||||
EXTERN_C bool StringToBoolW (const WCHAR *str)
|
||||
{
|
||||
WCHAR buf [32] = {0};
|
||||
lstrcpyW (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !lstrcmpW (buf, L"true") ||
|
||||
!lstrcmpW (buf, L"yes") ||
|
||||
!lstrcmpW (buf, L"ok") ||
|
||||
!lstrcmpW (buf, L"sure") ||
|
||||
!lstrcmpW (buf, L"okay") ||
|
||||
!lstrcmpW (buf, L"zhen") ||
|
||||
!lstrcmpW (buf, L"真");
|
||||
}
|
||||
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
|
||||
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
|
||||
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
|
||||
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
|
||||
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
|
||||
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
|
||||
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
|
||||
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
|
||||
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
|
||||
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
int StringToInt (LPCSTR str) { return StringToIntA (str); }
|
||||
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
|
||||
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
|
||||
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
|
||||
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
|
||||
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
|
||||
long StringToLong (LPCSTR str) { return StringToLongA (str); }
|
||||
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
|
||||
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
|
||||
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
|
||||
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
|
||||
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
|
||||
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
|
||||
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
|
||||
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
|
||||
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
|
||||
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
|
||||
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) && defined (__cplusplus_cli)
|
||||
using namespace System;
|
||||
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
|
||||
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
|
||||
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
|
||||
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
|
||||
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
|
||||
bool objToBool (Object ^result)
|
||||
{
|
||||
if (!result) return false;
|
||||
try
|
||||
{
|
||||
String ^strValue = safe_cast <String ^> (result);
|
||||
return (strValue->ToLower () == "on");
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert::ToBoolean (result);
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
|
||||
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
|
||||
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
|
||||
#endif
|
||||
193
desktopini/version.h
Normal file
193
desktopini/version.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
typedef uint64_t UINT64;
|
||||
typedef int64_t INT64;
|
||||
typedef uint16_t UINT16;
|
||||
typedef struct version
|
||||
{
|
||||
UINT16 major = 0, minor = 0, build = 0, revision = 0;
|
||||
version (UINT64 value):
|
||||
major ((value >> 0x30) & 0xFFFF), minor ((value >> 0x20) & 0xFFFF),
|
||||
build ((value >> 0x10) & 0xFFFF), revision ((value) & 0xFFFF) {}
|
||||
version (UINT16 major, UINT16 minor, UINT16 build, UINT16 revision):
|
||||
major (major), minor (minor), build (build), revision (revision) {}
|
||||
version (const std::wstring &verstr) { this->interpret (verstr); }
|
||||
version (const std::string &verstr) { this->interpret (verstr); }
|
||||
version () {}
|
||||
version (const version &other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
|
||||
version (version &&other) noexcept: major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
|
||||
version &operator = (const version &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
major = other.major;
|
||||
minor = other.minor;
|
||||
build = other.build;
|
||||
revision = other.revision;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
version &operator = (version &&other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
major = other.major;
|
||||
minor = other.minor;
|
||||
build = other.build;
|
||||
revision = other.revision;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
version &operator = (UINT64 value) { this->data (value); return *this; }
|
||||
UINT64 data () const { return (((UINT64)major) << 48) | (((UINT64)minor) << 32) | (((UINT64)build) << 16) | ((UINT64)revision); }
|
||||
UINT64 data (UINT64 value)
|
||||
{
|
||||
major = (value >> 48) & 0xFFFF;
|
||||
minor = (value >> 32) & 0xFFFF;
|
||||
build = (value >> 16) & 0xFFFF;
|
||||
revision = value & 0xFFFF;
|
||||
return value;
|
||||
}
|
||||
std::wstring stringifyw () const
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << major << L'.' << minor << L'.' << build << L'.' << revision;
|
||||
return ss.str ();
|
||||
}
|
||||
std::string stringify () const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << major << '.' << minor << '.' << build << '.' << revision;
|
||||
return ss.str ();
|
||||
}
|
||||
version &interpret (const std::wstring &verstr)
|
||||
{
|
||||
auto result = split (verstr);
|
||||
if (result.size () > 0) this->major = _wtoi (result [0].c_str ());
|
||||
if (result.size () > 1) this->minor = _wtoi (result [1].c_str ());
|
||||
if (result.size () > 2) this->build = _wtoi (result [2].c_str ());
|
||||
if (result.size () > 3) this->revision = _wtoi (result [3].c_str ());
|
||||
return *this;
|
||||
}
|
||||
version &interpret (const std::string &verstr)
|
||||
{
|
||||
auto result = split (verstr);
|
||||
if (result.size () > 0) this->major = atoi (result [0].c_str ());
|
||||
if (result.size () > 1) this->minor = atoi (result [1].c_str ());
|
||||
if (result.size () > 2) this->build = atoi (result [2].c_str ());
|
||||
if (result.size () > 3) this->revision = atoi (result [3].c_str ());
|
||||
return *this;
|
||||
}
|
||||
bool empty () const { return *(UINT64 *)this == 0; }
|
||||
friend bool operator == (const version &l, const version &r) { return *(UINT64 *)&l == *(UINT64 *)&r; }
|
||||
friend bool operator == (const version &l, const UINT64 &r) { return l.data () == r; }
|
||||
friend bool operator == (const UINT64 &r, const version &l) { return l.data () == r; }
|
||||
friend bool operator < (const version &l, const version &r) { return l.data () < r.data (); }
|
||||
friend bool operator > (const version &l, const version &r) { return l.data () > r.data (); }
|
||||
friend bool operator <= (const version &l, const version &r) { return l.data () <= r.data (); }
|
||||
friend bool operator >= (const version &l, const version &r) { return l.data () >= r.data (); }
|
||||
friend bool operator != (const version &l, const version &r) { return *(UINT64 *)&l != *(UINT64 *)&r; }
|
||||
explicit operator bool () const { return !this->empty (); }
|
||||
bool operator ! () { return this->empty (); }
|
||||
friend std::ostream &operator << (std::ostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
|
||||
friend std::wostream &operator << (std::wostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
|
||||
bool equals (const version &r) const { return *this == r; }
|
||||
INT64 compare (const version &r) const { return this->data () - r.data (); }
|
||||
static version parse (const std::wstring &value) { return version (value); }
|
||||
static version parse (const std::string &value) { return version (value); }
|
||||
static std::wstring stringifyw (const version &v) { return v.stringifyw (); }
|
||||
static std::string stringify (const version &v) { return v.stringify (); }
|
||||
static bool equals (const version &l, const version &r) { return l == r; }
|
||||
static INT64 compare (const version &l, const version &r) { return l.data () - r.data (); }
|
||||
static version decode (UINT64 value) { return version (value); }
|
||||
static UINT64 encode (const version &v) { return v.data (); }
|
||||
protected:
|
||||
template <typename StringType> std::vector <StringType> split (const StringType &str, typename StringType::value_type delimiter1 = '.', typename StringType::value_type delimiter2 = ',')
|
||||
{
|
||||
std::vector <StringType> result;
|
||||
std::basic_stringstream<typename StringType::value_type> ss (str);
|
||||
StringType segment;
|
||||
while (std::getline (ss, segment, delimiter1))
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = segment.find (delimiter2)) != StringType::npos)
|
||||
{
|
||||
result.push_back (segment.substr (0, pos));
|
||||
segment.erase (0, pos + 1);
|
||||
}
|
||||
if (!segment.empty ()) result.push_back (segment);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} Version;
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
public ref class _I_Version
|
||||
{
|
||||
private:
|
||||
UINT16 major = 0, minor = 0, build = 0, revision = 0;
|
||||
public:
|
||||
property UINT16 Major { UINT16 get () { return major; } void set (UINT16 value) { major = value; } }
|
||||
property UINT16 Minor { UINT16 get () { return minor; } void set (UINT16 value) { minor = value; } }
|
||||
property UINT16 Build { UINT16 get () { return build; } void set (UINT16 value) { build = value; } }
|
||||
property UINT16 Revision { UINT16 get () { return revision; } void set (UINT16 value) { revision = value; } }
|
||||
property array <UINT16> ^Data
|
||||
{
|
||||
array <UINT16> ^get ()
|
||||
{
|
||||
return gcnew array <UINT16> {
|
||||
major, minor, build, revision
|
||||
};
|
||||
}
|
||||
void set (array <UINT16> ^arr)
|
||||
{
|
||||
major = minor = build = revision = 0;
|
||||
for (size_t i = 0; i < arr->Length; i ++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: major = arr [i]; break;
|
||||
case 1: minor = arr [i]; break;
|
||||
case 2: build = arr [i]; break;
|
||||
case 3: revision = arr [i]; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
property String ^DataStr
|
||||
{
|
||||
String ^get () { return Stringify (); }
|
||||
void set (String ^str) { Parse (str); }
|
||||
}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b, UINT16 p_r):
|
||||
major (p_ma), minor (p_mi), build (p_b), revision (p_r) {}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b):
|
||||
major (p_ma), minor (p_mi), build (p_b), revision (0) {}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi):
|
||||
major (p_ma), minor (p_mi), build (0), revision (0) {}
|
||||
_I_Version (UINT16 p_ma):
|
||||
major (p_ma), minor (0), build (0), revision (0) {}
|
||||
_I_Version () {}
|
||||
_I_Version %Parse (String ^ver)
|
||||
{
|
||||
auto strarr = ver->Split ('.');
|
||||
auto arr = gcnew array <UINT16> (4);
|
||||
for (size_t i = 0; i < strarr->Length; i ++)
|
||||
{
|
||||
try { arr [i] = Convert::ToUInt16 (strarr [i]); }
|
||||
catch (...) {}
|
||||
}
|
||||
Data = arr;
|
||||
return *this;
|
||||
}
|
||||
String ^Stringify () { return major + "." + minor + "." + build + "." + revision; }
|
||||
String ^ToString () override { return Stringify (); }
|
||||
bool Valid () { return Major != 0 && Minor != 0 && Build != 0 && Revision != 0; }
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user