mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Re-write Stub to execute Update.exe --processStart
This commit is contained in:
106
Squirrel.sln
106
Squirrel.sln
@@ -18,13 +18,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionLevel", "SolutionLe
|
||||
version.json = version.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubExecutable\StubExecutable.vcxproj", "{C028DB2A-E7C5-4232-8C22-D5FBA2176136}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SquirrelCli", "src\SquirrelCli\SquirrelCli.csproj", "{19E8EBF5-0277-422F-BF49-C66D9DBA5AA4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Setup", "src\Setup\Setup.vcxproj", "{6B406985-B2E1-4FED-A405-BD0694D68E93}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrel.Shared", "src\Squirrel.Shared\Squirrel.Shared.csproj", "{352C15EA-622F-4132-80D8-9B6E3C83404E}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrel.Shared", "src\Squirrel.Shared\Squirrel.Shared.csproj", "{352C15EA-622F-4132-80D8-9B6E3C83404E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubExecutable\StubExecutable.vcxproj", "{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -198,54 +198,6 @@ Global
|
||||
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.Build.0 = Debug|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.ActiveCfg = Debug|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.Build.0 = Debug|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.Build.0 = Debug|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.ActiveCfg = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.Build.0 = Release|x64
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.Build.0 = Release|Win32
|
||||
{19E8EBF5-0277-422F-BF49-C66D9DBA5AA4}.CIBuild|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19E8EBF5-0277-422F-BF49-C66D9DBA5AA4}.CIBuild|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19E8EBF5-0277-422F-BF49-C66D9DBA5AA4}.CIBuild|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
@@ -314,8 +266,8 @@ Global
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|Mixed Platforms.Build.0 = Debug|x64
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x64.Build.0 = Debug|x64
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x64.Build.0 = Debug|Win32
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93}.Mono Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
@@ -390,6 +342,54 @@ Global
|
||||
{352C15EA-622F-4132-80D8-9B6E3C83404E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{352C15EA-622F-4132-80D8-9B6E3C83404E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{352C15EA-622F-4132-80D8-9B6E3C83404E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|Any CPU.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|Any CPU.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|Mixed Platforms.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|x64.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|x64.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|x86.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.CIBuild|x86.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|Any CPU.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|Any CPU.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|Mixed Platforms.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|x64.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|x64.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|x86.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Coverage|x86.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|Mixed Platforms.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|x64.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|Mixed Platforms.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|x64.ActiveCfg = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|x64.Build.0 = Debug|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|x86.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Debug|x86.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|Any CPU.ActiveCfg = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|Any CPU.Build.0 = Debug|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|Mixed Platforms.Build.0 = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|x64.ActiveCfg = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|x64.Build.0 = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|x86.ActiveCfg = Release|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Mono Release|x86.Build.0 = Release|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|Any CPU.Build.0 = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|x64.ActiveCfg = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|x64.Build.0 = Release|x64
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -21,7 +21,7 @@ foreach ($Folder in $Folders) {
|
||||
}
|
||||
|
||||
# Build Squirrel C++ with msbuild as dotnet can't
|
||||
&"$MSBuildPath" /verbosity:minimal /restore /p:Configuration=Release
|
||||
&"$MSBuildPath" /verbosity:minimal /restore /p:Configuration=Release /p:Platform=x86
|
||||
|
||||
# Build single-exe packaged projects
|
||||
# New-Item -Path "$Out" -Name "win-x86" -ItemType "directory"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
This executable uses the semver library from https://github.com/zmarko/semver, under the following license:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Živanovc
|
||||
|
||||
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.
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Zivanovic
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "semver200.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace version
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Compare normal version identifiers.
|
||||
int compare_normal(const Version_data& l, const Version_data& r)
|
||||
{
|
||||
if (l.major > r.major) return 1;
|
||||
if (l.major < r.major) return -1;
|
||||
if (l.minor > r.minor) return 1;
|
||||
if (l.minor < r.minor) return -1;
|
||||
if (l.patch > r.patch) return 1;
|
||||
if (l.patch < r.patch) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare alphanumeric prerelease identifiers.
|
||||
inline int cmp_alnum_prerel_ids(const string& l, const string& r) {
|
||||
// If both versions have a prerelease section with the same prefix
|
||||
// and end with digits, compare based on the digits' numeric order
|
||||
auto index_l = l.find_last_not_of("0123456789");
|
||||
auto index_r = r.find_last_not_of("0123456789");
|
||||
|
||||
if (index_l != string::npos && index_r != string::npos) {
|
||||
string name_l = l.substr(0, index_l + 1);
|
||||
string name_r = r.substr(0, index_r + 1);
|
||||
|
||||
if (name_l == name_r) {
|
||||
int il = stoi(l.substr(index_l + 1));
|
||||
int ir = stoi(r.substr(index_r + 1));
|
||||
|
||||
return il > ir ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
auto cmp = l.compare(r);
|
||||
|
||||
if (cmp == 0) {
|
||||
return cmp;
|
||||
} else {
|
||||
return cmp > 0 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare numeric prerelease identifiers.
|
||||
inline int cmp_num_prerel_ids(const string& l, const string& r)
|
||||
{
|
||||
long long li = stoll(l);
|
||||
long long ri = stoll(r);
|
||||
if (li == ri) return 0;
|
||||
return li > ri ? 1 : -1;
|
||||
}
|
||||
|
||||
using Prerel_type_pair = pair<Id_type, Id_type>;
|
||||
using Prerel_id_comparator = function<int(const string&, const string&)>;
|
||||
const map<Prerel_type_pair, Prerel_id_comparator> comparators = {
|
||||
{ { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids },
|
||||
{ { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} },
|
||||
{ { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} },
|
||||
{ { Id_type::num, Id_type::num }, cmp_num_prerel_ids }
|
||||
};
|
||||
|
||||
// Compare prerelease identifiers based on their types.
|
||||
inline int compare_prerel_identifiers(const Prerelease_identifier& l, const Prerelease_identifier& r)
|
||||
{
|
||||
auto cmp = comparators.at({ l.second, r.second });
|
||||
return cmp(l.first, r.first);
|
||||
}
|
||||
|
||||
inline int cmp_rel_prerel(const Prerelease_identifiers& l, const Prerelease_identifiers& r)
|
||||
{
|
||||
if (l.empty() && !r.empty()) return 1;
|
||||
if (r.empty() && !l.empty()) return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const
|
||||
{
|
||||
// Compare normal version components.
|
||||
int cmp = compare_normal(l, r);
|
||||
if (cmp != 0) return cmp;
|
||||
|
||||
// Compare if one version is release and the other prerelease - release is always higher.
|
||||
cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids);
|
||||
if (cmp != 0) return cmp;
|
||||
|
||||
// Compare prerelease by looking at each identifier: numeric ones are compared as numbers,
|
||||
// alphanum as ASCII strings.
|
||||
auto shorter = min(l.prerelease_ids.size(), r.prerelease_ids.size());
|
||||
for (size_t i = 0; i < shorter; i++) {
|
||||
cmp = compare_prerel_identifiers(l.prerelease_ids[i], r.prerelease_ids[i]);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
|
||||
// Prerelease identifiers are the same, to the length of the shorter version string;
|
||||
// if they are the same length, then versions are equal, otherwise, longer one wins.
|
||||
if (l.prerelease_ids.size() == r.prerelease_ids.size()) return 0;
|
||||
return l.prerelease_ids.size() > r.prerelease_ids.size() ? 1 : -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Zivanovic
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "semver200.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disable symbol name too long warning
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace version
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class Parser_state
|
||||
{
|
||||
major, minor, patch, prerelease, build
|
||||
};
|
||||
|
||||
using Validator = function<void(const string&, const char)>;
|
||||
using State_transition_hook = function<void(string&)>;
|
||||
/// State transition is described by a character that triggers it, a state to transition to and
|
||||
/// optional hook to be invoked on transition.
|
||||
using Transition = tuple<const char, Parser_state, State_transition_hook>;
|
||||
using Transitions = vector<Transition>;
|
||||
using State = tuple<Transitions, string&, Validator>;
|
||||
using State_machine = map<Parser_state, State>;
|
||||
|
||||
// Ranges of characters allowed in prerelease and build identifiers.
|
||||
const vector<pair<char, char>> allowed_prerel_id_chars = {
|
||||
{ '0', '9' },{ 'A','Z' },{ 'a','z' },{ '-','-' }
|
||||
};
|
||||
|
||||
inline Transition mkx(const char c, Parser_state p, State_transition_hook pth)
|
||||
{
|
||||
return make_tuple(c, p, pth);
|
||||
}
|
||||
|
||||
/// Advance parser state machine by a single step.
|
||||
/**
|
||||
Perform single step of parser state machine: if character matches one from transition tables -
|
||||
trigger transition to next state; otherwise, validate if current token is in legal state
|
||||
(throw Parse_error if not) and then add character to current token; State transition includes
|
||||
preparing various vars for next state and invoking state transition hook (if specified) which is
|
||||
where whole tokens are validated.
|
||||
*/
|
||||
inline void process_char(const char c, Parser_state& cstate, Parser_state& pstate,
|
||||
const Transitions& transitions, string& target, Validator validate)
|
||||
{
|
||||
for (const auto& transition : transitions) {
|
||||
if (c == get<0>(transition)) {
|
||||
if (get<2>(transition)) get<2>(transition)(target);
|
||||
pstate = cstate;
|
||||
cstate = get<1>(transition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
validate(target, c);
|
||||
target.push_back(c);
|
||||
}
|
||||
|
||||
/// Validate normal (major, minor, patch) version components.
|
||||
inline void normal_version_validator(const string& tgt, const char c)
|
||||
{
|
||||
if (c < '0' || c > '9') throw Parse_error("invalid character encountered: " + string(1, c));
|
||||
if (tgt.compare(0, 1, "0") == 0) throw Parse_error("leading 0 not allowed");
|
||||
}
|
||||
|
||||
/// Validate that prerelease and build version identifiers are comprised of allowed chars only.
|
||||
inline void prerelease_version_validator(const string&, const char c)
|
||||
{
|
||||
bool res = false;
|
||||
for (const auto& r : allowed_prerel_id_chars) {
|
||||
res |= (c >= r.first && c <= r.second);
|
||||
}
|
||||
if (!res)
|
||||
throw Parse_error("invalid character encountered: " + string(1, c));
|
||||
}
|
||||
|
||||
inline bool is_identifier_numeric(const string& id)
|
||||
{
|
||||
return id.find_first_not_of("0123456789") == string::npos;
|
||||
}
|
||||
|
||||
inline bool check_for_leading_0(const string& str)
|
||||
{
|
||||
return str.length() > 1 && str[0] == '0';
|
||||
}
|
||||
|
||||
/// Validate every individual prerelease identifier, determine it's type and add it to collection.
|
||||
void prerelease_hook_impl(string& id, Prerelease_identifiers& prerelease)
|
||||
{
|
||||
if (id.empty()) throw Parse_error("version identifier cannot be empty");
|
||||
Id_type t = Id_type::alnum;
|
||||
if (is_identifier_numeric(id)) {
|
||||
t = Id_type::num;
|
||||
if (check_for_leading_0(id)) {
|
||||
throw Parse_error("numeric identifiers cannot have leading 0");
|
||||
}
|
||||
}
|
||||
prerelease.push_back(Prerelease_identifier(id, t));
|
||||
id.clear();
|
||||
}
|
||||
|
||||
/// Validate every individual build identifier and add it to collection.
|
||||
void build_hook_impl(string& id, Parser_state& pstate, Build_identifiers& build,
|
||||
std::string& prerelease_id, Prerelease_identifiers& prerelease)
|
||||
{
|
||||
// process last token left from parsing prerelease data
|
||||
if (pstate == Parser_state::prerelease) prerelease_hook_impl(prerelease_id, prerelease);
|
||||
if (id.empty()) throw Parse_error("version identifier cannot be empty");
|
||||
build.push_back(id);
|
||||
id.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Parse semver 2.0.0-compatible string to Version_data structure.
|
||||
/**
|
||||
Version text parser is implemented as a state machine. In each step one successive character from version
|
||||
string is consumed and is either added to current token or triggers state transition. Hooks can be
|
||||
injected into state transitions for validation/customization purposes.
|
||||
*/
|
||||
Version_data Semver200_parser::parse(const string& s) const
|
||||
{
|
||||
string major;
|
||||
string minor;
|
||||
string patch;
|
||||
string prerelease_id;
|
||||
string build_id;
|
||||
Prerelease_identifiers prerelease;
|
||||
Build_identifiers build;
|
||||
Parser_state cstate{ Parser_state::major };
|
||||
Parser_state pstate;
|
||||
|
||||
auto prerelease_hook = [&](string& id) {
|
||||
prerelease_hook_impl(id, prerelease);
|
||||
};
|
||||
|
||||
auto build_hook = [&](string& id) {
|
||||
build_hook_impl(id, pstate, build, prerelease_id, prerelease);
|
||||
};
|
||||
|
||||
// State transition tables
|
||||
auto major_trans = {
|
||||
mkx('.', Parser_state::minor, {})
|
||||
};
|
||||
auto minor_trans = {
|
||||
mkx('.', Parser_state::patch, {})
|
||||
};
|
||||
auto patch_trans = {
|
||||
mkx('-', Parser_state::prerelease, {}),
|
||||
mkx('+', Parser_state::build, {})
|
||||
};
|
||||
auto prerelease_trans = {
|
||||
// When identifier separator (.) is found, stay in the same state but invoke hook
|
||||
// in order to process each individual identifier separately.
|
||||
mkx('.', Parser_state::prerelease, prerelease_hook),
|
||||
mkx('+', Parser_state::build, {})
|
||||
};
|
||||
auto build_trans = {
|
||||
// Same stay-in-the-same-state-but-invoke-hook trick from above.
|
||||
mkx('.', Parser_state::build, build_hook)
|
||||
};
|
||||
|
||||
State_machine state_machine = {
|
||||
{Parser_state::major, State{major_trans, major, normal_version_validator}},
|
||||
{Parser_state::minor, State{minor_trans, minor, normal_version_validator}},
|
||||
{Parser_state::patch, State{patch_trans, patch, normal_version_validator}},
|
||||
{Parser_state::prerelease, State{prerelease_trans, prerelease_id, prerelease_version_validator}},
|
||||
{Parser_state::build, State{build_trans, build_id, prerelease_version_validator}}
|
||||
};
|
||||
|
||||
// Main loop.
|
||||
for (const auto& c : s) {
|
||||
auto state = state_machine.at(cstate);
|
||||
process_char(c, cstate, pstate, get<0>(state), get<1>(state), get<2>(state));
|
||||
}
|
||||
|
||||
// Trigger appropriate hooks in order to process last token, because no state transition was
|
||||
// triggered for it.
|
||||
if (cstate == Parser_state::prerelease) {
|
||||
prerelease_hook(prerelease_id);
|
||||
}
|
||||
else if (cstate == Parser_state::build) {
|
||||
build_hook(build_id);
|
||||
}
|
||||
|
||||
try {
|
||||
return Version_data{ stoi(major), stoi(minor), stoi(patch), prerelease, build };
|
||||
}
|
||||
catch (invalid_argument& ex) {
|
||||
throw Parse_error(ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +1,159 @@
|
||||
// StubExecutable.cpp : Defines the entry point for the application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "semver200.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
wchar_t* FindRootAppDir()
|
||||
void throwLastWin32Error(wstring addedInfo)
|
||||
{
|
||||
wchar_t* ourDirectory = new wchar_t[MAX_PATH];
|
||||
HRESULT hr = GetLastError();
|
||||
if (hr == 0) return;
|
||||
|
||||
GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH);
|
||||
wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\');
|
||||
if (!lastSlash) {
|
||||
delete[] ourDirectory;
|
||||
return NULL;
|
||||
// https://stackoverflow.com/a/17387176/184746
|
||||
// https://stackoverflow.com/a/455533/184746
|
||||
LPWSTR messageBuffer = nullptr;
|
||||
size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL);
|
||||
|
||||
wstring message(messageBuffer, size);
|
||||
|
||||
if (messageBuffer) {
|
||||
LocalFree(messageBuffer);
|
||||
messageBuffer = nullptr;
|
||||
}
|
||||
|
||||
// Null-terminate the string at the slash so now it's a directory
|
||||
*lastSlash = 0x0;
|
||||
return ourDirectory;
|
||||
if (addedInfo.empty()) throw message;
|
||||
else throw wstring(addedInfo + L" " + message);
|
||||
}
|
||||
|
||||
wchar_t* FindOwnExecutableName()
|
||||
wstring getProcessPath()
|
||||
{
|
||||
wchar_t* ourDirectory = new wchar_t[MAX_PATH];
|
||||
|
||||
GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH);
|
||||
wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\');
|
||||
if (!lastSlash) {
|
||||
delete[] ourDirectory;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t* ret = _wcsdup(lastSlash + 1);
|
||||
delete[] ourDirectory;
|
||||
return ret;
|
||||
wchar_t ourFile[MAX_PATH];
|
||||
HMODULE hMod = GetModuleHandle(NULL);
|
||||
GetModuleFileName(hMod, ourFile, _countof(ourFile));
|
||||
return wstring(ourFile);
|
||||
}
|
||||
|
||||
std::wstring FindLatestAppDir()
|
||||
void wexec(const wchar_t* cmd)
|
||||
{
|
||||
std::wstring ourDir;
|
||||
ourDir.assign(FindRootAppDir());
|
||||
LPTSTR szCmdline = _tcsdup(cmd); // https://stackoverflow.com/a/10044348/184746
|
||||
|
||||
ourDir += L"\\app-*";
|
||||
STARTUPINFO si = { 0 };
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.wShowWindow = SW_SHOW;
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
|
||||
WIN32_FIND_DATA fileInfo = { 0 };
|
||||
HANDLE hFile = FindFirstFile(ourDir.c_str(), &fileInfo);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
if (!CreateProcess(NULL, szCmdline, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
|
||||
throwLastWin32Error(L"Unable to start process.");
|
||||
}
|
||||
|
||||
version::Semver200_version acc("0.0.0");
|
||||
std::wstring acc_s;
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
do {
|
||||
std::wstring appVer = fileInfo.cFileName;
|
||||
appVer = appVer.substr(4); // Skip 'app-'
|
||||
if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
vector<wchar_t> commandChars{ L' ', L'"', L'\n', L'\t', L'\v' };
|
||||
wstring argsToCommandLine(const vector<wstring>& args)
|
||||
{
|
||||
wstringstream ss;
|
||||
for (unsigned int i = 0; i < args.size(); i++) {
|
||||
auto& arg = args[i];
|
||||
if (arg.empty()) continue;
|
||||
if (ss.tellp() > 0) ss << L" ";
|
||||
|
||||
bool ctrlChar = false;
|
||||
for (unsigned int n = 0; n < commandChars.size(); n++) {
|
||||
if (arg.find(commandChars[n]) != wstring::npos) {
|
||||
// there is a control char in this argument
|
||||
ctrlChar = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctrlChar) {
|
||||
ss << arg;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
#pragma warning( disable : 4244 ) // warning - conversion from 'wchar_t' to 'const _Elem', possible loss of data
|
||||
std::string s(appVer.begin(), appVer.end());
|
||||
|
||||
version::Semver200_version thisVer(s);
|
||||
|
||||
if (thisVer > acc) {
|
||||
acc = thisVer;
|
||||
acc_s = appVer;
|
||||
// need to surround with quotes and escape all the control characters
|
||||
ss << L"\"";
|
||||
for (unsigned int c = 0; c < arg.size(); c++) {
|
||||
int backslashes = 0;
|
||||
while (c < arg.size() && arg[c] == L'\\') {
|
||||
c++;
|
||||
backslashes++;
|
||||
}
|
||||
if (c == arg.size()) {
|
||||
ss << wstring(backslashes * 2, '\\');
|
||||
break;
|
||||
}
|
||||
else if (arg[c] == '"') {
|
||||
ss << wstring(backslashes * 2 + 1, '\\');
|
||||
ss << L"\"";
|
||||
}
|
||||
else {
|
||||
ss << wstring(backslashes, '\\');
|
||||
ss << arg[c];
|
||||
}
|
||||
}
|
||||
} while (FindNextFile(hFile, &fileInfo));
|
||||
|
||||
if (acc == version::Semver200_version("0.0.0")) {
|
||||
return NULL;
|
||||
ss << L"\"";
|
||||
}
|
||||
|
||||
ourDir.assign(FindRootAppDir());
|
||||
std::wstringstream ret;
|
||||
ret << ourDir << L"\\app-" << acc_s;
|
||||
|
||||
FindClose(hFile);
|
||||
return ret.str();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
||||
_In_opt_ HINSTANCE hPrevInstance,
|
||||
_In_ LPWSTR lpCmdLine,
|
||||
_In_ int nCmdShow)
|
||||
// https://stackoverflow.com/a/3418285/184746
|
||||
bool replace(std::wstring& str, const std::wstring& from, const std::wstring& to)
|
||||
{
|
||||
std::wstring appName;
|
||||
appName.assign(FindOwnExecutableName());
|
||||
|
||||
std::wstring workingDir(FindLatestAppDir());
|
||||
std::wstring fullPath(workingDir + L"\\" + appName);
|
||||
|
||||
STARTUPINFO si = { 0 };
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = nCmdShow;
|
||||
|
||||
std::wstring cmdLine(L"\"");
|
||||
cmdLine += fullPath;
|
||||
cmdLine += L"\" ";
|
||||
cmdLine += lpCmdLine;
|
||||
|
||||
wchar_t* lpCommandLine = _wcsdup(cmdLine.c_str());
|
||||
wchar_t* lpCurrentDirectory = _wcsdup(workingDir.c_str());
|
||||
if (!CreateProcess(NULL, lpCommandLine, NULL, NULL, true, 0, NULL, lpCurrentDirectory, &si, &pi)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AllowSetForegroundWindow(pi.dwProcessId);
|
||||
WaitForInputIdle(pi.hProcess, 5 * 1000);
|
||||
return 0;
|
||||
size_t start_pos = str.find(from);
|
||||
if (start_pos == std::wstring::npos)
|
||||
return false;
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
|
||||
{
|
||||
try {
|
||||
wstring myexepath = getProcessPath();
|
||||
wstring arguments(lpCmdLine);
|
||||
bool dryRun = replace(arguments, L"--stub-dry-run", L"");
|
||||
|
||||
auto lastSlash = myexepath.find_last_of(L'\\');
|
||||
if (lastSlash == wstring::npos) {
|
||||
throw wstring(L"Unable to find/parse running exe file path (no backslash).");
|
||||
}
|
||||
|
||||
wstring mydirectory = myexepath.substr(0, lastSlash);
|
||||
wstring myname = myexepath.substr(lastSlash + 1);
|
||||
if (myname.empty() || mydirectory.empty()) {
|
||||
throw wstring(L"Unable to find/parse running exe file path (empty).");
|
||||
}
|
||||
|
||||
wstring updatepath = mydirectory + L"\\Update.exe";
|
||||
|
||||
vector<wstring> nargs{};
|
||||
nargs.push_back(updatepath);
|
||||
nargs.emplace_back(L"--processStart");
|
||||
nargs.push_back(myname);
|
||||
|
||||
if (!arguments.empty()) {
|
||||
nargs.emplace_back(L"--process-start-args");
|
||||
nargs.push_back(arguments);
|
||||
}
|
||||
|
||||
wstring cmd = argsToCommandLine(nargs);
|
||||
|
||||
if (dryRun) MessageBox(0, cmd.c_str(), L"Stub Test Run", MB_OK);
|
||||
else wexec(cmd.c_str());
|
||||
}
|
||||
catch (wstring err) {
|
||||
wstring message = L"Stub: " + err;
|
||||
MessageBox(0, message.c_str(), L"Stub Failed", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
catch (...) {
|
||||
MessageBox(0, L"An unknown error has occurred.", L"Stub Failed", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -19,7 +19,8 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C028DB2A-E7C5-4232-8C22-D5FBA2176136}</ProjectGuid>
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{611a03d4-4cde-4da0-b151-de6faffb8b8c}</ProjectGuid>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>StubExecutable</RootNamespace>
|
||||
@@ -67,12 +68,12 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ControlFlowGuard>false</ControlFlowGuard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -81,10 +82,12 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -94,11 +97,12 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ControlFlowGuard>Guard</ControlFlowGuard>
|
||||
@@ -113,11 +117,15 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ControlFlowGuard>Guard</ControlFlowGuard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -127,18 +135,6 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="semver200.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
<ClInclude Include="version.inl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Semver200_comparator.cpp" />
|
||||
<ClCompile Include="Semver200_parser.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StubExecutable.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
@@ -15,34 +15,8 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="semver200.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.inl">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StubExecutable.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Semver200_comparator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Semver200_parser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Zivanovic
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "version.h"
|
||||
|
||||
namespace version
|
||||
{
|
||||
|
||||
/// Parse string into Version_data structure according to semantic versioning 2.0.0 rules.
|
||||
struct Semver200_parser
|
||||
{
|
||||
Version_data parse(const std::string&) const;
|
||||
};
|
||||
|
||||
/// Compare Version_data to another using semantic versioning 2.0.0 rules.
|
||||
struct Semver200_comparator
|
||||
{
|
||||
int compare(const Version_data&, const Version_data&) const;
|
||||
};
|
||||
|
||||
/// Concrete version class that binds all semver 2.0.0 functionality together.
|
||||
class Semver200_version : public Basic_version<Semver200_parser, Semver200_comparator>
|
||||
{
|
||||
public:
|
||||
Semver200_version()
|
||||
: Basic_version{ Semver200_parser(), Semver200_comparator() }
|
||||
{}
|
||||
|
||||
Semver200_version(const std::string& v)
|
||||
: Basic_version{ v, Semver200_parser(), Semver200_comparator() }
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// StubExecutable.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -1,23 +0,0 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
|
||||
// C RunTime Header Files
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#include <tchar.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Zivanovic
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace version
|
||||
{
|
||||
|
||||
/// Any error in parsing or validation of version string will result in Parse_error exception being thrown.
|
||||
class Parse_error : public std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Type of prerelease identifier: alphanumeric or numeric.
|
||||
/**
|
||||
Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while
|
||||
numeric identifiers are compared as numbers.
|
||||
*/
|
||||
enum class Id_type
|
||||
{
|
||||
alnum, ///< Identifier is alphanumerical
|
||||
num ///< Identifier is numeric
|
||||
};
|
||||
|
||||
/// Container for prerelease identifier value and it's type.
|
||||
/**
|
||||
Prerelease version string consist of an optional series of dot-separated identifiers.
|
||||
These identifiers can be either numerical or alphanumerical.
|
||||
This structure describes one such identifier.
|
||||
*/
|
||||
using Prerelease_identifier = std::pair<std::string, Id_type>;
|
||||
|
||||
/// Container for all prerelease identifiers for a given version string.
|
||||
using Prerelease_identifiers = std::vector<Prerelease_identifier>;
|
||||
|
||||
/// Build identifier is arbitrary string with no special meaning with regards to version precedence.
|
||||
using Build_identifier = std::string;
|
||||
|
||||
/// Container for all build identifiers of a given version string.
|
||||
using Build_identifiers = std::vector<Build_identifier>;
|
||||
|
||||
/// Description of version broken into parts, as per semantic versioning specification.
|
||||
struct Version_data
|
||||
{
|
||||
int major; ///< Major version, change only on incompatible API modifications.
|
||||
int minor; ///< Minor version, change on backwards-compatible API modifications.
|
||||
int patch; ///< Patch version, change only on bugfixes.
|
||||
|
||||
/// Optional series of prerelease identifiers.
|
||||
Prerelease_identifiers prerelease_ids;
|
||||
|
||||
/// Optional series of build identifiers.
|
||||
Build_identifiers build_ids;
|
||||
};
|
||||
|
||||
// Forward declaration required for operators' template declarations.
|
||||
template<typename Parser, typename Comparator>
|
||||
class Basic_version;
|
||||
|
||||
/// Test if left-hand version operand is of lower precedence than the right-hand version.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator<(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Test if left-hand version operand if of equal precedence as the right-hand version.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator==(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Output version object to stream using standard semver format (X.Y.Z-PR+B).
|
||||
template<typename Parser, typename Comparator>
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Test if left-hand version and right-hand version are of different precedence.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator!=(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Test if left-hand version operand is of higher precedence than the right-hand version.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator>(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Test if left-hand version operand is of higher or equal precedence as the right-hand version.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator>=(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
/// Test if left-hand version operand is of lower or equal precedence as the right-hand version.
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator<=(const Basic_version<Parser, Comparator>&,
|
||||
const Basic_version<Parser, Comparator>&);
|
||||
|
||||
|
||||
/// Base class for various version parsing and precedence ordering schemes.
|
||||
/**
|
||||
Basic_version class describes general version object without prescribing parsing,
|
||||
validation and comparison rules. These rules are implemented by supplied Parser and
|
||||
Comparator objects.
|
||||
*/
|
||||
template<typename Parser, typename Comparator>
|
||||
class Basic_version
|
||||
{
|
||||
public:
|
||||
/// Construct Basic_version object using Parser object to parse default ("0.0.0") version string and Comparator for comparison.
|
||||
Basic_version(Parser, Comparator);
|
||||
|
||||
/// Construct Basic_version object using Parser to parse supplied version string and Comparator for comparison.
|
||||
Basic_version(const std::string&, Parser, Comparator);
|
||||
|
||||
/// Construct Basic_version by copying data from another one.
|
||||
Basic_version(const Basic_version&);
|
||||
|
||||
/// Copy version data from another Basic_version to this one.
|
||||
Basic_version& operator=(const Basic_version&);
|
||||
|
||||
int major() const; ///< Get major version.
|
||||
int minor() const; ///< Get minor version.
|
||||
int patch() const; ///< Get patch version.
|
||||
const std::string prerelease() const; ///< Get prerelease version string.
|
||||
const std::string build() const; ///< Get build version string.
|
||||
|
||||
friend bool operator< <>(const Basic_version&, const Basic_version&);
|
||||
friend bool operator== <>(const Basic_version&, const Basic_version&);
|
||||
friend std::ostream& operator<< <>(std::ostream& s, const Basic_version&);
|
||||
|
||||
private:
|
||||
Parser parser_;
|
||||
Comparator comparator_;
|
||||
Version_data ver_;
|
||||
};
|
||||
}
|
||||
|
||||
#include "version.inl"
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marko Zivanovic
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include "version.h"
|
||||
|
||||
namespace version {
|
||||
|
||||
namespace {
|
||||
|
||||
/// Utility function to splice all vector elements to output stream, using designated separator
|
||||
/// between elements and function object for getting values from vector elements.
|
||||
template<typename T, typename F>
|
||||
std::ostream& splice(std::ostream& os, const std::vector<T>& vec, const std::string& sep, F read) {
|
||||
if (!vec.empty()) {
|
||||
for (auto it = vec.cbegin(); it < vec.cend() - 1; ++it) {
|
||||
os << read(*it) << sep;
|
||||
}
|
||||
os << read(*vec.crbegin());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
Basic_version<Parser, Comparator>::Basic_version(Parser p, Comparator c)
|
||||
: parser_(p), comparator_(c), ver_(parser_.parse("0.0.0")) {}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
Basic_version<Parser, Comparator>::Basic_version(const std::string& v, Parser p, Comparator c)
|
||||
: parser_(p), comparator_(c), ver_(parser_.parse(v)) {}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
Basic_version<Parser, Comparator>::Basic_version(const Basic_version<Parser, Comparator>&) = default;
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
Basic_version<Parser, Comparator>& Basic_version<Parser, Comparator>::operator=(
|
||||
const Basic_version<Parser, Comparator>&) = default;
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
int Basic_version<Parser, Comparator>::major() const {
|
||||
return ver_.major;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
int Basic_version<Parser, Comparator>::minor() const {
|
||||
return ver_.minor;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
int Basic_version<Parser, Comparator>::patch() const {
|
||||
return ver_.patch;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
const std::string Basic_version<Parser, Comparator>::prerelease() const {
|
||||
std::stringstream ss;
|
||||
splice(ss, ver_.prerelease_ids, ".", [](const auto& id) { return id.first;});
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
const std::string Basic_version<Parser, Comparator>::build() const {
|
||||
std::stringstream ss;
|
||||
splice(ss, ver_.build_ids, ".", [](const auto& id) { return id;});
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator<(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return l.comparator_.compare(l.ver_, r.ver_) == -1;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
bool operator==(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return l.comparator_.compare(l.ver_, r.ver_) == 0;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
const Basic_version<Parser, Comparator>& v) {
|
||||
os << v.ver_.major << "." << v.ver_.minor << "." << v.ver_.patch;
|
||||
std::string prl = v.prerelease();
|
||||
if (!prl.empty()) {
|
||||
os << "-" << prl;
|
||||
}
|
||||
std::string bld = v.build();
|
||||
if (!bld.empty()) {
|
||||
os << "+" << bld;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
inline bool operator!=(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
inline bool operator>(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return r < l;
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
inline bool operator>=(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return !(l < r);
|
||||
}
|
||||
|
||||
template<typename Parser, typename Comparator>
|
||||
inline bool operator<=(const Basic_version<Parser, Comparator>& l,
|
||||
const Basic_version<Parser, Comparator>& r) {
|
||||
return !(l > r);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user