Re-write Stub to execute Update.exe --processStart

This commit is contained in:
Caelan Sayler
2022-04-24 21:54:18 +01:00
parent 4d13304699
commit aba0d1d641
14 changed files with 204 additions and 979 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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.

View File

@@ -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;
}
}

View File

@@ -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());
}
}
}

View File

@@ -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);
}
}

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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() }
{}
};
}

View File

@@ -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

View 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

View File

@@ -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>

View File

@@ -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"

View File

@@ -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);
}
}