mirror of
https://github.com/tauri-apps/nsis-tauri-utils.git
synced 2026-01-31 00:45:23 +01:00
refactor: rewrite the plugin in rust
This commit is contained in:
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
target = "i686-pc-windows-msvc"
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,6 +1,4 @@
|
|||||||
Release/
|
/target
|
||||||
Debug/
|
/Cargo.lock
|
||||||
.vscode/
|
|
||||||
.vs/
|
|
||||||
*.user
|
|
||||||
*.exe
|
*.exe
|
||||||
|
.vscode/
|
||||||
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "nsis-semvercompare"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
semver = "1.0.16"
|
||||||
|
|
||||||
|
[dependencies.windows-sys]
|
||||||
|
version = "0.42.0"
|
||||||
|
features = ["Win32_System_Memory", "Win32_Foundation", "Win32_Globalization"]
|
||||||
177
LICENSE_APACHE-2.0
Normal file
177
LICENSE_APACHE-2.0
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 Alexei Sitnikov
|
Copyright (c) 2019 - 2022 Tauri Programme within The Commons Conservancy
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <strsafe.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "include\nsis\pluginapi.h"
|
|
||||||
#include "include\semver.hpp"
|
|
||||||
|
|
||||||
#define NSIS_MAX_STRLEN 1024
|
|
||||||
|
|
||||||
extern "C" void __declspec(dllexport) SemverCompare(HWND hwndParent,
|
|
||||||
int string_size,
|
|
||||||
TCHAR* variables,
|
|
||||||
stack_t** stacktop,
|
|
||||||
extra_parameters* extra) {
|
|
||||||
EXDLL_INIT();
|
|
||||||
|
|
||||||
TCHAR arg1[NSIS_MAX_STRLEN];
|
|
||||||
if (popstringn(arg1, NSIS_MAX_STRLEN))
|
|
||||||
return;
|
|
||||||
|
|
||||||
TCHAR arg2[NSIS_MAX_STRLEN];
|
|
||||||
if (popstringn(arg2, NSIS_MAX_STRLEN))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::wstring ver1w(arg1);
|
|
||||||
std::wstring ver2w(arg2);
|
|
||||||
|
|
||||||
std::string ver1(ver1w.begin(), ver1w.end());
|
|
||||||
std::string ver2(ver2w.begin(), ver2w.end());
|
|
||||||
|
|
||||||
std::optional<semver::version> v1 = semver::from_string_noexcept(ver1);
|
|
||||||
std::optional<semver::version> v2 = semver::from_string_noexcept(ver2);
|
|
||||||
|
|
||||||
if (v1.has_value() && !v2.has_value()) {
|
|
||||||
pushint(1);
|
|
||||||
} else if (!v1.has_value() && v2.has_value()) {
|
|
||||||
pushint(-1);
|
|
||||||
} else if (!v1.has_value() && !v2.has_value()) {
|
|
||||||
pushint(0);
|
|
||||||
} else {
|
|
||||||
pushint(v1.value().compare(v2.value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
Name "SemverCompare"
|
|
||||||
OutFile "SemverCompare.exe"
|
|
||||||
ShowInstDetails show
|
|
||||||
|
|
||||||
!addplugindir "Debug"
|
|
||||||
!addplugindir "Release"
|
|
||||||
|
|
||||||
Section "nsSemverCompare"
|
|
||||||
SemverCompare::SemverCompare "1.2.1" "1.2.0"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.0" "1.2.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.1" "1.2.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.1-alpha.1" "1.2.1-beta.5"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.1-rc.1" "1.2.1-beta.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.1-alpha.1" "1.2.1-alpha.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2qe2.1-alpha.1" "1.2.1-alpha.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.1-alpha.1" "-q1.2.1-alpha.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SemverCompare::SemverCompare "1.2.saf1-alpha.1" "-q1.2.1-alpha.1"
|
|
||||||
Pop $1
|
|
||||||
DetailPrint $1
|
|
||||||
SectionEnd
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
|
||||||
# Visual Studio 2010
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SemverCompare", "SemverCompare.vcxproj", "{EE997742-B1B4-4FA0-A46E-E8F2614D457B}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{EE997742-B1B4-4FA0-A46E-E8F2614D457B}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{EE997742-B1B4-4FA0-A46E-E8F2614D457B}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{EE997742-B1B4-4FA0-A46E-E8F2614D457B}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{EE997742-B1B4-4FA0-A46E-E8F2614D457B}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
<?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>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{EE997742-B1B4-4FA0-A46E-E8F2614D457B}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>SemverCompare</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<UseOfMfc>false</UseOfMfc>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</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>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SemverCompare_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>kernel32.lib;include/nsis/pluginapi.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</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;_WINDOWS;_USRDLL;SemverCompare_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>kernel32.lib;include/nsis/pluginapi.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="nsis\api.h" />
|
|
||||||
<ClInclude Include="nsis\pluginapi.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="SemverCompare.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="include\nsis\pluginapi.lib" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Resource Files">
|
|
||||||
<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>
|
|
||||||
<ClInclude Include="nsis\api.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="nsis\pluginapi.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="SemverCompare.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="include\nsis\pluginapi.lib" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
msbuild ./SemverCompare.sln /p:Configuration=Debug
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
msbuild ./SemverCompare.sln /p:Configuration=Release
|
|
||||||
16
demo.nsi
Normal file
16
demo.nsi
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Name "demo"
|
||||||
|
OutFile "demo.exe"
|
||||||
|
ShowInstDetails show
|
||||||
|
Unicode true
|
||||||
|
|
||||||
|
!addplugindir ".\target\release"
|
||||||
|
!addplugindir ".\target\debug"
|
||||||
|
!addplugindir ".\target\i686-pc-windows-msvc\release"
|
||||||
|
!addplugindir ".\target\i686-pc-windows-msvc\debug"
|
||||||
|
|
||||||
|
Section
|
||||||
|
nsis_semvercompare::SemverCompare "1.0.0" "1.1.0"
|
||||||
|
Pop $1
|
||||||
|
DetailPrint $1
|
||||||
|
SectionEnd
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* apih
|
|
||||||
*
|
|
||||||
* This file is a part of NSIS.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1999-2009 Nullsoft and Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the zlib/libpng license (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* Licence details can be found in the file COPYING.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NSIS_EXEHEAD_API_H_
|
|
||||||
#define _NSIS_EXEHEAD_API_H_
|
|
||||||
|
|
||||||
// Starting with NSIS 2.42, you can check the version of the plugin API in
|
|
||||||
// exec_flags->plugin_api_version The format is 0xXXXXYYYY where X is the major
|
|
||||||
// version and Y is the minor version (MAKELONG(y,x)) When doing version checks,
|
|
||||||
// always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >=
|
|
||||||
// NSISPIAPIVER_1_0) {}
|
|
||||||
|
|
||||||
#define NSISPIAPIVER_1_0 0x00010000
|
|
||||||
#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0
|
|
||||||
|
|
||||||
// NSIS Plug-In Callback Messages
|
|
||||||
enum NSPIM {
|
|
||||||
NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup
|
|
||||||
NSPIM_GUIUNLOAD, // Called after .onGUIEnd
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prototype for callbacks registered with
|
|
||||||
// extra_parameters->RegisterPluginCallback() Return NULL for unknown messages
|
|
||||||
// Should always be __cdecl for future expansion possibilities
|
|
||||||
typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
|
|
||||||
|
|
||||||
// extra_parameters data structures containing other interesting stuff
|
|
||||||
// but the stack, variables and HWND passed on to plug-ins.
|
|
||||||
typedef struct {
|
|
||||||
int autoclose;
|
|
||||||
int all_user_var;
|
|
||||||
int exec_error;
|
|
||||||
int abort;
|
|
||||||
int exec_reboot; // NSIS_SUPPORT_REBOOT
|
|
||||||
int reboot_called; // NSIS_SUPPORT_REBOOT
|
|
||||||
int XXX_cur_insttype; // depreacted
|
|
||||||
int plugin_api_version; // see NSISPIAPIVER_CURR
|
|
||||||
// used to be XXX_insttype_changed
|
|
||||||
int silent; // NSIS_CONFIG_SILENT_SUPPORT
|
|
||||||
int instdir_error;
|
|
||||||
int rtl;
|
|
||||||
int errlvl;
|
|
||||||
int alter_reg_view;
|
|
||||||
int status_update;
|
|
||||||
} exec_flags_t;
|
|
||||||
|
|
||||||
#ifndef NSISCALL
|
|
||||||
#define NSISCALL __stdcall
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
exec_flags_t* exec_flags;
|
|
||||||
int(NSISCALL* ExecuteCodeSegment)(int, HWND);
|
|
||||||
void(NSISCALL* validate_filename)(TCHAR*);
|
|
||||||
int(NSISCALL* RegisterPluginCallback)(
|
|
||||||
HMODULE,
|
|
||||||
NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and
|
|
||||||
// < 0 on errors
|
|
||||||
} extra_parameters;
|
|
||||||
|
|
||||||
// Definitions for page showing plug-ins
|
|
||||||
// See Ui.c to understand better how they're used
|
|
||||||
|
|
||||||
// sent to the outer window to tell it to go to the next inner window
|
|
||||||
#define WM_NOTIFY_OUTER_NEXT (WM_USER + 0x8)
|
|
||||||
|
|
||||||
// custom pages should send this message to let NSIS know they're ready
|
|
||||||
#define WM_NOTIFY_CUSTOM_READY (WM_USER + 0xd)
|
|
||||||
|
|
||||||
// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning
|
|
||||||
#define NOTIFY_BYE_BYE 'x'
|
|
||||||
|
|
||||||
#endif /* _PLUGIN_H_ */
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* nsis_tchar.h
|
|
||||||
*
|
|
||||||
* This file is a part of NSIS.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1999-2007 Nullsoft and Contributors
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty.
|
|
||||||
*
|
|
||||||
* For Unicode support by Jim Park -- 08/30/2007
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Jim Park: Only those we use are listed here.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef _UNICODE
|
|
||||||
|
|
||||||
#ifndef _T
|
|
||||||
#define __T(x) L##x
|
|
||||||
#define _T(x) __T(x)
|
|
||||||
#define _TEXT(x) __T(x)
|
|
||||||
#endif
|
|
||||||
typedef wchar_t TCHAR;
|
|
||||||
typedef wchar_t _TUCHAR;
|
|
||||||
|
|
||||||
// program
|
|
||||||
#define _tmain wmain
|
|
||||||
#define _tWinMain wWinMain
|
|
||||||
#define _tenviron _wenviron
|
|
||||||
#define __targv __wargv
|
|
||||||
|
|
||||||
// printfs
|
|
||||||
#define _ftprintf fwprintf
|
|
||||||
#define _sntprintf _snwprintf
|
|
||||||
#define _stprintf _swprintf
|
|
||||||
#define _tprintf wprintf
|
|
||||||
#define _vftprintf vfwprintf
|
|
||||||
#define _vsntprintf _vsnwprintf
|
|
||||||
#define _vstprintf _vswprintf
|
|
||||||
|
|
||||||
// scanfs
|
|
||||||
#define _tscanf wscanf
|
|
||||||
#define _stscanf swscanf
|
|
||||||
|
|
||||||
// string manipulations
|
|
||||||
#define _tcscat wcscat
|
|
||||||
#define _tcschr wcschr
|
|
||||||
#define _tcsclen wcslen
|
|
||||||
#define _tcscpy wcscpy
|
|
||||||
#define _tcsdup _wcsdup
|
|
||||||
#define _tcslen wcslen
|
|
||||||
#define _tcsnccpy wcsncpy
|
|
||||||
#define _tcsncpy wcsncpy
|
|
||||||
#define _tcsrchr wcsrchr
|
|
||||||
#define _tcsstr wcsstr
|
|
||||||
#define _tcstok wcstok
|
|
||||||
|
|
||||||
// string comparisons
|
|
||||||
#define _tcscmp wcscmp
|
|
||||||
#define _tcsicmp _wcsicmp
|
|
||||||
#define _tcsncicmp _wcsnicmp
|
|
||||||
#define _tcsncmp wcsncmp
|
|
||||||
#define _tcsnicmp _wcsnicmp
|
|
||||||
|
|
||||||
// upper / lower
|
|
||||||
#define _tcslwr _wcslwr
|
|
||||||
#define _tcsupr _wcsupr
|
|
||||||
#define _totlower towlower
|
|
||||||
#define _totupper towupper
|
|
||||||
|
|
||||||
// conversions to numbers
|
|
||||||
#define _tcstoi64 _wcstoi64
|
|
||||||
#define _tcstol wcstol
|
|
||||||
#define _tcstoul wcstoul
|
|
||||||
#define _tstof _wtof
|
|
||||||
#define _tstoi _wtoi
|
|
||||||
#define _tstoi64 _wtoi64
|
|
||||||
#define _ttoi _wtoi
|
|
||||||
#define _ttoi64 _wtoi64
|
|
||||||
#define _ttol _wtol
|
|
||||||
|
|
||||||
// conversion from numbers to strings
|
|
||||||
#define _itot _itow
|
|
||||||
#define _ltot _ltow
|
|
||||||
#define _i64tot _i64tow
|
|
||||||
#define _ui64tot _ui64tow
|
|
||||||
|
|
||||||
// file manipulations
|
|
||||||
#define _tfopen _wfopen
|
|
||||||
#define _topen _wopen
|
|
||||||
#define _tremove _wremove
|
|
||||||
#define _tunlink _wunlink
|
|
||||||
|
|
||||||
// reading and writing to i/o
|
|
||||||
#define _fgettc fgetwc
|
|
||||||
#define _fgetts fgetws
|
|
||||||
#define _fputts fputws
|
|
||||||
#define _gettchar getwchar
|
|
||||||
|
|
||||||
// directory
|
|
||||||
#define _tchdir _wchdir
|
|
||||||
|
|
||||||
// environment
|
|
||||||
#define _tgetenv _wgetenv
|
|
||||||
#define _tsystem _wsystem
|
|
||||||
|
|
||||||
// time
|
|
||||||
#define _tcsftime wcsftime
|
|
||||||
|
|
||||||
#else // ANSI
|
|
||||||
|
|
||||||
#ifndef _T
|
|
||||||
#define _T(x) x
|
|
||||||
#define _TEXT(x) x
|
|
||||||
#endif
|
|
||||||
typedef char TCHAR;
|
|
||||||
typedef unsigned char _TUCHAR;
|
|
||||||
|
|
||||||
// program
|
|
||||||
#define _tmain main
|
|
||||||
#define _tWinMain WinMain
|
|
||||||
#define _tenviron environ
|
|
||||||
#define __targv __argv
|
|
||||||
|
|
||||||
// printfs
|
|
||||||
#define _ftprintf fprintf
|
|
||||||
#define _sntprintf _snprintf
|
|
||||||
#define _stprintf sprintf
|
|
||||||
#define _tprintf printf
|
|
||||||
#define _vftprintf vfprintf
|
|
||||||
#define _vsntprintf _vsnprintf
|
|
||||||
#define _vstprintf vsprintf
|
|
||||||
|
|
||||||
// scanfs
|
|
||||||
#define _tscanf scanf
|
|
||||||
#define _stscanf sscanf
|
|
||||||
|
|
||||||
// string manipulations
|
|
||||||
#define _tcscat strcat
|
|
||||||
#define _tcschr strchr
|
|
||||||
#define _tcsclen strlen
|
|
||||||
#define _tcscnlen strnlen
|
|
||||||
#define _tcscpy strcpy
|
|
||||||
#define _tcsdup _strdup
|
|
||||||
#define _tcslen strlen
|
|
||||||
#define _tcsnccpy strncpy
|
|
||||||
#define _tcsrchr strrchr
|
|
||||||
#define _tcsstr strstr
|
|
||||||
#define _tcstok strtok
|
|
||||||
|
|
||||||
// string comparisons
|
|
||||||
#define _tcscmp strcmp
|
|
||||||
#define _tcsicmp _stricmp
|
|
||||||
#define _tcsncmp strncmp
|
|
||||||
#define _tcsncicmp _strnicmp
|
|
||||||
#define _tcsnicmp _strnicmp
|
|
||||||
|
|
||||||
// upper / lower
|
|
||||||
#define _tcslwr _strlwr
|
|
||||||
#define _tcsupr _strupr
|
|
||||||
|
|
||||||
#define _totupper toupper
|
|
||||||
#define _totlower tolower
|
|
||||||
|
|
||||||
// conversions to numbers
|
|
||||||
#define _tcstol strtol
|
|
||||||
#define _tcstoul strtoul
|
|
||||||
#define _tstof atof
|
|
||||||
#define _tstoi atoi
|
|
||||||
#define _tstoi64 _atoi64
|
|
||||||
#define _tstoi64 _atoi64
|
|
||||||
#define _ttoi atoi
|
|
||||||
#define _ttoi64 _atoi64
|
|
||||||
#define _ttol atol
|
|
||||||
|
|
||||||
// conversion from numbers to strings
|
|
||||||
#define _i64tot _i64toa
|
|
||||||
#define _itot _itoa
|
|
||||||
#define _ltot _ltoa
|
|
||||||
#define _ui64tot _ui64toa
|
|
||||||
|
|
||||||
// file manipulations
|
|
||||||
#define _tfopen fopen
|
|
||||||
#define _topen _open
|
|
||||||
#define _tremove remove
|
|
||||||
#define _tunlink _unlink
|
|
||||||
|
|
||||||
// reading and writing to i/o
|
|
||||||
#define _fgettc fgetc
|
|
||||||
#define _fgetts fgets
|
|
||||||
#define _fputts fputs
|
|
||||||
#define _gettchar getchar
|
|
||||||
|
|
||||||
// directory
|
|
||||||
#define _tchdir _chdir
|
|
||||||
|
|
||||||
// environment
|
|
||||||
#define _tgetenv getenv
|
|
||||||
#define _tsystem system
|
|
||||||
|
|
||||||
// time
|
|
||||||
#define _tcsftime strftime
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// is functions (the same in Unicode / ANSI)
|
|
||||||
#define _istgraph isgraph
|
|
||||||
#define _istascii __isascii
|
|
||||||
|
|
||||||
#define __TFILE__ _T(__FILE__)
|
|
||||||
#define __TDATE__ _T(__DATE__)
|
|
||||||
#define __TTIME__ _T(__TIME__)
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#ifndef ___NSIS_PLUGIN__H___
|
|
||||||
#define ___NSIS_PLUGIN__H___
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "api.h"
|
|
||||||
#include "nsis_tchar.h"
|
|
||||||
|
|
||||||
#ifndef NSISCALL
|
|
||||||
#define NSISCALL __stdcall
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EXDLL_INIT() \
|
|
||||||
{ \
|
|
||||||
g_stringsize = string_size; \
|
|
||||||
g_stacktop = stacktop; \
|
|
||||||
g_variables = variables; \
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct _stack_t {
|
|
||||||
struct _stack_t* next;
|
|
||||||
TCHAR text[1]; // this should be the length of string_size
|
|
||||||
} stack_t;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
INST_0, // $0
|
|
||||||
INST_1, // $1
|
|
||||||
INST_2, // $2
|
|
||||||
INST_3, // $3
|
|
||||||
INST_4, // $4
|
|
||||||
INST_5, // $5
|
|
||||||
INST_6, // $6
|
|
||||||
INST_7, // $7
|
|
||||||
INST_8, // $8
|
|
||||||
INST_9, // $9
|
|
||||||
INST_R0, // $R0
|
|
||||||
INST_R1, // $R1
|
|
||||||
INST_R2, // $R2
|
|
||||||
INST_R3, // $R3
|
|
||||||
INST_R4, // $R4
|
|
||||||
INST_R5, // $R5
|
|
||||||
INST_R6, // $R6
|
|
||||||
INST_R7, // $R7
|
|
||||||
INST_R8, // $R8
|
|
||||||
INST_R9, // $R9
|
|
||||||
INST_CMDLINE, // $CMDLINE
|
|
||||||
INST_INSTDIR, // $INSTDIR
|
|
||||||
INST_OUTDIR, // $OUTDIR
|
|
||||||
INST_EXEDIR, // $EXEDIR
|
|
||||||
INST_LANG, // $LANGUAGE
|
|
||||||
__INST_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
extern unsigned int g_stringsize;
|
|
||||||
extern stack_t** g_stacktop;
|
|
||||||
extern TCHAR* g_variables;
|
|
||||||
|
|
||||||
int NSISCALL popstring(TCHAR* str); // 0 on success, 1 on empty stack
|
|
||||||
int NSISCALL
|
|
||||||
popstringn(TCHAR* str,
|
|
||||||
int maxlen); // with length limit, pass 0 for g_stringsize
|
|
||||||
int NSISCALL popint(); // pops an integer
|
|
||||||
int NSISCALL popint_or(); // with support for or'ing (2|4|8)
|
|
||||||
int NSISCALL myatoi(const TCHAR* s); // converts a string to an integer
|
|
||||||
unsigned NSISCALL myatou(
|
|
||||||
const TCHAR* s); // converts a string to an unsigned integer, decimal only
|
|
||||||
int NSISCALL myatoi_or(const TCHAR* s); // with support for or'ing (2|4|8)
|
|
||||||
void NSISCALL pushstring(const TCHAR* str);
|
|
||||||
void NSISCALL pushint(int value);
|
|
||||||
TCHAR* NSISCALL getuservariable(const int varnum);
|
|
||||||
void NSISCALL setuservariable(const int varnum, const TCHAR* var);
|
|
||||||
|
|
||||||
#ifdef _UNICODE
|
|
||||||
#define PopStringW(x) popstring(x)
|
|
||||||
#define PushStringW(x) pushstring(x)
|
|
||||||
#define SetUserVariableW(x, y) setuservariable(x, y)
|
|
||||||
|
|
||||||
int NSISCALL PopStringA(char* ansiStr);
|
|
||||||
void NSISCALL PushStringA(const char* ansiStr);
|
|
||||||
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
|
|
||||||
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
|
|
||||||
void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr);
|
|
||||||
|
|
||||||
#else
|
|
||||||
// ANSI defs
|
|
||||||
|
|
||||||
#define PopStringA(x) popstring(x)
|
|
||||||
#define PushStringA(x) pushstring(x)
|
|
||||||
#define SetUserVariableA(x, y) setuservariable(x, y)
|
|
||||||
|
|
||||||
int NSISCALL PopStringW(wchar_t* wideStr);
|
|
||||||
void NSISCALL PushStringW(wchar_t* wideStr);
|
|
||||||
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
|
|
||||||
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
|
|
||||||
void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //!___NSIS_PLUGIN__H___
|
|
||||||
Binary file not shown.
@@ -1,935 +0,0 @@
|
|||||||
// _____ _ _
|
|
||||||
// / ____| | | (_)
|
|
||||||
// | (___ ___ _ __ ___ __ _ _ __ | |_ _ ___
|
|
||||||
// \___ \ / _ \ '_ ` _ \ / _` | '_ \| __| |/ __|
|
|
||||||
// ____) | __/ | | | | | (_| | | | | |_| | (__
|
|
||||||
// |_____/ \___|_| |_| |_|\__,_|_| |_|\__|_|\___|
|
|
||||||
// __ __ _ _ _____
|
|
||||||
// \ \ / / (_) (_) / ____|_ _
|
|
||||||
// \ \ / /__ _ __ ___ _ ___ _ __ _ _ __ __ _ | | _| |_ _| |_
|
|
||||||
// \ \/ / _ \ '__/ __| |/ _ \| '_ \| | '_ \ / _` | | | |_ _|_ _|
|
|
||||||
// \ / __/ | \__ \ | (_) | | | | | | | | (_| | | |____|_| |_|
|
|
||||||
// \/ \___|_| |___/_|\___/|_| |_|_|_| |_|\__, | \_____|
|
|
||||||
// https://github.com/Neargye/semver __/ |
|
|
||||||
// version 0.3.0 |___/
|
|
||||||
//
|
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
// Copyright (c) 2018 - 2021 Daniil Goncharov <neargye@gmail.com>.
|
|
||||||
// Copyright (c) 2020 - 2021 Alexander Gorbunov <naratzul@gmail.com>.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
|
||||||
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef NEARGYE_SEMANTIC_VERSIONING_HPP
|
|
||||||
#define NEARGYE_SEMANTIC_VERSIONING_HPP
|
|
||||||
|
|
||||||
#define SEMVER_VERSION_MAJOR 0
|
|
||||||
#define SEMVER_VERSION_MINOR 3
|
|
||||||
#define SEMVER_VERSION_PATCH 0
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <limits>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#if __has_include(<charconv>)
|
|
||||||
#include <charconv>
|
|
||||||
#else
|
|
||||||
#include <system_error>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SEMVER_CONFIG_FILE)
|
|
||||||
#include SEMVER_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SEMVER_THROW)
|
|
||||||
// define SEMVER_THROW(msg) to override semver throw behavior.
|
|
||||||
#elif defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
|
||||||
#include <stdexcept>
|
|
||||||
#define SEMVER_THROW(msg) (throw std::invalid_argument{msg})
|
|
||||||
#else
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
|
||||||
#define SEMVER_THROW(msg) (assert(!msg), std::abort())
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored \
|
|
||||||
"-Wmissing-braces" // Ignore warning: suggest braces around initialization
|
|
||||||
// of subobject 'return {first,
|
|
||||||
// std::errc::invalid_argument};'.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace semver {
|
|
||||||
|
|
||||||
enum struct prerelease : std::uint8_t { alpha = 0, beta = 1, rc = 2, none = 3 };
|
|
||||||
|
|
||||||
#if __has_include(<charconv>)
|
|
||||||
struct from_chars_result : std::from_chars_result {
|
|
||||||
[[nodiscard]] constexpr operator bool() const noexcept {
|
|
||||||
return ec == std::errc{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct to_chars_result : std::to_chars_result {
|
|
||||||
[[nodiscard]] constexpr operator bool() const noexcept {
|
|
||||||
return ec == std::errc{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
struct from_chars_result {
|
|
||||||
const char* ptr;
|
|
||||||
std::errc ec;
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr operator bool() const noexcept {
|
|
||||||
return ec == std::errc{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct to_chars_result {
|
|
||||||
char* ptr;
|
|
||||||
std::errc ec;
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr operator bool() const noexcept {
|
|
||||||
return ec == std::errc{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Max version string length = 3(<major>) + 1(.) + 3(<minor>) + 1(.) +
|
|
||||||
// 3(<patch>) + 1(-) + 5(<prerelease>) + 1(.) + 3(<prereleaseversion>) = 21.
|
|
||||||
inline constexpr auto max_version_string_length = std::size_t{21};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
inline constexpr auto alpha = std::string_view{"alpha", 5};
|
|
||||||
inline constexpr auto beta = std::string_view{"beta", 4};
|
|
||||||
inline constexpr auto rc = std::string_view{"rc", 2};
|
|
||||||
|
|
||||||
// Min version string length = 1(<major>) + 1(.) + 1(<minor>) + 1(.) +
|
|
||||||
// 1(<patch>) = 5.
|
|
||||||
inline constexpr auto min_version_string_length = 5;
|
|
||||||
|
|
||||||
constexpr char to_lower(char c) noexcept {
|
|
||||||
return (c >= 'A' && c <= 'Z') ? static_cast<char>(c + ('a' - 'A')) : c;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_digit(char c) noexcept {
|
|
||||||
return c >= '0' && c <= '9';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_space(char c) noexcept {
|
|
||||||
return c == ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_operator(char c) noexcept {
|
|
||||||
return c == '<' || c == '>' || c == '=';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_dot(char c) noexcept {
|
|
||||||
return c == '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_logical_or(char c) noexcept {
|
|
||||||
return c == '|';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_hyphen(char c) noexcept {
|
|
||||||
return c == '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_letter(char c) noexcept {
|
|
||||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::uint8_t to_digit(char c) noexcept {
|
|
||||||
return static_cast<std::uint8_t>(c - '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::uint8_t length(std::uint8_t x) noexcept {
|
|
||||||
return x < 10 ? 1 : (x < 100 ? 2 : 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::uint8_t length(prerelease t) noexcept {
|
|
||||||
if (t == prerelease::alpha) {
|
|
||||||
return static_cast<std::uint8_t>(alpha.length());
|
|
||||||
} else if (t == prerelease::beta) {
|
|
||||||
return static_cast<std::uint8_t>(beta.length());
|
|
||||||
} else if (t == prerelease::rc) {
|
|
||||||
return static_cast<std::uint8_t>(rc.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool equals(const char* first,
|
|
||||||
const char* last,
|
|
||||||
std::string_view str) noexcept {
|
|
||||||
for (std::size_t i = 0; first != last && i < str.length(); ++i, ++first) {
|
|
||||||
if (to_lower(*first) != to_lower(str[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr char* to_chars(char* str, std::uint8_t x, bool dot = true) noexcept {
|
|
||||||
do {
|
|
||||||
*(--str) = static_cast<char>('0' + (x % 10));
|
|
||||||
x /= 10;
|
|
||||||
} while (x != 0);
|
|
||||||
|
|
||||||
if (dot) {
|
|
||||||
*(--str) = '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr char* to_chars(char* str, prerelease t) noexcept {
|
|
||||||
const auto p = t == prerelease::alpha ? alpha
|
|
||||||
: t == prerelease::beta ? beta
|
|
||||||
: t == prerelease::rc ? rc
|
|
||||||
: std::string_view{};
|
|
||||||
|
|
||||||
if (p.size() > 0) {
|
|
||||||
for (auto it = p.rbegin(); it != p.rend(); ++it) {
|
|
||||||
*(--str) = *it;
|
|
||||||
}
|
|
||||||
*(--str) = '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const char* from_chars(const char* first,
|
|
||||||
const char* last,
|
|
||||||
std::uint8_t& d) noexcept {
|
|
||||||
if (first != last && is_digit(*first)) {
|
|
||||||
std::int32_t t = 0;
|
|
||||||
for (; first != last && is_digit(*first); ++first) {
|
|
||||||
t = t * 10 + to_digit(*first);
|
|
||||||
}
|
|
||||||
if (t <= (std::numeric_limits<std::uint8_t>::max)()) {
|
|
||||||
d = static_cast<std::uint8_t>(t);
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const char* from_chars(const char* first,
|
|
||||||
const char* last,
|
|
||||||
std::optional<std::uint8_t>& d) noexcept {
|
|
||||||
if (first != last && is_digit(*first)) {
|
|
||||||
std::int32_t t = 0;
|
|
||||||
for (; first != last && is_digit(*first); ++first) {
|
|
||||||
t = t * 10 + to_digit(*first);
|
|
||||||
}
|
|
||||||
if (t <= (std::numeric_limits<std::uint8_t>::max)()) {
|
|
||||||
d = static_cast<std::uint8_t>(t);
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const char* from_chars(const char* first,
|
|
||||||
const char* last,
|
|
||||||
prerelease& p) noexcept {
|
|
||||||
if (is_hyphen(*first)) {
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (equals(first, last, alpha)) {
|
|
||||||
p = prerelease::alpha;
|
|
||||||
return first + alpha.length();
|
|
||||||
} else if (equals(first, last, beta)) {
|
|
||||||
p = prerelease::beta;
|
|
||||||
return first + beta.length();
|
|
||||||
} else if (equals(first, last, rc)) {
|
|
||||||
p = prerelease::rc;
|
|
||||||
return first + rc.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool check_delimiter(const char* first,
|
|
||||||
const char* last,
|
|
||||||
char d) noexcept {
|
|
||||||
return first != last && first != nullptr && *first == d;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct resize_uninitialized {
|
|
||||||
static auto resize(T& str, std::size_t size)
|
|
||||||
-> std::void_t<decltype(str.resize(size))> {
|
|
||||||
str.resize(size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct resize_uninitialized<
|
|
||||||
T,
|
|
||||||
std::void_t<decltype(std::declval<T>().__resize_default_init(42))>> {
|
|
||||||
static void resize(T& str, std::size_t size) {
|
|
||||||
str.__resize_default_init(size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
struct version {
|
|
||||||
std::uint8_t major = 0;
|
|
||||||
std::uint8_t minor = 1;
|
|
||||||
std::uint8_t patch = 0;
|
|
||||||
prerelease prerelease_type = prerelease::none;
|
|
||||||
std::optional<std::uint8_t> prerelease_number = std::nullopt;
|
|
||||||
|
|
||||||
constexpr version(std::uint8_t mj,
|
|
||||||
std::uint8_t mn,
|
|
||||||
std::uint8_t pt,
|
|
||||||
prerelease prt = prerelease::none,
|
|
||||||
std::optional<std::uint8_t> prn = std::nullopt) noexcept
|
|
||||||
: major{mj},
|
|
||||||
minor{mn},
|
|
||||||
patch{pt},
|
|
||||||
prerelease_type{prt},
|
|
||||||
prerelease_number{prt == prerelease::none ? std::nullopt : prn} {}
|
|
||||||
|
|
||||||
explicit constexpr version(std::string_view str)
|
|
||||||
: version(0, 0, 0, prerelease::none, 0) {
|
|
||||||
from_string(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr version() =
|
|
||||||
default; // https://semver.org/#how-should-i-deal-with-revisions-in-the-0yz-initial-development-phase
|
|
||||||
|
|
||||||
constexpr version(const version&) = default;
|
|
||||||
|
|
||||||
constexpr version(version&&) = default;
|
|
||||||
|
|
||||||
~version() = default;
|
|
||||||
|
|
||||||
version& operator=(const version&) = default;
|
|
||||||
|
|
||||||
version& operator=(version&&) = default;
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr from_chars_result from_chars(
|
|
||||||
const char* first,
|
|
||||||
const char* last) noexcept {
|
|
||||||
if (first == nullptr || last == nullptr ||
|
|
||||||
(last - first) < detail::min_version_string_length) {
|
|
||||||
return {first, std::errc::invalid_argument};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto next = first;
|
|
||||||
if (next = detail::from_chars(next, last, major);
|
|
||||||
detail::check_delimiter(next, last, '.')) {
|
|
||||||
if (next = detail::from_chars(++next, last, minor);
|
|
||||||
detail::check_delimiter(next, last, '.')) {
|
|
||||||
if (next = detail::from_chars(++next, last, patch); next == last) {
|
|
||||||
prerelease_type = prerelease::none;
|
|
||||||
prerelease_number = {};
|
|
||||||
return {next, std::errc{}};
|
|
||||||
} else if (detail::check_delimiter(next, last, '-')) {
|
|
||||||
if (next = detail::from_chars(next, last, prerelease_type);
|
|
||||||
next == last) {
|
|
||||||
prerelease_number = {};
|
|
||||||
return {next, std::errc{}};
|
|
||||||
} else if (detail::check_delimiter(next, last, '.')) {
|
|
||||||
if (next = detail::from_chars(++next, last, prerelease_number);
|
|
||||||
next == last) {
|
|
||||||
return {next, std::errc{}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {first, std::errc::invalid_argument};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr to_chars_result to_chars(char* first,
|
|
||||||
char* last) const noexcept {
|
|
||||||
const auto length = string_length();
|
|
||||||
if (first == nullptr || last == nullptr || (last - first) < length) {
|
|
||||||
return {last, std::errc::value_too_large};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto next = first + length;
|
|
||||||
if (prerelease_type != prerelease::none) {
|
|
||||||
if (prerelease_number.has_value()) {
|
|
||||||
next = detail::to_chars(next, prerelease_number.value());
|
|
||||||
}
|
|
||||||
next = detail::to_chars(next, prerelease_type);
|
|
||||||
}
|
|
||||||
next = detail::to_chars(next, patch);
|
|
||||||
next = detail::to_chars(next, minor);
|
|
||||||
next = detail::to_chars(next, major, false);
|
|
||||||
|
|
||||||
return {first + length, std::errc{}};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool from_string_noexcept(
|
|
||||||
std::string_view str) noexcept {
|
|
||||||
return from_chars(str.data(), str.data() + str.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr version& from_string(std::string_view str) {
|
|
||||||
if (!from_string_noexcept(str)) {
|
|
||||||
SEMVER_THROW("semver::version::from_string invalid version.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string to_string() const {
|
|
||||||
auto str = std::string{};
|
|
||||||
detail::resize_uninitialized<std::string>::resize(str, string_length());
|
|
||||||
if (!to_chars(str.data(), str.data() + str.length())) {
|
|
||||||
SEMVER_THROW("semver::version::to_string invalid version.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::uint8_t string_length() const noexcept {
|
|
||||||
// (<major>) + 1(.) + (<minor>) + 1(.) + (<patch>)
|
|
||||||
auto length = detail::length(major) + detail::length(minor) +
|
|
||||||
detail::length(patch) + 2;
|
|
||||||
if (prerelease_type != prerelease::none) {
|
|
||||||
// + 1(-) + (<prerelease>)
|
|
||||||
length += detail::length(prerelease_type) + 1;
|
|
||||||
if (prerelease_number.has_value()) {
|
|
||||||
// + 1(.) + (<prereleaseversion>)
|
|
||||||
length += detail::length(prerelease_number.value()) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<std::uint8_t>(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr int compare(const version& other) const noexcept {
|
|
||||||
if (major != other.major) {
|
|
||||||
return major - other.major;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minor != other.minor) {
|
|
||||||
return minor - other.minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patch != other.patch) {
|
|
||||||
return patch - other.patch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prerelease_type != other.prerelease_type) {
|
|
||||||
return static_cast<std::uint8_t>(prerelease_type) -
|
|
||||||
static_cast<std::uint8_t>(other.prerelease_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prerelease_number.has_value()) {
|
|
||||||
if (other.prerelease_number.has_value()) {
|
|
||||||
return prerelease_number.value() - other.prerelease_number.value();
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
} else if (other.prerelease_number.has_value()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator==(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator!=(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator>(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator>=(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator<(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator<=(const version& lhs,
|
|
||||||
const version& rhs) noexcept {
|
|
||||||
return lhs.compare(rhs) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr version operator""_version(const char* str,
|
|
||||||
std::size_t length) {
|
|
||||||
return version{std::string_view{str, length}};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool valid(std::string_view str) noexcept {
|
|
||||||
return version{}.from_string_noexcept(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr from_chars_result from_chars(const char* first,
|
|
||||||
const char* last,
|
|
||||||
version& v) noexcept {
|
|
||||||
return v.from_chars(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr to_chars_result to_chars(char* first,
|
|
||||||
char* last,
|
|
||||||
const version& v) noexcept {
|
|
||||||
return v.to_chars(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::optional<version> from_string_noexcept(
|
|
||||||
std::string_view str) noexcept {
|
|
||||||
if (version v{}; v.from_string_noexcept(str)) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr version from_string(std::string_view str) {
|
|
||||||
return version{str};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline std::string to_string(const version& v) {
|
|
||||||
return v.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename Traits>
|
|
||||||
inline std::basic_ostream<Char, Traits>& operator<<(
|
|
||||||
std::basic_ostream<Char, Traits>& os,
|
|
||||||
const version& v) {
|
|
||||||
for (const auto c : v.to_string()) {
|
|
||||||
os.put(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline namespace comparators {
|
|
||||||
|
|
||||||
enum struct comparators_option : std::uint8_t {
|
|
||||||
exclude_prerelease,
|
|
||||||
include_prerelease
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr int compare(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
if (option == comparators_option::exclude_prerelease) {
|
|
||||||
return version{lhs.major, lhs.minor, lhs.patch}.compare(
|
|
||||||
version{rhs.major, rhs.minor, rhs.patch});
|
|
||||||
}
|
|
||||||
return lhs.compare(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool equal_to(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool not_equal_to(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool greater(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool greater_equal(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool less(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool less_equal(
|
|
||||||
const version& lhs,
|
|
||||||
const version& rhs,
|
|
||||||
comparators_option option =
|
|
||||||
comparators_option::include_prerelease) noexcept {
|
|
||||||
return compare(lhs, rhs, option) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace comparators
|
|
||||||
|
|
||||||
namespace range {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
using namespace semver::detail;
|
|
||||||
|
|
||||||
class range {
|
|
||||||
public:
|
|
||||||
constexpr explicit range(std::string_view str) noexcept : parser{str} {}
|
|
||||||
|
|
||||||
constexpr bool satisfies(const version& ver, bool include_prerelease) {
|
|
||||||
const bool has_prerelease = ver.prerelease_type != prerelease::none;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (is_logical_or_token()) {
|
|
||||||
parser.advance_token(range_token_type::logical_or);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains = true;
|
|
||||||
bool allow_compare = include_prerelease;
|
|
||||||
|
|
||||||
while (is_operator_token() || is_number_token()) {
|
|
||||||
const auto range = parser.parse_range();
|
|
||||||
const bool equal_without_tags =
|
|
||||||
equal_to(range.ver, ver, comparators_option::exclude_prerelease);
|
|
||||||
|
|
||||||
if (has_prerelease && equal_without_tags) {
|
|
||||||
allow_compare = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!range.satisfies(ver)) {
|
|
||||||
contains = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_prerelease) {
|
|
||||||
if (allow_compare && contains) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (contains) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (is_logical_or_token());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum struct range_operator : std::uint8_t {
|
|
||||||
less,
|
|
||||||
less_or_equal,
|
|
||||||
greater,
|
|
||||||
greater_or_equal,
|
|
||||||
equal
|
|
||||||
};
|
|
||||||
|
|
||||||
struct range_comparator {
|
|
||||||
range_operator op;
|
|
||||||
version ver;
|
|
||||||
|
|
||||||
constexpr bool satisfies(const version& version) const {
|
|
||||||
switch (op) {
|
|
||||||
case range_operator::equal:
|
|
||||||
return version == ver;
|
|
||||||
case range_operator::greater:
|
|
||||||
return version > ver;
|
|
||||||
case range_operator::greater_or_equal:
|
|
||||||
return version >= ver;
|
|
||||||
case range_operator::less:
|
|
||||||
return version < ver;
|
|
||||||
case range_operator::less_or_equal:
|
|
||||||
return version <= ver;
|
|
||||||
default:
|
|
||||||
SEMVER_THROW("semver::range unexpected operator.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum struct range_token_type : std::uint8_t {
|
|
||||||
none,
|
|
||||||
number,
|
|
||||||
range_operator,
|
|
||||||
dot,
|
|
||||||
logical_or,
|
|
||||||
hyphen,
|
|
||||||
prerelease,
|
|
||||||
end_of_line
|
|
||||||
};
|
|
||||||
|
|
||||||
struct range_token {
|
|
||||||
range_token_type type = range_token_type::none;
|
|
||||||
std::uint8_t number = 0;
|
|
||||||
range_operator op = range_operator::equal;
|
|
||||||
prerelease prerelease_type = prerelease::none;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct range_lexer {
|
|
||||||
std::string_view text;
|
|
||||||
std::size_t pos;
|
|
||||||
|
|
||||||
constexpr explicit range_lexer(std::string_view text) noexcept
|
|
||||||
: text{text}, pos{0} {}
|
|
||||||
|
|
||||||
constexpr range_token get_next_token() noexcept {
|
|
||||||
while (!end_of_line()) {
|
|
||||||
if (is_space(text[pos])) {
|
|
||||||
advance(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_logical_or(text[pos])) {
|
|
||||||
advance(2);
|
|
||||||
return {range_token_type::logical_or};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_operator(text[pos])) {
|
|
||||||
const auto op = get_operator();
|
|
||||||
return {range_token_type::range_operator, 0, op};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_digit(text[pos])) {
|
|
||||||
const auto number = get_number();
|
|
||||||
return {range_token_type::number, number};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dot(text[pos])) {
|
|
||||||
advance(1);
|
|
||||||
return {range_token_type::dot};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_hyphen(text[pos])) {
|
|
||||||
advance(1);
|
|
||||||
return {range_token_type::hyphen};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_letter(text[pos])) {
|
|
||||||
const auto prerelease = get_prerelease();
|
|
||||||
return {range_token_type::prerelease, 0, range_operator::equal,
|
|
||||||
prerelease};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {range_token_type::end_of_line};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool end_of_line() const noexcept { return pos >= text.length(); }
|
|
||||||
|
|
||||||
constexpr void advance(std::size_t i) noexcept { pos += i; }
|
|
||||||
|
|
||||||
constexpr range_operator get_operator() noexcept {
|
|
||||||
if (text[pos] == '<') {
|
|
||||||
advance(1);
|
|
||||||
if (text[pos] == '=') {
|
|
||||||
advance(1);
|
|
||||||
return range_operator::less_or_equal;
|
|
||||||
}
|
|
||||||
return range_operator::less;
|
|
||||||
} else if (text[pos] == '>') {
|
|
||||||
advance(1);
|
|
||||||
if (text[pos] == '=') {
|
|
||||||
advance(1);
|
|
||||||
return range_operator::greater_or_equal;
|
|
||||||
}
|
|
||||||
return range_operator::greater;
|
|
||||||
} else if (text[pos] == '=') {
|
|
||||||
advance(1);
|
|
||||||
return range_operator::equal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return range_operator::equal;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::uint8_t get_number() noexcept {
|
|
||||||
const auto first = text.data() + pos;
|
|
||||||
const auto last = text.data() + text.length();
|
|
||||||
if (std::uint8_t n{}; from_chars(first, last, n) != nullptr) {
|
|
||||||
advance(length(n));
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr prerelease get_prerelease() noexcept {
|
|
||||||
const auto first = text.data() + pos;
|
|
||||||
const auto last = text.data() + text.length();
|
|
||||||
if (first > last) {
|
|
||||||
advance(1);
|
|
||||||
return prerelease::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prerelease p{}; from_chars(first, last, p) != nullptr) {
|
|
||||||
advance(length(p));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
advance(1);
|
|
||||||
|
|
||||||
return prerelease::none;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct range_parser {
|
|
||||||
range_lexer lexer;
|
|
||||||
range_token current_token;
|
|
||||||
|
|
||||||
constexpr explicit range_parser(std::string_view str)
|
|
||||||
: lexer{str}, current_token{range_token_type::none} {
|
|
||||||
advance_token(range_token_type::none);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr void advance_token(range_token_type token_type) {
|
|
||||||
if (current_token.type != token_type) {
|
|
||||||
SEMVER_THROW("semver::range unexpected token.");
|
|
||||||
}
|
|
||||||
current_token = lexer.get_next_token();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr range_comparator parse_range() {
|
|
||||||
if (current_token.type == range_token_type::number) {
|
|
||||||
const auto version = parse_version();
|
|
||||||
return {range_operator::equal, version};
|
|
||||||
} else if (current_token.type == range_token_type::range_operator) {
|
|
||||||
const auto range_operator = current_token.op;
|
|
||||||
advance_token(range_token_type::range_operator);
|
|
||||||
const auto version = parse_version();
|
|
||||||
return {range_operator, version};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {range_operator::equal, version{}};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr version parse_version() {
|
|
||||||
const auto major = parse_number();
|
|
||||||
|
|
||||||
advance_token(range_token_type::dot);
|
|
||||||
const auto minor = parse_number();
|
|
||||||
|
|
||||||
advance_token(range_token_type::dot);
|
|
||||||
const auto patch = parse_number();
|
|
||||||
|
|
||||||
prerelease prerelease = prerelease::none;
|
|
||||||
std::optional<std::uint8_t> prerelease_number = std::nullopt;
|
|
||||||
|
|
||||||
if (current_token.type == range_token_type::hyphen) {
|
|
||||||
advance_token(range_token_type::hyphen);
|
|
||||||
prerelease = parse_prerelease();
|
|
||||||
if (current_token.type == range_token_type::dot) {
|
|
||||||
advance_token(range_token_type::dot);
|
|
||||||
prerelease_number = parse_number();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {major, minor, patch, prerelease, prerelease_number};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::uint8_t parse_number() {
|
|
||||||
const auto token = current_token;
|
|
||||||
advance_token(range_token_type::number);
|
|
||||||
|
|
||||||
return token.number;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr prerelease parse_prerelease() {
|
|
||||||
const auto token = current_token;
|
|
||||||
advance_token(range_token_type::prerelease);
|
|
||||||
|
|
||||||
return token.prerelease_type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool is_logical_or_token() const noexcept {
|
|
||||||
return parser.current_token.type == range_token_type::logical_or;
|
|
||||||
}
|
|
||||||
[[nodiscard]] constexpr bool is_operator_token() const noexcept {
|
|
||||||
return parser.current_token.type == range_token_type::range_operator;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool is_number_token() const noexcept {
|
|
||||||
return parser.current_token.type == range_token_type::number;
|
|
||||||
}
|
|
||||||
|
|
||||||
range_parser parser;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
enum struct satisfies_option : std::uint8_t {
|
|
||||||
exclude_prerelease,
|
|
||||||
include_prerelease
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr bool satisfies(
|
|
||||||
const version& ver,
|
|
||||||
std::string_view str,
|
|
||||||
satisfies_option option = satisfies_option::exclude_prerelease) {
|
|
||||||
switch (option) {
|
|
||||||
case satisfies_option::exclude_prerelease:
|
|
||||||
return detail::range{str}.satisfies(ver, false);
|
|
||||||
case satisfies_option::include_prerelease:
|
|
||||||
return detail::range{str}.satisfies(ver, true);
|
|
||||||
default:
|
|
||||||
SEMVER_THROW("semver::range unexpected satisfies_option.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace range
|
|
||||||
|
|
||||||
// Version lib semver.
|
|
||||||
inline constexpr auto semver_version =
|
|
||||||
version{SEMVER_VERSION_MAJOR, SEMVER_VERSION_MINOR, SEMVER_VERSION_PATCH};
|
|
||||||
|
|
||||||
} // namespace semver
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // NEARGYE_SEMANTIC_VERSIONING_HPP
|
|
||||||
71
src/lib.rs
Normal file
71
src/lib.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
mod utils;
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use semver::Version;
|
||||||
|
use utils::{exdll_init, popstring, pushint, stack_t, wchar_t};
|
||||||
|
use windows_sys::Win32::Foundation::HWND;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn SemverCompare(
|
||||||
|
_hwnd_parent: HWND,
|
||||||
|
string_size: u32,
|
||||||
|
variables: *mut wchar_t,
|
||||||
|
stacktop: *mut *mut stack_t,
|
||||||
|
) {
|
||||||
|
exdll_init(string_size, variables, stacktop);
|
||||||
|
|
||||||
|
let v1 = popstring().unwrap();
|
||||||
|
let v2 = popstring().unwrap();
|
||||||
|
|
||||||
|
let ret = semver_compare(&v1, &v2);
|
||||||
|
pushint(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn semver_compare(v1: &str, v2: &str) -> i32 {
|
||||||
|
let v1 = Version::from_str(&v1);
|
||||||
|
let v2 = Version::from_str(&v2);
|
||||||
|
|
||||||
|
let (v1, v2) = match (v1, v2) {
|
||||||
|
(Ok(_), Err(_)) => return 1,
|
||||||
|
(Err(_), Err(_)) => return 0,
|
||||||
|
(Err(_), Ok(_)) => return -1,
|
||||||
|
(Ok(v1), Ok(v2)) => (v1, v2),
|
||||||
|
};
|
||||||
|
|
||||||
|
if v1 > v2 {
|
||||||
|
1
|
||||||
|
} else if v1 == v2 {
|
||||||
|
0
|
||||||
|
} else if v1 < v2 {
|
||||||
|
-1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
for (v1, v2, ret) in [
|
||||||
|
("1.2.1", "1.2.0", 1),
|
||||||
|
("1.2.0", "1.2.1", -1),
|
||||||
|
("1.2.1", "1.2.1", 0),
|
||||||
|
("1.2.1-alpha.1", "1.2.1-beta.5", -1),
|
||||||
|
("1.2.1-rc.1", "1.2.1-beta.1", 1),
|
||||||
|
("1.2.1-alpha.1", "1.2.1-alpha.1", 0),
|
||||||
|
("1.2qe2.1-alpha.1", "1.2.1-alpha.1", -1),
|
||||||
|
("1.2.1-alpha.1", "-q1.2.1-alpha.1", 1),
|
||||||
|
("1.2.saf1-alpha.1", "-q1.2.1-alpha.1", 0),
|
||||||
|
("1.0.0-aluc.0", "1.0.0", -1),
|
||||||
|
(" 1.0.0-aluc.1", "1.0.0-bdfsf.0", -1),
|
||||||
|
("1.2.1-fffasd.1", "1.2.1-dasdqwe.1", 1),
|
||||||
|
("1.2.1-gasfdlkj.1", "1.2.1-calskjd.1", 1),
|
||||||
|
] {
|
||||||
|
assert_eq!(semver_compare(v1, v2), ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
82
src/utils.rs
Normal file
82
src/utils.rs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
ffi::{OsStr, OsString},
|
||||||
|
iter::once,
|
||||||
|
mem::{size_of, size_of_val},
|
||||||
|
os::windows::prelude::{OsStrExt, OsStringExt},
|
||||||
|
};
|
||||||
|
|
||||||
|
use windows_sys::Win32::{
|
||||||
|
Globalization::{lstrcpyW, lstrcpynW},
|
||||||
|
System::Memory::{GlobalAlloc, GlobalFree, GPTR},
|
||||||
|
};
|
||||||
|
|
||||||
|
static mut G_STRINGSIZE: u32 = 0;
|
||||||
|
static mut G_VARIABLES: *mut wchar_t = std::ptr::null_mut();
|
||||||
|
static mut G_STACKTOP: *mut *mut stack_t = std::ptr::null_mut();
|
||||||
|
|
||||||
|
pub unsafe fn exdll_init(string_size: u32, variables: *mut wchar_t, stacktop: *mut *mut stack_t) {
|
||||||
|
G_STRINGSIZE = string_size;
|
||||||
|
G_VARIABLES = variables;
|
||||||
|
G_STACKTOP = stacktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type wchar_t = i32;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct stack_t {
|
||||||
|
next: *mut stack_t,
|
||||||
|
text: [wchar_t; 1],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn pushstring(s: impl AsRef<OsStr>) {
|
||||||
|
if G_STACKTOP.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let string_wide = encode_wide(s);
|
||||||
|
let th: *mut stack_t = GlobalAlloc(
|
||||||
|
GPTR,
|
||||||
|
size_of::<stack_t>() + G_STRINGSIZE as usize * size_of_val(&string_wide),
|
||||||
|
) as _;
|
||||||
|
lstrcpynW(
|
||||||
|
(*th).text.as_ptr() as _,
|
||||||
|
string_wide.as_ptr() as _,
|
||||||
|
G_STRINGSIZE as _,
|
||||||
|
);
|
||||||
|
(*th).next = *G_STACKTOP;
|
||||||
|
*G_STACKTOP = th;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn popstring() -> Result<String, ()> {
|
||||||
|
if G_STACKTOP.is_null() || (*G_STACKTOP).is_null() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut string_wide: Vec<u16> = vec![0; G_STRINGSIZE as _];
|
||||||
|
let th: *mut stack_t = *G_STACKTOP;
|
||||||
|
lstrcpyW(string_wide.as_mut_ptr(), (*th).text.as_ptr() as _);
|
||||||
|
let string = decode_wide(&string_wide).to_str().ok_or(())?.to_string();
|
||||||
|
*G_STACKTOP = (*th).next;
|
||||||
|
GlobalFree(th as _);
|
||||||
|
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn pushint(int: i32) {
|
||||||
|
pushstring(int.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_wide(string: impl AsRef<OsStr>) -> Vec<u16> {
|
||||||
|
string.as_ref().encode_wide().chain(once(0)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_wide(mut wide_c_string: &[u16]) -> OsString {
|
||||||
|
if let Some(null_pos) = wide_c_string.iter().position(|c| *c == 0) {
|
||||||
|
wide_c_string = &wide_c_string[..null_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
OsString::from_wide(wide_c_string)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user