mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
Allow builds on MSVC (#518)
* Import cxxopts to replace getopts usage * Add visual studio build things * Fixup abseil build parts * Replace __attribute__((unused)) with ABSL_ATTRIBUTE_UNUSED * Fixup minor windows build issues * Replace getopts usage * Temporarily fixup .rc files * More minor windows fixes * Get a working build * Revert .rc files * Revert changes to nodedb
This commit is contained in:
parent
52b2b3bf44
commit
0195152e05
62 changed files with 14047 additions and 176 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -35,6 +35,7 @@ testnet_tmp
|
|||
|
||||
*.pid
|
||||
vsproject/
|
||||
.vs
|
||||
|
||||
daemon.ini
|
||||
lokinet-win32.exe
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
cmake_minimum_required(VERSION 3.6.0)
|
||||
|
||||
set(PROJECT_NAME lokinet)
|
||||
project(${PROJECT_NAME} C CXX ASM)
|
||||
project(${PROJECT_NAME} C CXX)
|
||||
|
||||
# Core options
|
||||
option(USE_AVX2 "enable avx2 code" )
|
||||
|
@ -28,15 +28,23 @@ if(CCACHE_PROGRAM)
|
|||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||
endif()
|
||||
|
||||
if (MSVC_VERSION)
|
||||
enable_language(ASM_MASM)
|
||||
list(APPEND CMAKE_ASM_MASM_SOURCE_FILE_EXTENSIONS s)
|
||||
add_definitions(/D_WIN32_WINNT=0x0600 /DNOMINMAX /DSODIUM_STATIC)
|
||||
else()
|
||||
enable_language(ASM)
|
||||
endif(MSVC_VERSION)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
# check if we have the (saner) emulation of epoll here
|
||||
# it's basically linux epoll but with a sane method of
|
||||
# dealing with closed file handles that still exist in the
|
||||
# epoll set
|
||||
#
|
||||
# Note that the zombie of Oracle Solaris 2.11.x will NOT have
|
||||
# this, the header check is the only method we have to distinguish
|
||||
# them. -rick the svr4 guy
|
||||
# check if we have the (saner) emulation of epoll here
|
||||
# it's basically linux epoll but with a sane method of
|
||||
# dealing with closed file handles that still exist in the
|
||||
# epoll set
|
||||
#
|
||||
# Note that the zombie of Oracle Solaris 2.11.x will NOT have
|
||||
# this, the header check is the only method we have to distinguish
|
||||
# them. -rick the svr4 guy
|
||||
set(SOLARIS ON)
|
||||
option(USE_POLL "Revert to using poll(2) event loop (useful if targeting Oracle Solaris)" OFF)
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lsocket -lnsl")
|
||||
|
@ -72,6 +80,7 @@ if (WIN32 AND NOT STATIC_LINK_RUNTIME)
|
|||
message("for release builds, turn on STATIC_LINK_RUNTIME in cmake options")
|
||||
endif(WIN32 AND NOT STATIC_LINK_RUNTIME)
|
||||
|
||||
add_subdirectory(vendor/cxxopts)
|
||||
add_subdirectory(vendor/nlohmann)
|
||||
|
||||
# still need the headers unconditionally
|
||||
|
@ -90,11 +99,13 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||
add_compile_options(-Wno-unknown-warning-option)
|
||||
endif()
|
||||
|
||||
add_compile_options(-Wall -Wextra -Wno-unknown-pragmas)
|
||||
# vla are evil
|
||||
add_compile_options(-Wvla)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
|
||||
add_compile_options(-Wno-unused-function -Wno-deprecated-declarations -Wno-unknown-pragmas)
|
||||
if (NOT MSVC_VERSION)
|
||||
add_compile_options(-Wall -Wextra -Wno-unknown-pragmas)
|
||||
# vla are evil
|
||||
add_compile_options(-Wvla)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
|
||||
add_compile_options(-Wno-unused-function -Wno-deprecated-declarations -Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wthread-safety)
|
||||
|
@ -127,15 +138,15 @@ if (WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
|
|||
endif()
|
||||
endif(WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32 AND NOT MSVC_VERSION)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-bad-function-cast>)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-cast-function-type>)
|
||||
# unlike unix where you get a *single* compiler ID string in .comment
|
||||
# GNU ld sees fit to merge *all* the .ident sections in object files
|
||||
# to .r[o]data section one after the other!
|
||||
# unlike unix where you get a *single* compiler ID string in .comment
|
||||
# GNU ld sees fit to merge *all* the .ident sections in object files
|
||||
# to .r[o]data section one after the other!
|
||||
add_compile_options(-fno-ident)
|
||||
set(FS_LIB stdc++fs)
|
||||
endif(WIN32)
|
||||
endif()
|
||||
|
||||
if(DEBIAN)
|
||||
add_definitions(-DDEBIAN)
|
||||
|
@ -184,10 +195,10 @@ if(TESTNET)
|
|||
add_definitions(-DTESTNET=1)
|
||||
endif(TESTNET)
|
||||
|
||||
if(NOT DEBIAN)
|
||||
if(NOT DEBIAN AND NOT MSVC_VERSION)
|
||||
set(OPTIMIZE_FLAGS -O3)
|
||||
set(DEBUG_FLAGS -O0 -g3)
|
||||
endif(NOT DEBIAN)
|
||||
endif()
|
||||
|
||||
if(ASAN)
|
||||
set(DEBUG_FLAGS ${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer)
|
||||
|
@ -232,8 +243,9 @@ endif(NON_PC_TARGET)
|
|||
add_compile_options(${OPTIMIZE_FLAGS} ${CRYPTO_FLAGS})
|
||||
|
||||
if(NOT GIT_VERSION)
|
||||
exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "rev-parse --short HEAD" OUTPUT_VARIABLE GIT_VERSION)
|
||||
add_definitions(-DGIT_REV="${GIT_VERSION}")
|
||||
exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "rev-parse --short HEAD" OUTPUT_VARIABLE GIT_VERSION_UNSTRIP)
|
||||
string(STRIP "${GIT_VERSION_UNSTRIP}" GIT_VERSION)
|
||||
add_definitions("-DGIT_REV=\"${GIT_VERSION}\"")
|
||||
endif(NOT GIT_VERSION)
|
||||
|
||||
if(RELEASE_MOTTO)
|
||||
|
@ -320,7 +332,7 @@ if(UNIX)
|
|||
elseif(WIN32)
|
||||
get_filename_component(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-windows.c ABSOLUTE)
|
||||
get_filename_component(EV_SRC "llarp/ev/ev_win32.cpp" ABSOLUTE)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN -DWIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN -DWIN32 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602)
|
||||
else()
|
||||
message(FATAL_ERROR "What operating system _are_ you building on/for?")
|
||||
endif(UNIX)
|
||||
|
@ -366,12 +378,17 @@ target_link_libraries(${ABYSS_LIB} PUBLIC ${PLATFORM_LIB})
|
|||
if (NOT WIN32)
|
||||
add_executable(${ABYSS_EXE} ${ABYSS}/main.cpp)
|
||||
target_link_libraries(${ABYSS_EXE} PUBLIC ${ABYSS_LIB} Threads::Threads)
|
||||
else()
|
||||
elseif(NOT MSVC_VERSION)
|
||||
add_executable(${ABYSS_EXE} ${ABYSS}/main.cpp llarp/win32/abyss.rc)
|
||||
target_link_libraries(${ABYSS_EXE} PUBLIC ${ABYSS_LIB} ${STATIC_LIB} ws2_32)
|
||||
else()
|
||||
add_executable(${ABYSS_EXE} ${ABYSS}/main.cpp)
|
||||
target_link_libraries(${ABYSS_EXE} PUBLIC ${ABYSS_LIB} ${STATIC_LIB} ws2_32)
|
||||
endif(NOT WIN32)
|
||||
|
||||
target_include_directories(${ABYSS_LIB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${ABYSS}/include")
|
||||
target_include_directories(${ABYSS_EXE} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/${ABYSS}/include")
|
||||
|
||||
# for freebsd
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
target_include_directories(${ABYSS_LIB} PUBLIC /usr/local/include)
|
||||
|
@ -395,8 +412,10 @@ if(SHADOW)
|
|||
else()
|
||||
if(NOT WIN32)
|
||||
add_executable(${EXE} ${EXE_SRC})
|
||||
else()
|
||||
elseif(NOT MSVC_VERSION)
|
||||
add_executable(${EXE} ${EXE_SRC} llarp/win32/version.rc)
|
||||
else()
|
||||
add_executable(${EXE} ${EXE_SRC})
|
||||
endif(NOT WIN32)
|
||||
|
||||
add_log_tag(${EXE})
|
||||
|
@ -424,6 +443,6 @@ endif(SHADOW)
|
|||
|
||||
enable_testing()
|
||||
|
||||
if (NOT SHADOW)
|
||||
if (NOT SHADOW AND NOT MSVC_VERSION)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
|
16
CMakeSettings.json
Normal file
16
CMakeSettings.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
|
||||
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -19,8 +19,7 @@
|
|||
/* C++Builder defines a "random" macro */
|
||||
#undef random
|
||||
|
||||
static const randombytes_implementation *implementation =
|
||||
&randombytes_salsa20_implementation;
|
||||
static const randombytes_implementation *implementation = 0;
|
||||
|
||||
static void
|
||||
randombytes_init_if_needed(void)
|
||||
|
|
|
@ -69,8 +69,12 @@ typedef NTSTATUS(FAR PASCAL *CNGAPI_DRBG)(BCRYPT_ALG_HANDLE, UCHAR *, ULONG,
|
|||
#endif
|
||||
|
||||
#ifndef TLS
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define TLS __declspec(thread)
|
||||
#else
|
||||
#define TLS __thread
|
||||
#endif
|
||||
#else
|
||||
#define TLS
|
||||
#endif
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#include <config.hpp> // for ensure_config
|
||||
#include <libgen.h>
|
||||
#include <llarp.h>
|
||||
#include <util/fs.hpp>
|
||||
#include <util/logger.hpp>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if !defined(_WIN32) && !defined(__OpenBSD__)
|
||||
#include <wordexp.h>
|
||||
#endif
|
||||
|
||||
#include <cxxopts.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
@ -104,43 +103,75 @@ main(int argc, char *argv[])
|
|||
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
|
||||
#endif
|
||||
|
||||
int opt = 0;
|
||||
// clang-format off
|
||||
cxxopts::Options options(
|
||||
"lokinet",
|
||||
"Lokinet is a private, decentralized and IP based overlay network for the internet"
|
||||
);
|
||||
options.add_options()
|
||||
("v,verbose", "Verbose", cxxopts::value<bool>())
|
||||
("h,help", "help", cxxopts::value<bool>())
|
||||
("g,generate", "generate config", cxxopts::value<bool>())
|
||||
("c,config", "generate config", cxxopts::value<bool>())
|
||||
("r,router", "run as router", cxxopts::value<bool>())
|
||||
("f,force", "overwrite", cxxopts::value<bool>());
|
||||
options.parse_positional({"config_file"});
|
||||
// clang-format on
|
||||
|
||||
bool genconfigOnly = false;
|
||||
bool asRouter = false;
|
||||
bool overWrite = false;
|
||||
while((opt = getopt(argc, argv, "hgcfrv")) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'v':
|
||||
SetLogLevel(llarp::eLogDebug);
|
||||
llarp::LogDebug("debug logging activated");
|
||||
break;
|
||||
case 'h':
|
||||
return printHelp(argv[0], 0);
|
||||
case 'g':
|
||||
genconfigOnly = true;
|
||||
break;
|
||||
case 'c':
|
||||
genconfigOnly = true;
|
||||
break;
|
||||
case 'r':
|
||||
asRouter = true;
|
||||
break;
|
||||
case 'f':
|
||||
overWrite = true;
|
||||
break;
|
||||
default:
|
||||
return printHelp(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string conffname; // suggestions: confFName? conf_fname?
|
||||
|
||||
if(optind < argc)
|
||||
try
|
||||
{
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
if(result.count("verbose") > 0)
|
||||
{
|
||||
SetLogLevel(llarp::eLogDebug);
|
||||
llarp::LogDebug("debug logging activated");
|
||||
}
|
||||
|
||||
if(result.count("help"))
|
||||
{
|
||||
return printHelp(argv[0], 0);
|
||||
}
|
||||
|
||||
if(result.count("generate") > 0 || result.count("config") > 0)
|
||||
{
|
||||
genconfigOnly = true;
|
||||
}
|
||||
|
||||
if(result.count("force") > 0)
|
||||
{
|
||||
overWrite = true;
|
||||
}
|
||||
|
||||
if(result.count("router") > 0)
|
||||
{
|
||||
asRouter = true;
|
||||
}
|
||||
|
||||
if(result.count("config_file") > 0)
|
||||
{
|
||||
auto vec = result["config_file"].as< std::vector< std::string > >();
|
||||
if(!vec.empty())
|
||||
{
|
||||
conffname = vec[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const cxxopts::option_not_exists_exception& ex)
|
||||
{
|
||||
std::cerr << ex.what();
|
||||
return printHelp(argv[0]);
|
||||
}
|
||||
|
||||
if(!conffname.empty())
|
||||
{
|
||||
// when we have an explicit filepath
|
||||
fs::path fname = fs::path(argv[optind]);
|
||||
fs::path fname = fs::path(conffname);
|
||||
fs::path basedir = fname.parent_path();
|
||||
conffname = fname.string();
|
||||
conffname = resolvePath(conffname);
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
* - t_tun_in6_addr: struct in6_addr/IN6_ADDR
|
||||
*/
|
||||
#if defined Windows
|
||||
#include <windows.h>
|
||||
#include <in6addr.h>
|
||||
#include <winsock2.h>
|
||||
typedef HANDLE t_tun;
|
||||
|
|
|
@ -15,7 +15,7 @@ struct DemoHandler : public abyss::httpd::IRPCHandler
|
|||
|
||||
absl::optional< Response >
|
||||
HandleJSONRPC(Method_t method,
|
||||
__attribute__((unused)) const Params& params) override
|
||||
ABSL_ATTRIBUTE_UNUSED const Params& params) override
|
||||
{
|
||||
llarp::LogInfo("method: ", method);
|
||||
return Response::object();
|
||||
|
@ -50,7 +50,7 @@ struct DemoCall : public abyss::http::IRPCClientHandler
|
|||
}
|
||||
|
||||
void
|
||||
PopulateReqHeaders(__attribute__((unused))
|
||||
PopulateReqHeaders(ABSL_ATTRIBUTE_UNUSED
|
||||
abyss::http::Headers_t& hdr) override
|
||||
{
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ struct DemoServer : public abyss::httpd::BaseReqHandler
|
|||
};
|
||||
|
||||
int
|
||||
main(__attribute__((unused)) int argc, __attribute__((unused)) char* argv[])
|
||||
main(ABSL_ATTRIBUTE_UNUSED int argc, ABSL_ATTRIBUTE_UNUSED char* argv[])
|
||||
{
|
||||
// Ignore on Windows, we don't even get SIGPIPE (even though native *and*
|
||||
// emulated UNIX pipes exist - CreatePipe(2), pipe(3))
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace abyss
|
|||
}
|
||||
|
||||
static void
|
||||
OnTick(__attribute__((unused)) llarp_tcp_conn* conn)
|
||||
OnTick(ABSL_ATTRIBUTE_UNUSED llarp_tcp_conn* conn)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ typedef uint32 utp_link_t;
|
|||
#pragma warning(disable : 4200)
|
||||
#endif
|
||||
|
||||
#include <absl/base/attributes.h>
|
||||
|
||||
typedef uint32 (*utp_hash_compute_t)(const void *keyp, size_t keysize);
|
||||
typedef uint (*utp_hash_equal_t)(const void *key_a, const void *key_b,
|
||||
size_t keysize);
|
||||
|
@ -146,12 +148,12 @@ class utpHashTable
|
|||
|
||||
public:
|
||||
static uint
|
||||
compare(const void *k1, const void *k2, __attribute__((unused)) size_t ks)
|
||||
compare(const void *k1, const void *k2, ABSL_ATTRIBUTE_UNUSED size_t ks)
|
||||
{
|
||||
return *((K *)k1) == *((K *)k2);
|
||||
}
|
||||
static uint32
|
||||
compute_hash(const void *k, __attribute__((unused)) size_t ks)
|
||||
compute_hash(const void *k, ABSL_ATTRIBUTE_UNUSED size_t ks)
|
||||
{
|
||||
return ((K *)k)->compute_hash();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#include <absl/base/attributes.h>
|
||||
#include "utp_utils.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -286,20 +287,20 @@ utp_default_get_udp_overhead(utp_callback_arguments *args)
|
|||
}
|
||||
|
||||
uint64
|
||||
utp_default_get_random(__attribute__((unused)) utp_callback_arguments *args)
|
||||
utp_default_get_random(ABSL_ATTRIBUTE_UNUSED utp_callback_arguments *args)
|
||||
{
|
||||
return rand();
|
||||
}
|
||||
|
||||
uint64
|
||||
utp_default_get_milliseconds(__attribute__((unused))
|
||||
utp_default_get_milliseconds(ABSL_ATTRIBUTE_UNUSED
|
||||
utp_callback_arguments *args)
|
||||
{
|
||||
return UTP_GetMilliseconds();
|
||||
}
|
||||
|
||||
uint64
|
||||
utp_default_get_microseconds(__attribute__((unused))
|
||||
utp_default_get_microseconds(ABSL_ATTRIBUTE_UNUSED
|
||||
utp_callback_arguments *args)
|
||||
{
|
||||
return UTP_GetMicroseconds();
|
||||
|
|
|
@ -46,12 +46,12 @@ set(LIB_UTIL_SRC
|
|||
|
||||
add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC})
|
||||
target_include_directories(${UTIL_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include)
|
||||
target_link_libraries(${UTIL_LIB} PUBLIC absl::synchronization)
|
||||
target_link_libraries(${UTIL_LIB} PUBLIC absl::synchronization absl::hash)
|
||||
target_link_libraries(${UTIL_LIB} PUBLIC nlohmann_json::nlohmann_json)
|
||||
|
||||
# cut back on fluff
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(${UTIL_LIB} PUBLIC absl::optional absl::variant absl::strings absl::hash cppbackport)
|
||||
target_link_libraries(${UTIL_LIB} PUBLIC absl::optional absl::variant absl::strings cppbackport)
|
||||
endif(NOT WIN32)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
@ -239,7 +239,7 @@ endif()
|
|||
|
||||
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
|
||||
set(LIBS ${LIBS} libutp)
|
||||
target_link_libraries(${STATIC_LIB} PUBLIC ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${LIBS})
|
||||
target_link_libraries(${STATIC_LIB} PUBLIC cxxopts ${ABYSS_LIB} ${PLATFORM_LIB} ${UTIL_LIB} ${CRYPTOGRAPHY_LIB} ${LIBS})
|
||||
|
||||
if(WITH_SHARED)
|
||||
add_library(${SHARED_LIB} SHARED ${LIB_SRC})
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
#include <util/scheduler.hpp>
|
||||
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <getopt.h>
|
||||
#include <cxxopts.hpp>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/param.h> // for MIN
|
||||
|
||||
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
@ -645,50 +643,40 @@ extern "C"
|
|||
const char *
|
||||
handleBaseCmdLineArgs(int argc, char *argv[])
|
||||
{
|
||||
const char *conffname = "daemon.ini";
|
||||
int c;
|
||||
while(1)
|
||||
|
||||
// clang-format off
|
||||
cxxopts::Options options(
|
||||
"lokinet",
|
||||
"Lokinet is a private, decentralized and IP based overlay network for the internet"
|
||||
);
|
||||
options.add_options()
|
||||
("c,config", "Config file", cxxopts::value< std::string >()->default_value("daemon.ini"))
|
||||
("o,logLevel", "logging level");
|
||||
// clang-format on
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
std::string logLevel = result["logLevel"].as< std::string >();
|
||||
|
||||
if(logLevel == "debug")
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"logLevel", required_argument, 0, 'o'},
|
||||
{0, 0, 0, 0}};
|
||||
int option_index = 0;
|
||||
c = getopt_long(argc, argv, "c:o:", long_options, &option_index);
|
||||
if(c == -1)
|
||||
break;
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 'c':
|
||||
conffname = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
if(strncmp(optarg, "debug", std::min(strlen(optarg), size_t(5))) == 0)
|
||||
{
|
||||
cSetLogLevel(eLogDebug);
|
||||
}
|
||||
else if(strncmp(optarg, "info", std::min(strlen(optarg), size_t(4)))
|
||||
== 0)
|
||||
{
|
||||
cSetLogLevel(eLogInfo);
|
||||
}
|
||||
else if(strncmp(optarg, "warn", std::min(strlen(optarg), size_t(4)))
|
||||
== 0)
|
||||
{
|
||||
cSetLogLevel(eLogWarn);
|
||||
}
|
||||
else if(strncmp(optarg, "error", std::min(strlen(optarg), size_t(5)))
|
||||
== 0)
|
||||
{
|
||||
cSetLogLevel(eLogError);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cSetLogLevel(eLogDebug);
|
||||
}
|
||||
return conffname;
|
||||
else if(logLevel == "info")
|
||||
{
|
||||
cSetLogLevel(eLogInfo);
|
||||
}
|
||||
else if(logLevel == "warn")
|
||||
{
|
||||
cSetLogLevel(eLogWarn);
|
||||
}
|
||||
else if(logLevel == "error")
|
||||
{
|
||||
cSetLogLevel(eLogError);
|
||||
}
|
||||
|
||||
// this isn't thread safe, but reconfiguring during run is likely unsafe either way
|
||||
static std::string confname = result["config"].as< std::string >();
|
||||
|
||||
return confname.c_str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ dns_iptracker_init()
|
|||
|
||||
// not sure we want tunGatewayIP... we'll know when we get further
|
||||
bool
|
||||
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll,
|
||||
__attribute__((unused))
|
||||
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, ABSL_ATTRIBUTE_UNUSED
|
||||
llarp::huint32_t tunGatewayIp)
|
||||
{
|
||||
dll->ip_tracker = &g_dns_iptracker;
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#include <netdb.h> /* getaddrinfo, getnameinfo */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h> /* close */
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* exit */
|
||||
#include <string.h> /* memset */
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h> /* close */
|
||||
|
||||
#include <algorithm> // for std::find_if
|
||||
#include <stdio.h> // sprintf
|
||||
|
@ -814,7 +814,7 @@ llarp_dnsc_init(struct dnsc_context *const dnsc, llarp::Logic *const logic,
|
|||
}
|
||||
|
||||
bool
|
||||
llarp_dnsc_stop(__attribute__((unused)) struct dnsc_context *const dnsc)
|
||||
llarp_dnsc_stop(ABSL_ATTRIBUTE_UNUSED struct dnsc_context *const dnsc)
|
||||
{
|
||||
// delete(sockaddr_in *)dnsc->server; // deallocation
|
||||
return true;
|
||||
|
|
|
@ -9,9 +9,14 @@
|
|||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wspiapi.h>
|
||||
#ifndef ssize_t
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#else
|
||||
#define ssize_t long
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
// writev
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <future>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <win32/win32_up.h>
|
||||
|
|
|
@ -35,6 +35,12 @@ win32_tun_io::queue_write(const byte_t* buf, size_t sz)
|
|||
bool
|
||||
win32_tun_io::setup()
|
||||
{
|
||||
// Create a critical section to synchronise access to the TUN handler.
|
||||
// This *probably* has the effect of making packets move in order now
|
||||
// as only one IOCP thread will have access to the TUN handler at a
|
||||
// time
|
||||
InitializeCriticalSection(&HandlerMtx);
|
||||
|
||||
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
|
||||
{
|
||||
llarp::LogWarn("failed to start interface");
|
||||
|
@ -59,12 +65,6 @@ win32_tun_io::setup()
|
|||
if(tunif->tun_fd == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// Create a critical section to synchronise access to the TUN handler.
|
||||
// This *probably* has the effect of making packets move in order now
|
||||
// as only one IOCP thread will have access to the TUN handler at a
|
||||
// time
|
||||
InitializeCriticalSection(&HandlerMtx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <ev/pipe.hpp>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
llarp_ev_pkt_pipe::llarp_ev_pkt_pipe(llarp_ev_loop_ptr loop)
|
||||
|
|
|
@ -38,14 +38,14 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
DecodeKey(__attribute__((unused)) const llarp_buffer_t& key,
|
||||
__attribute__((unused)) llarp_buffer_t* buf) override
|
||||
DecodeKey(ABSL_ATTRIBUTE_UNUSED const llarp_buffer_t& key,
|
||||
ABSL_ATTRIBUTE_UNUSED llarp_buffer_t* buf) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HandleMessage(__attribute__((unused)) AbstractRouter* router) const override
|
||||
HandleMessage(ABSL_ATTRIBUTE_UNUSED AbstractRouter* router) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <util/logger.hpp>
|
||||
#include <util/metrics.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct InboundMessageParser::msg_holder_t
|
||||
|
@ -21,18 +23,21 @@ namespace llarp
|
|||
DHTImmediateMessage m;
|
||||
LR_CommitMessage c;
|
||||
DiscardMessage x;
|
||||
|
||||
msg_holder_t() = default;
|
||||
};
|
||||
|
||||
InboundMessageParser::InboundMessageParser(AbstractRouter* _router)
|
||||
: router(_router)
|
||||
, from(nullptr)
|
||||
, msg(nullptr)
|
||||
, holder(std::make_unique< msg_holder_t >())
|
||||
, holder(new msg_holder_t())
|
||||
{
|
||||
}
|
||||
|
||||
InboundMessageParser::~InboundMessageParser()
|
||||
{
|
||||
delete holder;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace llarp
|
|||
ILinkMessage* msg;
|
||||
|
||||
struct msg_holder_t;
|
||||
std::unique_ptr< msg_holder_t > holder;
|
||||
msg_holder_t *holder;
|
||||
};
|
||||
} // namespace llarp
|
||||
#endif
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace llarp
|
|||
|
||||
for(const std::string &val : toSend)
|
||||
{
|
||||
ssize_t sentLen = 0;
|
||||
int sentLen = 0;
|
||||
|
||||
do
|
||||
{
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
static void
|
||||
checksumDstIPv4TCP(byte_t *pld, __attribute__((unused)) size_t psz,
|
||||
checksumDstIPv4TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz,
|
||||
size_t fragoff, size_t chksumoff, nuint32_t oSrcIP,
|
||||
nuint32_t oDstIP, nuint32_t nSrcIP, nuint32_t nDstIP)
|
||||
{
|
||||
|
@ -117,7 +117,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
static void
|
||||
checksumDstIPv4UDP(byte_t *pld, __attribute__((unused)) size_t psz,
|
||||
checksumDstIPv4UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz,
|
||||
size_t fragoff, nuint32_t oSrcIP, nuint32_t oDstIP,
|
||||
nuint32_t nSrcIP, nuint32_t nDstIP)
|
||||
{
|
||||
|
@ -186,7 +186,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
static void
|
||||
checksumSrcIPv4TCP(byte_t *pld, __attribute__((unused)) size_t psz,
|
||||
checksumSrcIPv4TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz,
|
||||
size_t fragoff, size_t chksumoff, nuint32_t oSrcIP,
|
||||
nuint32_t oDstIP)
|
||||
{
|
||||
|
@ -206,7 +206,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
static void
|
||||
checksumSrcIPv4UDP(byte_t *pld, __attribute__((unused)) size_t psz,
|
||||
checksumSrcIPv4UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz,
|
||||
size_t fragoff, nuint32_t oSrcIP, nuint32_t oDstIP)
|
||||
{
|
||||
if(fragoff > 6)
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* nodedb.hpp
|
||||
*
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <util/threading.hpp>
|
||||
#include <util/time.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
|
|
@ -11,8 +11,8 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
PoW::DecodeKey(__attribute__((unused)) const llarp_buffer_t& k,
|
||||
__attribute__((unused)) llarp_buffer_t* val)
|
||||
PoW::DecodeKey(ABSL_ATTRIBUTE_UNUSED const llarp_buffer_t& k,
|
||||
ABSL_ATTRIBUTE_UNUSED llarp_buffer_t* val)
|
||||
{
|
||||
// TODO: implement me
|
||||
return false;
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace llarp
|
|||
NetID::BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
auto term = std::find(begin(), end(), '\0');
|
||||
return bencode_write_bytestring(buf, begin(), std::distance(begin(), term));
|
||||
return bencode_write_bytestring(buf, data(), std::distance(begin(), term));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -20,7 +20,7 @@ bool
|
|||
llarp_buffer_t::writef(const char* fmt, ...)
|
||||
{
|
||||
int written;
|
||||
ssize_t sz = size_left();
|
||||
size_t sz = size_left();
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
written = vsnprintf(reinterpret_cast< char* >(cur), sz, fmt, args);
|
||||
|
|
|
@ -128,12 +128,14 @@ struct llarp_buffer_t
|
|||
#ifndef _WIN32
|
||||
bool
|
||||
writef(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
||||
;
|
||||
#else
|
||||
|
||||
#elif defined(__MINGW64__) || defined(__MINGW32__)
|
||||
bool
|
||||
writef(const char *fmt, ...)
|
||||
__attribute__((__format__(__MINGW_PRINTF_FORMAT, 2, 3)));
|
||||
;
|
||||
#else
|
||||
bool
|
||||
writef(const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
|
|
@ -16,7 +16,9 @@ namespace fs = std::experimental::filesystem;
|
|||
namespace fs = cpp17::filesystem;
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -26,6 +28,15 @@ namespace llarp
|
|||
using PathIter = std::function< void(const fs::path &, PathVisitor) >;
|
||||
|
||||
static PathIter IterDir = [](const fs::path &path, PathVisitor visit) {
|
||||
#ifdef _MSC_VER
|
||||
for(auto &p : fs::directory_iterator(path))
|
||||
{
|
||||
if(!visit(p.path()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
DIR *d = opendir(path.string().c_str());
|
||||
if(d == nullptr)
|
||||
return;
|
||||
|
@ -42,6 +53,7 @@ namespace llarp
|
|||
break;
|
||||
} while(ent);
|
||||
closedir(d);
|
||||
#endif
|
||||
};
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef LLARP_UTIL_LOGGER_INTERNAL_HPP
|
||||
#define LLARP_UTIL_LOGGER_INTERNAL_HPP
|
||||
|
||||
#include <absl/time/clock.h>
|
||||
#include <absl/time/time.h>
|
||||
#include <util/time.hpp>
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
|
@ -55,8 +57,7 @@ namespace llarp
|
|||
(void)ts;
|
||||
return out << time_now_ms();
|
||||
#else
|
||||
auto now = llarp::Clock_t::to_time_t(llarp::Clock_t::now());
|
||||
return out << std::put_time(std::localtime(&now), ts.format);
|
||||
return out << absl::FormatTime(ts.format, absl::Now(), absl::LocalTimeZone());
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include <util/mem.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <absl/base/attributes.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
void
|
||||
|
@ -17,9 +19,9 @@ namespace llarp
|
|||
} // namespace llarp
|
||||
|
||||
void
|
||||
llarp_mem_slab(__attribute__((unused)) struct llarp_alloc *mem,
|
||||
__attribute__((unused)) uint32_t *buf,
|
||||
__attribute__((unused)) size_t sz)
|
||||
llarp_mem_slab(ABSL_ATTRIBUTE_UNUSED struct llarp_alloc *mem,
|
||||
ABSL_ATTRIBUTE_UNUSED uint32_t *buf,
|
||||
ABSL_ATTRIBUTE_UNUSED size_t sz)
|
||||
{
|
||||
// not implemented
|
||||
abort();
|
||||
|
|
|
@ -93,15 +93,4 @@ namespace llarp
|
|||
|
||||
} // namespace llarp
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
namespace std
|
||||
{
|
||||
template < typename T, typename... Args >
|
||||
std::unique_ptr< T >
|
||||
make_unique(Args &&... args)
|
||||
{
|
||||
return std::unique_ptr< T >(new T(std::forward< Args >(args)...));
|
||||
}
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace llarp
|
|||
/// a lock that does nothing
|
||||
struct SCOPED_LOCKABLE NullLock
|
||||
{
|
||||
NullLock(__attribute__((unused)) const NullMutex* mtx)
|
||||
NullLock(ABSL_ATTRIBUTE_UNUSED const NullMutex* mtx)
|
||||
EXCLUSIVE_LOCK_FUNCTION(mtx)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
|
|||
if(nev > FD_SETSIZE)
|
||||
nev = FD_SETSIZE;
|
||||
|
||||
unote_t* nvec[nev];
|
||||
unote_t** nvec = calloc(nev, sizeof(unote_t *));
|
||||
int i, maxfd = 0, e = 0, nfds = 0;
|
||||
|
||||
fd_set pollin, pollout, pollerr;
|
||||
|
@ -240,6 +240,7 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
|
|||
if(rc == SOCKET_ERROR)
|
||||
{
|
||||
assert(WSAGetLastError() == WSAENOTSOCK);
|
||||
free(nvec);
|
||||
return -WSAGetLastError();
|
||||
}
|
||||
|
||||
|
@ -269,6 +270,7 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
|
|||
++e;
|
||||
}
|
||||
}
|
||||
free(nvec);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,5 +67,5 @@ if(NOT WIN32)
|
|||
target_link_libraries(${TEST_EXE} PUBLIC absl::variant)
|
||||
else()
|
||||
target_sources(${TEST_EXE} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/win32/test.rc")
|
||||
target_link_libraries(${TEST_EXE} PUBLIC ws2_32 iphlpapi)
|
||||
target_link_libraries(${TEST_EXE} PUBLIC ws2_32 iphlpapi shlwapi)
|
||||
endif(NOT WIN32)
|
||||
|
|
|
@ -31,7 +31,7 @@ struct AbyssTestBase : public ::testing::Test
|
|||
}
|
||||
|
||||
static void
|
||||
CancelIt(void* u, __attribute__((unused)) uint64_t orig, uint64_t left)
|
||||
CancelIt(void* u, ABSL_ATTRIBUTE_UNUSED uint64_t orig, uint64_t left)
|
||||
{
|
||||
if(left)
|
||||
return;
|
||||
|
@ -104,12 +104,12 @@ struct ClientHandler : public abyss::http::IRPCClientHandler
|
|||
}
|
||||
|
||||
void
|
||||
PopulateReqHeaders(__attribute__((unused)) abyss::http::Headers_t& hdr)
|
||||
PopulateReqHeaders(ABSL_ATTRIBUTE_UNUSED abyss::http::Headers_t& hdr)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
HandleResponse(__attribute__((unused)) abyss::http::RPC_Response response)
|
||||
HandleResponse(ABSL_ATTRIBUTE_UNUSED abyss::http::RPC_Response response)
|
||||
{
|
||||
test->AsyncStop();
|
||||
return true;
|
||||
|
@ -125,7 +125,7 @@ struct ServerHandler : public abyss::httpd::IRPCHandler
|
|||
}
|
||||
|
||||
absl::optional< Response >
|
||||
HandleJSONRPC(Method_t method, __attribute__((unused)) const Params& params)
|
||||
HandleJSONRPC(Method_t method, ABSL_ATTRIBUTE_UNUSED const Params& params)
|
||||
{
|
||||
test->AssertMethod(method);
|
||||
test->called = true;
|
||||
|
|
4
vendor/abseil-cpp/CMakeLists.txt
vendored
4
vendor/abseil-cpp/CMakeLists.txt
vendored
|
@ -69,11 +69,11 @@ endif()
|
|||
list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# -std=X
|
||||
if (WIN32)
|
||||
if (WIN32 AND NOT MSVC_VERSION)
|
||||
set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS} -fno-ident")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
|
||||
endif(WIN32)
|
||||
endif(WIN32 AND NOT MSVC_VERSION)
|
||||
|
||||
# -fexceptions
|
||||
set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}")
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifdef _WIN32
|
||||
#include <shlwapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
|
|
|
@ -181,9 +181,9 @@ absl_cc_library(
|
|||
NAME
|
||||
leak_check
|
||||
HDRS
|
||||
"$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:leak_check.h>"
|
||||
"leak_check.h"
|
||||
SRCS
|
||||
"$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:leak_check.cc>"
|
||||
"leak_check.cc"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
|
|
8
vendor/cxxopts/.gitignore
vendored
Normal file
8
vendor/cxxopts/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
*.swp
|
||||
build*
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
CMakeFiles/
|
||||
Testing/
|
||||
CTestTestfile.cmake
|
||||
cmake_install.cmake
|
70
vendor/cxxopts/.travis.yml
vendored
Normal file
70
vendor/cxxopts/.travis.yml
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
sudo: required
|
||||
dist: trusty
|
||||
language: cpp
|
||||
os:
|
||||
- linux
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: COMPILER=g++-4.9
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources: &sources
|
||||
- llvm-toolchain-trusty-3.8
|
||||
- llvm-toolchain-trusty-5.0
|
||||
- ubuntu-toolchain-r-test
|
||||
- os: linux
|
||||
env: COMPILER=g++-4.9 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources: *sources
|
||||
- os: linux
|
||||
env: COMPILER=g++-5
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources: *sources
|
||||
- os: linux
|
||||
env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources: *sources
|
||||
- os: linux
|
||||
env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
- libc++-dev
|
||||
sources: *sources
|
||||
- os: linux
|
||||
env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++ UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
- libc++-dev
|
||||
sources: *sources
|
||||
- os: linux
|
||||
env: COMPILER=clang++-5.0 CMAKE_OPTIONS=-DCXXOPTS_CXX_STANDARD=17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-5.0
|
||||
- g++-5
|
||||
sources: *sources
|
||||
script: >
|
||||
cmake -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER
|
||||
-DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS $CMAKE_OPTIONS .
|
||||
&& make && make ARGS=--output-on-failure test
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install icu4c; fi
|
82
vendor/cxxopts/CHANGELOG.md
vendored
Normal file
82
vendor/cxxopts/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Changelog
|
||||
|
||||
This is the changelog for `cxxopts`, a C++11 library for parsing command line
|
||||
options. The project adheres to semantic versioning.
|
||||
|
||||
## 2.2
|
||||
|
||||
### Changed
|
||||
|
||||
* Allow integers to have leading zeroes.
|
||||
* Build the tests by default.
|
||||
|
||||
### Added
|
||||
|
||||
* Iterator inputs to `parse_positional`.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix a warning about possible loss of data.
|
||||
* Fix version numbering in CMakeLists.txt
|
||||
* Remove unused declaration of the undefined `ParseResult::get_option`.
|
||||
* Throw on invalid option syntax when beginning with a `-`.
|
||||
* Throw in `as` when option wasn't present.
|
||||
* Fix catching exceptions by reference.
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Revert the change adding `const` type for `argv`, because most users expect
|
||||
to pass a non-const `argv` from `main`.
|
||||
|
||||
## 2.1
|
||||
|
||||
### Changed
|
||||
|
||||
* Options with implicit arguments now require the `--option=value` form if
|
||||
they are to be specified with an option. This is to remove the ambiguity
|
||||
when a positional argument could follow an option with an implicit value.
|
||||
For example, `--foo value`, where `foo` has an implicit value, will be
|
||||
parsed as `--foo=implicit` and a positional argument `value`.
|
||||
* Boolean values are no longer special, but are just an option with a default
|
||||
and implicit value.
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for `std::optional` as a storage type.
|
||||
* Allow the help string to be customised.
|
||||
* Use `const` for the type in the `argv` parameter, since the contents of the
|
||||
arguments is never modified.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Building against GCC 4.9 was broken due to overly strict shadow warnings.
|
||||
* Fixed an ambiguous overload in the `parse_positional` function when an
|
||||
`initializer_list` was directly passed.
|
||||
* Fixed precedence in the Boolean value regex.
|
||||
|
||||
## 2.0
|
||||
|
||||
### Changed
|
||||
|
||||
* `Options::parse` returns a ParseResult rather than storing the parse
|
||||
result internally.
|
||||
* Options with default values now get counted as appearing once if they
|
||||
were not specified by the user.
|
||||
|
||||
### Added
|
||||
|
||||
* A new `ParseResult` object that is the immutable result of parsing. It
|
||||
responds to the same `count` and `operator[]` as `Options` of 1.x did.
|
||||
* The function `ParseResult::arguments` returns a vector of the parsed
|
||||
arguments to iterate through in the order they were provided.
|
||||
* The symbol `cxxopts::version` for the version of the library.
|
||||
* Booleans can be specified with various strings and explicitly set false.
|
||||
|
||||
## 1.x
|
||||
|
||||
The 1.x series was the first major version of the library, with release numbers
|
||||
starting to follow semantic versioning, after 0.x being unstable. It never had
|
||||
a changelog maintained for it. Releases mostly contained bug fixes, with the
|
||||
occasional feature added.
|
104
vendor/cxxopts/CMakeLists.txt
vendored
Normal file
104
vendor/cxxopts/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Copyright (c) 2014 Jarryd Beck
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# parse the current version from the cxxopts header
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/cxxopts.hpp" cxxopts_version_defines
|
||||
REGEX "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH)")
|
||||
foreach(ver ${cxxopts_version_defines})
|
||||
if(ver MATCHES "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
|
||||
set(CXXOPTS__VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
set(VERSION ${CXXOPTS__VERSION_MAJOR}.${CXXOPTS__VERSION_MINOR}.${CXXOPTS__VERSION_PATCH})
|
||||
message(STATUS "cxxopts version ${VERSION}")
|
||||
|
||||
project(cxxopts VERSION "${VERSION}")
|
||||
|
||||
enable_testing()
|
||||
|
||||
option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON)
|
||||
option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" ON)
|
||||
|
||||
# request c++11 without gnu extension for the whole project and enable more warnings
|
||||
if (CXXOPTS_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD ${CXXOPTS_CXX_STANDARD})
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -Wshadow")
|
||||
endif()
|
||||
|
||||
add_library(cxxopts INTERFACE)
|
||||
|
||||
# optionally, enable unicode support using the ICU library
|
||||
set(CXXOPTS_USE_UNICODE_HELP FALSE CACHE BOOL "Use ICU Unicode library")
|
||||
if(CXXOPTS_USE_UNICODE_HELP)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(ICU REQUIRED icu-uc)
|
||||
|
||||
target_link_libraries(cxxopts INTERFACE ${ICU_LDFLAGS})
|
||||
target_compile_options(cxxopts INTERFACE ${ICU_CFLAGS})
|
||||
target_compile_definitions(cxxopts INTERFACE CXXOPTS_USE_UNICODE)
|
||||
endif()
|
||||
|
||||
target_include_directories(cxxopts INTERFACE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(CXXOPTS_CMAKE_DIR "lib/cmake/cxxopts" CACHE STRING
|
||||
"Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
|
||||
set(version_config "${PROJECT_BINARY_DIR}/cxxopts-config-version.cmake")
|
||||
set(project_config "${PROJECT_BINARY_DIR}/cxxopts-config.cmake")
|
||||
set(targets_export_name cxxopts-targets)
|
||||
|
||||
# Generate the version, config and target files into the build directory.
|
||||
write_basic_package_version_file(
|
||||
${version_config}
|
||||
VERSION ${VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
configure_package_config_file(
|
||||
${PROJECT_SOURCE_DIR}/cxxopts-config.cmake.in
|
||||
${project_config}
|
||||
INSTALL_DESTINATION ${CXXOPTS_CMAKE_DIR})
|
||||
export(TARGETS cxxopts NAMESPACE cxxopts::
|
||||
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
|
||||
|
||||
# Install version, config and target files.
|
||||
install(
|
||||
FILES ${project_config} ${version_config}
|
||||
DESTINATION ${CXXOPTS_CMAKE_DIR})
|
||||
install(EXPORT ${targets_export_name} DESTINATION ${CXXOPTS_CMAKE_DIR}
|
||||
NAMESPACE cxxopts::)
|
||||
|
||||
# Install the header file and export the target
|
||||
install(TARGETS cxxopts EXPORT ${targets_export_name} DESTINATION lib)
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/include/cxxopts.hpp DESTINATION include)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
23
vendor/cxxopts/INSTALL
vendored
Normal file
23
vendor/cxxopts/INSTALL
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
== System installation ==
|
||||
|
||||
This library is header only. So you can either copy `include/cxxopts.hpp` to `/usr/include` or `/usr/local/include`, or add `include` to your search path.
|
||||
|
||||
== Building the examples and tests ==
|
||||
|
||||
It is preferable to build out of source. Make a build directory somewhere, and then
|
||||
do the following, where `${CXXOPTS_DIR}` is the path that you checked out `cxxopts`
|
||||
to:
|
||||
|
||||
cmake ${CXXOPTS_DIR}
|
||||
make
|
||||
|
||||
You can use another build tool, such as ninja.
|
||||
|
||||
cmake -G Ninja ${CXXOPTS_DIR}
|
||||
ninja
|
||||
|
||||
|
||||
To run the tests, you have to configure `cxxopts` with another flag:
|
||||
cmake -D CXXOPTS_BUILD_TESTS=On ${CXXOPTS_DIR}
|
||||
make
|
||||
make test
|
19
vendor/cxxopts/LICENSE
vendored
Normal file
19
vendor/cxxopts/LICENSE
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 Jarryd Beck
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
136
vendor/cxxopts/README.md
vendored
Normal file
136
vendor/cxxopts/README.md
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
[![Build Status](https://travis-ci.org/jarro2783/cxxopts.svg?branch=master)](https://travis-ci.org/jarro2783/cxxopts)
|
||||
|
||||
# Release versions
|
||||
|
||||
Note that `master` is generally a work in progress, and you probably want to use a
|
||||
tagged release version.
|
||||
|
||||
# Quick start
|
||||
|
||||
This is a lightweight C++ option parser library, supporting the standard GNU
|
||||
style syntax for options.
|
||||
|
||||
Options can be given as:
|
||||
|
||||
--long
|
||||
--long=argument
|
||||
--long argument
|
||||
-a
|
||||
-ab
|
||||
-abc argument
|
||||
|
||||
where c takes an argument, but a and b do not.
|
||||
|
||||
Additionally, anything after `--` will be parsed as a positional argument.
|
||||
|
||||
## Basics
|
||||
|
||||
#include <cxxopts.hpp>
|
||||
|
||||
Create a cxxopts::Options instance.
|
||||
|
||||
cxxopts::Options options("MyProgram", "One line description of MyProgram");
|
||||
|
||||
Then use `add_options`.
|
||||
|
||||
options.add_options()
|
||||
("d,debug", "Enable debugging")
|
||||
("f,file", "File name", cxxopts::value<std::string>())
|
||||
;
|
||||
|
||||
Options are declared with a long and an optional short option. A description
|
||||
must be provided. The third argument is the value, if omitted it is boolean.
|
||||
Any type can be given as long as it can be parsed, with operator>>.
|
||||
|
||||
To parse the command line do:
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
To retrieve an option use `result.count("option")` to get the number of times
|
||||
it appeared, and
|
||||
|
||||
result["opt"].as<type>()
|
||||
|
||||
to get its value. If "opt" doesn't exist, or isn't of the right type, then an
|
||||
exception will be thrown.
|
||||
|
||||
Note that the result of `options.parse` should only be used as long as the
|
||||
`options` object that created it is in scope.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Exceptional situations throw C++ exceptions. There are two types of
|
||||
exceptions: errors defining the options, and errors when parsing a list of
|
||||
arguments. All exceptions derive from `cxxopts::OptionException`. Errors
|
||||
defining options derive from `cxxopts::OptionSpecException` and errors
|
||||
parsing arguments derive from `cxxopts::OptionParseException`.
|
||||
|
||||
All exceptions define a `what()` function to get a printable string
|
||||
explaining the error.
|
||||
|
||||
## Help groups
|
||||
|
||||
Options can be placed into groups for the purposes of displaying help messages.
|
||||
To place options in a group, pass the group as a string to `add_options`. Then,
|
||||
when displaying the help, pass the groups that you would like displayed as a
|
||||
vector to the `help` function.
|
||||
|
||||
## Positional Arguments
|
||||
|
||||
Positional arguments can be optionally parsed into one or more options.
|
||||
To set up positional arguments, call
|
||||
|
||||
options.parse_positional({"first", "second", "last"})
|
||||
|
||||
where "last" should be the name of an option with a container type, and the
|
||||
others should have a single value.
|
||||
|
||||
## Default and implicit values
|
||||
|
||||
An option can be declared with a default or an implicit value, or both.
|
||||
|
||||
A default value is the value that an option takes when it is not specified
|
||||
on the command line. The following specifies a default value for an option:
|
||||
|
||||
cxxopts::value<std::string>()->default_value("value")
|
||||
|
||||
An implicit value is the value that an option takes when it is given on the
|
||||
command line without an argument. The following specifies an implicit value:
|
||||
|
||||
cxxopts::value<std::string>()->implicit_value("implicit")
|
||||
|
||||
If an option had both, then not specifying it would give the value `"value"`,
|
||||
writing it on the command line as `--option` would give the value `"implicit"`,
|
||||
and writing `--option=another` would give it the value `"another"`.
|
||||
|
||||
Note that the default and implicit value is always stored as a string,
|
||||
regardless of the type that you want to store it in. It will be parsed as
|
||||
though it was given on the command line.
|
||||
|
||||
## Boolean values
|
||||
|
||||
Boolean options have a default implicit value of `"true"`, which can be
|
||||
overridden. The effect is that writing `-o` by itself will set option `o` to
|
||||
`true`. However, they can also be written with various strings using `=value`.
|
||||
There is no way to disambiguate positional arguments from the value following
|
||||
a boolean, so we have chosen that they will be positional arguments, and
|
||||
therefore, `-o false` does not work.
|
||||
|
||||
## Custom help
|
||||
|
||||
The string after the program name on the first line of the help can be
|
||||
completely replaced by calling `options.custom_help`. Note that you might
|
||||
also want to override the positional help by calling `options.positional_help`.
|
||||
|
||||
# Linking
|
||||
|
||||
This is a header only library.
|
||||
|
||||
# Requirements
|
||||
|
||||
The only build requirement is a C++ compiler that supports C++11 regular
|
||||
expressions. For example GCC >= 4.9 or clang with libc++.
|
||||
|
||||
# TODO list
|
||||
|
||||
* Allow unrecognised options.
|
4
vendor/cxxopts/cxxopts-config.cmake.in
vendored
Normal file
4
vendor/cxxopts/cxxopts-config.cmake.in
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake)
|
||||
check_required_components(cxxopts)
|
2082
vendor/cxxopts/include/cxxopts.hpp
vendored
Normal file
2082
vendor/cxxopts/include/cxxopts.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
vendor/cxxopts/src/.gitignore
vendored
Normal file
1
vendor/cxxopts/src/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
example
|
24
vendor/cxxopts/src/CMakeLists.txt
vendored
Normal file
24
vendor/cxxopts/src/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Copyright (c) 2014 Jarryd Beck
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
if(CXXOPTS_BUILD_EXAMPLES)
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example cxxopts)
|
||||
endif()
|
151
vendor/cxxopts/src/example.cpp
vendored
Normal file
151
vendor/cxxopts/src/example.cpp
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014 Jarryd Beck
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
cxxopts::ParseResult
|
||||
parse(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
cxxopts::Options options(argv[0], " - example command line options");
|
||||
options
|
||||
.positional_help("[optional args]")
|
||||
.show_positional_help();
|
||||
|
||||
bool apple = false;
|
||||
|
||||
options
|
||||
.allow_unrecognised_options()
|
||||
.add_options()
|
||||
("a,apple", "an apple", cxxopts::value<bool>(apple))
|
||||
("b,bob", "Bob")
|
||||
("t,true", "True", cxxopts::value<bool>()->default_value("true"))
|
||||
("f, file", "File", cxxopts::value<std::vector<std::string>>(), "FILE")
|
||||
("i,input", "Input", cxxopts::value<std::string>())
|
||||
("o,output", "Output file", cxxopts::value<std::string>()
|
||||
->default_value("a.out")->implicit_value("b.def"), "BIN")
|
||||
("positional",
|
||||
"Positional arguments: these are the arguments that are entered "
|
||||
"without an option", cxxopts::value<std::vector<std::string>>())
|
||||
("long-description",
|
||||
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
|
||||
("help", "Print help")
|
||||
("int", "An integer", cxxopts::value<int>(), "N")
|
||||
("float", "A floating point number", cxxopts::value<float>())
|
||||
("option_that_is_too_long_for_the_help", "A very long option")
|
||||
#ifdef CXXOPTS_USE_UNICODE
|
||||
("unicode", u8"A help option with non-ascii: à. Here the size of the"
|
||||
" string should be correct")
|
||||
#endif
|
||||
;
|
||||
|
||||
options.add_options("Group")
|
||||
("c,compile", "compile")
|
||||
("d,drop", "drop", cxxopts::value<std::vector<std::string>>());
|
||||
|
||||
options.parse_positional({"input", "output", "positional"});
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
if (result.count("help"))
|
||||
{
|
||||
std::cout << options.help({"", "Group"}) << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (apple)
|
||||
{
|
||||
std::cout << "Saw option ‘a’ " << result.count("a") << " times " <<
|
||||
std::endl;
|
||||
}
|
||||
|
||||
if (result.count("b"))
|
||||
{
|
||||
std::cout << "Saw option ‘b’" << std::endl;
|
||||
}
|
||||
|
||||
if (result.count("f"))
|
||||
{
|
||||
auto& ff = result["f"].as<std::vector<std::string>>();
|
||||
std::cout << "Files" << std::endl;
|
||||
for (const auto& f : ff)
|
||||
{
|
||||
std::cout << f << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.count("input"))
|
||||
{
|
||||
std::cout << "Input = " << result["input"].as<std::string>()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (result.count("output"))
|
||||
{
|
||||
std::cout << "Output = " << result["output"].as<std::string>()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (result.count("positional"))
|
||||
{
|
||||
std::cout << "Positional = {";
|
||||
auto& v = result["positional"].as<std::vector<std::string>>();
|
||||
for (const auto& s : v) {
|
||||
std::cout << s << ", ";
|
||||
}
|
||||
std::cout << "}" << std::endl;
|
||||
}
|
||||
|
||||
if (result.count("int"))
|
||||
{
|
||||
std::cout << "int = " << result["int"].as<int>() << std::endl;
|
||||
}
|
||||
|
||||
if (result.count("float"))
|
||||
{
|
||||
std::cout << "float = " << result["float"].as<float>() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Arguments remain = " << argc << std::endl;
|
||||
|
||||
return result;
|
||||
|
||||
} catch (const cxxopts::OptionException& e)
|
||||
{
|
||||
std::cout << "error parsing options: " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto result = parse(argc, argv);
|
||||
auto arguments = result.arguments();
|
||||
std::cout << "Saw " << arguments.size() << " arguments" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
1
vendor/cxxopts/test/.gitignore
vendored
Normal file
1
vendor/cxxopts/test/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
options_test
|
35
vendor/cxxopts/test/CMakeLists.txt
vendored
Normal file
35
vendor/cxxopts/test/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
if (CXXOPTS_BUILD_TESTS)
|
||||
add_executable(options_test main.cpp options.cpp)
|
||||
target_link_libraries(options_test cxxopts)
|
||||
add_test(options options_test)
|
||||
|
||||
# test if the targets are findable from the build directory
|
||||
add_test(find-package-test ${CMAKE_CTEST_COMMAND}
|
||||
-C ${CMAKE_BUILD_TYPE}
|
||||
--build-and-test
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/find-package-test"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/find-package-test"
|
||||
--build-generator ${CMAKE_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
|
||||
--build-options
|
||||
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
"-Dcxxopts_DIR=${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# test if the targets are findable when add_subdirectory is used
|
||||
add_test(add-subdirectory-test ${CMAKE_CTEST_COMMAND}
|
||||
-C ${CMAKE_BUILD_TYPE}
|
||||
--build-and-test
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test"
|
||||
--build-generator ${CMAKE_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
|
||||
--build-options
|
||||
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
)
|
||||
|
||||
add_executable(link_test link_a.cpp link_b.cpp)
|
||||
target_link_libraries(link_test cxxopts)
|
||||
endif()
|
11
vendor/cxxopts/test/add-subdirectory-test/CMakeLists.txt
vendored
Normal file
11
vendor/cxxopts/test/add-subdirectory-test/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(cxxopts-test)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
add_subdirectory(../.. cxxopts EXCLUDE_FROM_ALL)
|
||||
|
||||
add_executable(library-test "../../src/example.cpp")
|
||||
target_link_libraries(library-test cxxopts)
|
10460
vendor/cxxopts/test/catch.hpp
vendored
Normal file
10460
vendor/cxxopts/test/catch.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
11
vendor/cxxopts/test/find-package-test/CMakeLists.txt
vendored
Normal file
11
vendor/cxxopts/test/find-package-test/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(cxxopts-test)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
find_package(cxxopts REQUIRED)
|
||||
|
||||
add_executable(library-test "../../src/example.cpp")
|
||||
target_link_libraries(library-test cxxopts::cxxopts)
|
6
vendor/cxxopts/test/link_a.cpp
vendored
Normal file
6
vendor/cxxopts/test/link_a.cpp
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "cxxopts.hpp"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
return 0;
|
||||
}
|
1
vendor/cxxopts/test/link_b.cpp
vendored
Normal file
1
vendor/cxxopts/test/link_b.cpp
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include <cxxopts.hpp>
|
2
vendor/cxxopts/test/main.cpp
vendored
Normal file
2
vendor/cxxopts/test/main.cpp
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
550
vendor/cxxopts/test/options.cpp
vendored
Normal file
550
vendor/cxxopts/test/options.cpp
vendored
Normal file
|
@ -0,0 +1,550 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
class Argv {
|
||||
public:
|
||||
|
||||
Argv(std::initializer_list<const char*> args)
|
||||
: m_argv(new char*[args.size()])
|
||||
, m_argc(args.size())
|
||||
{
|
||||
int i = 0;
|
||||
auto iter = args.begin();
|
||||
while (iter != args.end()) {
|
||||
auto len = strlen(*iter) + 1;
|
||||
auto ptr = std::unique_ptr<char[]>(new char[len]);
|
||||
|
||||
strcpy(ptr.get(), *iter);
|
||||
m_args.push_back(std::move(ptr));
|
||||
m_argv.get()[i] = m_args.back().get();
|
||||
|
||||
++iter;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
char** argv() const {
|
||||
return m_argv.get();
|
||||
}
|
||||
|
||||
int argc() const {
|
||||
return m_argc;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::unique_ptr<char[]>> m_args;
|
||||
std::unique_ptr<char*[]> m_argv;
|
||||
int m_argc;
|
||||
};
|
||||
|
||||
TEST_CASE("Basic options", "[options]")
|
||||
{
|
||||
|
||||
cxxopts::Options options("tester", " - test basic options");
|
||||
|
||||
options.add_options()
|
||||
("long", "a long option")
|
||||
("s,short", "a short option")
|
||||
("value", "an option with a value", cxxopts::value<std::string>())
|
||||
("a,av", "a short option with a value", cxxopts::value<std::string>())
|
||||
("6,six", "a short number option")
|
||||
("p, space", "an option with space between short and long")
|
||||
("nothing", "won't exist", cxxopts::value<std::string>())
|
||||
;
|
||||
|
||||
Argv argv({
|
||||
"tester",
|
||||
"--long",
|
||||
"-s",
|
||||
"--value",
|
||||
"value",
|
||||
"-a",
|
||||
"b",
|
||||
"-6",
|
||||
"-p",
|
||||
"--space",
|
||||
});
|
||||
|
||||
char** actual_argv = argv.argv();
|
||||
auto argc = argv.argc();
|
||||
|
||||
auto result = options.parse(argc, actual_argv);
|
||||
|
||||
CHECK(result.count("long") == 1);
|
||||
CHECK(result.count("s") == 1);
|
||||
CHECK(result.count("value") == 1);
|
||||
CHECK(result.count("a") == 1);
|
||||
CHECK(result["value"].as<std::string>() == "value");
|
||||
CHECK(result["a"].as<std::string>() == "b");
|
||||
CHECK(result.count("6") == 1);
|
||||
CHECK(result.count("p") == 2);
|
||||
CHECK(result.count("space") == 2);
|
||||
|
||||
auto& arguments = result.arguments();
|
||||
REQUIRE(arguments.size() == 7);
|
||||
CHECK(arguments[0].key() == "long");
|
||||
CHECK(arguments[0].value() == "true");
|
||||
CHECK(arguments[0].as<bool>() == true);
|
||||
|
||||
CHECK(arguments[1].key() == "short");
|
||||
CHECK(arguments[2].key() == "value");
|
||||
CHECK(arguments[3].key() == "av");
|
||||
|
||||
CHECK_THROWS_AS(result["nothing"].as<std::string>(), std::domain_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("Short options", "[options]")
|
||||
{
|
||||
cxxopts::Options options("test_short", " - test short options");
|
||||
|
||||
options.add_options()
|
||||
("a", "a short option", cxxopts::value<std::string>());
|
||||
|
||||
Argv argv({"test_short", "-a", "value"});
|
||||
|
||||
auto actual_argv = argv.argv();
|
||||
auto argc = argv.argc();
|
||||
|
||||
auto result = options.parse(argc, actual_argv);
|
||||
|
||||
CHECK(result.count("a") == 1);
|
||||
CHECK(result["a"].as<std::string>() == "value");
|
||||
|
||||
REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
|
||||
cxxopts::invalid_option_format_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("No positional", "[positional]")
|
||||
{
|
||||
cxxopts::Options options("test_no_positional",
|
||||
" - test no positional options");
|
||||
|
||||
Argv av({"tester", "a", "b", "def"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(argc == 4);
|
||||
CHECK(strcmp(argv[1], "a") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("All positional", "[positional]")
|
||||
{
|
||||
std::vector<std::string> positional;
|
||||
|
||||
cxxopts::Options options("test_all_positional", " - test all positional");
|
||||
options.add_options()
|
||||
("positional", "Positional parameters",
|
||||
cxxopts::value<std::vector<std::string>>(positional))
|
||||
;
|
||||
|
||||
Argv av({"tester", "a", "b", "c"});
|
||||
|
||||
auto argc = av.argc();
|
||||
auto argv = av.argv();
|
||||
|
||||
std::vector<std::string> pos_names = {"positional"};
|
||||
|
||||
options.parse_positional(pos_names.begin(), pos_names.end());
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(argc == 1);
|
||||
REQUIRE(positional.size() == 3);
|
||||
|
||||
CHECK(positional[0] == "a");
|
||||
CHECK(positional[1] == "b");
|
||||
CHECK(positional[2] == "c");
|
||||
}
|
||||
|
||||
TEST_CASE("Some positional explicit", "[positional]")
|
||||
{
|
||||
cxxopts::Options options("positional_explicit", " - test positional");
|
||||
|
||||
options.add_options()
|
||||
("input", "Input file", cxxopts::value<std::string>())
|
||||
("output", "Output file", cxxopts::value<std::string>())
|
||||
("positional", "Positional parameters",
|
||||
cxxopts::value<std::vector<std::string>>())
|
||||
;
|
||||
|
||||
options.parse_positional({"input", "output", "positional"});
|
||||
|
||||
Argv av({"tester", "--output", "a", "b", "c", "d"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
CHECK(argc == 1);
|
||||
CHECK(result.count("output"));
|
||||
CHECK(result["input"].as<std::string>() == "b");
|
||||
CHECK(result["output"].as<std::string>() == "a");
|
||||
|
||||
auto& positional = result["positional"].as<std::vector<std::string>>();
|
||||
|
||||
REQUIRE(positional.size() == 2);
|
||||
CHECK(positional[0] == "c");
|
||||
CHECK(positional[1] == "d");
|
||||
}
|
||||
|
||||
TEST_CASE("No positional with extras", "[positional]")
|
||||
{
|
||||
cxxopts::Options options("posargmaster", "shows incorrect handling");
|
||||
options.add_options()
|
||||
("dummy", "oh no", cxxopts::value<std::string>())
|
||||
;
|
||||
|
||||
Argv av({"extras", "--", "a", "b", "c", "d"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto old_argv = argv;
|
||||
auto old_argc = argc;
|
||||
|
||||
options.parse(argc, argv);
|
||||
|
||||
REQUIRE(argc == old_argc - 1);
|
||||
CHECK(argv[0] == std::string("extras"));
|
||||
CHECK(argv[1] == std::string("a"));
|
||||
}
|
||||
|
||||
TEST_CASE("Empty with implicit value", "[implicit]")
|
||||
{
|
||||
cxxopts::Options options("empty_implicit", "doesn't handle empty");
|
||||
options.add_options()
|
||||
("implicit", "Has implicit", cxxopts::value<std::string>()
|
||||
->implicit_value("foo"));
|
||||
|
||||
Argv av({"implicit", "--implicit="});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("implicit") == 1);
|
||||
REQUIRE(result["implicit"].as<std::string>() == "");
|
||||
}
|
||||
|
||||
TEST_CASE("Default values", "[default]")
|
||||
{
|
||||
cxxopts::Options options("defaults", "has defaults");
|
||||
options.add_options()
|
||||
("default", "Has implicit", cxxopts::value<int>()
|
||||
->default_value("42"));
|
||||
|
||||
SECTION("Sets defaults") {
|
||||
Argv av({"implicit"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
CHECK(result.count("default") == 0);
|
||||
CHECK(result["default"].as<int>() == 42);
|
||||
}
|
||||
|
||||
SECTION("When values provided") {
|
||||
Argv av({"implicit", "--default", "5"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
CHECK(result.count("default") == 1);
|
||||
CHECK(result["default"].as<int>() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Parse into a reference", "[reference]")
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
cxxopts::Options options("into_reference", "parses into a reference");
|
||||
options.add_options()
|
||||
("ref", "A reference", cxxopts::value(value));
|
||||
|
||||
Argv av({"into_reference", "--ref", "42"});
|
||||
|
||||
auto argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
CHECK(result.count("ref") == 1);
|
||||
CHECK(value == 42);
|
||||
}
|
||||
|
||||
TEST_CASE("Integers", "[options]")
|
||||
{
|
||||
cxxopts::Options options("parses_integers", "parses integers correctly");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<int>>());
|
||||
|
||||
Argv av({"ints", "--", "5", "6", "-6", "0", "0xab", "0xAf", "0x0"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("positional") == 7);
|
||||
|
||||
auto& positional = result["positional"].as<std::vector<int>>();
|
||||
REQUIRE(positional.size() == 7);
|
||||
CHECK(positional[0] == 5);
|
||||
CHECK(positional[1] == 6);
|
||||
CHECK(positional[2] == -6);
|
||||
CHECK(positional[3] == 0);
|
||||
CHECK(positional[4] == 0xab);
|
||||
CHECK(positional[5] == 0xaf);
|
||||
CHECK(positional[6] == 0x0);
|
||||
}
|
||||
|
||||
TEST_CASE("Leading zero integers", "[options]")
|
||||
{
|
||||
cxxopts::Options options("parses_integers", "parses integers correctly");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<int>>());
|
||||
|
||||
Argv av({"ints", "--", "05", "06", "0x0ab", "0x0001"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("positional") == 4);
|
||||
|
||||
auto& positional = result["positional"].as<std::vector<int>>();
|
||||
REQUIRE(positional.size() == 4);
|
||||
CHECK(positional[0] == 5);
|
||||
CHECK(positional[1] == 6);
|
||||
CHECK(positional[2] == 0xab);
|
||||
CHECK(positional[3] == 0x1);
|
||||
}
|
||||
|
||||
TEST_CASE("Unsigned integers", "[options]")
|
||||
{
|
||||
cxxopts::Options options("parses_unsigned", "detects unsigned errors");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<unsigned int>>());
|
||||
|
||||
Argv av({"ints", "--", "-2"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
||||
}
|
||||
|
||||
TEST_CASE("Integer bounds", "[integer]")
|
||||
{
|
||||
cxxopts::Options options("integer_boundaries", "check min/max integer");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<int8_t>>());
|
||||
|
||||
SECTION("No overflow")
|
||||
{
|
||||
Argv av({"ints", "--", "127", "-128", "0x7f", "-0x80", "0x7e"});
|
||||
|
||||
auto argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("positional") == 5);
|
||||
|
||||
auto& positional = result["positional"].as<std::vector<int8_t>>();
|
||||
CHECK(positional[0] == 127);
|
||||
CHECK(positional[1] == -128);
|
||||
CHECK(positional[2] == 0x7f);
|
||||
CHECK(positional[3] == -0x80);
|
||||
CHECK(positional[4] == 0x7e);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Overflow on boundary", "[integer]")
|
||||
{
|
||||
using namespace cxxopts::values;
|
||||
|
||||
int8_t si;
|
||||
uint8_t ui;
|
||||
|
||||
CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::argument_incorrect_type&);
|
||||
CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::argument_incorrect_type&);
|
||||
CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::argument_incorrect_type&);
|
||||
CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::argument_incorrect_type&);
|
||||
CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::argument_incorrect_type&);
|
||||
CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::argument_incorrect_type&);
|
||||
}
|
||||
|
||||
TEST_CASE("Integer overflow", "[options]")
|
||||
{
|
||||
cxxopts::Options options("reject_overflow", "rejects overflowing integers");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<int8_t>>());
|
||||
|
||||
Argv av({"ints", "--", "128"});
|
||||
|
||||
auto argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
||||
}
|
||||
|
||||
TEST_CASE("Floats", "[options]")
|
||||
{
|
||||
cxxopts::Options options("parses_floats", "parses floats correctly");
|
||||
options.add_options()
|
||||
("double", "Double precision", cxxopts::value<double>())
|
||||
("positional", "Floats", cxxopts::value<std::vector<float>>());
|
||||
|
||||
Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("double") == 1);
|
||||
REQUIRE(result.count("positional") == 4);
|
||||
|
||||
CHECK(result["double"].as<double>() == 0.5);
|
||||
|
||||
auto& positional = result["positional"].as<std::vector<float>>();
|
||||
CHECK(positional[0] == 4);
|
||||
CHECK(positional[1] == -4);
|
||||
CHECK(positional[2] == 1.5e6);
|
||||
CHECK(positional[3] == -1.5e6);
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid integers", "[integer]") {
|
||||
cxxopts::Options options("invalid_integers", "rejects invalid integers");
|
||||
options.add_options()
|
||||
("positional", "Integers", cxxopts::value<std::vector<int>>());
|
||||
|
||||
Argv av({"ints", "--", "Ae"});
|
||||
|
||||
char **argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse_positional("positional");
|
||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
||||
}
|
||||
|
||||
TEST_CASE("Booleans", "[boolean]") {
|
||||
cxxopts::Options options("parses_floats", "parses floats correctly");
|
||||
options.add_options()
|
||||
("bool", "A Boolean", cxxopts::value<bool>())
|
||||
("debug", "Debugging", cxxopts::value<bool>())
|
||||
("timing", "Timing", cxxopts::value<bool>())
|
||||
("noExplicitDefault", "No Explicit Default", cxxopts::value<bool>())
|
||||
("defaultTrue", "Timing", cxxopts::value<bool>()->default_value("true"))
|
||||
("defaultFalse", "Timing", cxxopts::value<bool>()->default_value("false"))
|
||||
("others", "Other arguments", cxxopts::value<std::vector<std::string>>())
|
||||
;
|
||||
|
||||
options.parse_positional("others");
|
||||
|
||||
Argv av({"booleans", "--bool=false", "--debug=true", "--timing", "extra"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
REQUIRE(result.count("bool") == 1);
|
||||
REQUIRE(result.count("debug") == 1);
|
||||
REQUIRE(result.count("timing") == 1);
|
||||
REQUIRE(result.count("noExplicitDefault") == 0);
|
||||
REQUIRE(result.count("defaultTrue") == 0);
|
||||
REQUIRE(result.count("defaultFalse") == 0);
|
||||
|
||||
CHECK(result["bool"].as<bool>() == false);
|
||||
CHECK(result["debug"].as<bool>() == true);
|
||||
CHECK(result["timing"].as<bool>() == true);
|
||||
CHECK(result["noExplicitDefault"].as<bool>() == false);
|
||||
CHECK(result["defaultTrue"].as<bool>() == true);
|
||||
CHECK(result["defaultFalse"].as<bool>() == false);
|
||||
|
||||
REQUIRE(result.count("others") == 1);
|
||||
}
|
||||
|
||||
#ifdef CXXOPTS_HAS_OPTIONAL
|
||||
TEST_CASE("std::optional", "[optional]") {
|
||||
std::optional<std::string> optional;
|
||||
cxxopts::Options options("optional", " - tests optional");
|
||||
options.add_options()
|
||||
("optional", "an optional option", cxxopts::value<std::optional<std::string>>(optional));
|
||||
|
||||
Argv av({"optional", "--optional", "foo"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse(argc, argv);
|
||||
|
||||
REQUIRE(optional.has_value());
|
||||
CHECK(*optional == "foo");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("Unrecognised options", "[options]") {
|
||||
cxxopts::Options options("unknown_options", " - test unknown options");
|
||||
|
||||
options.add_options()
|
||||
("long", "a long option")
|
||||
("s,short", "a short option");
|
||||
|
||||
Argv av({
|
||||
"unknown_options",
|
||||
"--unknown",
|
||||
"--long",
|
||||
"-su",
|
||||
"--another_unknown",
|
||||
});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
SECTION("Default behaviour") {
|
||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
|
||||
}
|
||||
|
||||
SECTION("After allowing unrecognised options") {
|
||||
options.allow_unrecognised_options();
|
||||
CHECK_NOTHROW(options.parse(argc, argv));
|
||||
REQUIRE(argc == 3);
|
||||
CHECK_THAT(argv[1], Catch::Equals("--unknown"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid option syntax", "[options]") {
|
||||
cxxopts::Options options("invalid_syntax", " - test invalid syntax");
|
||||
|
||||
Argv av({
|
||||
"invalid_syntax",
|
||||
"--a",
|
||||
});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
SECTION("Default behaviour") {
|
||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue