mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
v1.0.2
This commit is contained in:
parent
d0fc286c43
commit
4423d5f3d5
@ -4,10 +4,6 @@ cd src
|
||||
msbuild olympus.sln /t:Rebuild /p:Configuration=Release
|
||||
cd ..
|
||||
|
||||
cd configurator
|
||||
msbuild configurator.sln /t:Rebuild /p:Configuration=Release
|
||||
cd ..
|
||||
|
||||
cd client
|
||||
rmdir /s /q "hgt"
|
||||
call npm install
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
call build.bat
|
||||
call "C:\Program Files (x86)\Inno Setup 6\iscc.exe" "installer\olympus.iss"
|
||||
call "C:\Program Files (x86)\Inno Setup 6\iscc.exe" "installer\olympus.iss" \DNode
|
||||
|
||||
@ -112,5 +112,7 @@ function onListening() {
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
|
||||
console.log("DCS Olympus server v1.0.1 started correctly!")
|
||||
console.log("DCS Olympus server v1.0.2 started correctly!")
|
||||
console.log("Waiting for connections...")
|
||||
|
||||
process.title = `DCS Olympus server v1.0.2 (${port})`;
|
||||
9041
client/package-lock.json
generated
9041
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"version": "v1.0.1",
|
||||
"version": "v1.0.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "browserify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
|
||||
|
||||
@ -29,7 +29,7 @@ import { UnitListPanel } from "./panels/unitlistpanel";
|
||||
import { ContextManager } from "./context/contextmanager";
|
||||
import { Context } from "./context/context";
|
||||
|
||||
var VERSION = "v1.0.1";
|
||||
var VERSION = "v1.0.2";
|
||||
var DEBUG = false;
|
||||
|
||||
export class OlympusApp {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div id="app-summary">
|
||||
<h2>DCS Olympus</h2>
|
||||
<h4>Dynamic Unit Command</h4>
|
||||
<div class="app-version">Version <span class="app-version-number">v1.0.1</span></div>
|
||||
<div class="app-version">Version <span class="app-version-number">v1.0.2</span></div>
|
||||
<div class="app-version">Latest version <span id="latest-version" class="app-version-number"></span></div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<div class="ol-select-options">
|
||||
<div id="toolbar-summary">
|
||||
<h3>DCS Olympus</h3>
|
||||
<div class="accent-green app-version-number">version v1.0.1</div>
|
||||
<div class="accent-green app-version-number">version v1.0.2</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://discord.gg/wWXyVVBZT7" target="_blank">Discord</a>
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32929.385
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "configurator", "configurator\configurator.vcxproj", "{FF484257-F6D1-43E9-B6BA-A892B86E8963}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Debug|x64.Build.0 = Debug|x64
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Debug|x86.Build.0 = Debug|Win32
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Release|x64.ActiveCfg = Release|x64
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Release|x64.Build.0 = Release|x64
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Release|x86.ActiveCfg = Release|Win32
|
||||
{FF484257-F6D1-43E9-B6BA-A892B86E8963}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {19612EF0-B177-4572-A304-ECE142C31BDC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -1,170 +0,0 @@
|
||||
// configurator.cpp : This file contains the 'main' function. Program execution begins and ends there.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "argparse/argparse.hpp"
|
||||
#include "sha256.h"
|
||||
#include "windows.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
||||
using json = nlohmann::json;
|
||||
using namespace std;
|
||||
|
||||
struct MyArgs : public argparse::Args {
|
||||
string& address = kwarg("a", "Address");
|
||||
int& clientPort = kwarg("c", "Client port");
|
||||
int& backendPort = kwarg("b", "Backend port");
|
||||
string& gameMasterPassword = kwarg("p", "Game master password");
|
||||
string& blueCommanderPassword = kwarg("bp", "Blue commander password");
|
||||
string& redCommanderPassword = kwarg("rp", "Red commander password");
|
||||
};
|
||||
|
||||
void SetStdinEcho(bool enable = true)
|
||||
{
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode;
|
||||
GetConsoleMode(hStdin, &mode);
|
||||
|
||||
if (!enable)
|
||||
mode &= ~ENABLE_ECHO_INPUT;
|
||||
else
|
||||
mode |= ENABLE_ECHO_INPUT;
|
||||
|
||||
SetConsoleMode(hStdin, mode);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
cout << "DCS Olympus configurator v1.0.1" << endl << endl << endl;
|
||||
|
||||
SHA256 sha256;
|
||||
|
||||
std::ifstream f("olympus.json");
|
||||
json data = json::parse(f);
|
||||
|
||||
string address = data["server"]["address"];
|
||||
int clientPort = data["client"]["port"];
|
||||
int backendPort = data["server"]["port"];
|
||||
string gameMasterPassword = data["authentication"]["gameMasterPassword"];
|
||||
string blueCommanderPassword = data["authentication"]["blueCommanderPassword"];
|
||||
string redCommanderPassword = data["authentication"]["redCommanderPassword"];
|
||||
|
||||
if (argc > 1) {
|
||||
auto args = argparse::parse<MyArgs>(argc, argv);
|
||||
args.print(); // prints all variables
|
||||
|
||||
address = args.address;
|
||||
clientPort = args.clientPort;
|
||||
backendPort = args.backendPort;
|
||||
gameMasterPassword = sha256(args.gameMasterPassword);
|
||||
blueCommanderPassword = sha256(args.blueCommanderPassword);
|
||||
redCommanderPassword = sha256(args.redCommanderPassword);
|
||||
|
||||
} else {
|
||||
cout << "No arguments provided, running in interactive mode" << endl;
|
||||
|
||||
SetStdinEcho(true);
|
||||
|
||||
string newValue;
|
||||
|
||||
cout << "Insert a new address or press Enter to keep current value: " << address << endl << ">";
|
||||
getline(cin, newValue);
|
||||
if (newValue != "")
|
||||
address = newValue;
|
||||
|
||||
while (true) {
|
||||
cout << "Insert a new client port or press Enter to keep current value: " << clientPort << endl << ">";
|
||||
getline(cin, newValue);
|
||||
if (newValue != "") {
|
||||
try {
|
||||
clientPort = stoi(newValue);
|
||||
break;
|
||||
}
|
||||
catch (...) {
|
||||
cout << "Insert a valid integer number" << endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cout << "Insert a new backend port or press Enter to keep current value: " << backendPort << endl << ">";
|
||||
getline(cin, newValue);
|
||||
if (newValue != "") {
|
||||
try {
|
||||
backendPort = stoi(newValue);
|
||||
break;
|
||||
}
|
||||
catch (...) {
|
||||
cout << "Insert a valid integer number" << endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
SetStdinEcho(false);
|
||||
|
||||
while (true) {
|
||||
cout << "Insert a new Game Master password" << endl << ">";
|
||||
getline(cin, newValue);
|
||||
cout << endl;
|
||||
if (newValue != "") {
|
||||
gameMasterPassword = sha256(newValue);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
cout << "Value can't be empty" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cout << "Insert a new Blue Commander password" << endl << ">";
|
||||
getline(cin, newValue);
|
||||
cout << endl;
|
||||
if (newValue != "") {
|
||||
blueCommanderPassword = sha256(newValue);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
cout << "Value can't be empty" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cout << "Insert a new Red Commander password" << endl << ">";
|
||||
getline(cin, newValue);
|
||||
cout << endl;
|
||||
if (newValue != "") {
|
||||
redCommanderPassword = sha256(newValue);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
cout << "Value can't be empty" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data["server"]["address"] = address;
|
||||
data["server"]["port"] = backendPort;
|
||||
data["authentication"]["gameMasterPassword"] = gameMasterPassword;
|
||||
data["authentication"]["blueCommanderPassword"] = blueCommanderPassword;
|
||||
data["authentication"]["redCommanderPassword"] = redCommanderPassword;
|
||||
data["client"]["port"] = clientPort;
|
||||
|
||||
std::ofstream o("olympus.json");
|
||||
o << std::setw(4) << data << std::endl;
|
||||
|
||||
cout << endl;
|
||||
cout << "Configuration updated successfully, bye!" << endl;
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(2000));
|
||||
}
|
||||
|
||||
@ -1,143 +0,0 @@
|
||||
<?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>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{ff484257-f6d1-43e9-b6ba-a892b86e8963}</ProjectGuid>
|
||||
<RootNamespace>configurator</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>third-party\hash-library\include;third-party</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>third-party\hash-library\include;third-party</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="configurator.cpp" />
|
||||
<ClCompile Include="third-party\hash-library\src\sha256.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="argparse.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="configurator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="third-party\hash-library\src\sha256.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="argparse.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,586 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// @author : Morris Franken
|
||||
// https://github.com/morrisfranken/argparse
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#include <cctype> // for isdigit, tolower
|
||||
#include <sstream>
|
||||
#include <cstdlib> // for size_t, exit
|
||||
#include <algorithm> // for max, transform, copy, min
|
||||
#include <iomanip> // for operator<<, setw
|
||||
#include <iostream> // for operator<<, basic_ostream, endl, ostream
|
||||
#include <iterator> // for ostream_iterator
|
||||
#include <map> // for operator!=, map, _Rb_tree_iterator
|
||||
#include <memory> // for allocator, shared_ptr, __shared_ptr_ac...
|
||||
#include <optional> // for optional, nullopt
|
||||
#include <stdexcept> // for runtime_error, invalid_argument
|
||||
#include <filesystem> // for getting program_name from path
|
||||
#include <string> // for string, operator+, basic_string, char_...
|
||||
#include <type_traits> // for declval, false_type, true_type, is_enum
|
||||
#include <utility> // for move, pair
|
||||
#include <vector> // for vector
|
||||
|
||||
#if __has_include(<magic_enum.hpp>)
|
||||
#include <magic_enum.hpp> // for enum_entries
|
||||
#define HAS_MAGIC_ENUM
|
||||
#endif
|
||||
|
||||
#define ARGPARSE_VERSION 4
|
||||
|
||||
namespace argparse {
|
||||
class Args;
|
||||
using std::cout, std::cerr, std::endl, std::setw, std::size_t;
|
||||
|
||||
template<typename T> struct is_vector : public std::false_type {};
|
||||
template<typename T, typename A> struct is_vector<std::vector<T, A>> : public std::true_type {};
|
||||
|
||||
template<typename T> struct is_optional : public std::false_type {};
|
||||
template<typename T> struct is_optional<std::optional<T>> : public std::true_type {};
|
||||
|
||||
template<typename T> struct is_shared_ptr : public std::false_type {};
|
||||
template<typename T> struct is_shared_ptr<std::shared_ptr<T>> : public std::true_type {};
|
||||
|
||||
template <typename, typename = void> struct has_ostream_operator : std::false_type {};
|
||||
template <typename T> struct has_ostream_operator<T, decltype(void(std::declval<std::ostream&>() << std::declval<const T&>()))> : std::true_type {};
|
||||
|
||||
inline std::string bold(const std::string& input_str) {
|
||||
#ifdef _WIN32
|
||||
return input_str; // no bold for windows
|
||||
#else
|
||||
return "\033[1m" + input_str + "\033[0m";
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T> std::string toString(const T &v) {
|
||||
if constexpr (has_ostream_operator<T>::value) {
|
||||
return static_cast<std::ostringstream &&>((std::ostringstream() << std::boolalpha << v)).str(); // https://github.com/stan-dev/math/issues/590#issuecomment-550122627
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> inline split(const std::string &str) {
|
||||
std::vector<std::string> splits;
|
||||
std::stringstream ss(str);
|
||||
std::string key;
|
||||
while (std::getline(ss, key, ',')) {
|
||||
if (!key.empty() && key.back() == '\0')
|
||||
key.pop_back(); // last variables contain a '\0', which is unexpected when comparing to raw string, e.g. value == "test" will fail when the last character is '\0'. Therefore we can remove it
|
||||
splits.emplace_back(std::move(key));
|
||||
}
|
||||
return splits;
|
||||
}
|
||||
|
||||
template <typename T> std::string to_lower(const T &str_) { // both std::string and std::basic_string_view<char> (for magic_enum) are using to_lower
|
||||
std::string str(str_.size(), '\0');
|
||||
std::transform(str_.begin(), str_.end(), str.begin(), ::tolower);
|
||||
return str;
|
||||
}
|
||||
|
||||
template<typename T> inline T get(const std::string &v);
|
||||
template<> inline std::string get(const std::string &v) { return v; }
|
||||
template<> inline char get(const std::string &v) { return v.empty()? throw std::invalid_argument("empty string") : v.size() > 1? v.substr(0,2) == "0x"? (char)std::stoul(v, nullptr, 16) : (char)std::stoi(v) : v[0]; }
|
||||
template<> inline int get(const std::string &v) { return std::stoi(v); }
|
||||
template<> inline short get(const std::string &v) { return std::stoi(v); }
|
||||
template<> inline long get(const std::string &v) { return std::stol(v); }
|
||||
template<> inline bool get(const std::string &v) { return to_lower(v) == "true" || v == "1"; }
|
||||
template<> inline float get(const std::string &v) { return std::stof(v); }
|
||||
template<> inline double get(const std::string &v) { return std::stod(v); }
|
||||
template<> inline unsigned char get(const std::string &v) { return get<char>(v); }
|
||||
template<> inline unsigned int get(const std::string &v) { return std::stoul(v); }
|
||||
template<> inline unsigned short get(const std::string &v) { return std::stoul(v); }
|
||||
template<> inline unsigned long get(const std::string &v) { return std::stoul(v); }
|
||||
|
||||
template<typename T> inline T get(const std::string &v) { // remaining types
|
||||
if constexpr (is_vector<T>::value) {
|
||||
const std::vector<std::string> splitted = split(v);
|
||||
T res(splitted.size());
|
||||
if (!v.empty())
|
||||
std::transform (splitted.begin(), splitted.end(), res.begin(), get<typename T::value_type>);
|
||||
return res;
|
||||
} else if constexpr (std::is_pointer<T>::value) {
|
||||
return new typename std::remove_pointer<T>::type(get<typename std::remove_pointer<T>::type>(v));
|
||||
} else if constexpr (is_shared_ptr<T>::value) {
|
||||
return std::make_shared<typename T::element_type>(get<typename T::element_type>(v));
|
||||
} else if constexpr (is_optional<T>::value) {
|
||||
return get<typename T::value_type>(v);
|
||||
} else if constexpr (std::is_enum<T>::value) { // case-insensitive enum conversion
|
||||
#ifdef HAS_MAGIC_ENUM
|
||||
constexpr auto& enum_entries = magic_enum::enum_entries<T>();
|
||||
const std::string lower_str = to_lower(v);
|
||||
for (const auto &[value, name] : enum_entries) {
|
||||
if (to_lower(name) == lower_str)
|
||||
return value;
|
||||
}
|
||||
std::string error = "enum is only accepting [";
|
||||
for (size_t i = 0; i < enum_entries.size(); i++)
|
||||
error += (i==0? "" : ", ") + to_lower(enum_entries[i].second);
|
||||
error += "]";
|
||||
throw std::runtime_error(error);
|
||||
#else
|
||||
throw std::runtime_error("Enum not supported, please install magic_enum (https://github.com/Neargye/magic_enum)");
|
||||
#endif
|
||||
} else {
|
||||
return T(v);
|
||||
}
|
||||
}
|
||||
|
||||
struct ConvertBase {
|
||||
virtual ~ConvertBase() = default;
|
||||
virtual void convert(const std::string &v) = 0;
|
||||
virtual void set_default(const std::unique_ptr<ConvertBase> &default_value, const std::string &default_string) = 0;
|
||||
[[nodiscard]] virtual size_t get_type_id() const = 0;
|
||||
[[nodiscard]] virtual std::string get_allowed_entries() const = 0;
|
||||
};
|
||||
|
||||
template <typename T> struct ConvertType : public ConvertBase {
|
||||
T data;
|
||||
~ConvertType() override = default;
|
||||
ConvertType() : ConvertBase() {};
|
||||
explicit ConvertType(const T &value) : ConvertBase(), data(value) {};
|
||||
|
||||
void convert(const std::string &v) override {
|
||||
data = get<T>(v);
|
||||
}
|
||||
|
||||
void set_default(const std::unique_ptr<ConvertBase> &default_value, const std::string &default_string) override {
|
||||
if (this->get_type_id() == default_value->get_type_id()) // When the types do not match exactly. resort to string conversion
|
||||
data = ((ConvertType<T>*)(default_value.get()))->data;
|
||||
else
|
||||
data = get<T>(default_string);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t get_type_id() const override {
|
||||
return typeid(T).hash_code();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string get_allowed_entries() const override {
|
||||
std::stringstream ss;
|
||||
|
||||
#ifdef HAS_MAGIC_ENUM
|
||||
if constexpr (std::is_enum<T>::value) {
|
||||
for (const auto &[value, name] : magic_enum::enum_entries<T>()) {
|
||||
ss << to_lower(name) << ", ";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
enum ARG_TYPE {ARG, KWARG, FLAG} type;
|
||||
|
||||
Entry(ARG_TYPE type, const std::string& key, std::string help, std::optional<std::string> implicit_value=std::nullopt) :
|
||||
type(type),
|
||||
keys_(split(key)),
|
||||
help(std::move(help)),
|
||||
implicit_value_(std::move(implicit_value)) {
|
||||
}
|
||||
|
||||
// Allow both string inputs and direct-type inputs. Where a string-input will be converted like it would when using the commandline, and the direct approach is to simply use the value provided.
|
||||
template <typename T> Entry &set_default(const T &default_value) {
|
||||
this->default_str_ = toString(default_value);
|
||||
if constexpr (!(std::is_array<T>::value || std::is_same<typename std::remove_all_extents<T>::type, char>::value)) {
|
||||
data_default = std::make_unique<ConvertType<T>>(default_value);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Entry &multi_argument() {
|
||||
_is_multi_argument = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Magically convert the value string to the requested type
|
||||
template <typename T> operator T&() {
|
||||
// Automatically set the default to nullptr for pointer types and empty for optional types
|
||||
if constexpr (is_optional<T>::value || std::is_pointer<T>::value || is_shared_ptr<T>::value) {
|
||||
if (!default_str_.has_value()) {
|
||||
default_str_ = "none";
|
||||
if constexpr(is_optional<T>::value) {
|
||||
data_default = std::make_unique<ConvertType<T>> (T{std::nullopt});
|
||||
} else {
|
||||
data_default = std::make_unique<ConvertType<T>> ((T) nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
datap = std::make_unique<ConvertType<T>>();
|
||||
return ((ConvertType<T>*)(datap.get()))->data;
|
||||
}
|
||||
|
||||
// Force an ambiguous error when not using a reference.
|
||||
template <typename T> operator T() {} // When you get here because you received an error, make sure all parameters of argparse are references (e.g. with `&`)
|
||||
|
||||
private:
|
||||
std::vector<std::string> keys_;
|
||||
std::string help;
|
||||
std::optional<std::string> value_;
|
||||
std::optional<std::string> implicit_value_;
|
||||
std::optional<std::string> default_str_;
|
||||
std::string error;
|
||||
std::unique_ptr<ConvertBase> datap;
|
||||
std::unique_ptr<ConvertBase> data_default;
|
||||
bool _is_multi_argument = false;
|
||||
bool is_set_by_user = true;
|
||||
|
||||
[[nodiscard]] std::string _get_keys() const {
|
||||
std::stringstream ss;
|
||||
for (size_t i = 0; i < keys_.size(); i++)
|
||||
ss << (i? "," : "") << (type == ARG? "" : (keys_[i].size() > 1 ? "--" : "-")) + keys_[i];
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void _convert(const std::string &value) {
|
||||
try {
|
||||
this->value_ = value;
|
||||
datap->convert(value);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
error = "Invalid argument, could not convert \"" + value + "\" for " + _get_keys() + " (" + help + ")";
|
||||
} catch (const std::runtime_error &e) {
|
||||
error = "Invalid argument \"" + value + "\" for " + _get_keys() + " (" + help + "). Error: " + e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void _apply_default() {
|
||||
is_set_by_user = false;
|
||||
if (data_default != nullptr) {
|
||||
value_ = *default_str_; // for printing
|
||||
datap->set_default(data_default, *default_str_);
|
||||
} else if (default_str_.has_value()) { // in cases where a string is provided to the `set_default` function
|
||||
_convert(default_str_.value());
|
||||
} else {
|
||||
error = "Argument missing: " + _get_keys() + " (" + help + ")";
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string info() const {
|
||||
const std::string allowed_entries = datap->get_allowed_entries();
|
||||
const std::string default_value = default_str_.has_value() ? "default: " + *default_str_ : "required";
|
||||
const std::string implicit_value = implicit_value_.has_value() ? "implicit: \"" + *implicit_value_ + "\", ": "";
|
||||
const std::string allowed_value = !allowed_entries.empty()? "allowed: <" + allowed_entries.substr(0, allowed_entries.size()-2) + ">, ": "";
|
||||
return " [" + allowed_value + implicit_value + default_value + "]";
|
||||
}
|
||||
|
||||
friend class Args;
|
||||
};
|
||||
|
||||
struct SubcommandEntry {
|
||||
std::shared_ptr<Args> subargs;
|
||||
std::string subcommand_name;
|
||||
|
||||
explicit SubcommandEntry(std::string subcommand_name) : subcommand_name(std::move(subcommand_name)) {}
|
||||
|
||||
template<typename T> operator T &() {
|
||||
static_assert(std::is_base_of_v<Args, T>, "Subcommand type must be a derivative of argparse::Args");
|
||||
|
||||
std::shared_ptr<T> res = std::make_shared<T>();
|
||||
res->program_name = subcommand_name;
|
||||
subargs = res;
|
||||
return *(T*)(subargs.get());
|
||||
}
|
||||
|
||||
// Force an ambiguous error when not using a reference.
|
||||
template <typename T> operator T() {} // When you get here because you received an error, make sure all parameters of argparse are references (e.g. with `&`)
|
||||
};
|
||||
|
||||
class Args {
|
||||
private:
|
||||
size_t _arg_idx = 0;
|
||||
std::vector<std::string> params;
|
||||
std::vector<std::shared_ptr<Entry>> all_entries;
|
||||
std::map<std::string, std::shared_ptr<Entry>> kwarg_entries;
|
||||
std::vector<std::shared_ptr<Entry>> arg_entries;
|
||||
std::map<std::string, std::shared_ptr<SubcommandEntry>> subcommand_entries;
|
||||
|
||||
public:
|
||||
std::string program_name;
|
||||
bool is_valid = false;
|
||||
|
||||
virtual ~Args() = default;
|
||||
|
||||
/* Add a positional argument, the order in which it is defined equals the order in which they are being read.
|
||||
* help : Description of the variable
|
||||
*
|
||||
* Returns a reference to the Entry, which will collapse into the requested type in `Entry::operator T()`
|
||||
*/
|
||||
Entry &arg(const std::string &help) {
|
||||
return arg("arg_" + std::to_string(_arg_idx), help);
|
||||
}
|
||||
|
||||
/* Add a *named* positional argument, the order in which it is defined equals the order in which they are being read.
|
||||
* key : The name of the argument, otherwise arg_<position> will be used
|
||||
* help : Description of the variable
|
||||
*
|
||||
* Returns a reference to the Entry, which will collapse into the requested type in `Entry::operator T()`
|
||||
*/
|
||||
Entry &arg(const std::string& key, const std::string &help) {
|
||||
std::shared_ptr<Entry> entry = std::make_shared<Entry>(Entry::ARG, key, help);
|
||||
// Increasing _arg_idx, so that arg2 will be arg_2, irregardless of whether it is preceded by other positional arguments
|
||||
_arg_idx++;
|
||||
arg_entries.emplace_back(entry);
|
||||
all_entries.emplace_back(entry);
|
||||
return *entry;
|
||||
}
|
||||
|
||||
/* Add a Key-Worded argument that takes a variable.
|
||||
* key : A comma-separated string, e.g. "k,key", which denotes the short (-k) and long(--key) keys_
|
||||
* help : Description of the variable
|
||||
* implicit_value : Implicit values are used when no value is provided.
|
||||
*
|
||||
* Returns a reference to the Entry, which will collapse into the requested type in `Entry::operator T()`
|
||||
*/
|
||||
Entry &kwarg(const std::string &key, const std::string &help, const std::optional<std::string>& implicit_value=std::nullopt) {
|
||||
std::shared_ptr<Entry> entry = std::make_shared<Entry>(Entry::KWARG, key, help, implicit_value);
|
||||
all_entries.emplace_back(entry);
|
||||
for (const std::string &k : entry->keys_) {
|
||||
kwarg_entries[k] = entry;
|
||||
}
|
||||
return *entry;
|
||||
}
|
||||
|
||||
/* Add a flag which will be false by default.
|
||||
* key : A comma-separated string, e.g. "k,key", which denotes the short (-k) and long(--key) keys_
|
||||
* help : Description of the variable
|
||||
*
|
||||
* Returns reference to Entry like kwarg
|
||||
*/
|
||||
Entry &flag(const std::string &key, const std::string &help) {
|
||||
return kwarg(key, help, "true").set_default<bool>(false);
|
||||
}
|
||||
|
||||
/* Add a a subcommand
|
||||
* command : name of the subcommand, e.g. 'commit', if you wish to implement a function like 'git commit'
|
||||
*
|
||||
* Returns a reference to the Entry, which will collapse into the requested type in `Entry::operator T()`
|
||||
* Expected type *Must* be an std::shared_ptr of derivative of the argparse::Args class
|
||||
*/
|
||||
SubcommandEntry &subcommand(const std::string &command) {
|
||||
std::shared_ptr<SubcommandEntry> entry = std::make_shared<SubcommandEntry>(command);
|
||||
subcommand_entries[command] = entry;
|
||||
return *entry;
|
||||
}
|
||||
|
||||
virtual void welcome() {} // Allow to overwrite the `welcome` function to add a welcome-message to the help output
|
||||
virtual void help() {
|
||||
welcome();
|
||||
cout << "Usage: " << program_name << " ";
|
||||
for (const auto &entry : arg_entries)
|
||||
cout << entry->keys_[0] << ' ';
|
||||
cout << " [options...]";
|
||||
if (!subcommand_entries.empty()) {
|
||||
cout << " [SUBCOMMAND: ";
|
||||
for (const auto &[subcommand, subentry]: subcommand_entries) {
|
||||
cout << subcommand << ", ";
|
||||
}
|
||||
cout << "]";
|
||||
}
|
||||
cout << endl;
|
||||
for (const auto &entry : arg_entries) {
|
||||
cout << setw(17) << entry->keys_[0] << " : " << entry->help << entry->info() << endl;
|
||||
}
|
||||
|
||||
cout << endl << "Options:" << endl;
|
||||
for (const auto &entry : all_entries) {
|
||||
if (entry->type != Entry::ARG) {
|
||||
cout << setw(17) << entry->_get_keys() << " : " << entry->help << entry->info() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &[subcommand, subentry] : subcommand_entries) {
|
||||
cout << endl << endl << bold("Subcommand: ") << bold(subcommand) << endl;
|
||||
subentry->subargs->help();
|
||||
}
|
||||
}
|
||||
|
||||
void validate(const bool &raise_on_error) {
|
||||
for (const auto &entry : all_entries) {
|
||||
if (!entry->error.empty()) {
|
||||
if (raise_on_error) {
|
||||
throw std::runtime_error(entry->error);
|
||||
} else {
|
||||
std::cerr << entry->error << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* parse all parameters and also check for the help_flag which was set in this constructor
|
||||
* Upon error, it will print the error and exit immediately if validation_action is ValidationAction::EXIT_ON_ERROR
|
||||
*/
|
||||
void parse(int argc, const char* const *argv, const bool &raise_on_error) {
|
||||
auto parse_subcommands = [&]() -> int {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
for (auto &[subcommand, subentry] : subcommand_entries) {
|
||||
if (subcommand == argv[i]) {
|
||||
subentry->subargs->parse(argc - i, argv + i, raise_on_error);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return argc;
|
||||
};
|
||||
argc = parse_subcommands(); // argc_ is the number of arguments that should be parsed after the subcommand has finished parsing
|
||||
|
||||
program_name = std::filesystem::path(argv[0]).stem().string();
|
||||
params = std::vector<std::string>(argv + 1, argv + argc);
|
||||
|
||||
bool& _help = flag("?,help", "print help");
|
||||
|
||||
auto is_value = [&](const size_t &i) -> bool {
|
||||
return params.size() > i && (params[i][0] != '-' || (params[i].size() > 1 && std::isdigit(params[i][1]))); // check for number to not accidentally mark negative numbers as non-parameter
|
||||
};
|
||||
auto parse_param = [&](size_t &i, const std::string &key, const bool is_short, const std::optional<std::string> &equal_value=std::nullopt) {
|
||||
auto itt = kwarg_entries.find(key);
|
||||
if (itt != kwarg_entries.end()) {
|
||||
auto &entry = itt->second;
|
||||
if (equal_value.has_value()) {
|
||||
entry->_convert(equal_value.value());
|
||||
} else if (entry->implicit_value_.has_value()) {
|
||||
entry->_convert(*entry->implicit_value_);
|
||||
} else if (!is_short) { // short values are not allowed to look ahead for the next parameter
|
||||
if (is_value(i + 1)) {
|
||||
std::string value = params[++i];
|
||||
if (entry->_is_multi_argument) {
|
||||
while (is_value(i + 1))
|
||||
value += "," + params[++i];
|
||||
}
|
||||
entry->_convert(value);
|
||||
} else if (entry->_is_multi_argument) {
|
||||
entry->_convert(""); // for multiargument parameters, return an empty vector when not passing any more values
|
||||
} else {
|
||||
entry->error = "No value provided for: " + key;
|
||||
}
|
||||
} else {
|
||||
entry->error = "No value provided for: " + key;
|
||||
}
|
||||
} else {
|
||||
cerr << "unrecognised commandline argument: " << key << endl;
|
||||
}
|
||||
};
|
||||
auto add_param = [&](size_t &i, const size_t &start) {
|
||||
size_t eq_idx = params[i].find('='); // check if value was passed using the '=' sign
|
||||
if (eq_idx != std::string::npos) { // key/value from = notation
|
||||
std::string key = params[i].substr(start, eq_idx - start);
|
||||
std::string value = params[i].substr(eq_idx + 1);
|
||||
parse_param(i, key, false, value);
|
||||
} else {
|
||||
std::string key = std::string(params[i].substr(start));
|
||||
parse_param(i, key, false);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::string> arguments_flat;
|
||||
for (size_t i = 0; i < params.size(); i++) {
|
||||
if (!is_value(i)) {
|
||||
if (params[i].size() > 1 && params[i][1] == '-') { // long --
|
||||
add_param(i, 2);
|
||||
} else { // short -
|
||||
const size_t j_end = std::min(params[i].size(), params[i].find('=')) - 1;
|
||||
for (size_t j = 1; j < j_end; j++) { // add possible other flags
|
||||
const std::string key = std::string(1, params[i][j]);
|
||||
parse_param(i, key, true);
|
||||
}
|
||||
add_param(i, j_end);
|
||||
}
|
||||
} else {
|
||||
arguments_flat.emplace_back(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all the positional arguments, making sure multi_argument positional arguments are processed last to enable arguments afterwards
|
||||
size_t arg_i = 0;
|
||||
for (; arg_i < arg_entries.size() && !arg_entries[arg_i]->_is_multi_argument; arg_i++) { // iterate over positional arguments until a multi-argument is found
|
||||
if (arg_i < arguments_flat.size())
|
||||
arg_entries[arg_i]->_convert(arguments_flat[arg_i]);
|
||||
}
|
||||
size_t arg_j = 1;
|
||||
for (size_t j_end = arg_entries.size() - arg_i; arg_j <= j_end; arg_j++) { // iterate from back to front, to ensure non-multi-arguments in the front and back are given preference
|
||||
size_t flat_idx = arguments_flat.size() - arg_j;
|
||||
if (flat_idx < arguments_flat.size() && flat_idx >= arg_i) {
|
||||
if (arg_entries[arg_entries.size() - arg_j]->_is_multi_argument) {
|
||||
std::stringstream s; // Combine multiple arguments into 1 comma-separated string for parsing
|
||||
copy(&arguments_flat[arg_i],&arguments_flat[flat_idx] + 1, std::ostream_iterator<std::string>(s,","));
|
||||
std::string value = s.str();
|
||||
value.back() = '\0'; // remove trailing ','
|
||||
arg_entries[arg_i]->_convert(value);
|
||||
} else {
|
||||
arg_entries[arg_entries.size() - arg_j]->_convert(arguments_flat[flat_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try to apply default values for arguments which have not been set
|
||||
for (const auto &entry : all_entries) {
|
||||
if (!entry->value_.has_value()) {
|
||||
entry->_apply_default();
|
||||
}
|
||||
}
|
||||
|
||||
if (_help) {
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
validate(raise_on_error);
|
||||
is_valid = true;
|
||||
}
|
||||
|
||||
void print() const {
|
||||
for (const auto &entry : all_entries) {
|
||||
std::string snip = entry->type == Entry::ARG ? "(" + (entry->help.size() > 10 ? entry->help.substr(0, 7) + "..." : entry->help) + ")" : "";
|
||||
cout << setw(21) << entry->_get_keys() + snip << " : " << (entry->is_set_by_user? bold(entry->value_.value_or("null")) : entry->value_.value_or("null")) << endl;
|
||||
}
|
||||
|
||||
for (const auto &[subcommand, subentry] : subcommand_entries) {
|
||||
if (subentry->subargs->is_valid) {
|
||||
cout << endl << "--- Subcommand: " << subcommand << endl;
|
||||
subentry->subargs->print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual int run() {return 0;} // For automatically running subcommands
|
||||
int run_subcommands() {
|
||||
for (const auto &[subcommand, subentry] : subcommand_entries) {
|
||||
if (subentry->subargs->is_valid) {
|
||||
return subentry->subargs->run();
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "No subcommand provided" << std::endl;
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> T parse(int argc, const char* const *argv, const bool &raise_on_error=false) {
|
||||
T args = T();
|
||||
args.parse(argc, argv, raise_on_error);
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
zlib License
|
||||
|
||||
Copyright (c) 2014,2015 Stephan Brumme
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
@ -1,69 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// crc32.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute CRC32 hash, based on Intel's Slicing-by-8 algorithm
|
||||
/** Usage:
|
||||
CRC32 crc32;
|
||||
std::string myHash = crc32("Hello World"); // std::string
|
||||
std::string myHash2 = crc32("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
CRC32 crc32;
|
||||
while (more data available)
|
||||
crc32.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = crc32.getHash();
|
||||
|
||||
Note:
|
||||
You can find code for the faster Slicing-by-16 algorithm on my website, too:
|
||||
http://create.stephan-brumme.com/crc32/
|
||||
Its unrolled version is about twice as fast but its look-up table doubled in size as well.
|
||||
*/
|
||||
class CRC32 //: public Hash
|
||||
{
|
||||
public:
|
||||
/// hash is 4 bytes long
|
||||
enum { HashBytes = 4 };
|
||||
|
||||
/// same as reset()
|
||||
CRC32();
|
||||
|
||||
/// compute CRC32 of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute CRC32 of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as 8 hex characters
|
||||
std::string getHash();
|
||||
/// return latest hash as bytes
|
||||
void getHash(unsigned char buffer[HashBytes]);
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// hash
|
||||
uint32_t m_hash;
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// hash.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
/// abstract base class
|
||||
class Hash
|
||||
{
|
||||
public:
|
||||
/// compute hash of a memory block
|
||||
virtual std::string operator()(const void* data, size_t numBytes) = 0;
|
||||
/// compute hash of a string, excluding final zero
|
||||
virtual std::string operator()(const std::string& text) = 0;
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
virtual void add(const void* data, size_t numBytes) = 0;
|
||||
|
||||
/// return latest hash as hex characters
|
||||
virtual std::string getHash() = 0;
|
||||
|
||||
/// restart
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
@ -1,83 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// hmac.h
|
||||
// Copyright (c) 2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// based on http://tools.ietf.org/html/rfc2104
|
||||
// see also http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
|
||||
|
||||
/** Usage:
|
||||
std::string msg = "The quick brown fox jumps over the lazy dog";
|
||||
std::string key = "key";
|
||||
std::string md5hmac = hmac< MD5 >(msg, key);
|
||||
std::string sha1hmac = hmac< SHA1 >(msg, key);
|
||||
std::string sha2hmac = hmac<SHA256>(msg, key);
|
||||
|
||||
Note:
|
||||
To keep my code simple, HMAC computation currently needs the whole message at once.
|
||||
This is in contrast to the hashes MD5, SHA1, etc. where an add() method is available
|
||||
for incremental computation.
|
||||
You can use any hash for HMAC as long as it provides:
|
||||
- constant HashMethod::BlockSize (typically 64)
|
||||
- constant HashMethod::HashBytes (length of hash in bytes, e.g. 20 for SHA1)
|
||||
- HashMethod::add(buffer, bufferSize)
|
||||
- HashMethod::getHash(unsigned char buffer[HashMethod::BlockSize])
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <cstring> // memcpy
|
||||
|
||||
/// compute HMAC hash of data and key using MD5, SHA1 or SHA256
|
||||
template <typename HashMethod>
|
||||
std::string hmac(const void* data, size_t numDataBytes, const void* key, size_t numKeyBytes)
|
||||
{
|
||||
// initialize key with zeros
|
||||
unsigned char usedKey[HashMethod::BlockSize] = {0};
|
||||
|
||||
// adjust length of key: must contain exactly blockSize bytes
|
||||
if (numKeyBytes <= HashMethod::BlockSize)
|
||||
{
|
||||
// copy key
|
||||
memcpy(usedKey, key, numKeyBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// shorten key: usedKey = hashed(key)
|
||||
HashMethod keyHasher;
|
||||
keyHasher.add(key, numKeyBytes);
|
||||
keyHasher.getHash(usedKey);
|
||||
}
|
||||
|
||||
// create initial XOR padding
|
||||
for (size_t i = 0; i < HashMethod::BlockSize; i++)
|
||||
usedKey[i] ^= 0x36;
|
||||
|
||||
// inside = hash((usedKey ^ 0x36) + data)
|
||||
unsigned char inside[HashMethod::HashBytes];
|
||||
HashMethod insideHasher;
|
||||
insideHasher.add(usedKey, HashMethod::BlockSize);
|
||||
insideHasher.add(data, numDataBytes);
|
||||
insideHasher.getHash(inside);
|
||||
|
||||
// undo usedKey's previous 0x36 XORing and apply a XOR by 0x5C
|
||||
for (size_t i = 0; i < HashMethod::BlockSize; i++)
|
||||
usedKey[i] ^= 0x5C ^ 0x36;
|
||||
|
||||
// hash((usedKey ^ 0x5C) + hash((usedKey ^ 0x36) + data))
|
||||
HashMethod finalHasher;
|
||||
finalHasher.add(usedKey, HashMethod::BlockSize);
|
||||
finalHasher.add(inside, HashMethod::HashBytes);
|
||||
|
||||
return finalHasher.getHash();
|
||||
}
|
||||
|
||||
|
||||
/// convenience function for std::string
|
||||
template <typename HashMethod>
|
||||
std::string hmac(const std::string& data, const std::string& key)
|
||||
{
|
||||
return hmac<HashMethod>(data.c_str(), data.size(), key.c_str(), key.size());
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// keccak.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute Keccak hash (designated SHA3)
|
||||
/** Usage:
|
||||
Keccak keccak;
|
||||
std::string myHash = keccak("Hello World"); // std::string
|
||||
std::string myHash2 = keccak("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
Keccak keccak;
|
||||
while (more data available)
|
||||
keccak.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = keccak.getHash();
|
||||
*/
|
||||
class Keccak //: public Hash
|
||||
{
|
||||
public:
|
||||
/// algorithm variants
|
||||
enum Bits { Keccak224 = 224, Keccak256 = 256, Keccak384 = 384, Keccak512 = 512 };
|
||||
|
||||
/// same as reset()
|
||||
explicit Keccak(Bits bits = Keccak256);
|
||||
|
||||
/// compute hash of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute hash of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as hex characters
|
||||
std::string getHash();
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// process a full block
|
||||
void processBlock(const void* data);
|
||||
/// process everything left in the internal buffer
|
||||
void processBuffer();
|
||||
|
||||
/// 1600 bits, stored as 25x64 bit, BlockSize is no more than 1152 bits (Keccak224)
|
||||
enum { StateSize = 1600 / (8 * 8),
|
||||
MaxBlockSize = 200 - 2 * (224 / 8) };
|
||||
|
||||
/// hash
|
||||
uint64_t m_hash[StateSize];
|
||||
/// size of processed data in bytes
|
||||
uint64_t m_numBytes;
|
||||
/// block size (less or equal to MaxBlockSize)
|
||||
size_t m_blockSize;
|
||||
/// valid bytes in m_buffer
|
||||
size_t m_bufferSize;
|
||||
/// bytes not processed yet
|
||||
uint8_t m_buffer[MaxBlockSize];
|
||||
/// variant
|
||||
Bits m_bits;
|
||||
};
|
||||
@ -1,78 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// md5.h
|
||||
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute MD5 hash
|
||||
/** Usage:
|
||||
MD5 md5;
|
||||
std::string myHash = md5("Hello World"); // std::string
|
||||
std::string myHash2 = md5("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
MD5 md5;
|
||||
while (more data available)
|
||||
md5.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = md5.getHash();
|
||||
*/
|
||||
class MD5 //: public Hash
|
||||
{
|
||||
public:
|
||||
/// split into 64 byte blocks (=> 512 bits), hash is 16 bytes long
|
||||
enum { BlockSize = 512 / 8, HashBytes = 16 };
|
||||
|
||||
/// same as reset()
|
||||
MD5();
|
||||
|
||||
/// compute MD5 of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute MD5 of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as 32 hex characters
|
||||
std::string getHash();
|
||||
/// return latest hash as bytes
|
||||
void getHash(unsigned char buffer[HashBytes]);
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// process 64 bytes
|
||||
void processBlock(const void* data);
|
||||
/// process everything left in the internal buffer
|
||||
void processBuffer();
|
||||
|
||||
/// size of processed data in bytes
|
||||
uint64_t m_numBytes;
|
||||
/// valid bytes in m_buffer
|
||||
size_t m_bufferSize;
|
||||
/// bytes not processed yet
|
||||
uint8_t m_buffer[BlockSize];
|
||||
|
||||
enum { HashValues = HashBytes / 4 };
|
||||
/// hash, stored as integers
|
||||
uint32_t m_hash[HashValues];
|
||||
};
|
||||
@ -1,78 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// sha1.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute SHA1 hash
|
||||
/** Usage:
|
||||
SHA1 sha1;
|
||||
std::string myHash = sha1("Hello World"); // std::string
|
||||
std::string myHash2 = sha1("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
SHA1 sha1;
|
||||
while (more data available)
|
||||
sha1.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = sha1.getHash();
|
||||
*/
|
||||
class SHA1 //: public Hash
|
||||
{
|
||||
public:
|
||||
/// split into 64 byte blocks (=> 512 bits), hash is 20 bytes long
|
||||
enum { BlockSize = 512 / 8, HashBytes = 20 };
|
||||
|
||||
/// same as reset()
|
||||
SHA1();
|
||||
|
||||
/// compute SHA1 of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute SHA1 of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as 40 hex characters
|
||||
std::string getHash();
|
||||
/// return latest hash as bytes
|
||||
void getHash(unsigned char buffer[HashBytes]);
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// process 64 bytes
|
||||
void processBlock(const void* data);
|
||||
/// process everything left in the internal buffer
|
||||
void processBuffer();
|
||||
|
||||
/// size of processed data in bytes
|
||||
uint64_t m_numBytes;
|
||||
/// valid bytes in m_buffer
|
||||
size_t m_bufferSize;
|
||||
/// bytes not processed yet
|
||||
uint8_t m_buffer[BlockSize];
|
||||
|
||||
enum { HashValues = HashBytes / 4 };
|
||||
/// hash, stored as integers
|
||||
uint32_t m_hash[HashValues];
|
||||
};
|
||||
@ -1,78 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// sha256.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute SHA256 hash
|
||||
/** Usage:
|
||||
SHA256 sha256;
|
||||
std::string myHash = sha256("Hello World"); // std::string
|
||||
std::string myHash2 = sha256("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
SHA256 sha256;
|
||||
while (more data available)
|
||||
sha256.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = sha256.getHash();
|
||||
*/
|
||||
class SHA256 //: public Hash
|
||||
{
|
||||
public:
|
||||
/// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
|
||||
enum { BlockSize = 512 / 8, HashBytes = 32 };
|
||||
|
||||
/// same as reset()
|
||||
SHA256();
|
||||
|
||||
/// compute SHA256 of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute SHA256 of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as 64 hex characters
|
||||
std::string getHash();
|
||||
/// return latest hash as bytes
|
||||
void getHash(unsigned char buffer[HashBytes]);
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// process 64 bytes
|
||||
void processBlock(const void* data);
|
||||
/// process everything left in the internal buffer
|
||||
void processBuffer();
|
||||
|
||||
/// size of processed data in bytes
|
||||
uint64_t m_numBytes;
|
||||
/// valid bytes in m_buffer
|
||||
size_t m_bufferSize;
|
||||
/// bytes not processed yet
|
||||
uint8_t m_buffer[BlockSize];
|
||||
|
||||
enum { HashValues = HashBytes / 4 };
|
||||
/// hash, stored as integers
|
||||
uint32_t m_hash[HashValues];
|
||||
};
|
||||
@ -1,81 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// sha3.h
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "hash.h"
|
||||
#include <string>
|
||||
|
||||
// define fixed size integer types
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// GCC
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// compute SHA3 hash
|
||||
/** Usage:
|
||||
SHA3 sha3;
|
||||
std::string myHash = sha3("Hello World"); // std::string
|
||||
std::string myHash2 = sha3("How are you", 11); // arbitrary data, 11 bytes
|
||||
|
||||
// or in a streaming fashion:
|
||||
|
||||
SHA3 sha3;
|
||||
while (more data available)
|
||||
sha3.add(pointer to fresh data, number of new bytes);
|
||||
std::string myHash3 = sha3.getHash();
|
||||
*/
|
||||
class SHA3 //: public Hash
|
||||
{
|
||||
public:
|
||||
/// algorithm variants
|
||||
enum Bits { Bits224 = 224, Bits256 = 256, Bits384 = 384, Bits512 = 512 };
|
||||
|
||||
/// same as reset()
|
||||
explicit SHA3(Bits bits = Bits256);
|
||||
|
||||
/// compute hash of a memory block
|
||||
std::string operator()(const void* data, size_t numBytes);
|
||||
/// compute hash of a string, excluding final zero
|
||||
std::string operator()(const std::string& text);
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void add(const void* data, size_t numBytes);
|
||||
|
||||
/// return latest hash as hex characters
|
||||
std::string getHash();
|
||||
|
||||
/// restart
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/// process a full block
|
||||
void processBlock(const void* data);
|
||||
/// process everything left in the internal buffer
|
||||
void processBuffer();
|
||||
|
||||
/// 1600 bits, stored as 25x64 bit, BlockSize is no more than 1152 bits (Keccak224)
|
||||
enum { StateSize = 1600 / (8 * 8),
|
||||
MaxBlockSize = 200 - 2 * (224 / 8) };
|
||||
|
||||
/// hash
|
||||
uint64_t m_hash[StateSize];
|
||||
/// size of processed data in bytes
|
||||
uint64_t m_numBytes;
|
||||
/// block size (less or equal to MaxBlockSize)
|
||||
size_t m_blockSize;
|
||||
/// valid bytes in m_buffer
|
||||
size_t m_bufferSize;
|
||||
/// bytes not processed yet
|
||||
uint8_t m_buffer[MaxBlockSize];
|
||||
/// variant
|
||||
Bits m_bits;
|
||||
};
|
||||
@ -1,51 +0,0 @@
|
||||
# Portable C++ Hashing Library
|
||||
|
||||
This is a mirror of my library hosted at https://create.stephan-brumme.com/hash-library/
|
||||
|
||||
In a nutshell:
|
||||
|
||||
- computes CRC32, MD5, SHA1 and SHA256 (most common member of the SHA2 functions), Keccak and its SHA3 sibling
|
||||
- optional HMAC (keyed-hash message authentication code)
|
||||
- no external dependencies, small code size
|
||||
- can work chunk-wise (for example when reading streams block-by-block)
|
||||
- portable: supports Windows and Linux, tested on Little Endian and Big Endian CPUs
|
||||
- roughly as fast as Linux core hashing functions
|
||||
- open source, zlib license
|
||||
|
||||
You can find code examples, benchmarks and much more on my website https://create.stephan-brumme.com/hash-library/
|
||||
|
||||
# How to use
|
||||
|
||||
This example computes SHA256 hashes but the API is more or less identical for all hash algorithms:
|
||||
|
||||
``` cpp
|
||||
// SHA2 test program
|
||||
#include "sha256.h"
|
||||
#include <iostream> // for std::cout only, not needed for hashing library
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// create a new hashing object
|
||||
SHA256 sha256;
|
||||
|
||||
// hashing an std::string
|
||||
std::cout << sha256("Hello World") << std::endl;
|
||||
// => a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
|
||||
|
||||
// hashing a buffer of bytes
|
||||
const char* buffer = "How are you";
|
||||
std::cout << sha256(buffer, 11) << std::endl;
|
||||
// => 9c7d5b046878838da72e40ceb3179580958df544b240869b80d0275cc07209cc
|
||||
|
||||
// or in a streaming fashion (re-use "How are you")
|
||||
SHA256 sha256stream;
|
||||
const char* url = "create.stephan-brumme.com"; // 25 bytes
|
||||
int step = 5;
|
||||
for (int i = 0; i < 25; i += step)
|
||||
sha256stream.add(url + i, step); // add five bytes at a time
|
||||
std::cout << sha256stream.getHash() << std::endl;
|
||||
// => 82aa771f1183c52f973c798c9243a1c73833ea40961c73e55e12430ec77b69f6
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
@ -1,411 +0,0 @@
|
||||
// //////////////////////////////////////////////////////////
|
||||
// sha256.cpp
|
||||
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
|
||||
#ifndef _MSC_VER
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// same as reset()
|
||||
SHA256::SHA256()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
/// restart
|
||||
void SHA256::reset()
|
||||
{
|
||||
m_numBytes = 0;
|
||||
m_bufferSize = 0;
|
||||
|
||||
// according to RFC 1321
|
||||
m_hash[0] = 0x6a09e667;
|
||||
m_hash[1] = 0xbb67ae85;
|
||||
m_hash[2] = 0x3c6ef372;
|
||||
m_hash[3] = 0xa54ff53a;
|
||||
m_hash[4] = 0x510e527f;
|
||||
m_hash[5] = 0x9b05688c;
|
||||
m_hash[6] = 0x1f83d9ab;
|
||||
m_hash[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
inline uint32_t rotate(uint32_t a, uint32_t c)
|
||||
{
|
||||
return (a >> c) | (a << (32 - c));
|
||||
}
|
||||
|
||||
inline uint32_t swap(uint32_t x)
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap32(x);
|
||||
#endif
|
||||
#ifdef MSC_VER
|
||||
return _byteswap_ulong(x);
|
||||
#endif
|
||||
|
||||
return (x >> 24) |
|
||||
((x >> 8) & 0x0000FF00) |
|
||||
((x << 8) & 0x00FF0000) |
|
||||
(x << 24);
|
||||
}
|
||||
|
||||
// mix functions for processBlock()
|
||||
inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
|
||||
{
|
||||
uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
|
||||
uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
|
||||
return term1 + term2;
|
||||
}
|
||||
|
||||
inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
|
||||
uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
|
||||
return term1 + term2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// process 64 bytes
|
||||
void SHA256::processBlock(const void* data)
|
||||
{
|
||||
// get last hash
|
||||
uint32_t a = m_hash[0];
|
||||
uint32_t b = m_hash[1];
|
||||
uint32_t c = m_hash[2];
|
||||
uint32_t d = m_hash[3];
|
||||
uint32_t e = m_hash[4];
|
||||
uint32_t f = m_hash[5];
|
||||
uint32_t g = m_hash[6];
|
||||
uint32_t h = m_hash[7];
|
||||
|
||||
// data represented as 16x 32-bit words
|
||||
const uint32_t* input = (uint32_t*) data;
|
||||
// convert to big endian
|
||||
uint32_t words[64];
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
words[i] = input[i];
|
||||
#else
|
||||
words[i] = swap(input[i]);
|
||||
#endif
|
||||
|
||||
uint32_t x,y; // temporaries
|
||||
|
||||
// first round
|
||||
x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// secound round
|
||||
x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 24 words
|
||||
for (; i < 24; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// third round
|
||||
x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 32 words
|
||||
for (; i < 32; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// fourth round
|
||||
x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 40 words
|
||||
for (; i < 40; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// fifth round
|
||||
x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 48 words
|
||||
for (; i < 48; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// sixth round
|
||||
x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 56 words
|
||||
for (; i < 56; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// seventh round
|
||||
x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// extend to 64 words
|
||||
for (; i < 64; i++)
|
||||
words[i] = words[i-16] +
|
||||
(rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
|
||||
words[i-7] +
|
||||
(rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
|
||||
|
||||
// eigth round
|
||||
x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
|
||||
x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
|
||||
x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
|
||||
x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
|
||||
x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
|
||||
x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
|
||||
x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
|
||||
x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
|
||||
|
||||
// update hash
|
||||
m_hash[0] += a;
|
||||
m_hash[1] += b;
|
||||
m_hash[2] += c;
|
||||
m_hash[3] += d;
|
||||
m_hash[4] += e;
|
||||
m_hash[5] += f;
|
||||
m_hash[6] += g;
|
||||
m_hash[7] += h;
|
||||
}
|
||||
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void SHA256::add(const void* data, size_t numBytes)
|
||||
{
|
||||
const uint8_t* current = (const uint8_t*) data;
|
||||
|
||||
if (m_bufferSize > 0)
|
||||
{
|
||||
while (numBytes > 0 && m_bufferSize < BlockSize)
|
||||
{
|
||||
m_buffer[m_bufferSize++] = *current++;
|
||||
numBytes--;
|
||||
}
|
||||
}
|
||||
|
||||
// full buffer
|
||||
if (m_bufferSize == BlockSize)
|
||||
{
|
||||
processBlock(m_buffer);
|
||||
m_numBytes += BlockSize;
|
||||
m_bufferSize = 0;
|
||||
}
|
||||
|
||||
// no more data ?
|
||||
if (numBytes == 0)
|
||||
return;
|
||||
|
||||
// process full blocks
|
||||
while (numBytes >= BlockSize)
|
||||
{
|
||||
processBlock(current);
|
||||
current += BlockSize;
|
||||
m_numBytes += BlockSize;
|
||||
numBytes -= BlockSize;
|
||||
}
|
||||
|
||||
// keep remaining bytes in buffer
|
||||
while (numBytes > 0)
|
||||
{
|
||||
m_buffer[m_bufferSize++] = *current++;
|
||||
numBytes--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// process final block, less than 64 bytes
|
||||
void SHA256::processBuffer()
|
||||
{
|
||||
// the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
|
||||
|
||||
// - append "1" bit to message
|
||||
// - append "0" bits until message length in bit mod 512 is 448
|
||||
// - append length as 64 bit integer
|
||||
|
||||
// number of bits
|
||||
size_t paddedLength = m_bufferSize * 8;
|
||||
|
||||
// plus one bit set to 1 (always appended)
|
||||
paddedLength++;
|
||||
|
||||
// number of bits must be (numBits % 512) = 448
|
||||
size_t lower11Bits = paddedLength & 511;
|
||||
if (lower11Bits <= 448)
|
||||
paddedLength += 448 - lower11Bits;
|
||||
else
|
||||
paddedLength += 512 + 448 - lower11Bits;
|
||||
// convert from bits to bytes
|
||||
paddedLength /= 8;
|
||||
|
||||
// only needed if additional data flows over into a second block
|
||||
unsigned char extra[BlockSize];
|
||||
|
||||
// append a "1" bit, 128 => binary 10000000
|
||||
if (m_bufferSize < BlockSize)
|
||||
m_buffer[m_bufferSize] = 128;
|
||||
else
|
||||
extra[0] = 128;
|
||||
|
||||
size_t i;
|
||||
for (i = m_bufferSize + 1; i < BlockSize; i++)
|
||||
m_buffer[i] = 0;
|
||||
for (; i < paddedLength; i++)
|
||||
extra[i - BlockSize] = 0;
|
||||
|
||||
// add message length in bits as 64 bit number
|
||||
uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
|
||||
// find right position
|
||||
unsigned char* addLength;
|
||||
if (paddedLength < BlockSize)
|
||||
addLength = m_buffer + paddedLength;
|
||||
else
|
||||
addLength = extra + paddedLength - BlockSize;
|
||||
|
||||
// must be big endian
|
||||
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
|
||||
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
|
||||
*addLength = (unsigned char)( msgBits & 0xFF);
|
||||
|
||||
// process blocks
|
||||
processBlock(m_buffer);
|
||||
// flowed over into a second block ?
|
||||
if (paddedLength > BlockSize)
|
||||
processBlock(extra);
|
||||
}
|
||||
|
||||
|
||||
/// return latest hash as 64 hex characters
|
||||
std::string SHA256::getHash()
|
||||
{
|
||||
// compute hash (as raw bytes)
|
||||
unsigned char rawHash[HashBytes];
|
||||
getHash(rawHash);
|
||||
|
||||
// convert to hex string
|
||||
std::string result;
|
||||
result.reserve(2 * HashBytes);
|
||||
for (int i = 0; i < HashBytes; i++)
|
||||
{
|
||||
static const char dec2hex[16+1] = "0123456789abcdef";
|
||||
result += dec2hex[(rawHash[i] >> 4) & 15];
|
||||
result += dec2hex[ rawHash[i] & 15];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// return latest hash as bytes
|
||||
void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
|
||||
{
|
||||
// save old hash if buffer is partially filled
|
||||
uint32_t oldHash[HashValues];
|
||||
for (int i = 0; i < HashValues; i++)
|
||||
oldHash[i] = m_hash[i];
|
||||
|
||||
// process remaining bytes
|
||||
processBuffer();
|
||||
|
||||
unsigned char* current = buffer;
|
||||
for (int i = 0; i < HashValues; i++)
|
||||
{
|
||||
*current++ = (m_hash[i] >> 24) & 0xFF;
|
||||
*current++ = (m_hash[i] >> 16) & 0xFF;
|
||||
*current++ = (m_hash[i] >> 8) & 0xFF;
|
||||
*current++ = m_hash[i] & 0xFF;
|
||||
|
||||
// restore old hash
|
||||
m_hash[i] = oldHash[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// compute SHA256 of a memory block
|
||||
std::string SHA256::operator()(const void* data, size_t numBytes)
|
||||
{
|
||||
reset();
|
||||
add(data, numBytes);
|
||||
return getHash();
|
||||
}
|
||||
|
||||
|
||||
/// compute SHA256 of a string, excluding final zero
|
||||
std::string SHA256::operator()(const std::string& text)
|
||||
{
|
||||
reset();
|
||||
add(text.c_str(), text.size());
|
||||
return getHash();
|
||||
}
|
||||
@ -1,13 +1,15 @@
|
||||
#define nwjsFolder "..\..\nwjs\"
|
||||
#define nodejsFolder "..\..\node\"
|
||||
#define version "v1.0.1"
|
||||
#define version "v1.0.2"
|
||||
|
||||
[Setup]
|
||||
AppName=DCS Olympus
|
||||
AppVerName=DCS Olympus {#version}
|
||||
DefaultDirName={usersavedgames}\DCS.openbeta
|
||||
DefaultGroupName=DCSOlympus
|
||||
#ifdef Node
|
||||
OutputBaseFilename=DCSOlympus_{#version}_node
|
||||
#else
|
||||
OutputBaseFilename=DCSOlympus_{#version}
|
||||
#endif
|
||||
UninstallFilesDir={app}\Mods\Services\Olympus
|
||||
SetupIconFile="..\img\olympus.ico"
|
||||
DirExistsWarning=no
|
||||
@ -26,36 +28,60 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
|
||||
[Files]
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
|
||||
Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist
|
||||
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
|
||||
Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\templates.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\mist.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
|
||||
Source: "..\mod\*"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion recursesubdirs;
|
||||
|
||||
Source: "..\bin\*.dll"; DestDir: "{app}\Mods\Services\Olympus\bin"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\client\bin\*"; DestDir: "{app}\Mods\Services\Olympus\client\bin"; Flags: ignoreversion;
|
||||
Source: "..\client\node_modules\*"; DestDir: "{app}\Mods\Services\Olympus\client\node_modules"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\public"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\app.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\demo.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\package.json"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\run_client.js"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\client\install_modules.bat"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\node\configurator.js"; DestDir: "{app}\Mods\Services\Olympus\node"; Flags: ignoreversion;
|
||||
Source: "..\node\install_modules.bat"; DestDir: "{app}\Mods\Services\Olympus\node"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_server.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus_configurator.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "..\img\configurator_logo.png"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "{#nwjsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs; Check: CheckLocalInstall
|
||||
Source: "{#nodejsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs; Check: CheckServerInstall
|
||||
Source: "..\configurator\x64\Release\configurator.exe"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion;
|
||||
|
||||
Source: "..\LEGAL"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion;
|
||||
|
||||
#ifdef Node
|
||||
Source: "..\prerequisites\node-v20.10.0-x64.msi"; DestDir: "{app}\Mods\Services\Olympus\temp"; Flags: ignoreversion deleteafterinstall;
|
||||
#endif
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\Mods\Services\Olympus\configurator.exe"; Parameters: -a {code:GetAddress} -c {code:GetClientPort} -b {code:GetBackendPort} -p {code:GetPassword} --bp {code:GetBluePassword} --rp {code:GetRedPassword}; Check: CheckCallConfigurator
|
||||
Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\node"; Parameters: configurator.js -a {code:GetAddress} -c {code:GetClientPort} -b {code:GetBackendPort} -p {code:GetPassword} --bp {code:GetBluePassword} --rp {code:GetRedPassword}; Check: CheckCallConfigurator; Flags: runhidden;
|
||||
Filename: "{app}\Mods\Services\Olympus\node\install_modules.bat"; WorkingDir:"{app}\Mods\Services\Olympus\node";
|
||||
Filename: "{app}\Mods\Services\Olympus\client\install_modules.bat"; WorkingDir:"{app}\Mods\Services\Olympus\client";
|
||||
|
||||
#ifdef Node
|
||||
Filename: "msiexec.exe"; Parameters: "/i ""{app}\Mods\Services\Olympus\temp\node-v20.10.0-x64.msi"" /qb"; WorkingDir: {tmp};
|
||||
#endif
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall
|
||||
Name: "{userdesktop}\DCS Olympus Server"; Filename: "{app}\Mods\Services\Olympus\client\node.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www"; Check: CheckServerInstall
|
||||
Name: "{userdesktop}\DCS Olympus Configurator"; Filename: "{app}\Mods\Services\Olympus\configurator.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_configurator.ico"; Check: CheckServerInstall
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall; Parameters: "run_client.js"; Flags: runminimized;
|
||||
Name: "{userdesktop}\DCS Olympus Server"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www";
|
||||
Name: "{userdesktop}\DCS Olympus Configurator"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\node"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_configurator.ico"; Check: CheckServerInstall; Parameters: "configurator.js";
|
||||
Name: "{app}\Mods\Services\Olympus\DCS Olympus Client"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall; Parameters: "run_client.js"; Flags: runminimized;
|
||||
Name: "{app}\Mods\Services\Olympus\DCS Olympus Server"; Filename: "node.exe"; WorkingDir:"{app}\Mods\Services\Olympus\client"; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www";
|
||||
|
||||
[UninstallDelete]
|
||||
Type: filesandordirs; Name: "{app}\Mods\Services\Olympus"
|
||||
|
||||
[Code]
|
||||
var
|
||||
|
||||
@ -15,7 +15,7 @@ declare_plugin(self_ID,
|
||||
shortName = "Olympus",
|
||||
fileMenuName = "Olympus",
|
||||
|
||||
version = "v1.0.1",
|
||||
version = "v1.0.2",
|
||||
state = "installed",
|
||||
developerName= "DCS Refugees 767 squadron",
|
||||
info = _("DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available."),
|
||||
|
||||
17
node/.vscode/launch.json
vendored
Normal file
17
node/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}\\run_client.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
117
node/configurator.js
Normal file
117
node/configurator.js
Normal file
@ -0,0 +1,117 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const yargs = require('yargs');
|
||||
const prompt = require('prompt-sync')({sigint: true});
|
||||
const sha256 = require('sha256');
|
||||
const jsonPath = path.join('..', 'olympus.json');
|
||||
|
||||
/* Set the acceptable values */
|
||||
yargs.alias('a', 'address').describe('a', 'Backend address').string('a');
|
||||
yargs.alias('b', 'backendPort').describe('b', 'Backend port').number('b');
|
||||
yargs.alias('c', 'clientPort').describe('c', 'Client port').number('c');
|
||||
yargs.alias('p', 'gameMasterPassword').describe('p', 'Game Master password').string('p');
|
||||
yargs.alias('bp', 'blueCommanderPassword').describe('bp', 'Blue Commander password').string('bp');
|
||||
yargs.alias('rp', 'redCommanderPassword').describe('rp', 'Red Commander password').string('rp');
|
||||
args = yargs.argv;
|
||||
|
||||
async function run() {
|
||||
/* Check that we can read the json */
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
var json = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
||||
|
||||
var address = args.address ?? json["server"]["address"];
|
||||
var clientPort = args.clientPort ?? json["client"]["port"];
|
||||
var backendPort = args.backendPort ?? json["server"]["port"];
|
||||
var gameMasterPassword = args.gameMasterPassword? sha256(args.gameMasterPassword): json["authentication"]["gameMasterPassword"];
|
||||
var blueCommanderPassword = args.blueCommanderPassword? sha256(args.blueCommanderPassword): json["authentication"]["blueCommanderPassword"];
|
||||
var redCommanderPassword = args.redCommanderPassword? sha256(args.redCommanderPassword): json["authentication"]["redCommanderPassword"];
|
||||
|
||||
/* Run in interactive mode */
|
||||
if (args.address === undefined && args.clientPort === undefined && args.backendPort === undefined &&
|
||||
args.gameMasterPassword === undefined && args.blueCommanderPassword === undefined && args.redCommanderPassword === undefined) {
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "* |___/ |_| *");
|
||||
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
|
||||
console.log('\x1b[36m%s\x1b[0m', "");
|
||||
|
||||
console.log("DCS Olympus configurator v1.0.2");
|
||||
console.log("");
|
||||
|
||||
var newValue;
|
||||
var result;
|
||||
|
||||
/* Get the new address */
|
||||
newValue = prompt(`Insert an address or press Enter to keep current value ${address}. Use * for any address: `);
|
||||
address = newValue !== ""? newValue: address;
|
||||
|
||||
/* Get the new client port */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a client port or press Enter to keep current value ${clientPort}. Integers between 1025 and 65535: `);
|
||||
if (newValue === "")
|
||||
break;
|
||||
result = Number(newValue);
|
||||
|
||||
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535)
|
||||
break;
|
||||
}
|
||||
clientPort = newValue? result: clientPort;
|
||||
|
||||
/* Get the new backend port */
|
||||
while (true) {
|
||||
newValue = prompt(`Insert a backend port or press Enter to keep current value ${backendPort}. Integers between 1025 and 65535: `);
|
||||
if (newValue === "")
|
||||
break;
|
||||
result = Number(newValue);
|
||||
|
||||
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535 && result != clientPort)
|
||||
break;
|
||||
|
||||
if (result === clientPort)
|
||||
console.log("Client port and backend port must be different.");
|
||||
}
|
||||
backendPort = newValue? result: backendPort;
|
||||
|
||||
/* Get the new Game Master password */
|
||||
newValue = prompt(`Insert a new Game Master password or press Enter to keep current value: `, {echo: "*"});
|
||||
gameMasterPassword = newValue !== ""? sha256(newValue): gameMasterPassword;
|
||||
|
||||
/* Get the new Blue Commander password */
|
||||
newValue = prompt(`Insert a new Blue Commander password or press Enter to keep current value: `, {echo: "*"});
|
||||
blueCommanderPassword = newValue !== ""? sha256(newValue): blueCommanderPassword;
|
||||
|
||||
/* Get the new Red Commander password */
|
||||
newValue = prompt(`Insert a new Red Commander password or press Enter to keep current value: `, {echo: "*"});
|
||||
redCommanderPassword = newValue !== ""? sha256(newValue): redCommanderPassword;
|
||||
}
|
||||
|
||||
/* Apply the inputs */
|
||||
json["server"]["address"] = address;
|
||||
json["client"]["port"] = clientPort;
|
||||
json["server"]["port"] = backendPort;
|
||||
json["authentication"]["gameMasterPassword"] = gameMasterPassword;
|
||||
json["authentication"]["blueCommanderPassword"] = blueCommanderPassword;
|
||||
json["authentication"]["redCommanderPassword"] = redCommanderPassword;
|
||||
|
||||
/* Write the result to disk */
|
||||
const serialized = JSON.stringify(json, null, 4);
|
||||
fs.writeFileSync(jsonPath, serialized, 'utf8');
|
||||
console.log("Olympus.json updated correctly, goodbye!");
|
||||
}
|
||||
else {
|
||||
console.error("Error, could not read olympus.json file!")
|
||||
}
|
||||
|
||||
/* Wait a bit before closing the window */
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
/* Run the configurator */
|
||||
run();
|
||||
1
node/install_modules.bat
Normal file
1
node/install_modules.bat
Normal file
@ -0,0 +1 @@
|
||||
start /min npm install yargs prompt-sync sha256 tcp-ping-port
|
||||
@ -4,9 +4,9 @@
|
||||
"port": 3001
|
||||
},
|
||||
"authentication": {
|
||||
"gameMasterPassword": "4b8823ed9e5c2392ab4a791913bb8ce41956ea32e308b760eefb97536746dd33",
|
||||
"blueCommanderPassword": "302bcbaf2a3fdcf175b689bf102d6cdf9328f68a13d4096101bba806482bfed9",
|
||||
"redCommanderPassword": "b0ea4230c1558c5313165eda1bdb7fced008ca7f2ca6b823fb4d26292f309098"
|
||||
"gameMasterPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6",
|
||||
"blueCommanderPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6",
|
||||
"redCommanderPassword": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6"
|
||||
},
|
||||
"client": {
|
||||
"port": 3000,
|
||||
|
||||
BIN
prerequisites/node-v20.10.0-x64.msi
Normal file
BIN
prerequisites/node-v20.10.0-x64.msi
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
local version = "v1.0.1"
|
||||
local version = "v1.0.2"
|
||||
|
||||
local debug = false -- True enables debug printing using DCS messages
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
local version = 'v1.0.1'
|
||||
local version = 'v1.0.2'
|
||||
local lfs = require("lfs")
|
||||
|
||||
Olympus = {}
|
||||
|
||||
BIN
src/core/core.aps
Normal file
BIN
src/core/core.aps
Normal file
Binary file not shown.
110
src/core/core.rc
Normal file
110
src/core/core.rc
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United Kingdom) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,1,0
|
||||
PRODUCTVERSION 1,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "InternalName", "core.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "core.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United Kingdom) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -174,6 +174,7 @@
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||
<Version>v1.0.2</Version>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
||||
14
src/core/resource.h
Normal file
14
src/core/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by core.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
BIN
src/dcstools/dcstools.aps
Normal file
BIN
src/dcstools/dcstools.aps
Normal file
Binary file not shown.
110
src/dcstools/dcstools.rc
Normal file
110
src/dcstools/dcstools.rc
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United Kingdom) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,1,0
|
||||
PRODUCTVERSION 1,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "InternalName", "dcstools.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "dcstools.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United Kingdom) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -134,6 +134,7 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<Version>v1.0.2</Version>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
||||
14
src/dcstools/resource.h
Normal file
14
src/dcstools/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by dcstools.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
BIN
src/logger/logger.aps
Normal file
BIN
src/logger/logger.aps
Normal file
Binary file not shown.
110
src/logger/logger.rc
Normal file
110
src/logger/logger.rc
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United Kingdom) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,1,0
|
||||
PRODUCTVERSION 1,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "InternalName", "logger.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "logger.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United Kingdom) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -133,6 +133,7 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<Version>v1.0.2</Version>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
||||
14
src/logger/resource.h
Normal file
14
src/logger/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by logger.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
BIN
src/luatools/luatools.aps
Normal file
BIN
src/luatools/luatools.aps
Normal file
Binary file not shown.
110
src/luatools/luatools.rc
Normal file
110
src/luatools/luatools.rc
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United Kingdom) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,1,0
|
||||
PRODUCTVERSION 1,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "InternalName", "luatools.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "luatools.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United Kingdom) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -121,6 +121,7 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<Version>v1.0.2</Version>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
||||
14
src/luatools/resource.h
Normal file
14
src/luatools/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by luatools.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
Binary file not shown.
110
src/olympus/olympus.rc
Normal file
110
src/olympus/olympus.rc
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United Kingdom) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,1,0
|
||||
PRODUCTVERSION 1,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "DCS Olympus"
|
||||
VALUE "FileDescription", "DCS Olympus"
|
||||
VALUE "FileVersion", "1.0.2.0"
|
||||
VALUE "InternalName", "olympus.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "olympus.dll"
|
||||
VALUE "ProductName", "DCS Olympus"
|
||||
VALUE "ProductVersion", "1.0.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United Kingdom) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -90,6 +90,7 @@
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||
<Version>1.0</Version>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
||||
14
src/olympus/resource.h
Normal file
14
src/olympus/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by olympus.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION "v1.0.1"
|
||||
#define VERSION "v1.0.2"
|
||||
#define LOG_NAME "Olympus_log.txt"
|
||||
#define REST_ADDRESS "http://localhost:30000"
|
||||
#define REST_URI "olympus"
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "v1.0.1"
|
||||
"version": "v1.0.2"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user