diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fd9c8f..ef1fafb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,66 +6,34 @@ on: - '*' - '*/*' - '!master' - pull_request: - branches: [ develop ] jobs: compile: strategy: - fail-fast: false matrix: - os: [ ubuntu-20.04, ubuntu-22.04, macos-latest, windows-latest ] - build: [ cli, cli-mt, cli-ansi, cli-ansi-mt, gui, gui-mt ] - include: - - build: cli - cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=OFF - - build: cli-mt - cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=ON - - build: cli-ansi - cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=OFF - - build: cli-ansi-mt - cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=ON - - build: gui - cmake-opts: -DCOMPONENT_CLI=OFF -DCOMPONENT_GUI=ON -DUSE_THREADS=OFF - - build: gui-mt - cmake-opts: -DCOMPONENT_CLI=OFF -DCOMPONENT_GUI=ON -DUSE_THREADS=ON + os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] + build-opts: [ "-DFORCE_ANSI=ON", "-DFORCE_ANSI=OFF" ] - name: ${{matrix.os}} (${{matrix.build}}) + name: ${{matrix.os}} (${{matrix.build-opts}}) runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v1 - - name: OpenSSL OSX - if: runner.os == 'macOS' - shell: bash - run: brew install openssl - - - name: Qt - Ubuntu - if: startsWith(matrix.build, 'gui') && runner.os == 'Linux' + - name: Dependancies shell: bash run: | - sudo apt-get update - if [ "${{matrix.os}}" == "ubuntu-22.04" ]; then - sudo apt-get install qtbase5-dev=5.15.3+dfsg-2ubuntu0.2 - else : - sudo apt-get install qt5-default=5.12.8+dfsg-0ubuntu2.1 + if [ "$RUNNER_OS" == "macOS" ]; then + brew install openssl fi - - name: Qt - Windows/Mac - if: startsWith(matrix.build, 'gui') && runner.os != 'Linux' - uses: jurplel/install-qt-action@v3 - with: - version: '5.15.2' - - name: Configure shell: bash run: | - OPTS="${{matrix.cmake-opts}}" if [ "$RUNNER_OS" == "macOS" ]; then - OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1 ${OPTS}" + SSL_OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" fi - cmake ${OPTS} -B build + cmake ${SSL_OPTS} ${{matrix.build-opts}} -B build - name: Build shell: bash @@ -74,5 +42,5 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v1 with: - name: ${{matrix.os}}_${{matrix.build}}-build + name: ${{matrix.os}}_${{matrix.build-opts}}-build path: build diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 30106ea..8398b5e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -9,36 +9,19 @@ jobs: ubuntu: strategy: matrix: - os: [ ubuntu-20.04, ubuntu-22.04 ] - component: [ cli, gui ] - include: - - os: ubuntu-20.04 - qt: qt5-default=5.12.8+dfsg-0ubuntu2.1 - - os: ubuntu-22.04 - qt: qtbase5-dev=5.15.3+dfsg-2ubuntu0.2 - - component: cli - build-opts: --cli --no-gui -t Release --pkg-type deb - - component: gui - build-opts: --no-cli --gui -t Release --pkg-type deb - name: DEB ${{matrix.os}} (${{matrix.component}}) + os: [ ubuntu-16.04, ubuntu-18.04 ] + name: ${{matrix.os}} runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 - - - name: Qt - if: startsWith(matrix.component, 'gui') - shell: bash - run: | - sudo apt-get update - sudo apt-get install ${{matrix.qt}} + - uses: actions/checkout@v1 - name: Package id: package run: | - ./build.sh ${{matrix.build-opts}} + ./build.sh -t Release --pkg-type deb FILE=$(ls build/*.deb | head -1) - echo "filename=$FILE" >> "$GITHUB_OUTPUT" - echo "name=$(basename $FILE)" >> "$GITHUB_OUTPUT" + echo "::set-output name=filename::$FILE" + echo "::set-output name=name::$(basename $FILE)" - name: Upload uses: actions/upload-release-asset@v1 @@ -50,105 +33,35 @@ jobs: asset_path: ${{ steps.package.outputs.filename }} asset_content_type: application/x-deb - # RPM package for redhat based systems. - rpm: - strategy: - matrix: - container: - - name: "fedora:36" - deps: - gcc-12.2.1-4.fc36.x86_64 - gcc-c++-12.2.1-4.fc36.x86_64 - cmake-3.26.3-1.fc36.x86_64 - openssl1.1-devel-1.1.1q-1.fc36.x86_64 - qt: qt5-qtbase-devel-5.15.3-1.fc36.x86_64 - - - name: "fedora:37" - deps: - gcc-12.3.1-1.fc37.x86_64 - gcc-c++-12.3.1-1.fc37.x86_64 - cmake-3.27.1-1.fc37.x86_64 - openssl-devel-3.0.9-1.fc37.x86_64 - qt: qt5-qtbase-devel-5.15.9-3.fc37.x86_64 - - - name: "fedora:38" - deps: - gcc-13.2.1-1.fc38.x86_64 - gcc-c++-13.2.1-1.fc38.x86_64 - cmake-3.26.2-1.fc38.x86_64 - openssl-devel-1:3.0.9-2.fc38.x86_64 - qt: qt5-qtbase-devel-5.15.10-5.fc38.x86_64 - component: [ cli, gui ] - include: - - component: cli - build-opts: --cli --no-gui -t Release --pkg-type rpm - - component: gui - build-opts: --no-cli --gui -t Release --pkg-type rpm - name: RPM ${{matrix.container.name}} (${{matrix.component}}) - runs-on: ubuntu-latest - container: ${{ matrix.container.name }} - steps: - - uses: actions/checkout@v3 - - - name: Dependancies - run: | - sudo dnf install -y util-linux rpmdevtools git ${{ matrix.container.deps }} - - - name: Qt - if: startsWith(matrix.component, 'gui') - shell: bash - run: | - sudo dnf install -y ${{ matrix.container.qt }} - - - name: Package - id: package - run: | - ./build.sh ${{matrix.build-opts}} - FILE=$(ls build/*.rpm | head -1) - echo "filename=$FILE" >> "$GITHUB_OUTPUT" - echo "name=$(basename $FILE)" >> "$GITHUB_OUTPUT" - - - name: Upload - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_name: ${{ steps.package.outputs.name }} - asset_path: ${{ steps.package.outputs.filename }} - asset_content_type: application/octet-stream - # Windows installer windows: strategy: matrix: - arch: [ Win32, x64 ] - include: - - arch: Win32 - qt-arch: win32_msvc2015 - - arch: x64 - qt-arch: win64_msvc2015_64 + arch: [ x86, x64 ] name: Windows (${{matrix.arch}}) runs-on: windows-latest steps: - - uses: actions/checkout@v3 - - - name: Qt - uses: jurplel/install-qt-action@v3 - with: - arch: ${{ matrix.qt-arch }} - version: '5.11.0' + - uses: actions/checkout@v1 - name: Configure - run: cmake -A ${{matrix.arch}} -DCOMPONENT_GUI=ON -DCOMPONENT_CLI=ON -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build + run: | + if ("${{matrix.arch}}" -eq "x86") { + $PLATFORM="Win32" + } else { + $PLATFORM="${{matrix.arch}}" + } + cmake -A $PLATFORM -D CPACK_GENERATOR=NSIS -S . -B build + + - name: Build + run: cmake --build build --config Release - name: Package id: package run: | - cmake --build build --config Release --target package + cmake --build build --target package $FILE=(ls build/*.exe) - echo "filename=$FILE" >> "$GITHUB_OUTPUT" - echo "name=$(([io.fileinfo]"$FILE").basename)" >> "$GITHUB_OUTPUT" + echo "::set-output name=filename::$FILE" + echo "::set-output name=name::$(([io.fileinfo]"$FILE").basename).exe" - name: Upload uses: actions/upload-release-asset@v1 diff --git a/.gitignore b/.gitignore index 02e2c31..6f31401 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ build/ .vscode/ -.cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3074eea..d5c1d1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,141 +1,108 @@ cmake_minimum_required(VERSION 3.15) -# -------------------------------- -# Project Info -# -------------------------------- - -project(antelope-keygen - VERSION 1.1.0 - DESCRIPTION "Keygenerator for Antelope based blockchain" - HOMEPAGE_URL "https://github.com/eosswedenorg/antelope-keygen" ) +# Project name and version +project(eosio-keygen + VERSION 1.0.4 + DESCRIPTION "Keygenerator for EOSIO" + HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) set( PROJECT_MAINTAINER "Henrik Hautakoski ") -set( PROJECT_LICENSE_FILE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) -# -------------------------------- -# Options -# -------------------------------- +# Options +option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) -option(COMPONENT_CLI "Build CLI Component" ON) -option(COMPONENT_GUI "Build GUI Component (Qt5)" OFF) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") -if (NOT COMPONENT_CLI AND NOT COMPONENT_GUI) - message(FATAL_ERROR "Atleast one of BUILD_COMPONENT_GUI,BUILD_COMPONENT_CLI must be set to ON") -endif() +include(libeoskeygen) -# -------------------------------- -# CMake settings -# -------------------------------- - -# Append modules dir -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -# Default to debug build if none is set. -if (NOT CMAKE_BUILD_TYPE) - set( CMAKE_BUILD_TYPE Debug ) -endif() - -# Install path +# Use installpath from GNUInstallDirs as default. include(GNUInstallDirs) set( CMAKE_INSTALL_SHAREDIR ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME} ) if (WIN32) # "Flat" install on windows. - set( CMAKE_INSTALL_BINDIR "bin" ) + set( CMAKE_INSTALL_BINDIR "." ) set( CMAKE_INSTALL_DATADIR "." ) set( CMAKE_INSTALL_SHAREDIR "." ) set( CMAKE_INSTALL_MANDIR "." ) endif (WIN32) -# Path to a directory outside of CMAKE_BUILD_DIR -# Should be used to cache large downloaded data that won't be deleted on clean builds. -set( DOWNLOAD_CACHE_DIR ${CMAKE_CURRENT_LIST_DIR}/.cache ) - -set( components ) -if (COMPONENT_CLI) - list(APPEND components cli ) -endif() - -if (COMPONENT_GUI) - list(APPEND components gui ) -endif() - -# -------------------------------- -# Compiler settings -# -------------------------------- - +# Configure the compiler options set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF ) -# c++ flags -add_compile_options( - "$<$:-Wall;-Wconversion;-Wno-sign-conversion;-Wextra>" - "$<$:/W3;-D_CRT_SECURE_NO_WARNINGS=1>" +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wconversion -Wno-sign-conversion -Wextra" ) +elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_definitions( "-D_CRT_SECURE_NO_WARNINGS=1" ) +endif() - # Debug - "$<$:$<$:-O0;-g>>" - "$<$:$<$:/Od;/Zi>>" +# -------------------------------- +# Program +# -------------------------------- - # Release - "$<$:$<$:-O3>>" - "$<$:$<$:/O2>>" +set (PROGRAM_EXE ${CMAKE_PROJECT_NAME}) - # MinSizeRel - "$<$:$<$:-Os>>" - "$<$:$<$:/O1>>" +set (PROGRAM_SOURCE + src/isatty.cpp + src/cli_key_search_result.cpp + src/console.cpp + src/benchmark.cpp + src/main.cpp ) -add_link_options( - # Release - "$<$:$<$:-s>>" -) - -include(CheckPIESupported) -check_pie_supported() -#cmake_policy(SET CMP0083 NEW) - -set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) +if (WIN32 AND NOT FORCE_ANSI) + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_win32.cpp) +else() + # *nix should have ansi support. + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_ansi.cpp) +endif() # Project config file -configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) +configure_file(src/config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) include_directories(${PROJECT_BINARY_DIR}) -# Bundle antelope-extras on windows. -if (WIN32) - include(extras) - list(APPEND components extras ) -endif() +add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) + +target_link_libraries( ${PROGRAM_EXE} PUBLIC eoskeygen ) + +# -------------------------------- +# Install +# -------------------------------- + +install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +# Readme and license +install(FILES README.md LICENSE LICENSE.bitcoin + DESTINATION ${CMAKE_INSTALL_SHAREDIR}) + +# Documentation + +if (UNIX) + configure_file( docs/eosio-keygen.1.in ${PROJECT_BINARY_DIR}/man1/eosio-keygen.1 ) + + install(DIRECTORY ${PROJECT_BINARY_DIR}/man1 + DESTINATION ${CMAKE_INSTALL_MANDIR}) +endif (UNIX) # -------------------------------- # Package # -------------------------------- -include(CPackConfig) - -set( CPACK_COMPONENTS_ALL ${components} ) - if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") - set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) + set( NSIS_LICENSE_FILE ${PROJECT_BINARY_DIR}/NSIS_LICENSE ) + file(WRITE ${NSIS_LICENSE_FILE} "") + foreach(file IN ITEMS LICENSE LICENSE.bitcoin) + file(READ ${CMAKE_CURRENT_LIST_DIR}/${file} content) + file(APPEND ${NSIS_LICENSE_FILE} "--- ${file}\n\n${content}\n") + endforeach() + set( CPACK_RESOURCE_FILE_LICENSE ${NSIS_LICENSE_FILE} ) endif() -set (CPACK_PROPERTIES_FILE ${PROJECT_BINARY_DIR}/CPackComponentsInclude.cmake) -configure_file(cmake/CPackProperties.cmake.in ${CPACK_PROPERTIES_FILE} @ONLY) +set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) +set( CPACK_DEBIAN_PACKAGE_SECTION "misc" ) +set( CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON ) -# -------------------------------- -# Components -# -------------------------------- - -add_subdirectory( common ) - -foreach(comp ${components}) - if ( EXISTS ${CMAKE_CURRENT_LIST_DIR}/${comp} ) - add_subdirectory( ${comp} ) - endif() -endforeach() - -# -------------------------------- -# CPack -# -------------------------------- -include (CPack) +include( cpack_custom ) diff --git a/cmake/CPackConfig.cmake b/CMakeModules/cpack_custom.cmake similarity index 87% rename from cmake/CPackConfig.cmake rename to CMakeModules/cpack_custom.cmake index 8f55ba5..d4fad9b 100644 --- a/cmake/CPackConfig.cmake +++ b/CMakeModules/cpack_custom.cmake @@ -93,23 +93,12 @@ set( CPACK_DEBIAN_PACKAGE_RELEASE "1" CACHE STRING "Debian package release versi # So we have to do it here. set( CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}" ) -# Always build components for deb packages -set( CPACK_DEB_COMPONENT_INSTALL ON ) +# Set "correct" filename that also include system version and architecture. +set( CPACK_DEBIAN_FILE_NAME + "${PROJECT_NAME}-${PROJECT_VERSION}-${CPACK_DEBIAN_PACKAGE_RELEASE}-${CPACK_SYSTEM_NAME}-${CPACK_SYSTEM_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb" +) -# RPM - -# Always build components for rpm packages -set( CPACK_RPM_COMPONENT_INSTALL ON ) - -# Same as with DEB package. -set( CPACK_RPM_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}" ) - -set( CPACK_RPM_PACKAGE_RELEASE_DIST ON ) -set( CPACK_RPM_PACKAGE_RELEASE "1" CACHE STRING "RPM package release version" ) -set( CPACK_RPM_PACKAGE_LICENSE "MIT" ) -set( CPACK_RPM_FILE_NAME "RPM-DEFAULT" ) - # -------------------------------- # Generator default # -------------------------------- @@ -123,3 +112,10 @@ if (NOT CPACK_GENERATOR) set( CPACK_GENERATOR "ZIP" ) endif() endif() + + +# -------------------------------- +# Include original CPack module. +# -------------------------------- + +include( CPack ) diff --git a/CMakeModules/libeoskeygen.cmake b/CMakeModules/libeoskeygen.cmake new file mode 100644 index 0000000..d58803f --- /dev/null +++ b/CMakeModules/libeoskeygen.cmake @@ -0,0 +1,52 @@ + +# -------------------------------- +# Variables +# -------------------------------- +set( LIBEOSKEYGEN_GIT_URL "https://github.com/eosswedenorg/libeoskeygen.git" ) +set( LIBEOSKEYGEN_WANTED_VERSION 0.1.1 ) + +# -------------------------------- +# Macros +# -------------------------------- +macro(fromGit tag) + + message ("Using libeoskeygen from: ${LIBEOSKEYGEN_GIT_URL}@${tag}") + + include(FetchContent) + FetchContent_Declare(libeoskeygen + GIT_REPOSITORY ${LIBEOSKEYGEN_GIT_URL} + GIT_TAG ${tag} + ) + + FetchContent_GetProperties(libeoskeygen) + if (NOT libeoskeygen_POPULATED) + FetchContent_Populate(libeoskeygen) + add_subdirectory(${libeoskeygen_SOURCE_DIR} ${libeoskeygen_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() +endmacro() + +macro(buildLocal src) + message ("Using local libeoskeygen at: ${src}") + add_subdirectory(${src} ${src}/build EXCLUDE_FROM_ALL) +endmacro() + +# If we have a local libeoskeygen +if (LIBEOSKEYGEN_SOURCE_DIR) + buildLocal( ${LIBEOSKEYGEN_SOURCE_DIR} ) +else() + + # Check if version is in fact a version. + if (LIBEOSKEYGEN_WANTED_VERSION MATCHES "^[0-9]+(.[0-9]+)?(.[0-9]+)(-[a-zA-Z0-9]+)?$") + # Try finding the package on the system. + find_package(libeoskeygen ${LIBEOSKEYGEN_WANTED_VERSION} QUIET) + if (libeoskeygen_FOUND) + message ("Using libeoskeygen in: ${libeoskeygen_DIR}") + # Not found, download from git. + else() + fromGit( v${LIBEOSKEYGEN_WANTED_VERSION} ) + endif() + # Assume version contains a git branch. + else() + fromGit( ${LIBEOSKEYGEN_WANTED_VERSION} ) + endif() +endif() diff --git a/LICENSE b/LICENSE index 635055a..ea09337 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2023 EOS Sw/eden +Copyright (c) 2019-2020 EOS Sw/eden Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE.bitcoin b/LICENSE.bitcoin new file mode 100644 index 0000000..9d54ecb --- /dev/null +++ b/LICENSE.bitcoin @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2009-2019 The Bitcoin Core developers +Copyright (c) 2009-2019 Bitcoin Developers + +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. diff --git a/README.md b/README.md index 5609aa3..3b72adf 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,18 @@ -[![CI Test](https://github.com/eosswedenorg/antelope-keygen/workflows/CI/badge.svg)](https://github.com/eosswedenorg/antelope-keygen/actions) -[![GitHub release](https://img.shields.io/github/v/release/eosswedenorg/antelope-keygen?include_prereleases)](https://github.com/eosswedenorg/antelope-keygen/releases/latest) +![](https://github.com/eosswedenorg/eosio-keygen/workflows/CI/badge.svg) +[![GitHub release](https://img.shields.io/github/v/release/eosswedenorg/eosio-keygen?include_prereleases)](https://github.com/eosswedenorg/eosio-keygen/releases/latest) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -# Antelope Keygen +# EOSIO Keygen -This program generates public and private keypair for [Antelope IO](https://antelope.io) +This program generates public and private keypair for [EOS](https://eos.io/) ## Compile -You will need `libantelope` and `cmake 3.15` or later to compile this project. - -`Qt 5.9.0` or later is required for the graphical program. +You will need `libeoskeygen` and `cmake 3.15` or later to compile this project. ### Linux/MacOS -**NOTE:** Only Ubuntu 20.04 and 22.04 and Fedoora 36 is officially supported. - -The project should compile fine on most versions/distros but it is only tested -and distributed for those distros/versions by [Sw/eden](http://www.eossweden.org). - #### Dependencies #### Linux @@ -32,6 +25,31 @@ First you need to have a compiler. this can be installed with apt. $ apt-get install gcc g++ ``` +You then need `libeoskeygen`. + +This can be installed from [EOS Sweden's APT Repository](https://eosswedenorg.github.io/apt) like this: + +```sh +$ sudo apt-get install software-properties-common +$ curl https://apt.eossweden.org/key 2> /dev/null | sudo apt-key add - +$ sudo apt-add-repository -y 'deb [arch=amd64] https://apt.eossweden.org/main `lsb_release -cs` stable' +$ sudo apt-get install libeoskeygen-dev +``` + +or manually via `.deb` file from [github](https://github.com/eosswedenorg/libeoskeygen/releases) + +```sh +$ wget +$ sudo apt install ./libeoskeygen-dev-.deb +``` + +**Other**: + +Consult the manual for you package manager. +`libeoskeygen` will be downloaded and compiled if it's not installed automatically (however this is slower). + +Consult [libeoskeygen's github](https://github.com/eosswedenorg/libeoskeygen) if you want to compile and install it manually. + **CMake** If your package manager don't provide a sufficiently new version of cmake, you can install it with these commands: @@ -52,23 +70,8 @@ $ wget -O cmake.sh https://github.com/Kitware/CMake/releases/download/v3.15.5/cm Other methods is documanted at https://cmake.org/download -**Qt (only for gui program)** - -You will need to install `qt >= 5.9.0` - -On **ubuntu** you can do this via `apt` - -``` -$ apt-get install qt5-default -``` - -For other distributions, download the official [qt-installer](https://www.qt.io/download-qt-installer). -It is recommended to install the latest stable version. - #### MacOS -**NOTE:** Support for MacOS is still experimental and may or may not work as expected. - You must have a compiler installed. This project is known to build with `Xcode 11.0` but other versions should work. You need to have cmake installed also, this can be done with this `brew` command: @@ -78,15 +81,7 @@ $ brew install cmake If you need a newer version of cmake, you can download the official `.dmg` file: [cmake-3.15.7-Darwin-x86_64.dmg](https://github.com/Kitware/CMake/releases/download/v3.15.7/cmake-3.15.7-Darwin-x86_64.dmg). or see https://cmake.org/download for other versions. -`libantelope` needs to be compiled and installed from source. [Go here](https://github.com/eosswedenorg/libantelope) - -**Qt (only for gui program)** - -This can be installed with brew. - -```sh -$ brew install qt -``` +`libeoskeygen` needs to be compiled and installed from source. [Go here](https://github.com/eosswedenorg/libeoskeygen) #### Build @@ -110,9 +105,7 @@ Download and install `cmake` version `3.15` or newer from [cmake.org](https://cm You will also need a compiler. [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16) (Selecting C++ during installation) is recommended. -**Qt (only for gui program)** -Download the official [qt-installer](https://www.qt.io/download-qt-installer) and follow the steps. It is recommended to install the latest stable version. #### Build. @@ -124,16 +117,10 @@ you need to set `OPENSSL_ROOT_DIR` to the directory where you unpacked For example: ``` -C:\repo> cmake -D OPENSSL_ROOT_DIR="C:/path/to/openssl-1.1/x86" -B build -C:\repo> cmake --build build --config Release -``` - -**Qt** - -If you are compiling the gui program. you will need to point `cmake` to the location `qt` where installed. this can be done by the `CMAKE_PREFIX_PATH` variable: - -``` -C:\repo> cmake -D CMAKE_PREFIX_PATH="C:/path/to/qt/msvc2017_64" +C:\repo> mkdir build +C:\repo> cd build +C:\repo\build> cmake -D OPENSSL_ROOT_DIR="C:/path/to/openssl-1.1/x86" .. +C:\repo\build> cmake --build . --config Release ``` ## Compile options @@ -141,40 +128,12 @@ C:\repo> cmake -D CMAKE_PREFIX_PATH="C:/path/to/qt/msvc2017_64" These compile options are available: | Cmake | build.sh | Description | -|--------------------------- | ----------------- | ----------------------------------------- | -| -DCOMPONENT_CLI=`OFF` | --no-cli | Do not build cli program | -| -DCOMPONENT_GUI=`ON` | --gui | Build gui program (Qt5) | -| -DUSE_THREADS=`OFF` | --disable-threads | Disable thread support | -| -DCMAKE_BUILD_TYPE=`value` | -t `value` | Type of build | +|--------------------------- | ----------------- | ------------------------------------------| +| -DCMAKE_BUILD_TYPE=`value` | -t `value` | Type of build | | -DFORCE_ANSI=`ON` | --force-ansi | Force ANSI console colors even on windows | For more details about options run `./build.sh -l` or `mkdir build && cmake build -LA` -### libantelope - -To speed up the build process, you can install `libantelope` - -#### Ubuntu - -You can use [Sw/eden's APT Repository](https://eosswedenorg.github.io/apt) like this: - -```sh -$ sudo apt-get install software-properties-common -$ curl https://apt.eossweden.org/key 2> /dev/null | sudo apt-key add - -$ sudo apt-add-repository -y 'deb [arch=amd64] https://apt.eossweden.org/main `lsb_release -cs` stable' -$ sudo apt-get install libantelope-dev -``` -or manually via `.deb` file from [github](https://github.com/eosswedenorg/libantelope/releases) - -```sh -$ wget -$ sudo apt install ./libantelope-dev-.deb -``` - -#### Other - -Consult [libantelope's github](https://github.com/eosswedenorg/libantelope) - ## Install After the project has been compiled. run `sudo ./install.sh` or the following code if you dont want to use that: @@ -195,12 +154,13 @@ Run `sudo ./uninstall.sh` or remove the files listed in `build/install_manifest. ## Security notice -Keys are generated using [libantelope](https://github.com/eosswedenorg/libantelope) -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). +Keys are generated by `OpenSSL`'s `EC_KEY_generate_key` function. The program will +never expose your keys to anything but the computers memory and output of the +program. You are free to inspect the source code and compile yourself to verify. -Use at your own risk. The author and [Sw/eden](https://eossweden.org/) does not take responsability -for any damage caused by keys generated by the program. +However, use this at your own risk. we cannot guarantee that the keys are +cryptographically secure as this depends on OpenSSL's implementation (alto it is +widely used and should be safe) Please read the `LICENSE` file. @@ -215,4 +175,4 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Author -Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) +Henrik Hautakoski - [henrik@eossweden.org](mailto:henrik@eossweden.org) diff --git a/build.sh b/build.sh index 7a6d1d7..05ef766 100755 --- a/build.sh +++ b/build.sh @@ -1,20 +1,18 @@ #!/bin/bash function usage() { - echo "Usage: ${0##*/} [ -h|--help ] [ --cli|--no-cli ] [ --gui|--no-gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [ --libeosio= ] [ --pkg-type nsis|deb|zip|tgz ] [ --disable-threads ] [ --force-ansi ]" + echo "Usage: ${0##*/} [ -h|--help ] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" exit 1 } -options=$(getopt -n "${0##*/}" -o "lht:" -l "help,cli,no-cli,gui,no-gui,type:,libeosio:,pkg-type:,disable-threads,force-ansi" -- "$@") +options=$(getopt -n "${0##*/}" -o "lht:" -l "help,type:,pkg-type:,disable-threads,force-ansi" -- "$@") [ $? -eq 0 ] || usage eval set -- "$options" -TARGET="all" ONLY_CONFIG=0 ARGS="" -BUILD_ARGS="--clean-first" while true; do case $1 in @@ -25,29 +23,16 @@ while true; do usage } ARGS="${ARGS} -DCMAKE_BUILD_TYPE=${1}" - BUILD_ARGS="${BUILD_ARGS} --config ${1}" ;; --pkg-type) shift - [[ ! "$1" =~ ^(nsis|deb|rpm|zip|tgz)$ ]] && { + [[ ! "$1" =~ ^(deb|zip|tgz)$ ]] && { echo "Incorrect package type '$1' provided" usage } TARGET="package" ARGS="${ARGS} -DCPACK_GENERATOR=${1^^}" ;; - --libeosio) - shift - ARGS="${ARGS} -DLIBEOSIO_SOURCE_DIR=${1}" - ;; - --cli) - ARGS="${ARGS} -DCOMPONENT_CLI=ON" ;; - --no-cli) - ARGS="${ARGS} -DCOMPONENT_CLI=OFF" ;; - --gui) - ARGS="${ARGS} -DCOMPONENT_GUI=ON" ;; - --no-gui) - ARGS="${ARGS} -DCOMPONENT_GUI=OFF" ;; --disable-threads) ARGS="${ARGS} -DUSE_THREADS=OFF" ;; --force-ansi) @@ -63,10 +48,7 @@ while true; do shift done -# Remove cache first -rm build/CMakeCache.txt 2> /dev/null - cmake -B build $ARGS . if [ ${ONLY_CONFIG} -eq 0 ]; then - cmake --build build ${BUILD_ARGS} --target ${TARGET} + cmake --build build --clean-first --target ${TARGET} fi diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt deleted file mode 100644 index ff3512f..0000000 --- a/cli/CMakeLists.txt +++ /dev/null @@ -1,84 +0,0 @@ -cmake_minimum_required(VERSION 3.15) - -# -------------------------------- -# Project Info -# -------------------------------- - -project(antelope-keygen - VERSION ${CMAKE_PROJECT_VERSION} - LANGUAGES CXX) - -# Options -option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) - -# -------------------------------- -# Program -# -------------------------------- - -set (PROGRAM_EXE ${PROJECT_NAME}) - -set (PROGRAM_SOURCE - src/isatty.cpp - src/cli_key_search_result.cpp - src/console.cpp - src/benchmark.cpp - src/main.cpp -) - -if (WIN32 AND NOT FORCE_ANSI) - set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_win32.cpp) -else() - # *nix should have ansi support. - set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_ansi.cpp) -endif() - -add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) - -# Include CLI11 -include ( ${CMAKE_SOURCE_DIR}/lib/CLI11/CMakeLists.txt ) - -target_include_directories( ${PROGRAM_EXE} PRIVATE ${LIBCLI11_INCLUDE} ) -target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) - -# -------------------------------- -# Install -# -------------------------------- - -install(TARGETS ${PROGRAM_EXE} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT cli) - -install(FILES ${PROJECT_LICENSE_FILE} - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT cli - RENAME LICENSE.cli) - -install (FILES ${LIBCLI11_LICENSE} - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT cli - RENAME LICENSE.libcli11) - - -# Documentation - -configure_file( docs/README.md.in ${PROJECT_BINARY_DIR}/README.cli.md @ONLY ) -install(FILES ${PROJECT_BINARY_DIR}/README.cli.md - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT cli) - -if (UNIX) - configure_file( docs/antelope-keygen.1.in ${PROJECT_BINARY_DIR}/man1/antelope-keygen.1 ) - configure_file( docs/antelope-keygen-search.1.in ${PROJECT_BINARY_DIR}/man1/antelope-keygen-search.1 ) - configure_file( docs/antelope-keygen-benchmark.1.in ${PROJECT_BINARY_DIR}/man1/antelope-keygen-benchmark.1 ) - - install(DIRECTORY ${PROJECT_BINARY_DIR}/man1 - DESTINATION ${CMAKE_INSTALL_MANDIR} - COMPONENT cli) -endif (UNIX) - -# -------------------------------- -# Package -# -------------------------------- - -configure_file(cmake/CPackComponentConfig.cmake.in - ${PROJECT_BINARY_DIR}/CPackProperties.cmake) diff --git a/cli/cmake/CPackComponentConfig.cmake.in b/cli/cmake/CPackComponentConfig.cmake.in deleted file mode 100644 index a8b5500..0000000 --- a/cli/cmake/CPackComponentConfig.cmake.in +++ /dev/null @@ -1,16 +0,0 @@ - -# -------------------------------- -# CPack Component Config -# -------------------------------- - -set( CPACK_PACKAGE_CLI_NAME "${PROJECT_NAME}" ) -set( CPACK_PACKAGE_CLI_CONTACT "${PROJECT_MAINTAINER}" ) - -set( CPACK_COMPONENT_CLI_DESCRIPTION "Command line application" ) - -# Debian specific -set( CPACK_DEBIAN_CLI_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${CPACK_DEBIAN_PACKAGE_RELEASE}-${CPACK_SYSTEM_NAME}-${CPACK_SYSTEM_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") -set( CPACK_DEBIAN_CLI_PACKAGE_NAME "${PROJECT_NAME}" ) -set( CPACK_DEBIAN_CLI_PACKAGE_PRIORITY "optional" ) -set( CPACK_DEBIAN_CLI_PACKAGE_SECTION "misc" ) -set( CPACK_DEBIAN_CLI_PACKAGE_DEPENDS "libssl1.1 (>= 1.1.0) | libssl3 (>= 3.0.0), libstdc++6 (>= 6)") diff --git a/cli/docs/README.md.in b/cli/docs/README.md.in deleted file mode 100644 index 17768e5..0000000 --- a/cli/docs/README.md.in +++ /dev/null @@ -1,106 +0,0 @@ - -# @PROJECT_NAME@ (cli) - -Generate public and private keypair for [Antelope IO](https://antelope.io) - -Source code is available at [github.com](https://github.com/eosswedenorg/antelope-keygen) - -## Synopsis - -```shell -@PROJECT_NAME@ [-h|--help] - -@PROJECT_NAME@ [-v] - -@PROJECT_NAME@ search [-m] [--l33t] [--threads ] [--dict ...] [--lang ...] word_list [count] - -@PROJECT_NAME@ benchmark [num_keys] -``` - -## Description - -Output one Antelope key pair if no arguments are given. -Options and subcommands are as follows: - -### General flags - -| syntax | Description | -| --------------- | ---------------- | -| -h, --help | Shows help text. | -| -v | Shows version | - - -### search command - -`@PROJECT_NAME@ search [-m] [--l33t] [--threads ] [--dict ...] [--lang ...] word_list [count]` - -performs a search, finding `count` public keys containing one or more words from `word_list` (separated with ','). - -Instead of a list it is possible to specify a file with words (separated with newline '\n') using `file:/path/to/file` - -#### Search specific options - -#### -m - -Monochrome, disables all color output. - -#### --leet - -Takes each word in `word_list` and find all l33tspeak combinations of that word and uses the new list for the search. - -#### --threads num - -Use `num` of parallel threads for searching. Default is what the operating system recommends. - -#### --dict file -Use words found in `file` (separated by newline) to highlight words in the keys -found (note that the words in this file are not used for search. only for highlight output). - -There can be more then one `--dict` flag. In that case contents of all files are merged into one dictionary. - -#### --lang value - -Same as `--dict` but will use `value` to find a file in `@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@/dict`. -There can be more then one `--lang` flag. In that case contents of all files are merged into one dictionary. - -#### count - -Number of keys to search for (default is 10) - - -### benchmark command - -`@PROJECT_NAME@ benchmark [num_keys]` - -performs a benchmark test, generating `num_keys` keys and measuring the time. - -#### Benchmark specific options: - -#### num_keys - -Number of keys to search for (default is 10) - - -## Security notice - -Keys are generated using [libantelope](https://github.com/eosswedenorg/libantelope) -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). - -Use at your own risk. The author and [Sw/eden](https://eossweden.org/) does not take responsability -for any damage caused by keys generated by the program. - -Please read the `LICENSE.cli` file. - -``` -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. -``` - -## Author - -Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) diff --git a/cli/docs/antelope-keygen-benchmark.1.in b/cli/docs/antelope-keygen-benchmark.1.in deleted file mode 100644 index cd16012..0000000 --- a/cli/docs/antelope-keygen-benchmark.1.in +++ /dev/null @@ -1,67 +0,0 @@ -.TH @PROJECT_NAME@-benchmark 1 "April, 2023" "@PROJECT_NAME@-benchmark @PROJECT_VERSION@" - -.SH NAME -@PROJECT_NAME@ benchmark - Benchmark the performance of the @PROJECT_NAME@ key generator. - -.SH SYNOPSIS - -.SY @PROJECT_NAME@ -benchmark -.OP \-h|--help -.YS - -.SY @PROJECT_NAME@ -benchmark -.OP num_keys -.YS - -.SH DESCRIPTION - -performs a benchmark test, generating \fInum_keys\fR (default 1000) keys and measuring the time. - -.SH SECURITY NOTICE - -.PP -Keys are generated using -.UR https://github.com/eosswedenorg/libantelope -libantelope -.UE . -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). - -.PP -Use at your own risk. The author and -.UR https://eossweden.org -Sw/eden -.UE -does not take responsability for any damage caused by keys generated by the program. - -.P -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -.br -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -.br -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -.br -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -.br -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -.br -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -.SH BUGS - -Report bugs to -.UR https://github.com/eosswedenorg/eosio-keygen/issues -Github -.UE . Thank you. - -.SH AUTHOR - -.MT henrik@eossweden.org -Henrik Hautakoski -.ME - -.UR https://eossweden.org -EOS Sw/eden -.UE \ No newline at end of file diff --git a/cli/docs/antelope-keygen-search.1.in b/cli/docs/antelope-keygen-search.1.in deleted file mode 100644 index 1ab0af3..0000000 --- a/cli/docs/antelope-keygen-search.1.in +++ /dev/null @@ -1,112 +0,0 @@ -.TH @PROJECT_NAME@-search 1 "April, 2023" "@PROJECT_NAME@-search @PROJECT_VERSION@" - -.SH NAME -@PROJECT_NAME@ search - Search after -.UR https://antelope.io -Antelope IO -.UE -vanity keys. - -.SH SYNOPSIS - -.SY @PROJECT_NAME@ -search -.OP \-h|--help -.YS - -.SY @PROJECT_NAME@ -search -.OP -m -.OP \--l33t -.OP \--threads -.OP \--dict ... -.OP \--lang ... -.B word_list -.OP count -.YS - -.SH DESCRIPTION - -.PP -performs a search, finding \fIcount\fR public keys containing one or more words from -\fIword_list\fR (separated with ','). -.PP -Instead of a list it is possible to specify a file with words (separated with newline \fB'\\n'\fR) using -\fIfile: and find all l33tspeak combinations of that word and uses the new list for the search. -.TP -\fB\-\-threads\fR \fInum\fR -Use <\fInum\fR> of parallel threads for searching. Default is what the operating system recommends. -.TP -\fB\-\-dict\fR \fIfile\fR -Use words found in \fIfile\fR (separated by newline) to highlight words in the keys found. -.br -There can be more then one \fB\-\-dict\fR flag. -In that case contents of all files are merged into one dictionary. -.br -\fBnote:\fR the words in this file are not used for search. only for highlight output. -.TP -\fB\-\-lang\fR \fIvalue\fR -Same as \fB\-\-dict\fR but will use \fIvalue\fR to find a file in -\fB@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@/dict\fR. -.br -There can be more then one \fB\-\-lang\fR flag. In that case contents of all files are merged into one dictionary. -.TP -\fBcount\fR -Number of keys to search for (default is 10) - -.SH SECURITY NOTICE - -.PP -Keys are generated using -.UR https://github.com/eosswedenorg/libantelope -libantelope -.UE . -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). - -.PP -Use at your own risk. The author and -.UR https://eossweden.org -Sw/eden -.UE -does not take responsability for any damage caused by keys generated by the program. - -.P -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -.br -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -.br -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -.br -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -.br -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -.br -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -.SH BUGS - -Report bugs to -.UR https://github.com/eosswedenorg/eosio-keygen/issues -Github -.UE . Thank you. - -.SH AUTHOR - -.MT henrik@eossweden.org -Henrik Hautakoski -.ME - -.UR https://eossweden.org -EOS Sw/eden -.UE \ No newline at end of file diff --git a/cli/docs/antelope-keygen.1.in b/cli/docs/antelope-keygen.1.in deleted file mode 100644 index 16273cc..0000000 --- a/cli/docs/antelope-keygen.1.in +++ /dev/null @@ -1,106 +0,0 @@ -.TH @PROJECT_NAME@ 1 "April, 2023" "@PROJECT_NAME@ @PROJECT_VERSION@" - -.SH NAME -@PROJECT_NAME@ - Generate public and private keypair for -.UR https://antelope.io -Antelope IO -.UE . - -.SH SYNOPSIS - -.SY @PROJECT_NAME@ -.OP \-h|--help -.YS - -.SY @PROJECT_NAME@ -.OP \-v -.YS - -.SY @PROJECT_NAME@ -.OP \--format -.YS - -.SH SUBCOMMANDS - -.PP -\fB@PROJECT_NAME@ search\fR -.RS 4 -Search after -.UR https://antelope.io -Antelope IO -.UE -vanity keys. -.br -see \fB@PROJECT_NAME@-search\fR(1) -.RE - -.PP -\fB@PROJECT_NAME@ benchmark\fR -.RS 4 -Benchmark the performance of the @PROJECT_NAME@ key generator. -.br -see \fB@PROJECT_NAME@-benchmark\fR(1) -.RE - -.SH DESCRIPTION -.PP -Output one Antelope key pair if no arguments are given -.PP -Options and subcommands are as follows: - -.TP -\fB\-h\fR, \fB\-\-help\fR -Shows this help text. -.TP -\fB\-v\fR -Shows version. -.TP -\fB\-\-format\fR \fR\fI\,value\/\fR -What keyformat to use, valid values are: \fIK1\fR, \fIlegacy\fR, \fIfio\fR - -.SH SECURITY NOTICE - -.PP -Keys are generated using -.UR https://github.com/eosswedenorg/libantelope -libantelope -.UE . -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). - -.PP -Use at your own risk. The author and -.UR https://eossweden.org -Sw/eden -.UE -does not take responsability for any damage caused by keys generated by the program. - -.P -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -.br -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -.br -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -.br -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -.br -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -.br -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -.SH BUGS - -Report bugs to -.UR https://github.com/eosswedenorg/eosio-keygen/issues -Github -.UE . Thank you. - -.SH AUTHOR - -.MT henrik@eossweden.org -Henrik Hautakoski -.ME - -.UR https://eossweden.org -EOS Sw/eden -.UE diff --git a/cli/src/isatty.cpp b/cli/src/isatty.cpp deleted file mode 100644 index 75d0778..0000000 --- a/cli/src/isatty.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 _WIN32 -#include -#else -#include -#define _isatty isatty -#define _fileno fileno -#endif -#include "isatty.hpp" - -namespace antelopekeygen { - -bool isatty(int fd) { - return ::_isatty(fd); -} - -bool isatty(FILE* fd) { - // fileno() segfaults if fd is null. - return fd ? isatty(_fileno(fd)) : false; -} - -} // namespace antelopekeygen diff --git a/cli/src/main.cpp b/cli/src/main.cpp deleted file mode 100644 index 0b8ca7a..0000000 --- a/cli/src/main.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cli_key_search_result.hpp" -#include "console.hpp" -#include "benchmark.hpp" -#include "config.hpp" - -// Command line options. -bool option_l33t = false; -libantelope::wif_codec_t key_codec; - -#ifdef EOSIOKEYGEN_HAVE_THREADS -size_t option_num_threads; -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - -class CustomFormatter : public CLI::Formatter { -public: - - std::string make_usage(const CLI::App *app, std::string name) const - { - std::stringstream out; - - out << std::endl << CLI::Formatter::make_usage(app, name) - << std::endl - << "Outputs one EOSIO key pair if no subcommand is given" - << std::endl; - - return out.str(); - } -}; - -int cmd_search(const antelopekeygen::strlist_t& words, const antelopekeygen::Dictionary& dict, int count) { - - antelopekeygen::KeySearch ks; - antelopekeygen::CliKeySearchResult rs(dict, key_codec); - - ks.setPrefix(key_codec.pub); - ks.setCallback(&rs); - - for(auto it = words.begin(); it != words.end(); it++) { - size_t p = libantelope::is_base58(*it); - if (p != std::string::npos) { - std::cerr << "The word '" - << *it << "' contains an invalid non-base58 character '" - << (*it)[p] << "'" << std::endl; - return 1; - } - } - - if (option_l33t) { - for(std::size_t i = 0; i < words.size(); i++) { - ks.addList(antelopekeygen::l33twords(words[i])); - } - } else { - ks.addList(words); - } - -#ifdef EOSIOKEYGEN_HAVE_THREADS - ks.setThreadCount(option_num_threads); -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - - std::cout << "Searching for " << count - << " keys containing: " << antelopekeygen::strlist::join(ks.getList(), ",") -#ifdef EOSIOKEYGEN_HAVE_THREADS - << ", Using: " << ks.getThreadCount() << " threads" -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - << std::endl; - - ks.find(count); - - return 0; -} - -void cmd_benchmark(size_t num_keys) { - - struct antelopekeygen::benchmark_result res; - - std::cout << "Benchmark: Generating " - << num_keys << " keys" << std::endl; - - antelopekeygen::benchmark(num_keys, &res); - - std::cout << "Result: Took " << res.sec << " seconds, " - << res.kps << " keys per second." << std::endl; -} - -int main(int argc, char **argv) { - - CLI::App cmd("Keygenerator for Antelope based blockchains", PROGRAM_NAME); - std::vector dict_list; - std::vector lang_list; - std::string search_words; - std::string key_format; - int search_count; - size_t bench_count; - int rc = 0; - - libantelope::ec_init(); - - CLI::Option* version = cmd.add_flag("-v,--version", "Show version"); - cmd.add_option("--format", key_format, "valid values: K1, fio, legacy")->default_val("K1"); - - // Search - CLI::App* search_cmd = cmd.add_subcommand("search", - "performs a search, finding public keys containing " - "one or more words from (separated with \",\")"); - CLI::Option* monocrome = search_cmd->add_flag("-m", "Monochrome, disables all color output."); - - search_cmd->add_flag("--l33t", option_l33t, "Takes each word in and find all l33tspeak" - " combinations of that word and uses the new list for the search."); - -#ifdef EOSIOKEYGEN_HAVE_THREADS - search_cmd->add_option("--threads", option_num_threads, - "Use of parallel threads for searching.\n" - "Default is what the operating system recomends.") - ->default_val(antelopekeygen::KeySearch::max_threads()); - -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - - search_cmd->add_option("--dict", dict_list, ""); - search_cmd->add_option("--lang", lang_list, ""); - search_cmd->add_option("word_list", search_words, - "one or more words (separated with \",\")\n\n" - "Instead of a list it is possible to specify a file with words\n" - "(separated with newline '\\n') using file:")->required(); - search_cmd->add_option("count", search_count, "Number of keys to search for before the program terminates.")->default_val(10); - - // Benchmark - CLI::App* bench_cmd = cmd.add_subcommand("benchmark", "performs a benchmark test, " - "generating keys and measuring the time."); - bench_cmd->add_option("count", bench_count, "")->default_val(1000); - - // Parse command line. - cmd.formatter(std::make_shared()); - - CLI11_PARSE(cmd, argc, argv); - - if (*version) { - std::cout << PROGRAM_NAME << ": v" << PROGRAM_VERSION << std::endl; - goto end; - } - - if (key_format == "fio") { - key_codec = libantelope::wif_create_legacy_codec("FIO"); - } else if (key_format == "legacy") { - key_codec = libantelope::WIF_CODEC_LEG; - } else if (key_format == "K1") { - key_codec = libantelope::WIF_CODEC_K1; - } else { - std::cerr << "invalid key format: " << key_format << std::endl; - goto end; - } - - if (search_cmd->parsed()) { - antelopekeygen::strlist_t words; - antelopekeygen::Dictionary dict; - - if (*monocrome) { - antelopekeygen::console::disable_color = true; - } - - for (auto item : dict_list) { - antelopekeygen::Dictionary d; - - if (d.loadFromFile(item)) { - dict.add(d); - } else { - std::cerr << "Could not load dictionary from file: " << item << std::endl; - } - } - - for (auto item : lang_list) { - antelopekeygen::Dictionary d; - std::string filename(CONFIG_SHARE_FULL_PATH "/dicts/" + item); - - if (d.loadFromFile(filename)) { - dict.add(d); - } else { - std::cerr << "Could not load dictionary from language file: " << filename << std::endl; - } - } - - if (search_words.rfind("file:", 0) == 0) { - std::string filename = search_words.substr(5); - if (!antelopekeygen::readLines(filename, words)) { - std::cerr << "Could not read file: " << filename << std::endl; - goto end; - } - - if (words.size() < 1) { - std::cerr << filename << " did not contain any words" << std::endl; - goto end; - } - } else { - words = antelopekeygen::strlist::splitw(search_words); - } - - rc = cmd_search(words, dict, search_count); - goto end; - - } else if (bench_cmd->parsed()) { - cmd_benchmark(bench_count); - } - // No subcommand given, just generate and print a keypair. - else { - struct libantelope::ec_keypair pair; - libantelope::ec_generate_key(&pair); - libantelope::wif_print_key(&pair, key_codec); - goto end; - } - -end: libantelope::ec_shutdown(); - return rc; -} diff --git a/cmake/CPackProperties.cmake.in b/cmake/CPackProperties.cmake.in deleted file mode 100644 index 6a75e0c..0000000 --- a/cmake/CPackProperties.cmake.in +++ /dev/null @@ -1,7 +0,0 @@ - -# Include component specific config -foreach( component @CPACK_COMPONENTS_ALL@ ) - if (EXISTS "@CMAKE_CURRENT_BINARY_DIR@/${component}/CPackProperties.cmake") - include("@CMAKE_CURRENT_BINARY_DIR@/${component}/CPackProperties.cmake") - endif() -endforeach() diff --git a/cmake/extras.cmake b/cmake/extras.cmake deleted file mode 100644 index a23a1fe..0000000 --- a/cmake/extras.cmake +++ /dev/null @@ -1,43 +0,0 @@ - -set( EXTRAS_DIRECTORY ${DOWNLOAD_CACHE_DIR}/eosio-keygen-extras-0.1.0 ) -set( FILENAME ${DOWNLOAD_CACHE_DIR}/eosio-keygen-extras-0.1.0.zip ) - -# -------------------------------- -# Download/Unpack -# -------------------------------- - -if (NOT EXISTS ${FILENAME}) - - set( URL "https://github.com/eosswedenorg/eosio-keygen-extras/releases/download/v0.1.0/eosio-keygen-extras-0.1.0.zip" ) - set( CHECKSUM "7be3188a52a39876e37986e6a7d78e0d6c89e68e8391cf48821c800563aaa036" ) - - message( STATUS "Downloading ${URL}" ) - - file(DOWNLOAD ${URL} ${FILENAME} - TIMEOUT 60 - EXPECTED_HASH SHA256=${CHECKSUM} - TLS_VERIFY ON) -endif() - -if (NOT EXISTS ${EXTRAS_DIRECTORY}) - - message( STATUS "Unpacking ${FILENAME}" ) - - execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xf ${FILENAME} - WORKING_DIRECTORY ${DOWNLOAD_CACHE_DIR}) -endif() - - -# -------------------------------- -# Install -# -------------------------------- - -install(DIRECTORY ${EXTRAS_DIRECTORY}/dict - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT extras ) - -# -------------------------------- -# CPack -# -------------------------------- - -set( CPACK_COMPONENT_EXTRAS_DESCRIPTION "Dictionary files" ) diff --git a/common/.gitignore b/common/.gitignore deleted file mode 100644 index 3d2564d..0000000 --- a/common/.gitignore +++ /dev/null @@ -1 +0,0 @@ -include/eoskeygen/config.h* diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt deleted file mode 100644 index eb3e3a7..0000000 --- a/common/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# ------------------------------------------------------------ -# Common CMake file -# -# Compiles the code that should be shared between the cli -# and gui programs into a static library. -# ------------------------------------------------------------ - -# Options -option(USE_THREADS "Compile with support for threads (if available)." ON) - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") - -# -------------------------------- -# Library -# -------------------------------- -set( COMMON_NAME common ) - -set( COMMON_SOURCE - src/core/file.cpp - src/core/dictionary.cpp - src/core/string.cpp - src/core/strlist.cpp - src/core/leet.cpp - src/key_search.cpp -) - -# Threads support -if (USE_THREADS) - find_package(Threads) - if (Threads_FOUND) - set( ANTELOPEKEYGEN_HAVE_THREADS TRUE ) - set( COMMON_SOURCE ${COMMON_SOURCE} src/key_search_mt.cpp ) - endif (Threads_FOUND) -endif (USE_THREADS) - -# Project config file -configure_file(config.hpp.in "${CMAKE_CURRENT_LIST_DIR}/include/eoskeygen/config.hpp" @ONLY) - -add_library( ${COMMON_NAME} STATIC ${COMMON_SOURCE} ) - -target_include_directories( ${COMMON_NAME} PUBLIC include ) - -# Link with libantelope and threads library. -include( libantelope ) -target_link_libraries( ${COMMON_NAME} - PUBLIC - libantelope - ${CMAKE_THREAD_LIBS_INIT} -) diff --git a/common/cmake/libantelope.cmake b/common/cmake/libantelope.cmake deleted file mode 100644 index 85a0ccd..0000000 --- a/common/cmake/libantelope.cmake +++ /dev/null @@ -1,53 +0,0 @@ -# -------------------------------- -# Variables -# -------------------------------- -set( LIBANTELOPE_GIT_URL "https://github.com/eosswedenorg/libantelope.git" ) -set( LIBANTELOPE_WANTED_VERSION v0.2.2 ) - -# -------------------------------- -# Macros -# -------------------------------- -macro(fromGit tag) - - message ("Using libantelope from: ${LIBANTELOPE_GIT_URL}@${tag}") - - include(FetchContent) - FetchContent_Declare(libantelope - GIT_REPOSITORY ${LIBANTELOPE_GIT_URL} - GIT_TAG ${tag} - SOURCE_DIR ${DOWNLOAD_CACHE_DIR}/libeosio/src - STAMP_DIR ${DOWNLOAD_CACHE_DIR}/libeosio/stamp - ) - - FetchContent_GetProperties(libantelope) - if (NOT libantelope_POPULATED) - FetchContent_Populate(libantelope) - add_subdirectory(${libantelope_SOURCE_DIR} ${libantelope_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() -endmacro() - -macro(buildLocal src) - message ("Using local libantelope at: ${src}") - add_subdirectory(${src} ${src}/build EXCLUDE_FROM_ALL) -endmacro() - -# If we have a local libantelope -if (LIBANTELOPE_SOURCE_DIR) - buildLocal( ${LIBANTELOPE_SOURCE_DIR} ) -else() - - # Check if version is in fact a version. - if (LIBANTELOPE_WANTED_VERSION MATCHES "^[0-9]+(.[0-9]+)?(.[0-9]+)(-[a-zA-Z0-9]+)?$") - # Try finding the package on the system. - find_package(libantelope ${LIBANTELOPE_WANTED_VERSION} QUIET) - if (libantelope_FOUND) - message ("Using libeosio in: ${libantelope_DIR}") - # Not found, download from git. - else() - fromGit( v${LIBANTELOPE_WANTED_VERSION} ) - endif() - # Assume version contains a git branch. - else() - fromGit( ${LIBANTELOPE_WANTED_VERSION} ) - endif() -endif() diff --git a/common/config.hpp.in b/common/config.hpp.in deleted file mode 100644 index 1cbe1c8..0000000 --- a/common/config.hpp.in +++ /dev/null @@ -1,30 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CONFIG_H -#define ANTELOPEKEYGEN_COMMON_CONFIG_H - -// Defined if we have thread support. -#cmakedefine ANTELOPEKEYGEN_HAVE_THREADS - -#endif /* ANTELOPEKEYGEN_COMMON_CONFIG_H */ diff --git a/common/include/eoskeygen/core/dictionary.hpp b/common/include/eoskeygen/core/dictionary.hpp deleted file mode 100644 index 8008a30..0000000 --- a/common/include/eoskeygen/core/dictionary.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CORE_DICTIONARY_H -#define ANTELOPEKEYGEN_COMMON_CORE_DICTIONARY_H - -#include -#include -#include - -namespace antelopekeygen { - -class Dictionary -{ -public : - // Map that contains position and length for substrings. - // - // key = position in the search string. - // value = length of the word from this position. - typedef std::map< size_t, size_t > search_result_t; - -public : - - // Load words from file. - bool loadFromFile(const std::string& filename); - - // Add a word to the dictionary. - void add(const std::string& word); - - // Add words from another dictionary. - void add(const Dictionary& dictionary); - - // Clear all words from the dictionary. - void clear(); - - // Returns the list of words in the dictionary. - const std::set& getWords() const; - - // Returns true if word exists in the dictionary. - bool contains(const std::string& word) const; - - // Searches the subject for words defined in the dictionary. - // Returns a search_result_t with the words found in subject. - // See search_result_t for more details. - search_result_t search(const std::string& subject) const; - -protected : - - // Words in the dictionary. - std::set m_words; -}; - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_CORE_DICTIONARY_H */ diff --git a/common/include/eoskeygen/core/file.hpp b/common/include/eoskeygen/core/file.hpp deleted file mode 100644 index 15ec64c..0000000 --- a/common/include/eoskeygen/core/file.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CORE_FILE_H -#define ANTELOPEKEYGEN_COMMON_CORE_FILE_H - -#include - -namespace antelopekeygen { - -bool readLines(const std::string& filename, strlist_t& lines); - -} // namespace - -#endif /* ANTELOPEKEYGEN_COMMON_CORE_FILE_H */ diff --git a/common/include/eoskeygen/core/leet.hpp b/common/include/eoskeygen/core/leet.hpp deleted file mode 100644 index 6cc3796..0000000 --- a/common/include/eoskeygen/core/leet.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CORE_LEET_H -#define ANTELOPEKEYGEN_COMMON_CORE_LEET_H - -#include -#include - -namespace antelopekeygen { - -strlist_t l33twords(std::string str); - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_CORE_LEET_H */ diff --git a/common/include/eoskeygen/core/string.hpp b/common/include/eoskeygen/core/string.hpp deleted file mode 100644 index a1ef0dc..0000000 --- a/common/include/eoskeygen/core/string.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CORE_STRING_H -#define ANTELOPEKEYGEN_COMMON_CORE_STRING_H - -#include -#include - -namespace antelopekeygen { - -std::string& strtolower(std::string& str); - -std::string& rtrim(std::string& str); -std::string& ltrim(std::string& str); -std::string& trim(std::string& str); - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_CORE_STRING_H */ diff --git a/common/include/eoskeygen/core/strlist.hpp b/common/include/eoskeygen/core/strlist.hpp deleted file mode 100644 index 2cc63b6..0000000 --- a/common/include/eoskeygen/core/strlist.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_CORE_STRLIST_H -#define ANTELOPEKEYGEN_COMMON_CORE_STRLIST_H - -#include -#include - -namespace antelopekeygen { - -typedef std::vector strlist_t; - -typedef std::string& (*strlist_stripfunc_t)(std::string& str); - -namespace strlist { - -strlist_t splitw(const std::string& str, const std::string& delim = ","); - -strlist_t split(const std::string& str, const std::string& delim); - -std::string join(const strlist_t& list, const std::string& delim); - -strlist_t& strip(strlist_t& list, strlist_stripfunc_t fn); - -} // namespace strlist - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_CORE_STRLIST_H */ diff --git a/common/include/eoskeygen/key_search.hpp b/common/include/eoskeygen/key_search.hpp deleted file mode 100644 index 5e0b9ae..0000000 --- a/common/include/eoskeygen/key_search.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_KEY_SEARCH_H -#define ANTELOPEKEYGEN_COMMON_KEY_SEARCH_H - -#include -#include -#include -#include -#include -#include - -namespace antelopekeygen { - -class IKeySearchResult; - -class KeySearch -{ -public : - - struct result { - size_t pos; // position where the word was found. - size_t len; // the length of the word. - }; - -public : - KeySearch(); - - void setPrefix(const std::string& prefix); - - // Add a word to search for. - void addWord(const std::string& str); - - // Add a list of words to search for. - void addList(const strlist_t& list); - - // get the list of words to search for. - const strlist_t& getList(); - - // Clears the search list. - void clear(); - - // Set callback for search result. - void setCallback(IKeySearchResult* callback); - -#ifdef ANTELOPEKEYGEN_HAVE_THREADS - // Returns the maximum number of threads - // reported by the operating system. - static size_t max_threads(); - - // Set the number of threads to use while searching. - void setThreadCount(size_t num); - - size_t getThreadCount() const; -#endif /* ANTELOPEKEYGEN_HAVE_THREADS */ - - // Aborts find() operation if started. - // This is useful for multithreaded code (like GUI application) - // If find() is started as a seperate thread. This method could be called - // from the gui thread if the user presses "cancel" button. - void abort(); - - // Perform a search. - void find(size_t num_results); - -protected : - - // Check if any word in appears in 's public key. - // returns true if a word was found (stored in ), false otherwise. - bool _contains_word(const struct libantelope::ec_keypair* key, struct result& result); - -#ifdef ANTELOPEKEYGEN_HAVE_THREADS - void _thr_proc(); - - void _search_mt(); -#endif /* ANTELOPEKEYGEN_HAVE_THREADS */ - - void _search_linear(); - -protected : - - // Public key prefix. - std::string m_prefix; - - // List of words to search for. - strlist_t m_words; - - // Max keys to search for. - std::size_t m_max; - - // Current number of keys found. - std::size_t m_count; - -#ifdef ANTELOPEKEYGEN_HAVE_THREADS - // Number of threads to use. - size_t m_threads; -#endif /* ANTELOPEKEYGEN_HAVE_THREADS */ - - IKeySearchResult* m_callback; -}; - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_KEY_SEARCH_H */ diff --git a/common/include/eoskeygen/key_search_result.hpp b/common/include/eoskeygen/key_search_result.hpp deleted file mode 100644 index ef598e0..0000000 --- a/common/include/eoskeygen/key_search_result.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ANTELOPEKEYGEN_COMMON_KEY_SEARCH_RESULT_H -#define ANTELOPEKEYGEN_COMMON_KEY_SEARCH_RESULT_H - -#include - -namespace antelopekeygen { - -class IKeySearchResult -{ -public : - - virtual void onResult(const struct libantelope::ec_keypair* key, const struct KeySearch::result& result) = 0; -}; - -} // namespace antelopekeygen - -#endif /* ANTELOPEKEYGEN_COMMON_KEY_SEARCH_RESULT_H */ diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp deleted file mode 100644 index 2e5033a..0000000 --- a/common/src/core/dictionary.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include -#include - -namespace antelopekeygen { - -struct StringContains { - StringContains(const std::string& str, std::vector& pos) : m_str(str), m_pos(pos) {} - bool operator()(const std::string& w) { - for(size_t p = m_str.find(w); p != std::string::npos; p = m_str.find(w, p+1)) { - m_pos.push_back(p); - } - return !m_pos.empty(); - } - std::string m_str; - std::vector& m_pos; -}; - -bool Dictionary::loadFromFile(const std::string& filename) -{ - strlist_t lines; - - // Clear before adding. - clear(); - - if (readLines(filename, lines)) { - - // Read each line and add to the dictionary. - for(auto it = lines.begin(); it != lines.end(); it++) { - add(*it); - } - return true; - } - return false; -} - -void Dictionary::add(const std::string& word) -{ - // Do not insert a empty string. - if (word.length()) { - m_words.insert(word); - } -} - -void Dictionary::add(const Dictionary& dictionary) -{ - std::set_union( - m_words.begin(), m_words.end(), - dictionary.m_words.begin(), dictionary.m_words.end(), - std::inserter(m_words, m_words.begin()) - ); -} - -const std::set& Dictionary::getWords() const -{ - return m_words; -} - -void Dictionary::clear() -{ - m_words.clear(); -} - -bool Dictionary::contains(const std::string& word) const -{ - return m_words.find(word) != m_words.cend(); -} - -Dictionary::search_result_t Dictionary::search(const std::string& subject) const -{ - search_result_t res; - - std::vector pos; - StringContains pred(subject, pos); - - // Find all words. - for(auto it = std::find_if(m_words.begin(), m_words.end(), pred); - it != m_words.end(); - it = std::find_if(++it, m_words.end(), pred)) { - - // Go through all found positions. - for (auto it2 = pos.begin(); it2 != pos.end(); it2++) { - - // Insert - auto rit = res.find(*it2); - if (rit == res.end()) { - res.emplace(*it2, it->length()); - } - // Update length if it's longer then the previous we found. - else if (rit->second < it->length()) { - rit->second = it->length(); - } - } - - // Clear positions - pos.clear(); - } - - return res; -} - -} // namespace antelopekeygen diff --git a/common/src/core/file.cpp b/common/src/core/file.cpp deleted file mode 100644 index 500d86b..0000000 --- a/common/src/core/file.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include - -namespace antelopekeygen { - -bool readLines(const std::string& filename, strlist_t& lines) { - - FILE *fd; - char buf[1024]; - - fd = fopen(filename.c_str(), "r"); - if (!fd) { - return false; - } - - while(fgets(buf, sizeof(buf), fd) != NULL) { - std::string line(buf); - lines.push_back(trim(line)); - } - - fclose(fd); - return true; -} - -} // namespace antelopekeygen diff --git a/common/src/core/leet.cpp b/common/src/core/leet.cpp deleted file mode 100644 index 763bc11..0000000 --- a/common/src/core/leet.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include - -namespace antelopekeygen { - -static bool is_l33t(char ch, char& r) { - - // '1', '2', '3', '4', '5', '6', '7', '8', '9' - static char alphabet[9] = { 'l', 'z', 'e', 'a', 's', 'G', 't', 'B', 'g' }; - - for(std::size_t i = 0; i < sizeof(alphabet) / sizeof(char); i++) { - - if (ch == alphabet[i]) { - r = static_cast('1' + i); - return true; - } - } - return false; -} - -static void _l33t(strlist_t& list, const std::string& a, std::size_t pos) { - - // Find the next character to be replaced. - for(std::size_t i = pos; i < a.length(); i++) { - - char ch; - if (is_l33t(a[i], ch)) { - // create a new string and replace the character. - std::string b = a; - b[i] = ch; - - // Store the new string as the result. - list.push_back(b); - - // Perform the same algorithm for both strings - // at the next position. - _l33t(list, a, i + 1); - _l33t(list, b, i + 1); - break; - } - } -} - -strlist_t l33twords(std::string str) { - - strlist_t list; - - // "l" is abit special and are not included in base58 so we set it to 1. - // All other characters in "l33t" are valid. - std::transform(str.begin(), str.end(), str.begin(), [](char c){ return c == 'l' ? '1' : c; }); - - // Store the original string as the first in list. - list.push_back(str); - - _l33t(list, str, 0); - return list; -} - -} // namespace antelopekeygen diff --git a/common/src/core/string.cpp b/common/src/core/string.cpp deleted file mode 100644 index 54acb8a..0000000 --- a/common/src/core/string.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include -#include - -namespace antelopekeygen { - -std::string& strtolower(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){ return std::tolower(c); }); - return str; -} - -std::string& ltrim(std::string& str) { - auto it = std::find_if(str.begin(), str.end(), [](char ch){ return !std::isspace(ch); }); - str.erase(str.begin(), it); - return str; -} - -std::string& rtrim(std::string& str) { - auto it = std::find_if(str.rbegin(), str.rend(), [](char ch){ return !std::isspace(ch); }); - str.erase(it.base(), str.end()); - return str; -} - -std::string& trim(std::string& str) { - return ltrim(rtrim(str)); -} - -} // namespace antelopekeygen diff --git a/common/src/core/strlist.cpp b/common/src/core/strlist.cpp deleted file mode 100644 index dc3e5db..0000000 --- a/common/src/core/strlist.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include - -namespace antelopekeygen { - -strlist_t strlist::splitw(const std::string& str, const std::string& delim) { - - strlist_t words = strlist::split(str, delim); - std::for_each(words.begin(), words.end(), trim); - return words; -} - -strlist_t strlist::split(const std::string& str, const std::string& delim) { - - strlist_t r; - size_t s = 0, e = 0, dlen = delim.length(); - - while((e = str.find(delim, s)) != std::string::npos) { - r.push_back(str.substr(s, e - s)); - s = e + dlen; - } - - r.push_back(str.substr(s)); - return r; -} - -std::string strlist::join(const strlist_t& list, const std::string& delim) { - - std::string out; - - for(const std::string& item : list) { - if (item.length() < 1) { - continue; - } - out += item + delim; - } - - if (out.length() > 0) { - out.erase(out.end() - delim.length()); - } - - return out; -} - -strlist_t& strlist::strip(strlist_t& list, strlist_stripfunc_t fn) { - - std::transform(list.begin(), list.end(), list.begin(), fn); - return list; -} - -} // namespace antelopekeygen diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp deleted file mode 100644 index d20597d..0000000 --- a/common/src/key_search.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include - -namespace antelopekeygen { - -KeySearch::KeySearch() : - m_prefix ("EOS"), - m_max (0), - m_count (0), -#ifdef EOSIOKEYGEN_HAVE_THREADS - m_threads (0), -#endif - m_callback (NULL) -{ -} - -void KeySearch::setPrefix(const std::string& prefix) -{ - m_prefix = prefix; -} - -void KeySearch::addWord(const std::string& str) -{ - std::string tmp = str; - strtolower(tmp); - m_words.push_back(tmp); -} - -void KeySearch::addList(const strlist_t& list) -{ - for(const std::string& item : list) { - addWord(item); - } -} - -const strlist_t& KeySearch::getList() -{ - return m_words; -} - -void KeySearch::clear() -{ - m_words.clear(); -} - -void KeySearch::setCallback(IKeySearchResult* callback) -{ - m_callback = callback; -} - -void KeySearch::_search_linear() -{ - struct libantelope::ec_keypair pair; - - while (m_count < m_max) { - struct result res; - libantelope::ec_generate_key(&pair); - if (_contains_word(&pair, res)) { - m_callback->onResult(&pair, res); - m_count++; - } - } -} - -void KeySearch::abort() -{ - // exit find() operation by setting m_max to zero. - m_max = 0; -} - -void KeySearch::find(size_t num_results) -{ - m_count = 0; - m_max = num_results; - -#ifdef EOSIOKEYGEN_HAVE_THREADS - // Only do multithread if number of threads makes sense. - if (m_threads >= 2) { - _search_mt(); - return; - } -#endif /* HAVE_THREADS */ - - _search_linear(); -} - -bool KeySearch::_contains_word(const struct libantelope::ec_keypair* key, struct result& result) { - - size_t prefix_len = m_prefix.length(); - std::string pubstr = libantelope::wif_pub_encode(key->pub, m_prefix).substr(prefix_len); - strtolower(pubstr); - - for(auto const& w: m_words) { - size_t p = pubstr.find(w); - if (p != std::string::npos) { - result.pos = p + prefix_len; - result.len = w.length(); - return true; - } - } - return false; -} - -} // namespace antelopekeygen diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp deleted file mode 100644 index f73a635..0000000 --- a/common/src/key_search_mt.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2019-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include -#include - -namespace antelopekeygen { - -// Mutex guard for m_count. -std::mutex g_count_mtx; - -// Thread process. -void KeySearch::_thr_proc() -{ - struct libantelope::ec_keypair pair; - - while (m_count < m_max) { - struct result res; - - libantelope::ec_generate_key(&pair); - if (_contains_word(&pair, res)) { - - // Guard output with mutex, so we don't get - // interrupted mid write and can write to m_count and res safely. - const std::lock_guard lock(g_count_mtx); - - // It is possible m_count was updated by another thread - // after we checked it in the while loop. - // So while we have the lock, we need to check it again. - if (m_count >= m_max) { - return; - } - - // Update count and call result function. - m_count++; - m_callback->onResult(&pair, res); - } - } -} - -void KeySearch::setThreadCount(size_t num) -{ - m_threads = num; -} - -size_t KeySearch::max_threads() -{ - return std::thread::hardware_concurrency(); -} - -size_t KeySearch::getThreadCount() const -{ - return m_threads; -} - -void KeySearch::_search_mt() -{ - std::vector t; - - t.resize(m_threads - 1); - - // Launch them. - for(std::size_t i = 0; i < t.size(); i++) { - t[i] = std::thread(&KeySearch::_thr_proc, this); - } - - // Use main thread for 1 search - _thr_proc(); - - // Wait for all threads to compelete. - for(std::size_t i = 0; i < t.size(); i++) { - t[i].join(); - } -} - -} // namespace antelopekeygen diff --git a/docs/eosio-keygen.1.in b/docs/eosio-keygen.1.in new file mode 100644 index 0000000..ef12205 --- /dev/null +++ b/docs/eosio-keygen.1.in @@ -0,0 +1,153 @@ +.TH @PROJECT_NAME@ 1 "January, 2020" "@PROJECT_NAME@ @PROJECT_VERSION@" + +.SH NAME +@PROJECT_NAME@ - Generate public and private keypair for +.UR https://eos.io/ +EOS +.UE . + +.SH SYNOPSIS + +.SY @PROJECT_NAME@ +.OP \-h|--help +.YS + +.SY @PROJECT_NAME@ +.OP \-v +.YS + +.SY @PROJECT_NAME@ +search +.OP -m +.OP \--l33t +.OP \--threads= +.OP \--dict= ... +.OP \--lang= ... +.B word_list +.OP count +.YS + +.SY @PROJECT_NAME@ +benchmark +.OP num_keys +.YS + +.SH DESCRIPTION +.P +Output one EOSIO key pair if no arguments are given +.P +Options and subcommands are as follows: + +.TP 15 +.B -h, --help +Shows this help text. +.TP 15 +.B -v +Shows version. +.TP 15 +.B search +performs a search, finding +.I +public keys containing one or more words from +.I +(separated with ','). +Instead of a list it is possible to specify a file with words (separated with newline '\\n') using +.I file: +.RS 16 +Search specific options: +.RS 2 +.TP 20 +.B -m +Monochrome, disables all color output. +.TP 20 +.B --l33t +Takes each word in +.I +and find all l33tspeak combinations of that word and uses the new list for the search. +.TP 20 +.B --threads= +Use +.I +of parallel threads for searching. Default is what the operating system recomends. +.TP 20 +.B --dict= +Use words found in +.I +(separated by newline) to highlight words in the keys found (note that the words in this + file are not used for search. only for highlight output). There can be more then one +.B --dict +flag. In that case contents of all files are merged into one dictionary. +.TP 20 +.B --lang= +Same as +.B --dict +but will use +.I +to find a file in +.B @CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@/dict. +There can be more then one +.B --lang +flag. In that case contents of all files are merged into one dictionary. +.TP 20 +.B count +Number of keys to search for (default is 10) +.RE 1 +.TP 15 +.B benchmark +performs a benchmark test, generating +.I +keys and measuring the time. +.PP +.RS 16 +Benchmark specific options: +.RS 2 +.TP 15 +.B num_keys +Number of keys to search for (default is 10) +.RE 1 + + +.SH SECURITY NOTICE + +Keys are generated by OpenSSL\'s +.B EC_KEY_generate_key +function. The program will +never expose your keys to anything but the computers memory and output of the\ +program. You are free to inspect the source code and compile yourself to verify. +.P +However, use this at your own risk. we cannot guarantee that the keys are\ +cryptographically secure as this depends on OpenSSL's implementation (alto it is\ +widely used and should be safe) +.P +Please read the +.I LICENSE +file. +.P +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +.br +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +.br +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +.br +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +.br +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +.br +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +.SH BUGS + +Report bugs to +.UR https://github.com/eosswedenorg/eosio-keygen/issues +Github +.UE . Thank you. + +.SH AUTHOR + +.MT henrik@eossweden.org +Henrik Hautakoski +.ME + +.UR https://eossweden.org +EOS Sw/eden +.UE diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt deleted file mode 100644 index fec8fec..0000000 --- a/gui/CMakeLists.txt +++ /dev/null @@ -1,85 +0,0 @@ -cmake_minimum_required(VERSION 3.15) - -project(antelope-keygen-gui - VERSION ${CMAKE_PROJECT_VERSION} - DESCRIPTION "Keygenerator for Antelope blockchain (gui)" - LANGUAGES CXX) - -# Append modules dir -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -include(QtUtils) - -# Qt5 needs MOC,RCC and UIC -set( CMAKE_AUTOMOC ON ) -set( CMAKE_AUTORCC ON ) -set( CMAKE_AUTOUIC ON ) - -# Autogenerate about config file - -file( READ ${PROJECT_LICENSE_FILE} GUI_ABOUT_LICENSE ) - -string(REGEX REPLACE "^([^\n]+)" "

\\1

" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) -string(REGEX REPLACE "\n\n([^\n]+)" "

\\1

" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) -string(REGEX REPLACE "\n" "" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) -string(REGEX REPLACE "\<(.+)\>" "- \\1" GUI_ABOUT_AUTHOR ${PROJECT_MAINTAINER}) - -configure_file(gui_text.h.in "${CMAKE_CURRENT_BINARY_DIR}/gui_text.h" @ONLY ESCAPE_QUOTES) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# -------------------------------- -# Program -# -------------------------------- - -set( PROGRAM_EXE ${PROJECT_NAME} ) - -set( PROGRAM_SRC - src/main.cpp - src/MainWindow.cpp - src/GenerateWindow.cpp - src/SearchWindow.cpp - src/MultiSelect.cpp - src/Settings.cpp - src/helpers.cpp -) - -add_executable( ${PROGRAM_EXE} WIN32 ${PROGRAM_SRC} ) - -# Libraries -target_link_libraries( ${PROGRAM_EXE} common ) - -# QT -qt5_app(TARGET ${PROGRAM_EXE} - SKIP_TRANSLATIONS - MODULES Core Gui Widgets Concurrent - INSTALL_COMPONENT gui -) - -# -------------------------------- -# Install -# -------------------------------- - -install(TARGETS ${PROGRAM_EXE} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT gui) - -install(FILES ${PROJECT_LICENSE_FILE} - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT gui - RENAME LICENSE.gui) - -install(FILES README.md - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT gui - RENAME README.gui.md) - -install(FILES LICENSE.qt5 - DESTINATION ${CMAKE_INSTALL_SHAREDIR} - COMPONENT gui) - -# -------------------------------- -# Package -# -------------------------------- - -configure_file(cmake/CPackComponentConfig.cmake.in - ${PROJECT_BINARY_DIR}/CPackProperties.cmake) diff --git a/gui/LICENSE.qt5 b/gui/LICENSE.qt5 deleted file mode 100644 index 0a04128..0000000 --- a/gui/LICENSE.qt5 +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/gui/README.md b/gui/README.md deleted file mode 100644 index b6d88ae..0000000 --- a/gui/README.md +++ /dev/null @@ -1,32 +0,0 @@ - -# antelope-keygen (gui) - -This is the graphical version of the [antelope-keygen](https://github.com/eosswedenorg/antelope-keygen) project. - -This program generates public and private keypair for [Antelope IO](https://antelope.io) - -Among the basic functionality the program can also search for keys containing specific words also know as _vanity keys_. - -## Security notice - -Keys are generated using [libantelope](https://github.com/eosswedenorg/libantelope) -while the library does not claim to guarantee cryptographically secure keys. it -relies on widly used open source cryptographic libraries (OpenSSL, libsecp256k1). - -Use at your own risk. The author and [Sw/eden](https://eossweden.org/) does not take responsability -for any damage caused by keys generated by the program. - -Please read the `LICENSE` file. - -``` -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. -``` - -## Author - -Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) diff --git a/gui/cmake/CPackComponentConfig.cmake.in b/gui/cmake/CPackComponentConfig.cmake.in deleted file mode 100644 index 4167b21..0000000 --- a/gui/cmake/CPackComponentConfig.cmake.in +++ /dev/null @@ -1,17 +0,0 @@ - -# -------------------------------- -# CPack Component Config -# -------------------------------- - -set( CPACK_PACKAGE_GUI_NAME "${PROJECT_NAME}" ) -set( CPACK_PACKAGE_GUI_CONTACT "${PROJECT_MAINTAINER}" ) - -# Additional description -set( CPACK_COMPONENT_GUI_DESCRIPTION "Graphical interface (Qt framework)" ) - -# Debian specific -set( CPACK_DEBIAN_GUI_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${CPACK_DEBIAN_PACKAGE_RELEASE}-${CPACK_SYSTEM_NAME}-${CPACK_SYSTEM_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") -set( CPACK_DEBIAN_GUI_PACKAGE_NAME "${PROJECT_NAME}" ) -set( CPACK_DEBIAN_GUI_PACKAGE_PRIORITY "optional" ) -set( CPACK_DEBIAN_GUI_PACKAGE_SECTION "misc" ) -set( CPACK_DEBIAN_GUI_PACKAGE_DEPENDS "libqt5core5a (>= 5.9.5), libqt5concurrent5 (>= 5.9.5), libqt5gui5 (>= 5.9.5), libqt5widgets5 (>= 5.9.5), libssl1.1") diff --git a/gui/cmake/QtUtils.cmake b/gui/cmake/QtUtils.cmake deleted file mode 100644 index 7d91a73..0000000 --- a/gui/cmake/QtUtils.cmake +++ /dev/null @@ -1,110 +0,0 @@ - -set(_QT_INSTALL_CONFIG_TEMPLATE ${CMAKE_CURRENT_LIST_DIR}/cmake_install_qt.cmake.in) -set(_QT_INSTALL_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/cmake_install_qt.cmake) - -# ------------------------------------------------------------------------------ -# Code Taken and modified from: -# https://github.com/equalsraf/neovim-qt/blob/master/cmake/WinDeployQt.cmake -# -# Wrapper to call windeployqt on Windows -# ------------------------------------------------------------------------------ -function(qt5_win_deploy) - cmake_parse_arguments(_deploy - "COMPILER_RUNTIME;FORCE;SKIP_TRANSLATIONS" - "TARGET;INSTALL_COMPONENT" - "MODULES;EXCLUDE_MODULES" - ${ARGN} - ) - - if(NOT _deploy_TARGET) - message(FATAL_ERROR "A TARGET must be specified") - endif() - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - list(APPEND _ARGS --debug) - elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - list(APPEND _ARGS --release-with-debug-info) - elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - list(APPEND _ARGS --release) - endif() - if(_deploy_COMPILER_RUNTIME) - list(APPEND _ARGS --compiler-runtime) - endif() - if(_deploy_FORCE) - list(APPEND _ARGS --force) - endif() - if(_deploy_SKIP_TRANSLATIONS) - list(APPEND _ARGS --no-translations) - endif() - - foreach(mod ${_deploy_MODULES}) - string(TOLOWER ${mod} mod) - string(REPLACE "qt5::" "" mod ${mod}) - list(APPEND _ARGS "--${mod}") - endforeach() - foreach(mod ${_deploy_EXCLUDE_MODULES}) - string(TOLOWER ${mod} mod) - string(REPLACE "qt5::" "" mod ${mod}) - list(APPEND _ARGS "--no-${mod}") - endforeach() - - find_program(_deploy_PROGRAM windeployqt PATHS $ENV{QTDIR}/bin) - if(_deploy_PROGRAM) - message(STATUS "Found ${_deploy_PROGRAM}") - else() - message(FATAL_ERROR "Unable to find windeployqt") - endif() - - if(COMPILER_RUNTIME AND NOT $ENV{VVVV}) - message(STATUS "not set, the VC++ redistributable installer will NOT be bundled") - endif() - - set( _QT_INSTALL_CONFIG_DEPFILE "${CMAKE_CURRENT_BINARY_DIR}/qt_deps_\${CMAKE_INSTALL_CONFIG_NAME}.cmake" ) - set( _QT_DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/qt_deps_${CMAKE_BUILD_TYPE}.cmake ) - - add_custom_target(${_deploy_TARGET}_windeployqt ALL - COMMAND ${CMAKE_COMMAND} -E echo "$" > ${_QT_DEPFILE} - COMMAND ${_deploy_PROGRAM} --list relative ${_ARGS} $ >> ${_QT_DEPFILE} - DEPENDS ${_deploy_TARGET} - COMMENT "Preparing Qt runtime dependencies") - - configure_file(${_QT_INSTALL_CONFIG_TEMPLATE} ${_QT_INSTALL_CONFIG} @ONLY) - - if (_deploy_INSTALL_COMPONENT) - set(_install_args COMPONENT ${_deploy_INSTALL_COMPONENT}) - endif() - - install(SCRIPT ${_QT_INSTALL_CONFIG} ${_install_args}) -endfunction() - -# ------------------------------------------------------------------------------ -# Macro for compile, link and deploy qt apps. -# ------------------------------------------------------------------------------ -macro(qt5_app) - cmake_parse_arguments(_args - "COMPILER_RUNTIME;FORCE;SKIP_TRANSLATIONS" - "TARGET;INSTALL_COMPONENT" - "MODULES" - ${ARGN} - ) - - if(NOT _args_TARGET) - message(FATAL_ERROR "A TARGET must be specified") - endif() - - if(NOT _args_MODULES) - message(FATAL_ERROR "Must define atleast one QT component") - endif() - - find_package( Qt5 COMPONENTS ${_args_MODULES} REQUIRED) - - # Link targets - list( TRANSFORM _args_MODULES PREPEND "Qt5::" OUTPUT_VARIABLE _qtargets) - target_link_libraries( ${_args_TARGET} ${_qtargets} ) - - - if (WIN32) - # Windows needs alot of extra stuff to copy all dll's. - qt5_win_deploy(${ARGN}) - endif() - -endmacro() diff --git a/gui/cmake/cmake_install_qt.cmake.in b/gui/cmake/cmake_install_qt.cmake.in deleted file mode 100644 index da01764..0000000 --- a/gui/cmake/cmake_install_qt.cmake.in +++ /dev/null @@ -1,23 +0,0 @@ - -# Custom script that installs Qt runtime files. - -if (EXISTS @_QT_INSTALL_CONFIG_DEPFILE@) - file(STRINGS @_QT_INSTALL_CONFIG_DEPFILE@ _lines) - - # First line is the output path. - list(GET _lines 0 BASE_PATH) - - # Rest of the lines are the files relative to the path. - list(SUBLIST _lines 1 -1 FILES) - - foreach(file ${FILES}) - get_filename_component(rel_path ${file} DIRECTORY BASE_DIR ${BASE_PATH}) - - set(install_path ${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_BINDIR@) - if (rel_path) - set(install_path "${install_path}/${rel_path}") - endif() - - file(INSTALL ${BASE_PATH}/${file} DESTINATION ${install_path}) - endforeach() -endif() diff --git a/gui/gui_text.h.in b/gui/gui_text.h.in deleted file mode 100644 index e119cb1..0000000 --- a/gui/gui_text.h.in +++ /dev/null @@ -1,54 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef EOSIOKEYGEN_GUI_TEXT_H -#define EOSIOKEYGEN_GUI_TEXT_H - -#include - -#define EOSIOKEYGEN_GUI_TEXT_ABOUT_TITLE "@PROJECT_NAME@ - About" - -#define EOSIOKEYGEN_GUI_TEXT_ABOUT_BODY \ - "

@PROJECT_NAME@ - v@PROJECT_VERSION@

" \ - "

@PROJECT_DESCRIPTION@

" \ - "

@PROJECT_HOMEPAGE_URL@

" \ - "@GUI_ABOUT_LICENSE@" \ - "

Author

" \ - "

@GUI_ABOUT_AUTHOR@

" - -#define EOSIOKEYGEN_GUI_TEXT_DICT_LANG_TOOLTIP \ - "

Highlight words from given language dictionary in the found keys (note that the words " \ - "are not used for search. only for highlight output).

" \ - "

There can be more then one language. In that case contents " \ - "of all languges are merged into one dictionary.

" \ - "

The langauges are stored in files at " CONFIG_SHARE_FULL_PATH "/dict

" - - -#define EOSIOKEYGEN_GUI_TEXT_DICT_FILE_TOOLTIP \ - "

Use words found in file (separated by newline) to highlight " \ - "words in the keys found (note that the words in this " \ - "file are not used for search. only for highlight output).

" \ - "

There can be more then one file. In that case contents " \ - "of all files are merged into one dictionary.

" - -#endif /* EOSIOKEYGEN_GUI_TEXT_H */ diff --git a/gui/src/GenerateWindow.cpp b/gui/src/GenerateWindow.cpp deleted file mode 100644 index 6d5e3f0..0000000 --- a/gui/src/GenerateWindow.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "Settings.hpp" -#include "GenerateWindow.hpp" - -void _initKeyWidget(QLineEdit& w, const QFont& font) { - w.setFixedWidth(460); - w.setFont(font); - w.setReadOnly(true); -} - -void _initKeyCopyButton(QPushButton& btn, const QIcon& icon) { - btn.setFixedWidth(32); - btn.setIcon(icon); -} - -GenerateWindow::GenerateWindow(QWidget *parent) : -QWidget (parent), -m_btn_gen ("Generate"), -m_btn_copy_both ("Copy keys") -{ - QFont mono = QFontDatabase::systemFont(QFontDatabase::FixedFont); - - QIcon copy_icon = QIcon::fromTheme("edit-copy"); - QGridLayout* layout; - - _initKeyWidget(m_pub, mono); - _initKeyWidget(m_priv, mono); - - _initKeyCopyButton(m_btn_copy_pub, copy_icon); - _initKeyCopyButton(m_btn_copy_priv, copy_icon); - - // Layout - layout = new QGridLayout(); - layout->setAlignment(Qt::AlignCenter); - - // Stretch first and last column to make the widgets horizontally centered. - layout->setColumnStretch(0, 1); - layout->setColumnStretch(4, 1); - - // Public key row - layout->addWidget(new QLabel("Public:"), 0, 1, Qt::AlignRight); - layout->addWidget(&m_pub, 0, 2); - layout->addWidget(&m_btn_copy_pub, 0, 3); - - // Private key row - - layout->addWidget(new QLabel("Private:"), 1, 1, Qt::AlignRight); - layout->addWidget(&m_priv, 1, 2); - layout->addWidget(&m_btn_copy_priv, 1, 3); - - // Bottom row - - m_btn_copy_both.setFixedWidth(80); - - layout->addWidget(&m_btn_gen, 2, 2); - layout->addWidget(&m_btn_copy_both, 2, 3); - - setLayout(layout); - - // Connections - connect(&m_btn_gen, SIGNAL(released()), this, SLOT(generate_key())); - connect(&m_btn_copy_both, SIGNAL(released()), this, SLOT(copy_both_keys())); - connect(&m_btn_copy_pub, SIGNAL(released()), this, SLOT(copy_pub_key())); - connect(&m_btn_copy_priv, SIGNAL(released()), this, SLOT(copy_priv_key())); -} - -void GenerateWindow::generate_key() -{ - std::string pubstr, pvtstr; - struct libantelope::ec_keypair pair; - const libantelope::wif_codec_t& codec = Settings::getKeyCodec(); - - libantelope::ec_generate_key(&pair); - - pubstr = libantelope::wif_pub_encode(pair.pub, codec.pub); - pvtstr = libantelope::wif_priv_encode(pair.secret, codec.pvt); - m_pub.setText(QString::fromStdString(pubstr)); - m_priv.setText(QString::fromStdString(pvtstr)); -} - -void GenerateWindow::copy_both_keys() -{ - QClipboard *clipboard = QGuiApplication::clipboard(); - clipboard->setText(m_pub.text() + "\n" + m_priv.text()); -} - -void GenerateWindow::copy_pub_key() -{ - QClipboard *clipboard = QGuiApplication::clipboard(); - clipboard->setText(m_pub.text()); -} - -void GenerateWindow::copy_priv_key() -{ - QClipboard *clipboard = QGuiApplication::clipboard(); - clipboard->setText(m_priv.text()); -} diff --git a/gui/src/GenerateWindow.hpp b/gui/src/GenerateWindow.hpp deleted file mode 100644 index 63a3c99..0000000 --- a/gui/src/GenerateWindow.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef GENERATE_WINDOW_H -#define GENERATE_WINDOW_H - -#include -#include -#include - -class GenerateWindow : public QWidget -{ - Q_OBJECT -public: - GenerateWindow(QWidget *parent = 0); - -public slots: - - // Genereate a new key. - void generate_key(); - - // Copy both keys to clipboard - void copy_both_keys(); - - // copy public key to clipboard - void copy_pub_key(); - - // copy private key to clipboard - void copy_priv_key(); - -protected: - - QLineEdit m_pub; - QLineEdit m_priv; - - QPushButton m_btn_gen; - QPushButton m_btn_copy_both; - QPushButton m_btn_copy_priv; - QPushButton m_btn_copy_pub; -}; - -#endif /* GENERATE_WINDOW_H */ diff --git a/gui/src/MainWindow.cpp b/gui/src/MainWindow.cpp deleted file mode 100644 index 9b1a043..0000000 --- a/gui/src/MainWindow.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include "gui_text.h" -#include "Settings.hpp" -#include "GenerateWindow.hpp" -#include "SearchWindow.hpp" -#include "MainWindow.hpp" - -MainWindow::MainWindow(QWidget *parent) : -QMainWindow (parent), -m_format_fio_action (nullptr), -m_format_legacy_action (nullptr), -m_format_k1_action (nullptr) -{ - libantelope::ec_init(); - - // Create sub windows and stacked widget. - m_stacked = new QStackedWidget(); - m_stacked->addWidget(new GenerateWindow()); - m_stacked->addWidget(new SearchWindow()); - - setCentralWidget(m_stacked); - - // Add to menu bar. - - menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); - menuBar()->addAction("Search", this, SLOT(switchToSearch())); - - // Settings - - QActionGroup* formatGroup = new QActionGroup(this); - - m_format_fio_action = new QAction("FIO", formatGroup); - m_format_fio_action->setCheckable(true); - m_format_legacy_action = new QAction("Legacy", formatGroup); - m_format_legacy_action->setCheckable(true); - m_format_k1_action = new QAction("K1", formatGroup); - m_format_k1_action->setCheckable(true); - - // Set k1 and trigger the changed action so we set the codec. - m_format_k1_action->setChecked(true); - formatK1CheckboxChanged(); - - connect(m_format_fio_action, SIGNAL(triggered()), this, SLOT(formatFioCheckboxChanged())); - connect(m_format_legacy_action, SIGNAL(triggered()), this, SLOT(formatLegacyCheckboxChanged())); - connect(m_format_k1_action, SIGNAL(triggered()), this, SLOT(formatK1CheckboxChanged())); - - QMenu *settings = menuBar()->addMenu("Settings"); - QMenu *format_menu = settings->addMenu("Key Format"); - format_menu->addAction(m_format_k1_action); - format_menu->addAction(m_format_legacy_action); - format_menu->addAction(m_format_fio_action); - - // About - menuBar()->addAction("About", this, SLOT(showAbout())); -} - -MainWindow::~MainWindow() -{ - libantelope::ec_shutdown(); -} - -void MainWindow::switchToGenerate() -{ - m_stacked->setCurrentIndex(0); -} - -void MainWindow::switchToSearch() -{ - m_stacked->setCurrentIndex(1); -} - -void MainWindow::showAbout() -{ - QMessageBox::about(this, - EOSIOKEYGEN_GUI_TEXT_ABOUT_TITLE, - EOSIOKEYGEN_GUI_TEXT_ABOUT_BODY); -} - -void MainWindow::formatFioCheckboxChanged() -{ - if (m_format_fio_action->isChecked()) { - Settings::setKeyCodec(libantelope::wif_create_legacy_codec("FIO")); - } -} - -void MainWindow::formatLegacyCheckboxChanged() -{ - if (m_format_legacy_action->isChecked()) { - Settings::setKeyCodec(libantelope::WIF_CODEC_LEG); - } -} - -void MainWindow::formatK1CheckboxChanged() -{ - if (m_format_k1_action->isChecked()) { - Settings::setKeyCodec(libantelope::WIF_CODEC_K1); - } -} diff --git a/gui/src/MainWindow.hpp b/gui/src/MainWindow.hpp deleted file mode 100644 index 3d4b172..0000000 --- a/gui/src/MainWindow.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef MAIN_WINDOW_H -#define MAIN_WINDOW_H - -#include -#include -#include - -class QStackedWidget; - -class MainWindow : public QMainWindow -{ - Q_OBJECT -public: - MainWindow(QWidget *parent = 0); - virtual ~MainWindow(); - -private slots : - - // Switch to generate window. - void switchToGenerate(); - - // Switch to search window. - void switchToSearch(); - - void showAbout(); - - void formatFioCheckboxChanged(); - void formatLegacyCheckboxChanged(); - void formatK1CheckboxChanged(); - -private : - - QStackedWidget* m_stacked; - - QPointer m_format_fio_action; - QPointer m_format_legacy_action; - QPointer m_format_k1_action; -}; - -#endif /* MAIN_WINDOW_H */ diff --git a/gui/src/MultiSelect.cpp b/gui/src/MultiSelect.cpp deleted file mode 100644 index 1b2ea89..0000000 --- a/gui/src/MultiSelect.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include "MultiSelect.hpp" - -MultiSelect::MultiSelect(const QString& text, bool user_can_add, QWidget *parent) : -QPushButton (text + ": none", parent) -{ - QPushButton* btn; - QVBoxLayout* layout; - - m_prefix = text; - - // Dialog - m_dialog = new QDialog(this); - - // Dialog Widgets - m_list = new QListWidget(); - btn = new QPushButton("Select"); - - // Dialog layout - layout = new QVBoxLayout(m_dialog); - layout->addWidget(m_list); - layout->addWidget(btn); - - // Connections - QObject::connect(btn, SIGNAL(clicked()), m_dialog, SLOT(accept())); - QObject::connect(m_dialog, SIGNAL(accepted()), this, SLOT(selectionConfirmed())); - QObject::connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); - - // Configured to let users add items. provide button and signal. - if (user_can_add) { - btn = new QPushButton("Add"); - layout->addWidget(btn); - QObject::connect(btn, SIGNAL(clicked()), this, SLOT(addBtnClicked())); - } -} - -void MultiSelect::addItem(const QString& text, bool checked) -{ - QListWidgetItem* item = new QListWidgetItem(text, m_list); - item->setFlags(Qt::ItemIsEnabled); - item->setCheckState(checked ? Qt::Checked : Qt::Unchecked); -} - -void MultiSelect::addItems(const QStringList& list, bool checked) -{ - QStringList::const_iterator it; - - for(it = list.cbegin(); it != list.cend(); it++) { - addItem(*it, checked); - } -} - -void MultiSelect::clearItems() -{ - m_list->clear(); -} - -QStringList MultiSelect::getSelectedItems() const -{ - QListWidgetItem* item; - QStringList ret; - - // Cannot use m_list->selectedItems() as that function only fetches - // _selected_ and not _checked_ items (there is a difference). - for(int i = 0; i < m_list->count(); i++) { - item = m_list->item(i); - // Include in list if checked. - if (item->checkState() == Qt::Checked) { - ret << item->text(); - } - } - return ret; -} - -void MultiSelect::selectionConfirmed() -{ - QStringList selected = getSelectedItems(); - - // Update the text for this widget to - // reflect the selected objects. - QString txt = m_prefix + ": "; - - // Have more than one item. show number of items. - if (selected.count() > 1) { - txt += QString::number(selected.count()) + " selected"; - } - // Just one, we can show the text. - else if (selected.count() == 1) { - txt += selected.at(0); - } - else { - txt += "none"; - } - - setText(txt); - - // Emit the selectionChanged signal with the updated list - emit selectionChanged(selected); -} - -void MultiSelect::listItemClicked(QListWidgetItem *item) -{ - // toggle state when user clicks. - bool checked = item->checkState() == Qt::Checked; - item->setCheckState(checked ? Qt::Unchecked : Qt::Checked); -} - -void MultiSelect::addBtnClicked() -{ - // Just emit addNewItem event. - emit addNewItem(); -} - -void MultiSelect::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) { - // Show select dialog. - m_dialog->show(); - } else { - // pass on other buttons to base class - QPushButton::mousePressEvent(event); - } -} diff --git a/gui/src/MultiSelect.hpp b/gui/src/MultiSelect.hpp deleted file mode 100644 index 5fe5d8a..0000000 --- a/gui/src/MultiSelect.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef MULTI_SELECT_H -#define MULTI_SELECT_H - -#include -#include -#include - -class QMouseEvent; -class QPushButton; -class QListWidget; -class QListWidgetItem; -class QDialog; -class MultiSelectDialog; - -// -// MultiSelect implements multi selection of items using -// a push button and a dialog with a list of checkbox items. -// -class MultiSelect : public QPushButton -{ - Q_OBJECT -public: - MultiSelect(const QString& text, bool user_add_item = false, QWidget *parent = 0); - - // Items. - - void addItem(const QString& text, bool checked = false); - - void addItems(const QStringList& list, bool checked = false); - - void clearItems(); - - // Get a list of currently selected items. - QStringList getSelectedItems() const; - -signals: - - // This signal is emitted whenever the user has made a new selection. - void selectionChanged(QStringList selected); - - // This signal is emitted whenever the user clicks the "Add" button. - // NOTE: Will only be emitted if `user_add_item` has been set to `true` in the constructor. - void addNewItem(); - -private slots : - - // Called when the dialog is accepted. - void selectionConfirmed(); - - // Called when a list item is clicked on. - void listItemClicked(QListWidgetItem *item); - - // Called when the add button is clicked on. - void addBtnClicked(); - -protected : - - // Event handlers - void mousePressEvent(QMouseEvent *e) override; - -private : - - // Prefix to show on the button before value. - QString m_prefix; - - // List of items - QListWidget* m_list; - - // Dialog to show if this widget are clicked on. - QDialog* m_dialog; -}; - -#endif /* MULTI_SELECT_H */ diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp deleted file mode 100644 index e4661e2..0000000 --- a/gui/src/SearchWindow.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Settings.hpp" -#include "gui_text.h" -#include "config.hpp" -#include "helpers.hpp" -#include "SearchWindow.hpp" - -SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : -QWidget (parent, flags), -m_status ("status"), -m_leet_cb ("L33t"), -m_dict_lang ("Dictionary Language"), -m_dict_file ("Dictionary File", true), -m_btn_exec ("Search"), -m_btn_clear ("Clear") -{ - setMinimumSize(600, 400); - - // Monospaced font - QFont f_mono("monospace"); - - // Output - m_output.setFont(f_mono); - m_output.setReadOnly(true); - - // Layout - // ------------------------ - setLayout(&m_layout); - m_layout.setColumnStretch(0, 10); - m_layout.setColumnStretch(1, 10); - - // First row. - m_dict_lang.addItems(get_files(CONFIG_DICT_FULL_PATH)); - m_dict_lang.setToolTip(EOSIOKEYGEN_GUI_TEXT_DICT_LANG_TOOLTIP); - m_dict_file.setToolTip(EOSIOKEYGEN_GUI_TEXT_DICT_FILE_TOOLTIP); - - m_layout.addWidget(&m_dict_lang, 0, 0); - m_layout.addWidget(&m_dict_file, 0, 1); - - m_layout.addWidget(&m_leet_cb, 0, 2); - -#ifdef EOSIOKEYGEN_HAVE_THREADS - m_num_threads.setValue((int) antelopekeygen::KeySearch::max_threads()); - m_num_threads.setRange(1, (int) antelopekeygen::KeySearch::max_threads()); - m_num_threads.setSuffix(" Threads"); - m_layout.addWidget(&m_num_threads, 0, 3); -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - - m_num_results.setValue(10); - m_num_results.setRange(1, 99); - m_num_results.setSuffix(" Results"); - m_layout.addWidget(&m_num_results, 0, 4); - - // Second row. - m_layout.addWidget(&m_status, 1, 0, 1, 3); - m_layout.addWidget(&m_txt_search, 1, 0, 1, 3); - m_layout.addWidget(&m_btn_exec, 1, 3); - m_layout.addWidget(&m_btn_clear, 1, 4); - - // Third row. - m_layout.addWidget(&m_output, 2, 0, 1, 0); - - // Search - // ------------------------ - - m_ksearch.setCallback(this); - - initSignals(); - - // Focus search field. - m_txt_search.setFocus(); -} - -void SearchWindow::initSignals() -{ - // Buttons - connect(&m_btn_exec, SIGNAL(released()), this, SLOT(search())); - connect(&m_btn_clear, SIGNAL(released()), &m_output, SLOT(clear())); - - // Worker Thread - connect(&m_worker, SIGNAL(started()), this, SLOT(searchStarted())); - connect(&m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); - - connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); - - connect(&m_dict_file, SIGNAL(addNewItem()), this, SLOT(langFileAdd())); -} - -void SearchWindow::loadDictionaries() -{ - QStringList list; - antelopekeygen::Dictionary tmpDict; - std::string base_path(CONFIG_DICT_FULL_PATH); - - // Clear dictionary first. - m_dict.clear(); - - // Go through all selected languages. - list = m_dict_lang.getSelectedItems(); - for(QStringList::const_iterator it = list.cbegin(); it != list.cend(); it++) { - - // Load and add them to dictionary. - tmpDict.loadFromFile(base_path + "/" + it->toStdString()); - m_dict.add(tmpDict); - } - - // Go through all selected files. - list = m_dict_file.getSelectedItems(); - for(QStringList::const_iterator it = list.cbegin(); it != list.cend(); it++) { - - // Load and add them to dictionary. - tmpDict.loadFromFile(it->toStdString()); - m_dict.add(tmpDict); - } -} - -void SearchWindow::onResult(const struct libantelope::ec_keypair* key, const struct antelopekeygen::KeySearch::result& result) -{ - int pos = (int) result.pos; - int len = (int) result.len; - libantelope::wif_codec_t codec = Settings::getKeyCodec(); - QString pub = QString::fromStdString(libantelope::wif_pub_encode(key->pub, codec.pub)); - int pub_prefix_len = (int) codec.pub.length(); - QString mid = pub.mid(pos, len); - QString left = pub.left(pos); - QString right = pub.mid(pos + len, pub.size() - pos); - antelopekeygen::Dictionary::search_result_t dict_res = m_dict.search(pub.toStdString()); - - QString out = "Public: " + pub.left(pub_prefix_len); - for(int i = pub_prefix_len; i < pub.length(); ) { - - if (i == pos) { - out += "" + pub.mid(pos, len) + ""; - i += len; - continue; - } - - // Look in the dictionary. - auto dp = dict_res.find(i); - if (dp != dict_res.end()) { - int p = (int) dp->first; - int l = (int) dp->second; - out += "" + pub.mid(p, l) + ""; - i += l; - continue; - } - - out += pub[i++]; - } - - out += "
Private: " + QString::fromStdString(libantelope::wif_priv_encode(key->secret, codec.pvt)); - - // As this function could be called from a non-gui thread. we use signals. - emit addOutput("

" + out + "

"); -} - -// -------------------- -// Slots -// -------------------- - -void SearchWindow::search() -{ - if (m_worker.isRunning()) { - m_ksearch.abort(); - return; - } - - const std::string& input = m_txt_search.text().toLocal8Bit().constData(); - antelopekeygen::strlist_t list; - - if (m_leet_cb.isChecked()) { - list = antelopekeygen::l33twords(input); - } else { - list = antelopekeygen::strlist::splitw(input); - } - - // Validate that we atleast got something to search for. - if (list.size() < 1 || (list.size() == 1 && list[0] == "")) { - QMessageBox::warning( this, - "Empty search field.", - "You must specify atleast one search string" ); - return; - } - - loadDictionaries(); - - m_ksearch.clear(); - m_ksearch.addList(list); -#ifdef EOSIOKEYGEN_HAVE_THREADS - m_ksearch.setThreadCount(m_num_threads.value()); -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - - QFuture future = QtConcurrent::run(&m_ksearch, &antelopekeygen::KeySearch::find, m_num_results.value()); - m_worker.setFuture(future); - - m_status.setText("Searching for: " + QString::fromStdString(antelopekeygen::strlist::join(list, ", "))); -} - -void SearchWindow::output(const std::string& html) -{ - output(QString::fromStdString(html)); -} - -void SearchWindow::output(const QString& html) -{ - if (m_output.toPlainText().size()) { - m_output.setHtml(m_output.toHtml() + html); - } else { - m_output.setHtml(html); - } - - // Force scrollbar to the bottom. - m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); -} - -void SearchWindow::langFileAdd() -{ - QStringList files = QFileDialog::getOpenFileNames(this, - "Select one or more language files"); - - m_dict_file.addItems(files, true); -} - -void SearchWindow::searchStarted() -{ - // Set prefix for search - m_ksearch.setPrefix(Settings::getKeyCodec().pub); - - m_btn_exec.setText("Cancel"); - - m_txt_search.setEnabled(false); - m_txt_search.setHidden(true); - m_dict_lang.setEnabled(false); - m_dict_file.setEnabled(false); - m_leet_cb.setEnabled(false); - m_btn_clear.setEnabled(false); -#ifdef EOSIOKEYGEN_HAVE_THREADS - m_num_threads.setEnabled(false); -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - m_num_results.setEnabled(false); -} - -void SearchWindow::searchFinished() -{ - m_btn_exec.setText("Search"); - - m_txt_search.setEnabled(true); - m_txt_search.setHidden(false); - m_dict_lang.setEnabled(true); - m_dict_file.setEnabled(true); - m_leet_cb.setEnabled(true); - m_btn_clear.setEnabled(true); -#ifdef EOSIOKEYGEN_HAVE_THREADS - m_num_threads.setEnabled(true); -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - m_num_results.setEnabled(true); -} diff --git a/gui/src/SearchWindow.hpp b/gui/src/SearchWindow.hpp deleted file mode 100644 index 9282ef4..0000000 --- a/gui/src/SearchWindow.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef SEARCH_WINDOW_H -#define SEARCH_WINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "MultiSelect.hpp" - -class SearchWindow : public QWidget, public antelopekeygen::IKeySearchResult -{ - Q_OBJECT -public: - explicit SearchWindow(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); - - void onResult(const struct libantelope::ec_keypair* key, const struct antelopekeygen::KeySearch::result& result); - -private : - void initSignals(); - - void loadDictionaries(); - -private slots: - - // Start a search - void search(); - - // Output html to screen. - void output(const std::string& html); - void output(const QString& html); - - // Called when a search is started. - void searchStarted(); - - // Called when a search is done. - void searchFinished(); - - // Called when a new language file should be added - void langFileAdd(); - -signals: - void addOutput(const QString& line); - -private: - - // Search worker thread. - QFutureWatcher m_worker; - - antelopekeygen::KeySearch m_ksearch; - - antelopekeygen::Dictionary m_dict; - - // Widgets - // ---------------- - - // Status text. - QLabel m_status; - - // Search input. - QLineEdit m_txt_search; - -#ifdef EOSIOKEYGEN_HAVE_THREADS - // Number of Threads. - QSpinBox m_num_threads; -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - - // Number of Results - QSpinBox m_num_results; - - QCheckBox m_leet_cb; - - MultiSelect m_dict_lang; - - MultiSelect m_dict_file; - - // Buttons - QPushButton m_btn_exec; - QPushButton m_btn_clear; - - // Text output. - QTextEdit m_output; - - // Gui Layout. - QGridLayout m_layout; -}; - -#endif /* SEARCH_WINDOW_H */ diff --git a/gui/src/Settings.cpp b/gui/src/Settings.cpp deleted file mode 100644 index aa8dad9..0000000 --- a/gui/src/Settings.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 "Settings.hpp" - -namespace priv { - - libantelope::wif_codec_t key_format = libantelope::WIF_CODEC_K1; -} // namespace priv - -void Settings::setKeyCodec(const libantelope::wif_codec_t& format) { - priv::key_format = format; -} - -const libantelope::wif_codec_t& Settings::getKeyCodec() { - return priv::key_format; -} diff --git a/gui/src/Settings.hpp b/gui/src/Settings.hpp deleted file mode 100644 index 08a56cd..0000000 --- a/gui/src/Settings.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include - -namespace Settings -{ - void setKeyCodec(const libantelope::wif_codec_t& format); - - const libantelope::wif_codec_t& getKeyCodec(); -}; - -#endif /* SEARCH_WINDOW_H */ diff --git a/gui/src/helpers.cpp b/gui/src/helpers.cpp deleted file mode 100644 index dc70b2f..0000000 --- a/gui/src/helpers.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 "helpers.hpp" - -QStringList get_files(const QDir& directory) { - - QFileInfoList list; - QStringList ret; - - list = directory.entryInfoList(QDir::Files); - for (int i = 0; i < list.size(); ++i) { - QFileInfo info = list.at(i); - ret << info.fileName(); - } - return ret; -} - -QStringList get_files(const QString& directory) -{ - return get_files(QDir(directory)); -} diff --git a/gui/src/helpers.hpp b/gui/src/helpers.hpp deleted file mode 100644 index da76ed2..0000000 --- a/gui/src/helpers.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef HELPERS_H -#define HELPERS_H - -#include -#include -#include - -// -// Get a list of files for a given directory. -// NOTE: only filenames are returned. relative to directory. -// -QStringList get_files(const QDir& directory); -QStringList get_files(const QString& directory); - -#endif /* HELPERS_H */ diff --git a/gui/src/main.cpp b/gui/src/main.cpp deleted file mode 100644 index 4d8ee5b..0000000 --- a/gui/src/main.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020-2021 EOS Sw/eden - * - * 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 -#include "MainWindow.hpp" - -int main(int argc, char **argv) { - - QApplication app(argc, argv); - - MainWindow window; - - window.show(); - - return app.exec(); -} diff --git a/install.sh b/install.sh index 33dde09..927f1c7 100755 --- a/install.sh +++ b/install.sh @@ -1,3 +1,5 @@ #!/bin/bash -cmake --install build $@ +pushd build > /dev/null +make install $@ +popd > /dev/null diff --git a/lib/CLI11/CMakeLists.txt b/lib/CLI11/CMakeLists.txt deleted file mode 100644 index fb43efb..0000000 --- a/lib/CLI11/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -set (LIBCLI11_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include) -set (LIBCLI11_LICENSE ${CMAKE_CURRENT_LIST_DIR}/LICENSE) \ No newline at end of file diff --git a/lib/CLI11/LICENSE b/lib/CLI11/LICENSE deleted file mode 100644 index f618d95..0000000 --- a/lib/CLI11/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -CLI11 2.2 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry -Schreiner under NSF AWARD 1414736. All rights reserved. - -Redistribution and use in source and binary forms of CLI11, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/CLI11/include/CLI11/CLI11.hpp b/lib/CLI11/include/CLI11/CLI11.hpp deleted file mode 100644 index f29a5c4..0000000 --- a/lib/CLI11/include/CLI11/CLI11.hpp +++ /dev/null @@ -1,9190 +0,0 @@ -// CLI11: Version 2.2.0 -// Originally designed by Henry Schreiner -// https://github.com/CLIUtils/CLI11 -// -// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts -// from: v2.2.0 -// -// CLI11 2.2.0 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry -// Schreiner under NSF AWARD 1414736. All rights reserved. -// -// Redistribution and use in source and binary forms of CLI11, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -// Standard combined includes: -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define CLI11_VERSION_MAJOR 2 -#define CLI11_VERSION_MINOR 2 -#define CLI11_VERSION_PATCH 0 -#define CLI11_VERSION "2.2.0" - - - - -// The following version macro is very similar to the one in pybind11 -#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER) -#if __cplusplus >= 201402L -#define CLI11_CPP14 -#if __cplusplus >= 201703L -#define CLI11_CPP17 -#if __cplusplus > 201703L -#define CLI11_CPP20 -#endif -#endif -#endif -#elif defined(_MSC_VER) && __cplusplus == 199711L -// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented) -// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer -#if _MSVC_LANG >= 201402L -#define CLI11_CPP14 -#if _MSVC_LANG > 201402L && _MSC_VER >= 1910 -#define CLI11_CPP17 -#if _MSVC_LANG > 201703L && _MSC_VER >= 1910 -#define CLI11_CPP20 -#endif -#endif -#endif -#endif - -#if defined(CLI11_CPP14) -#define CLI11_DEPRECATED(reason) [[deprecated(reason)]] -#elif defined(_MSC_VER) -#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason)) -#else -#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason))) -#endif - -/** detection of rtti */ -#ifndef CLI11_USE_STATIC_RTTI -#if(defined(_HAS_STATIC_RTTI) && _HAS_STATIC_RTTI) -#define CLI11_USE_STATIC_RTTI 1 -#elif defined(__cpp_rtti) -#if(defined(_CPPRTTI) && _CPPRTTI == 0) -#define CLI11_USE_STATIC_RTTI 1 -#else -#define CLI11_USE_STATIC_RTTI 0 -#endif -#elif(defined(__GCC_RTTI) && __GXX_RTTI) -#define CLI11_USE_STATIC_RTTI 0 -#else -#define CLI11_USE_STATIC_RTTI 1 -#endif -#endif - - - -// C standard library -// Only needed for existence checking -#if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM -#if __has_include() -// Filesystem cannot be used if targeting macOS < 10.15 -#if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 -#define CLI11_HAS_FILESYSTEM 0 -#elif defined(__wasi__) -// As of wasi-sdk-14, filesystem is not implemented -#define CLI11_HAS_FILESYSTEM 0 -#else -#include -#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703 -#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9 -#define CLI11_HAS_FILESYSTEM 1 -#elif defined(__GLIBCXX__) -// if we are using gcc and Version <9 default to no filesystem -#define CLI11_HAS_FILESYSTEM 0 -#else -#define CLI11_HAS_FILESYSTEM 1 -#endif -#else -#define CLI11_HAS_FILESYSTEM 0 -#endif -#endif -#endif -#endif - -#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 -#include // NOLINT(build/include) -#else -#include -#include -#endif - - - -namespace CLI { - - -/// Include the items in this namespace to get free conversion of enums to/from streams. -/// (This is available inside CLI as well, so CLI11 will use this without a using statement). -namespace enums { - -/// output streaming for enumerations -template ::value>::type> -std::ostream &operator<<(std::ostream &in, const T &item) { - // make sure this is out of the detail namespace otherwise it won't be found when needed - return in << static_cast::type>(item); -} - -} // namespace enums - -/// Export to CLI namespace -using enums::operator<<; - -namespace detail { -/// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not -/// produce overflow for some expected uses -constexpr int expected_max_vector_size{1 << 29}; -// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c -/// Split a string by a delim -inline std::vector split(const std::string &s, char delim) { - std::vector elems; - // Check to see if empty string, give consistent result - if(s.empty()) { - elems.emplace_back(); - } else { - std::stringstream ss; - ss.str(s); - std::string item; - while(std::getline(ss, item, delim)) { - elems.push_back(item); - } - } - return elems; -} - -/// Simple function to join a string -template std::string join(const T &v, std::string delim = ",") { - std::ostringstream s; - auto beg = std::begin(v); - auto end = std::end(v); - if(beg != end) - s << *beg++; - while(beg != end) { - s << delim << *beg++; - } - return s.str(); -} - -/// Simple function to join a string from processed elements -template ::value>::type> -std::string join(const T &v, Callable func, std::string delim = ",") { - std::ostringstream s; - auto beg = std::begin(v); - auto end = std::end(v); - auto loc = s.tellp(); - while(beg != end) { - auto nloc = s.tellp(); - if(nloc > loc) { - s << delim; - loc = nloc; - } - s << func(*beg++); - } - return s.str(); -} - -/// Join a string in reverse order -template std::string rjoin(const T &v, std::string delim = ",") { - std::ostringstream s; - for(std::size_t start = 0; start < v.size(); start++) { - if(start > 0) - s << delim; - s << v[v.size() - start - 1]; - } - return s.str(); -} - -// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string - -/// Trim whitespace from left of string -inline std::string <rim(std::string &str) { - auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale()); }); - str.erase(str.begin(), it); - return str; -} - -/// Trim anything from left of string -inline std::string <rim(std::string &str, const std::string &filter) { - auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); - str.erase(str.begin(), it); - return str; -} - -/// Trim whitespace from right of string -inline std::string &rtrim(std::string &str) { - auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale()); }); - str.erase(it.base(), str.end()); - return str; -} - -/// Trim anything from right of string -inline std::string &rtrim(std::string &str, const std::string &filter) { - auto it = - std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); - str.erase(it.base(), str.end()); - return str; -} - -/// Trim whitespace from string -inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } - -/// Trim anything from string -inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); } - -/// Make a copy of the string and then trim it -inline std::string trim_copy(const std::string &str) { - std::string s = str; - return trim(s); -} - -/// remove quotes at the front and back of a string either '"' or '\'' -inline std::string &remove_quotes(std::string &str) { - if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) { - if(str.front() == str.back()) { - str.pop_back(); - str.erase(str.begin(), str.begin() + 1); - } - } - return str; -} - -/// Add a leader to the beginning of all new lines (nothing is added -/// at the start of the first line). `"; "` would be for ini files -/// -/// Can't use Regex, or this would be a subs. -inline std::string fix_newlines(const std::string &leader, std::string input) { - std::string::size_type n = 0; - while(n != std::string::npos && n < input.size()) { - n = input.find('\n', n); - if(n != std::string::npos) { - input = input.substr(0, n + 1) + leader + input.substr(n + 1); - n += leader.size(); - } - } - return input; -} - -/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) -inline std::string trim_copy(const std::string &str, const std::string &filter) { - std::string s = str; - return trim(s, filter); -} -/// Print a two part "help" string -inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) { - name = " " + name; - out << std::setw(static_cast(wid)) << std::left << name; - if(!description.empty()) { - if(name.length() >= wid) - out << "\n" << std::setw(static_cast(wid)) << ""; - for(const char c : description) { - out.put(c); - if(c == '\n') { - out << std::setw(static_cast(wid)) << ""; - } - } - } - out << "\n"; - return out; -} - -/// Print subcommand aliases -inline std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid) { - if(!aliases.empty()) { - out << std::setw(static_cast(wid)) << " aliases: "; - bool front = true; - for(const auto &alias : aliases) { - if(!front) { - out << ", "; - } else { - front = false; - } - out << detail::fix_newlines(" ", alias); - } - out << "\n"; - } - return out; -} - -/// Verify the first character of an option -/// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with -template bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); } - -/// Verify following characters of an option -template bool valid_later_char(T c) { - // = and : are value separators, { has special meaning for option defaults, - // and \n would just be annoying to deal with in many places allowing space here has too much potential for - // inadvertent entry errors and bugs - return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n'); -} - -/// Verify an option/subcommand name -inline bool valid_name_string(const std::string &str) { - if(str.empty() || !valid_first_char(str[0])) { - return false; - } - auto e = str.end(); - for(auto c = str.begin() + 1; c != e; ++c) - if(!valid_later_char(*c)) - return false; - return true; -} - -/// Verify an app name -inline bool valid_alias_name_string(const std::string &str) { - static const std::string badChars(std::string("\n") + '\0'); - return (str.find_first_of(badChars) == std::string::npos); -} - -/// check if a string is a container segment separator (empty or "%%") -inline bool is_separator(const std::string &str) { - static const std::string sep("%%"); - return (str.empty() || str == sep); -} - -/// Verify that str consists of letters only -inline bool isalpha(const std::string &str) { - return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); }); -} - -/// Return a lower case version of a string -inline std::string to_lower(std::string str) { - std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) { - return std::tolower(x, std::locale()); - }); - return str; -} - -/// remove underscores from a string -inline std::string remove_underscore(std::string str) { - str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str)); - return str; -} - -/// Find and replace a substring with another substring -inline std::string find_and_replace(std::string str, std::string from, std::string to) { - - std::size_t start_pos = 0; - - while((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } - - return str; -} - -/// check if the flag definitions has possible false flags -inline bool has_default_flag_values(const std::string &flags) { - return (flags.find_first_of("{!") != std::string::npos); -} - -inline void remove_default_flag_values(std::string &flags) { - auto loc = flags.find_first_of('{', 2); - while(loc != std::string::npos) { - auto finish = flags.find_first_of("},", loc + 1); - if((finish != std::string::npos) && (flags[finish] == '}')) { - flags.erase(flags.begin() + static_cast(loc), - flags.begin() + static_cast(finish) + 1); - } - loc = flags.find_first_of('{', loc + 1); - } - flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end()); -} - -/// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores -inline std::ptrdiff_t find_member(std::string name, - const std::vector names, - bool ignore_case = false, - bool ignore_underscore = false) { - auto it = std::end(names); - if(ignore_case) { - if(ignore_underscore) { - name = detail::to_lower(detail::remove_underscore(name)); - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { - return detail::to_lower(detail::remove_underscore(local_name)) == name; - }); - } else { - name = detail::to_lower(name); - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { - return detail::to_lower(local_name) == name; - }); - } - - } else if(ignore_underscore) { - name = detail::remove_underscore(name); - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { - return detail::remove_underscore(local_name) == name; - }); - } else { - it = std::find(std::begin(names), std::end(names), name); - } - - return (it != std::end(names)) ? (it - std::begin(names)) : (-1); -} - -/// Find a trigger string and call a modify callable function that takes the current string and starting position of the -/// trigger and returns the position in the string to search for the next trigger string -template inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) { - std::size_t start_pos = 0; - while((start_pos = str.find(trigger, start_pos)) != std::string::npos) { - start_pos = modify(str, start_pos); - } - return str; -} - -/// Split a string '"one two" "three"' into 'one two', 'three' -/// Quote characters can be ` ' or " -inline std::vector split_up(std::string str, char delimiter = '\0') { - - const std::string delims("\'\"`"); - auto find_ws = [delimiter](char ch) { - return (delimiter == '\0') ? (std::isspace(ch, std::locale()) != 0) : (ch == delimiter); - }; - trim(str); - - std::vector output; - bool embeddedQuote = false; - char keyChar = ' '; - while(!str.empty()) { - if(delims.find_first_of(str[0]) != std::string::npos) { - keyChar = str[0]; - auto end = str.find_first_of(keyChar, 1); - while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes - end = str.find_first_of(keyChar, end + 1); - embeddedQuote = true; - } - if(end != std::string::npos) { - output.push_back(str.substr(1, end - 1)); - if(end + 2 < str.size()) { - str = str.substr(end + 2); - } else { - str.clear(); - } - - } else { - output.push_back(str.substr(1)); - str = ""; - } - } else { - auto it = std::find_if(std::begin(str), std::end(str), find_ws); - if(it != std::end(str)) { - std::string value = std::string(str.begin(), it); - output.push_back(value); - str = std::string(it + 1, str.end()); - } else { - output.push_back(str); - str = ""; - } - } - // transform any embedded quotes into the regular character - if(embeddedQuote) { - output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar)); - embeddedQuote = false; - } - trim(str); - } - return output; -} - -/// This function detects an equal or colon followed by an escaped quote after an argument -/// then modifies the string to replace the equality with a space. This is needed -/// to allow the split up function to work properly and is intended to be used with the find_and_modify function -/// the return value is the offset+1 which is required by the find_and_modify function. -inline std::size_t escape_detect(std::string &str, std::size_t offset) { - auto next = str[offset + 1]; - if((next == '\"') || (next == '\'') || (next == '`')) { - auto astart = str.find_last_of("-/ \"\'`", offset - 1); - if(astart != std::string::npos) { - if(str[astart] == ((str[offset] == '=') ? '-' : '/')) - str[offset] = ' '; // interpret this as a space so the split_up works properly - } - } - return offset + 1; -} - -/// Add quotes if the string contains spaces -inline std::string &add_quotes_if_needed(std::string &str) { - if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) { - char quote = str.find('"') < str.find('\'') ? '\'' : '"'; - if(str.find(' ') != std::string::npos) { - str.insert(0, 1, quote); - str.append(1, quote); - } - } - return str; -} - -} // namespace detail - - - - -// Use one of these on all error classes. -// These are temporary and are undef'd at the end of this file. -#define CLI11_ERROR_DEF(parent, name) \ - protected: \ - name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \ - name(std::string ename, std::string msg, ExitCodes exit_code) \ - : parent(std::move(ename), std::move(msg), exit_code) {} \ - \ - public: \ - name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \ - name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {} - -// This is added after the one above if a class is used directly and builds its own message -#define CLI11_ERROR_SIMPLE(name) \ - explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {} - -/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, -/// int values from e.get_error_code(). -enum class ExitCodes { - Success = 0, - IncorrectConstruction = 100, - BadNameString, - OptionAlreadyAdded, - FileError, - ConversionError, - ValidationError, - RequiredError, - RequiresError, - ExcludesError, - ExtrasError, - ConfigError, - InvalidError, - HorribleError, - OptionNotFound, - ArgumentMismatch, - BaseClass = 127 -}; - -// Error definitions - -/// @defgroup error_group Errors -/// @brief Errors thrown by CLI11 -/// -/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors. -/// @{ - -/// All errors derive from this one -class Error : public std::runtime_error { - int actual_exit_code; - std::string error_name{"Error"}; - - public: - int get_exit_code() const { return actual_exit_code; } - - std::string get_name() const { return error_name; } - - Error(std::string name, std::string msg, int exit_code = static_cast(ExitCodes::BaseClass)) - : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {} - - Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast(exit_code)) {} -}; - -// Note: Using Error::Error constructors does not work on GCC 4.7 - -/// Construction errors (not in parsing) -class ConstructionError : public Error { - CLI11_ERROR_DEF(Error, ConstructionError) -}; - -/// Thrown when an option is set to conflicting values (non-vector and multi args, for example) -class IncorrectConstruction : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) - CLI11_ERROR_SIMPLE(IncorrectConstruction) - static IncorrectConstruction PositionalFlag(std::string name) { - return IncorrectConstruction(name + ": Flags cannot be positional"); - } - static IncorrectConstruction Set0Opt(std::string name) { - return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead"); - } - static IncorrectConstruction SetFlag(std::string name) { - return IncorrectConstruction(name + ": Cannot set an expected number for flags"); - } - static IncorrectConstruction ChangeNotVector(std::string name) { - return IncorrectConstruction(name + ": You can only change the expected arguments for vectors"); - } - static IncorrectConstruction AfterMultiOpt(std::string name) { - return IncorrectConstruction( - name + ": You can't change expected arguments after you've changed the multi option policy!"); - } - static IncorrectConstruction MissingOption(std::string name) { - return IncorrectConstruction("Option " + name + " is not defined"); - } - static IncorrectConstruction MultiOptionPolicy(std::string name) { - return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options"); - } -}; - -/// Thrown on construction of a bad name -class BadNameString : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, BadNameString) - CLI11_ERROR_SIMPLE(BadNameString) - static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); } - static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); } - static BadNameString DashesOnly(std::string name) { - return BadNameString("Must have a name, not just dashes: " + name); - } - static BadNameString MultiPositionalNames(std::string name) { - return BadNameString("Only one positional name allowed, remove: " + name); - } -}; - -/// Thrown when an option already exists -class OptionAlreadyAdded : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) - explicit OptionAlreadyAdded(std::string name) - : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {} - static OptionAlreadyAdded Requires(std::string name, std::string other) { - return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded); - } - static OptionAlreadyAdded Excludes(std::string name, std::string other) { - return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded); - } -}; - -// Parsing errors - -/// Anything that can error in Parse -class ParseError : public Error { - CLI11_ERROR_DEF(Error, ParseError) -}; - -// Not really "errors" - -/// This is a successful completion on parsing, supposed to exit -class Success : public ParseError { - CLI11_ERROR_DEF(ParseError, Success) - Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {} -}; - -/// -h or --help on command line -class CallForHelp : public Success { - CLI11_ERROR_DEF(Success, CallForHelp) - CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} -}; - -/// Usually something like --help-all on command line -class CallForAllHelp : public Success { - CLI11_ERROR_DEF(Success, CallForAllHelp) - CallForAllHelp() - : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} -}; - -/// -v or --version on command line -class CallForVersion : public Success { - CLI11_ERROR_DEF(Success, CallForVersion) - CallForVersion() - : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} -}; - -/// Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code. -class RuntimeError : public ParseError { - CLI11_ERROR_DEF(ParseError, RuntimeError) - explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} -}; - -/// Thrown when parsing an INI file and it is missing -class FileError : public ParseError { - CLI11_ERROR_DEF(ParseError, FileError) - CLI11_ERROR_SIMPLE(FileError) - static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); } -}; - -/// Thrown when conversion call back fails, such as when an int fails to coerce to a string -class ConversionError : public ParseError { - CLI11_ERROR_DEF(ParseError, ConversionError) - CLI11_ERROR_SIMPLE(ConversionError) - ConversionError(std::string member, std::string name) - : ConversionError("The value " + member + " is not an allowed value for " + name) {} - ConversionError(std::string name, std::vector results) - : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {} - static ConversionError TooManyInputsFlag(std::string name) { - return ConversionError(name + ": too many inputs for a flag"); - } - static ConversionError TrueFalse(std::string name) { - return ConversionError(name + ": Should be true/false or a number"); - } -}; - -/// Thrown when validation of results fails -class ValidationError : public ParseError { - CLI11_ERROR_DEF(ParseError, ValidationError) - CLI11_ERROR_SIMPLE(ValidationError) - explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {} -}; - -/// Thrown when a required option is missing -class RequiredError : public ParseError { - CLI11_ERROR_DEF(ParseError, RequiredError) - explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {} - static RequiredError Subcommand(std::size_t min_subcom) { - if(min_subcom == 1) { - return RequiredError("A subcommand"); - } - return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", - ExitCodes::RequiredError); - } - static RequiredError - Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) { - if((min_option == 1) && (max_option == 1) && (used == 0)) - return RequiredError("Exactly 1 option from [" + option_list + "]"); - if((min_option == 1) && (max_option == 1) && (used > 1)) { - return RequiredError("Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) + - " were given", - ExitCodes::RequiredError); - } - if((min_option == 1) && (used == 0)) - return RequiredError("At least 1 option from [" + option_list + "]"); - if(used < min_option) { - return RequiredError("Requires at least " + std::to_string(min_option) + " options used and only " + - std::to_string(used) + "were given from [" + option_list + "]", - ExitCodes::RequiredError); - } - if(max_option == 1) - return RequiredError("Requires at most 1 options be given from [" + option_list + "]", - ExitCodes::RequiredError); - - return RequiredError("Requires at most " + std::to_string(max_option) + " options be used and " + - std::to_string(used) + "were given from [" + option_list + "]", - ExitCodes::RequiredError); - } -}; - -/// Thrown when the wrong number of arguments has been received -class ArgumentMismatch : public ParseError { - CLI11_ERROR_DEF(ParseError, ArgumentMismatch) - CLI11_ERROR_SIMPLE(ArgumentMismatch) - ArgumentMismatch(std::string name, int expected, std::size_t received) - : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name + - ", got " + std::to_string(received)) - : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + - ", got " + std::to_string(received)), - ExitCodes::ArgumentMismatch) {} - - static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) { - return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " + - std::to_string(received)); - } - static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) { - return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " + - std::to_string(received)); - } - static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) { - return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing"); - } - static ArgumentMismatch FlagOverride(std::string name) { - return ArgumentMismatch(name + " was given a disallowed flag override"); - } - static ArgumentMismatch PartialType(std::string name, int num, std::string type) { - return ArgumentMismatch(name + ": " + type + " only partially specified: " + std::to_string(num) + - " required for each element"); - } -}; - -/// Thrown when a requires option is missing -class RequiresError : public ParseError { - CLI11_ERROR_DEF(ParseError, RequiresError) - RequiresError(std::string curname, std::string subname) - : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {} -}; - -/// Thrown when an excludes option is present -class ExcludesError : public ParseError { - CLI11_ERROR_DEF(ParseError, ExcludesError) - ExcludesError(std::string curname, std::string subname) - : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {} -}; - -/// Thrown when too many positionals or options are found -class ExtrasError : public ParseError { - CLI11_ERROR_DEF(ParseError, ExtrasError) - explicit ExtrasError(std::vector args) - : ExtrasError((args.size() > 1 ? "The following arguments were not expected: " - : "The following argument was not expected: ") + - detail::rjoin(args, " "), - ExitCodes::ExtrasError) {} - ExtrasError(const std::string &name, std::vector args) - : ExtrasError(name, - (args.size() > 1 ? "The following arguments were not expected: " - : "The following argument was not expected: ") + - detail::rjoin(args, " "), - ExitCodes::ExtrasError) {} -}; - -/// Thrown when extra values are found in an INI file -class ConfigError : public ParseError { - CLI11_ERROR_DEF(ParseError, ConfigError) - CLI11_ERROR_SIMPLE(ConfigError) - static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); } - static ConfigError NotConfigurable(std::string item) { - return ConfigError(item + ": This option is not allowed in a configuration file"); - } -}; - -/// Thrown when validation fails before parsing -class InvalidError : public ParseError { - CLI11_ERROR_DEF(ParseError, InvalidError) - explicit InvalidError(std::string name) - : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) { - } -}; - -/// This is just a safety check to verify selection and parsing match - you should not ever see it -/// Strings are directly added to this error, but again, it should never be seen. -class HorribleError : public ParseError { - CLI11_ERROR_DEF(ParseError, HorribleError) - CLI11_ERROR_SIMPLE(HorribleError) -}; - -// After parsing - -/// Thrown when counting a non-existent option -class OptionNotFound : public Error { - CLI11_ERROR_DEF(Error, OptionNotFound) - explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} -}; - -#undef CLI11_ERROR_DEF -#undef CLI11_ERROR_SIMPLE - -/// @} - - - - -// Type tools - -// Utilities for type enabling -namespace detail { -// Based generally on https://rmf.io/cxx11/almost-static-if -/// Simple empty scoped class -enum class enabler {}; - -/// An instance to use in EnableIf -constexpr enabler dummy = {}; -} // namespace detail - -/// A copy of enable_if_t from C++14, compatible with C++11. -/// -/// We could check to see if C++14 is being used, but it does not hurt to redefine this -/// (even Google does this: https://github.com/google/skia/blob/main/include/private/SkTLogic.h) -/// It is not in the std namespace anyway, so no harm done. -template using enable_if_t = typename std::enable_if::type; - -/// A copy of std::void_t from C++17 (helper for C++11 and C++14) -template struct make_void { using type = void; }; - -/// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine -template using void_t = typename make_void::type; - -/// A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine -template using conditional_t = typename std::conditional::type; - -/// Check to see if something is bool (fail check by default) -template struct is_bool : std::false_type {}; - -/// Check to see if something is bool (true if actually a bool) -template <> struct is_bool : std::true_type {}; - -/// Check to see if something is a shared pointer -template struct is_shared_ptr : std::false_type {}; - -/// Check to see if something is a shared pointer (True if really a shared pointer) -template struct is_shared_ptr> : std::true_type {}; - -/// Check to see if something is a shared pointer (True if really a shared pointer) -template struct is_shared_ptr> : std::true_type {}; - -/// Check to see if something is copyable pointer -template struct is_copyable_ptr { - static bool const value = is_shared_ptr::value || std::is_pointer::value; -}; - -/// This can be specialized to override the type deduction for IsMember. -template struct IsMemberType { using type = T; }; - -/// The main custom type needed here is const char * should be a string. -template <> struct IsMemberType { using type = std::string; }; - -namespace detail { - -// These are utilities for IsMember and other transforming objects - -/// Handy helper to access the element_type generically. This is not part of is_copyable_ptr because it requires that -/// pointer_traits be valid. - -/// not a pointer -template struct element_type { using type = T; }; - -template struct element_type::value>::type> { - using type = typename std::pointer_traits::element_type; -}; - -/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of -/// the container -template struct element_value_type { using type = typename element_type::type::value_type; }; - -/// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing. -template struct pair_adaptor : std::false_type { - using value_type = typename T::value_type; - using first_type = typename std::remove_const::type; - using second_type = typename std::remove_const::type; - - /// Get the first value (really just the underlying value) - template static auto first(Q &&pair_value) -> decltype(std::forward(pair_value)) { - return std::forward(pair_value); - } - /// Get the second value (really just the underlying value) - template static auto second(Q &&pair_value) -> decltype(std::forward(pair_value)) { - return std::forward(pair_value); - } -}; - -/// Adaptor for map-like structure (true version, must have key_type and mapped_type). -/// This wraps a mapped container in a few utilities access it in a general way. -template -struct pair_adaptor< - T, - conditional_t, void>> - : std::true_type { - using value_type = typename T::value_type; - using first_type = typename std::remove_const::type; - using second_type = typename std::remove_const::type; - - /// Get the first value (really just the underlying value) - template static auto first(Q &&pair_value) -> decltype(std::get<0>(std::forward(pair_value))) { - return std::get<0>(std::forward(pair_value)); - } - /// Get the second value (really just the underlying value) - template static auto second(Q &&pair_value) -> decltype(std::get<1>(std::forward(pair_value))) { - return std::get<1>(std::forward(pair_value)); - } -}; - -// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a Wnarrowing warning -// in the unevaluated context even if the function that was using this wasn't used. The standard says narrowing in -// brace initialization shouldn't be allowed but for backwards compatibility gcc allows it in some contexts. It is a -// little fuzzy what happens in template constructs and I think that was something GCC took a little while to work out. -// But regardless some versions of gcc generate a warning when they shouldn't from the following code so that should be -// suppressed -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnarrowing" -#endif -// check for constructibility from a specific type and copy assignable used in the parse detection -template class is_direct_constructible { - template - static auto test(int, std::true_type) -> decltype( -// NVCC warns about narrowing conversions here -#ifdef __CUDACC__ -#pragma diag_suppress 2361 -#endif - TT { std::declval() } -#ifdef __CUDACC__ -#pragma diag_default 2361 -#endif - , - std::is_move_assignable()); - - template static auto test(int, std::false_type) -> std::false_type; - - template static auto test(...) -> std::false_type; - - public: - static constexpr bool value = decltype(test(0, typename std::is_constructible::type()))::value; -}; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -// Check for output streamability -// Based on https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream - -template class is_ostreamable { - template - static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); - - template static auto test(...) -> std::false_type; - - public: - static constexpr bool value = decltype(test(0))::value; -}; - -/// Check for input streamability -template class is_istreamable { - template - static auto test(int) -> decltype(std::declval() >> std::declval(), std::true_type()); - - template static auto test(...) -> std::false_type; - - public: - static constexpr bool value = decltype(test(0))::value; -}; - -/// Check for complex -template class is_complex { - template - static auto test(int) -> decltype(std::declval().real(), std::declval().imag(), std::true_type()); - - template static auto test(...) -> std::false_type; - - public: - static constexpr bool value = decltype(test(0))::value; -}; - -/// Templated operation to get a value from a stream -template ::value, detail::enabler> = detail::dummy> -bool from_stream(const std::string &istring, T &obj) { - std::istringstream is; - is.str(istring); - is >> obj; - return !is.fail() && !is.rdbuf()->in_avail(); -} - -template ::value, detail::enabler> = detail::dummy> -bool from_stream(const std::string & /*istring*/, T & /*obj*/) { - return false; -} - -// check to see if an object is a mutable container (fail by default) -template struct is_mutable_container : std::false_type {}; - -/// type trait to test if a type is a mutable container meaning it has a value_type, it has an iterator, a clear, and -/// end methods and an insert function. And for our purposes we exclude std::string and types that can be constructed -/// from a std::string -template -struct is_mutable_container< - T, - conditional_t().end()), - decltype(std::declval().clear()), - decltype(std::declval().insert(std::declval().end())>(), - std::declval()))>, - void>> - : public conditional_t::value, std::false_type, std::true_type> {}; - -// check to see if an object is a mutable container (fail by default) -template struct is_readable_container : std::false_type {}; - -/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an end -/// methods and an insert function. And for our purposes we exclude std::string and types that can be constructed from -/// a std::string -template -struct is_readable_container< - T, - conditional_t().end()), decltype(std::declval().begin())>, void>> - : public std::true_type {}; - -// check to see if an object is a wrapper (fail by default) -template struct is_wrapper : std::false_type {}; - -// check if an object is a wrapper (it has a value_type defined) -template -struct is_wrapper, void>> : public std::true_type {}; - -// Check for tuple like types, as in classes with a tuple_size type trait -template class is_tuple_like { - template - // static auto test(int) - // -> decltype(std::conditional<(std::tuple_size::value > 0), std::true_type, std::false_type>::type()); - static auto test(int) -> decltype(std::tuple_size::type>::value, std::true_type{}); - template static auto test(...) -> std::false_type; - - public: - static constexpr bool value = decltype(test(0))::value; -}; - -/// Convert an object to a string (directly forward if this can become a string) -template ::value, detail::enabler> = detail::dummy> -auto to_string(T &&value) -> decltype(std::forward(value)) { - return std::forward(value); -} - -/// Construct a string from the object -template ::value && !std::is_convertible::value, - detail::enabler> = detail::dummy> -std::string to_string(const T &value) { - return std::string(value); -} - -/// Convert an object to a string (streaming must be supported for that type) -template ::value && !std::is_constructible::value && - is_ostreamable::value, - detail::enabler> = detail::dummy> -std::string to_string(T &&value) { - std::stringstream stream; - stream << value; - return stream.str(); -} - -/// If conversion is not supported, return an empty string (streaming is not supported for that type) -template ::value && !is_ostreamable::value && - !is_readable_container::type>::value, - detail::enabler> = detail::dummy> -std::string to_string(T &&) { - return std::string{}; -} - -/// convert a readable container to a string -template ::value && !is_ostreamable::value && - is_readable_container::value, - detail::enabler> = detail::dummy> -std::string to_string(T &&variable) { - auto cval = variable.begin(); - auto end = variable.end(); - if(cval == end) { - return std::string("{}"); - } - std::vector defaults; - while(cval != end) { - defaults.emplace_back(CLI::detail::to_string(*cval)); - ++cval; - } - return std::string("[" + detail::join(defaults) + "]"); -} - -/// special template overload -template ::value, detail::enabler> = detail::dummy> -auto checked_to_string(T &&value) -> decltype(to_string(std::forward(value))) { - return to_string(std::forward(value)); -} - -/// special template overload -template ::value, detail::enabler> = detail::dummy> -std::string checked_to_string(T &&) { - return std::string{}; -} -/// get a string as a convertible value for arithmetic types -template ::value, detail::enabler> = detail::dummy> -std::string value_string(const T &value) { - return std::to_string(value); -} -/// get a string as a convertible value for enumerations -template ::value, detail::enabler> = detail::dummy> -std::string value_string(const T &value) { - return std::to_string(static_cast::type>(value)); -} -/// for other types just use the regular to_string function -template ::value && !std::is_arithmetic::value, detail::enabler> = detail::dummy> -auto value_string(const T &value) -> decltype(to_string(value)) { - return to_string(value); -} - -/// template to get the underlying value type if it exists or use a default -template struct wrapped_type { using type = def; }; - -/// Type size for regular object types that do not look like a tuple -template struct wrapped_type::value>::type> { - using type = typename T::value_type; -}; - -/// This will only trigger for actual void type -template struct type_count_base { static const int value{0}; }; - -/// Type size for regular object types that do not look like a tuple -template -struct type_count_base::value && !is_mutable_container::value && - !std::is_void::value>::type> { - static constexpr int value{1}; -}; - -/// the base tuple size -template -struct type_count_base::value && !is_mutable_container::value>::type> { - static constexpr int value{std::tuple_size::value}; -}; - -/// Type count base for containers is the type_count_base of the individual element -template struct type_count_base::value>::type> { - static constexpr int value{type_count_base::value}; -}; - -/// Set of overloads to get the type size of an object - -/// forward declare the subtype_count structure -template struct subtype_count; - -/// forward declare the subtype_count_min structure -template struct subtype_count_min; - -/// This will only trigger for actual void type -template struct type_count { static const int value{0}; }; - -/// Type size for regular object types that do not look like a tuple -template -struct type_count::value && !is_tuple_like::value && !is_complex::value && - !std::is_void::value>::type> { - static constexpr int value{1}; -}; - -/// Type size for complex since it sometimes looks like a wrapper -template struct type_count::value>::type> { - static constexpr int value{2}; -}; - -/// Type size of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) -template struct type_count::value>::type> { - static constexpr int value{subtype_count::value}; -}; - -/// Type size of types that are wrappers,except containers complex and tuples(which can also be wrappers sometimes) -template -struct type_count::value && !is_complex::value && !is_tuple_like::value && - !is_mutable_container::value>::type> { - static constexpr int value{type_count::value}; -}; - -/// 0 if the index > tuple size -template -constexpr typename std::enable_if::value, int>::type tuple_type_size() { - return 0; -} - -/// Recursively generate the tuple type name -template - constexpr typename std::enable_if < I::value, int>::type tuple_type_size() { - return subtype_count::type>::value + tuple_type_size(); -} - -/// Get the type size of the sum of type sizes for all the individual tuple types -template struct type_count::value>::type> { - static constexpr int value{tuple_type_size()}; -}; - -/// definition of subtype count -template struct subtype_count { - static constexpr int value{is_mutable_container::value ? expected_max_vector_size : type_count::value}; -}; - -/// This will only trigger for actual void type -template struct type_count_min { static const int value{0}; }; - -/// Type size for regular object types that do not look like a tuple -template -struct type_count_min< - T, - typename std::enable_if::value && !is_tuple_like::value && !is_wrapper::value && - !is_complex::value && !std::is_void::value>::type> { - static constexpr int value{type_count::value}; -}; - -/// Type size for complex since it sometimes looks like a wrapper -template struct type_count_min::value>::type> { - static constexpr int value{1}; -}; - -/// Type size min of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) -template -struct type_count_min< - T, - typename std::enable_if::value && !is_complex::value && !is_tuple_like::value>::type> { - static constexpr int value{subtype_count_min::value}; -}; - -/// 0 if the index > tuple size -template -constexpr typename std::enable_if::value, int>::type tuple_type_size_min() { - return 0; -} - -/// Recursively generate the tuple type name -template - constexpr typename std::enable_if < I::value, int>::type tuple_type_size_min() { - return subtype_count_min::type>::value + tuple_type_size_min(); -} - -/// Get the type size of the sum of type sizes for all the individual tuple types -template struct type_count_min::value>::type> { - static constexpr int value{tuple_type_size_min()}; -}; - -/// definition of subtype count -template struct subtype_count_min { - static constexpr int value{is_mutable_container::value - ? ((type_count::value < expected_max_vector_size) ? type_count::value : 0) - : type_count_min::value}; -}; - -/// This will only trigger for actual void type -template struct expected_count { static const int value{0}; }; - -/// For most types the number of expected items is 1 -template -struct expected_count::value && !is_wrapper::value && - !std::is_void::value>::type> { - static constexpr int value{1}; -}; -/// number of expected items in a vector -template struct expected_count::value>::type> { - static constexpr int value{expected_max_vector_size}; -}; - -/// number of expected items in a vector -template -struct expected_count::value && is_wrapper::value>::type> { - static constexpr int value{expected_count::value}; -}; - -// Enumeration of the different supported categorizations of objects -enum class object_category : int { - char_value = 1, - integral_value = 2, - unsigned_integral = 4, - enumeration = 6, - boolean_value = 8, - floating_point = 10, - number_constructible = 12, - double_constructible = 14, - integer_constructible = 16, - // string like types - string_assignable = 23, - string_constructible = 24, - other = 45, - // special wrapper or container types - wrapper_value = 50, - complex_number = 60, - tuple_value = 70, - container_value = 80, - -}; - -/// Set of overloads to classify an object according to type - -/// some type that is not otherwise recognized -template struct classify_object { - static constexpr object_category value{object_category::other}; -}; - -/// Signed integers -template -struct classify_object< - T, - typename std::enable_if::value && !std::is_same::value && std::is_signed::value && - !is_bool::value && !std::is_enum::value>::type> { - static constexpr object_category value{object_category::integral_value}; -}; - -/// Unsigned integers -template -struct classify_object::value && std::is_unsigned::value && - !std::is_same::value && !is_bool::value>::type> { - static constexpr object_category value{object_category::unsigned_integral}; -}; - -/// single character values -template -struct classify_object::value && !std::is_enum::value>::type> { - static constexpr object_category value{object_category::char_value}; -}; - -/// Boolean values -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::boolean_value}; -}; - -/// Floats -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::floating_point}; -}; - -/// String and similar direct assignment -template -struct classify_object::value && !std::is_integral::value && - std::is_assignable::value>::type> { - static constexpr object_category value{object_category::string_assignable}; -}; - -/// String and similar constructible and copy assignment -template -struct classify_object< - T, - typename std::enable_if::value && !std::is_integral::value && - !std::is_assignable::value && (type_count::value == 1) && - std::is_constructible::value>::type> { - static constexpr object_category value{object_category::string_constructible}; -}; - -/// Enumerations -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::enumeration}; -}; - -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::complex_number}; -}; - -/// Handy helper to contain a bunch of checks that rule out many common types (integers, string like, floating point, -/// vectors, and enumerations -template struct uncommon_type { - using type = typename std::conditional::value && !std::is_integral::value && - !std::is_assignable::value && - !std::is_constructible::value && !is_complex::value && - !is_mutable_container::value && !std::is_enum::value, - std::true_type, - std::false_type>::type; - static constexpr bool value = type::value; -}; - -/// wrapper type -template -struct classify_object::value && is_wrapper::value && - !is_tuple_like::value && uncommon_type::value)>::type> { - static constexpr object_category value{object_category::wrapper_value}; -}; - -/// Assignable from double or int -template -struct classify_object::value && type_count::value == 1 && - !is_wrapper::value && is_direct_constructible::value && - is_direct_constructible::value>::type> { - static constexpr object_category value{object_category::number_constructible}; -}; - -/// Assignable from int -template -struct classify_object::value && type_count::value == 1 && - !is_wrapper::value && !is_direct_constructible::value && - is_direct_constructible::value>::type> { - static constexpr object_category value{object_category::integer_constructible}; -}; - -/// Assignable from double -template -struct classify_object::value && type_count::value == 1 && - !is_wrapper::value && is_direct_constructible::value && - !is_direct_constructible::value>::type> { - static constexpr object_category value{object_category::double_constructible}; -}; - -/// Tuple type -template -struct classify_object< - T, - typename std::enable_if::value && - ((type_count::value >= 2 && !is_wrapper::value) || - (uncommon_type::value && !is_direct_constructible::value && - !is_direct_constructible::value))>::type> { - static constexpr object_category value{object_category::tuple_value}; - // the condition on this class requires it be like a tuple, but on some compilers (like Xcode) tuples can be - // constructed from just the first element so tuples of can be constructed from a string, which - // could lead to issues so there are two variants of the condition, the first isolates things with a type size >=2 - // mainly to get tuples on Xcode with the exception of wrappers, the second is the main one and just separating out - // those cases that are caught by other object classifications -}; - -/// container type -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::container_value}; -}; - -// Type name print - -/// Was going to be based on -/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template -/// But this is cleaner and works better in this case - -template ::value == object_category::char_value, detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "CHAR"; -} - -template ::value == object_category::integral_value || - classify_object::value == object_category::integer_constructible, - detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "INT"; -} - -template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "UINT"; -} - -template ::value == object_category::floating_point || - classify_object::value == object_category::number_constructible || - classify_object::value == object_category::double_constructible, - detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "FLOAT"; -} - -/// Print name for enumeration types -template ::value == object_category::enumeration, detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "ENUM"; -} - -/// Print name for enumeration types -template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "BOOLEAN"; -} - -/// Print name for enumeration types -template ::value == object_category::complex_number, detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "COMPLEX"; -} - -/// Print for all other types -template ::value >= object_category::string_assignable && - classify_object::value <= object_category::other, - detail::enabler> = detail::dummy> -constexpr const char *type_name() { - return "TEXT"; -} -/// typename for tuple value -template ::value == object_category::tuple_value && type_count_base::value >= 2, - detail::enabler> = detail::dummy> -std::string type_name(); // forward declaration - -/// Generate type name for a wrapper or container value -template ::value == object_category::container_value || - classify_object::value == object_category::wrapper_value, - detail::enabler> = detail::dummy> -std::string type_name(); // forward declaration - -/// Print name for single element tuple types -template ::value == object_category::tuple_value && type_count_base::value == 1, - detail::enabler> = detail::dummy> -inline std::string type_name() { - return type_name::type>::type>(); -} - -/// Empty string if the index > tuple size -template -inline typename std::enable_if::value, std::string>::type tuple_name() { - return std::string{}; -} - -/// Recursively generate the tuple type name -template -inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_name() { - std::string str = std::string(type_name::type>::type>()) + - ',' + tuple_name(); - if(str.back() == ',') - str.pop_back(); - return str; -} - -/// Print type name for tuples with 2 or more elements -template ::value == object_category::tuple_value && type_count_base::value >= 2, - detail::enabler>> -inline std::string type_name() { - auto tname = std::string(1, '[') + tuple_name(); - tname.push_back(']'); - return tname; -} - -/// get the type name for a type that has a value_type member -template ::value == object_category::container_value || - classify_object::value == object_category::wrapper_value, - detail::enabler>> -inline std::string type_name() { - return type_name(); -} - -// Lexical cast - -/// Convert to an unsigned integral -template ::value, detail::enabler> = detail::dummy> -bool integral_conversion(const std::string &input, T &output) noexcept { - if(input.empty()) { - return false; - } - char *val = nullptr; - std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); - output = static_cast(output_ll); - if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { - return true; - } - val = nullptr; - std::int64_t output_sll = std::strtoll(input.c_str(), &val, 0); - if(val == (input.c_str() + input.size())) { - output = (output_sll < 0) ? static_cast(0) : static_cast(output_sll); - return (static_cast(output) == output_sll); - } - return false; -} - -/// Convert to a signed integral -template ::value, detail::enabler> = detail::dummy> -bool integral_conversion(const std::string &input, T &output) noexcept { - if(input.empty()) { - return false; - } - char *val = nullptr; - std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); - output = static_cast(output_ll); - if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { - return true; - } - if(input == "true") { - // this is to deal with a few oddities with flags and wrapper int types - output = static_cast(1); - return true; - } - return false; -} - -/// Convert a flag into an integer value typically binary flags -inline std::int64_t to_flag_value(std::string val) { - static const std::string trueString("true"); - static const std::string falseString("false"); - if(val == trueString) { - return 1; - } - if(val == falseString) { - return -1; - } - val = detail::to_lower(val); - std::int64_t ret; - if(val.size() == 1) { - if(val[0] >= '1' && val[0] <= '9') { - return (static_cast(val[0]) - '0'); - } - switch(val[0]) { - case '0': - case 'f': - case 'n': - case '-': - ret = -1; - break; - case 't': - case 'y': - case '+': - ret = 1; - break; - default: - throw std::invalid_argument("unrecognized character"); - } - return ret; - } - if(val == trueString || val == "on" || val == "yes" || val == "enable") { - ret = 1; - } else if(val == falseString || val == "off" || val == "no" || val == "disable") { - ret = -1; - } else { - ret = std::stoll(val); - } - return ret; -} - -/// Integer conversion -template ::value == object_category::integral_value || - classify_object::value == object_category::unsigned_integral, - detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - return integral_conversion(input, output); -} - -/// char values -template ::value == object_category::char_value, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - if(input.size() == 1) { - output = static_cast(input[0]); - return true; - } - return integral_conversion(input, output); -} - -/// Boolean values -template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - try { - auto out = to_flag_value(input); - output = (out > 0); - return true; - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - // if the number is out of the range of a 64 bit value then it is still a number and for this purpose is still - // valid all we care about the sign - output = (input[0] != '-'); - return true; - } -} - -/// Floats -template ::value == object_category::floating_point, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - if(input.empty()) { - return false; - } - char *val = nullptr; - auto output_ld = std::strtold(input.c_str(), &val); - output = static_cast(output_ld); - return val == (input.c_str() + input.size()); -} - -/// complex -template ::value == object_category::complex_number, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - using XC = typename wrapped_type::type; - XC x{0.0}, y{0.0}; - auto str1 = input; - bool worked = false; - auto nloc = str1.find_last_of("+-"); - if(nloc != std::string::npos && nloc > 0) { - worked = detail::lexical_cast(str1.substr(0, nloc), x); - str1 = str1.substr(nloc); - if(str1.back() == 'i' || str1.back() == 'j') - str1.pop_back(); - worked = worked && detail::lexical_cast(str1, y); - } else { - if(str1.back() == 'i' || str1.back() == 'j') { - str1.pop_back(); - worked = detail::lexical_cast(str1, y); - x = XC{0}; - } else { - worked = detail::lexical_cast(str1, x); - y = XC{0}; - } - } - if(worked) { - output = T{x, y}; - return worked; - } - return from_stream(input, output); -} - -/// String and similar direct assignment -template ::value == object_category::string_assignable, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - output = input; - return true; -} - -/// String and similar constructible and copy assignment -template < - typename T, - enable_if_t::value == object_category::string_constructible, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - output = T(input); - return true; -} - -/// Enumerations -template ::value == object_category::enumeration, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - typename std::underlying_type::type val; - if(!integral_conversion(input, val)) { - return false; - } - output = static_cast(val); - return true; -} - -/// wrapper types -template ::value == object_category::wrapper_value && - std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - typename T::value_type val; - if(lexical_cast(input, val)) { - output = val; - return true; - } - return from_stream(input, output); -} - -template ::value == object_category::wrapper_value && - !std::is_assignable::value && std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - typename T::value_type val; - if(lexical_cast(input, val)) { - output = T{val}; - return true; - } - return from_stream(input, output); -} - -/// Assignable from double or int -template < - typename T, - enable_if_t::value == object_category::number_constructible, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - int val; - if(integral_conversion(input, val)) { - output = T(val); - return true; - } else { - double dval; - if(lexical_cast(input, dval)) { - output = T{dval}; - return true; - } - } - return from_stream(input, output); -} - -/// Assignable from int -template < - typename T, - enable_if_t::value == object_category::integer_constructible, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - int val; - if(integral_conversion(input, val)) { - output = T(val); - return true; - } - return from_stream(input, output); -} - -/// Assignable from double -template < - typename T, - enable_if_t::value == object_category::double_constructible, detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - double val; - if(lexical_cast(input, val)) { - output = T{val}; - return true; - } - return from_stream(input, output); -} - -/// Non-string convertible from an int -template ::value == object_category::other && std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - int val; - if(integral_conversion(input, val)) { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4800) -#endif - // with Atomic this could produce a warning due to the conversion but if atomic gets here it is an old style - // so will most likely still work - output = val; -#ifdef _MSC_VER -#pragma warning(pop) -#endif - return true; - } - // LCOV_EXCL_START - // This version of cast is only used for odd cases in an older compilers the fail over - // from_stream is tested elsewhere an not relevant for coverage here - return from_stream(input, output); - // LCOV_EXCL_STOP -} - -/// Non-string parsable by a stream -template ::value == object_category::other && !std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_cast(const std::string &input, T &output) { - static_assert(is_istreamable::value, - "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it " - "is convertible from another type use the add_option(...) with XC being the known type"); - return from_stream(input, output); -} - -/// Assign a value through lexical cast operations -/// Strings can be empty so we need to do a little different -template ::value && - (classify_object::value == object_category::string_assignable || - classify_object::value == object_category::string_constructible), - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - return lexical_cast(input, output); -} - -/// Assign a value through lexical cast operations -template ::value && std::is_assignable::value && - classify_object::value != object_category::string_assignable && - classify_object::value != object_category::string_constructible, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - if(input.empty()) { - output = AssignTo{}; - return true; - } - - return lexical_cast(input, output); -} - -/// Assign a value through lexical cast operations -template ::value && !std::is_assignable::value && - classify_object::value == object_category::wrapper_value, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - if(input.empty()) { - typename AssignTo::value_type emptyVal{}; - output = emptyVal; - return true; - } - return lexical_cast(input, output); -} - -/// Assign a value through lexical cast operations for int compatible values -/// mainly for atomic operations on some compilers -template ::value && !std::is_assignable::value && - classify_object::value != object_category::wrapper_value && - std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - if(input.empty()) { - output = 0; - return true; - } - int val; - if(lexical_cast(input, val)) { - output = val; - return true; - } - return false; -} - -/// Assign a value converted from a string in lexical cast to the output value directly -template ::value && std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - ConvertTo val{}; - bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; - if(parse_result) { - output = val; - } - return parse_result; -} - -/// Assign a value from a lexical cast through constructing a value and move assigning it -template < - typename AssignTo, - typename ConvertTo, - enable_if_t::value && !std::is_assignable::value && - std::is_move_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, AssignTo &output) { - ConvertTo val{}; - bool parse_result = input.empty() ? true : lexical_cast(input, val); - if(parse_result) { - output = AssignTo(val); // use () form of constructor to allow some implicit conversions - } - return parse_result; -} - -/// primary lexical conversion operation, 1 string to 1 type of some kind -template ::value <= object_category::other && - classify_object::value <= object_category::wrapper_value, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - return lexical_assign(strings[0], output); -} - -/// Lexical conversion if there is only one element but the conversion type is for two, then call a two element -/// constructor -template ::value <= 2) && expected_count::value == 1 && - is_tuple_like::value && type_count_base::value == 2, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - // the remove const is to handle pair types coming from a container - typename std::remove_const::type>::type v1; - typename std::tuple_element<1, ConvertTo>::type v2; - bool retval = lexical_assign(strings[0], v1); - if(strings.size() > 1) { - retval = retval && lexical_assign(strings[1], v2); - } - if(retval) { - output = AssignTo{v1, v2}; - } - return retval; -} - -/// Lexical conversion of a container types of single elements -template ::value && is_mutable_container::value && - type_count::value == 1, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - output.erase(output.begin(), output.end()); - if(strings.size() == 1 && strings[0] == "{}") { - return true; - } - bool skip_remaining = false; - if(strings.size() == 2 && strings[0] == "{}" && is_separator(strings[1])) { - skip_remaining = true; - } - for(const auto &elem : strings) { - typename AssignTo::value_type out; - bool retval = lexical_assign(elem, out); - if(!retval) { - return false; - } - output.insert(output.end(), std::move(out)); - if(skip_remaining) { - break; - } - } - return (!output.empty()); -} - -/// Lexical conversion for complex types -template ::value, detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - - if(strings.size() >= 2 && !strings[1].empty()) { - using XC2 = typename wrapped_type::type; - XC2 x{0.0}, y{0.0}; - auto str1 = strings[1]; - if(str1.back() == 'i' || str1.back() == 'j') { - str1.pop_back(); - } - auto worked = detail::lexical_cast(strings[0], x) && detail::lexical_cast(str1, y); - if(worked) { - output = ConvertTo{x, y}; - } - return worked; - } else { - return lexical_assign(strings[0], output); - } -} - -/// Conversion to a vector type using a particular single type as the conversion type -template ::value && (expected_count::value == 1) && - (type_count::value == 1), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - bool retval = true; - output.clear(); - output.reserve(strings.size()); - for(const auto &elem : strings) { - - output.emplace_back(); - retval = retval && lexical_assign(elem, output.back()); - } - return (!output.empty()) && retval; -} - -// forward declaration - -/// Lexical conversion of a container types with conversion type of two elements -template ::value && is_mutable_container::value && - type_count_base::value == 2, - detail::enabler> = detail::dummy> -bool lexical_conversion(std::vector strings, AssignTo &output); - -/// Lexical conversion of a vector types with type_size >2 forward declaration -template ::value && is_mutable_container::value && - type_count_base::value != 2 && - ((type_count::value > 2) || - (type_count::value > type_count_base::value)), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output); - -/// Conversion for tuples -template ::value && is_tuple_like::value && - (type_count_base::value != type_count::value || - type_count::value > 2), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output); // forward declaration - -/// Conversion for operations where the assigned type is some class but the conversion is a mutable container or large -/// tuple -template ::value && !is_mutable_container::value && - classify_object::value != object_category::wrapper_value && - (is_mutable_container::value || type_count::value > 2), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - - if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { - ConvertTo val; - auto retval = lexical_conversion(strings, val); - output = AssignTo{val}; - return retval; - } - output = AssignTo{}; - return true; -} - -/// function template for converting tuples if the static Index is greater than the tuple size -template -inline typename std::enable_if<(I >= type_count_base::value), bool>::type -tuple_conversion(const std::vector &, AssignTo &) { - return true; -} - -/// Conversion of a tuple element where the type size ==1 and not a mutable container -template -inline typename std::enable_if::value && type_count::value == 1, bool>::type -tuple_type_conversion(std::vector &strings, AssignTo &output) { - auto retval = lexical_assign(strings[0], output); - strings.erase(strings.begin()); - return retval; -} - -/// Conversion of a tuple element where the type size !=1 but the size is fixed and not a mutable container -template -inline typename std::enable_if::value && (type_count::value > 1) && - type_count::value == type_count_min::value, - bool>::type -tuple_type_conversion(std::vector &strings, AssignTo &output) { - auto retval = lexical_conversion(strings, output); - strings.erase(strings.begin(), strings.begin() + type_count::value); - return retval; -} - -/// Conversion of a tuple element where the type is a mutable container or a type with different min and max type sizes -template -inline typename std::enable_if::value || - type_count::value != type_count_min::value, - bool>::type -tuple_type_conversion(std::vector &strings, AssignTo &output) { - - std::size_t index{subtype_count_min::value}; - const std::size_t mx_count{subtype_count::value}; - const std::size_t mx{(std::max)(mx_count, strings.size())}; - - while(index < mx) { - if(is_separator(strings[index])) { - break; - } - ++index; - } - bool retval = lexical_conversion( - std::vector(strings.begin(), strings.begin() + static_cast(index)), output); - strings.erase(strings.begin(), strings.begin() + static_cast(index) + 1); - return retval; -} - -/// Tuple conversion operation -template -inline typename std::enable_if<(I < type_count_base::value), bool>::type -tuple_conversion(std::vector strings, AssignTo &output) { - bool retval = true; - using ConvertToElement = typename std:: - conditional::value, typename std::tuple_element::type, ConvertTo>::type; - if(!strings.empty()) { - retval = retval && tuple_type_conversion::type, ConvertToElement>( - strings, std::get(output)); - } - retval = retval && tuple_conversion(std::move(strings), output); - return retval; -} - -/// Lexical conversion of a container types with tuple elements of size 2 -template ::value && is_mutable_container::value && - type_count_base::value == 2, - detail::enabler>> -bool lexical_conversion(std::vector strings, AssignTo &output) { - output.clear(); - while(!strings.empty()) { - - typename std::remove_const::type>::type v1; - typename std::tuple_element<1, typename ConvertTo::value_type>::type v2; - bool retval = tuple_type_conversion(strings, v1); - if(!strings.empty()) { - retval = retval && tuple_type_conversion(strings, v2); - } - if(retval) { - output.insert(output.end(), typename AssignTo::value_type{v1, v2}); - } else { - return false; - } - } - return (!output.empty()); -} - -/// lexical conversion of tuples with type count>2 or tuples of types of some element with a type size>=2 -template ::value && is_tuple_like::value && - (type_count_base::value != type_count::value || - type_count::value > 2), - detail::enabler>> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - static_assert( - !is_tuple_like::value || type_count_base::value == type_count_base::value, - "if the conversion type is defined as a tuple it must be the same size as the type you are converting to"); - return tuple_conversion(strings, output); -} - -/// Lexical conversion of a vector types for everything but tuples of two elements and types of size 1 -template ::value && is_mutable_container::value && - type_count_base::value != 2 && - ((type_count::value > 2) || - (type_count::value > type_count_base::value)), - detail::enabler>> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - bool retval = true; - output.clear(); - std::vector temp; - std::size_t ii{0}; - std::size_t icount{0}; - std::size_t xcm{type_count::value}; - auto ii_max = strings.size(); - while(ii < ii_max) { - temp.push_back(strings[ii]); - ++ii; - ++icount; - if(icount == xcm || is_separator(temp.back()) || ii == ii_max) { - if(static_cast(xcm) > type_count_min::value && is_separator(temp.back())) { - temp.pop_back(); - } - typename AssignTo::value_type temp_out; - retval = retval && - lexical_conversion(temp, temp_out); - temp.clear(); - if(!retval) { - return false; - } - output.insert(output.end(), std::move(temp_out)); - icount = 0; - } - } - return retval; -} - -/// conversion for wrapper types -template ::value == object_category::wrapper_value && - std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - if(strings.empty() || strings.front().empty()) { - output = ConvertTo{}; - return true; - } - typename ConvertTo::value_type val; - if(lexical_conversion(strings, val)) { - output = ConvertTo{val}; - return true; - } - return false; -} - -/// conversion for wrapper types -template ::value == object_category::wrapper_value && - !std::is_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, AssignTo &output) { - using ConvertType = typename ConvertTo::value_type; - if(strings.empty() || strings.front().empty()) { - output = ConvertType{}; - return true; - } - ConvertType val; - if(lexical_conversion(strings, val)) { - output = val; - return true; - } - return false; -} - -/// Sum a vector of strings -inline std::string sum_string_vector(const std::vector &values) { - double val{0.0}; - bool fail{false}; - std::string output; - for(const auto &arg : values) { - double tv{0.0}; - auto comp = detail::lexical_cast(arg, tv); - if(!comp) { - try { - tv = static_cast(detail::to_flag_value(arg)); - } catch(const std::exception &) { - fail = true; - break; - } - } - val += tv; - } - if(fail) { - for(const auto &arg : values) { - output.append(arg); - } - } else { - if(val <= static_cast(std::numeric_limits::min()) || - val >= static_cast(std::numeric_limits::max()) || - val == static_cast(val)) { - output = detail::value_string(static_cast(val)); - } else { - output = detail::value_string(val); - } - } - return output; -} - -} // namespace detail - - - -namespace detail { - -// Returns false if not a short option. Otherwise, sets opt name and rest and returns true -inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { - if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { - name = current.substr(1, 1); - rest = current.substr(2); - return true; - } - return false; -} - -// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true -inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { - if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) { - auto loc = current.find_first_of('='); - if(loc != std::string::npos) { - name = current.substr(2, loc - 2); - value = current.substr(loc + 1); - } else { - name = current.substr(2); - value = ""; - } - return true; - } - return false; -} - -// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true -inline bool split_windows_style(const std::string ¤t, std::string &name, std::string &value) { - if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) { - auto loc = current.find_first_of(':'); - if(loc != std::string::npos) { - name = current.substr(1, loc - 1); - value = current.substr(loc + 1); - } else { - name = current.substr(1); - value = ""; - } - return true; - } - return false; -} - -// Splits a string into multiple long and short names -inline std::vector split_names(std::string current) { - std::vector output; - std::size_t val; - while((val = current.find(",")) != std::string::npos) { - output.push_back(trim_copy(current.substr(0, val))); - current = current.substr(val + 1); - } - output.push_back(trim_copy(current)); - return output; -} - -/// extract default flag values either {def} or starting with a ! -inline std::vector> get_default_flag_values(const std::string &str) { - std::vector flags = split_names(str); - flags.erase(std::remove_if(flags.begin(), - flags.end(), - [](const std::string &name) { - return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) && - (name.back() == '}')) || - (name[0] == '!')))); - }), - flags.end()); - std::vector> output; - output.reserve(flags.size()); - for(auto &flag : flags) { - auto def_start = flag.find_first_of('{'); - std::string defval = "false"; - if((def_start != std::string::npos) && (flag.back() == '}')) { - defval = flag.substr(def_start + 1); - defval.pop_back(); - flag.erase(def_start, std::string::npos); - } - flag.erase(0, flag.find_first_not_of("-!")); - output.emplace_back(flag, defval); - } - return output; -} - -/// Get a vector of short names, one of long names, and a single name -inline std::tuple, std::vector, std::string> -get_names(const std::vector &input) { - - std::vector short_names; - std::vector long_names; - std::string pos_name; - - for(std::string name : input) { - if(name.length() == 0) { - continue; - } - if(name.length() > 1 && name[0] == '-' && name[1] != '-') { - if(name.length() == 2 && valid_first_char(name[1])) - short_names.emplace_back(1, name[1]); - else - throw BadNameString::OneCharName(name); - } else if(name.length() > 2 && name.substr(0, 2) == "--") { - name = name.substr(2); - if(valid_name_string(name)) - long_names.push_back(name); - else - throw BadNameString::BadLongName(name); - } else if(name == "-" || name == "--") { - throw BadNameString::DashesOnly(name); - } else { - if(pos_name.length() > 0) - throw BadNameString::MultiPositionalNames(name); - pos_name = name; - } - } - - return std::tuple, std::vector, std::string>( - short_names, long_names, pos_name); -} - -} // namespace detail - - - -class App; - -/// Holds values to load into Options -struct ConfigItem { - /// This is the list of parents - std::vector parents{}; - - /// This is the name - std::string name{}; - - /// Listing of inputs - std::vector inputs{}; - - /// The list of parents and name joined by "." - std::string fullname() const { - std::vector tmp = parents; - tmp.emplace_back(name); - return detail::join(tmp, "."); - } -}; - -/// This class provides a converter for configuration files. -class Config { - protected: - std::vector items{}; - - public: - /// Convert an app into a configuration - virtual std::string to_config(const App *, bool, bool, std::string) const = 0; - - /// Convert a configuration into an app - virtual std::vector from_config(std::istream &) const = 0; - - /// Get a flag value - virtual std::string to_flag(const ConfigItem &item) const { - if(item.inputs.size() == 1) { - return item.inputs.at(0); - } - if(item.inputs.empty()) { - return "{}"; - } - throw ConversionError::TooManyInputsFlag(item.fullname()); - } - - /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure - std::vector from_file(const std::string &name) { - std::ifstream input{name}; - if(!input.good()) - throw FileError::Missing(name); - - return from_config(input); - } - - /// Virtual destructor - virtual ~Config() = default; -}; - -/// This converter works with INI/TOML files; to write INI files use ConfigINI -class ConfigBase : public Config { - protected: - /// the character used for comments - char commentChar = '#'; - /// the character used to start an array '\0' is a default to not use - char arrayStart = '['; - /// the character used to end an array '\0' is a default to not use - char arrayEnd = ']'; - /// the character used to separate elements in an array - char arraySeparator = ','; - /// the character used separate the name from the value - char valueDelimiter = '='; - /// the character to use around strings - char stringQuote = '"'; - /// the character to use around single characters - char characterQuote = '\''; - /// the maximum number of layers to allow - uint8_t maximumLayers{255}; - /// the separator used to separator parent layers - char parentSeparatorChar{'.'}; - /// Specify the configuration index to use for arrayed sections - int16_t configIndex{-1}; - /// Specify the configuration section that should be used - std::string configSection{}; - - public: - std::string - to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override; - - std::vector from_config(std::istream &input) const override; - /// Specify the configuration for comment characters - ConfigBase *comment(char cchar) { - commentChar = cchar; - return this; - } - /// Specify the start and end characters for an array - ConfigBase *arrayBounds(char aStart, char aEnd) { - arrayStart = aStart; - arrayEnd = aEnd; - return this; - } - /// Specify the delimiter character for an array - ConfigBase *arrayDelimiter(char aSep) { - arraySeparator = aSep; - return this; - } - /// Specify the delimiter between a name and value - ConfigBase *valueSeparator(char vSep) { - valueDelimiter = vSep; - return this; - } - /// Specify the quote characters used around strings and characters - ConfigBase *quoteCharacter(char qString, char qChar) { - stringQuote = qString; - characterQuote = qChar; - return this; - } - /// Specify the maximum number of parents - ConfigBase *maxLayers(uint8_t layers) { - maximumLayers = layers; - return this; - } - /// Specify the separator to use for parent layers - ConfigBase *parentSeparator(char sep) { - parentSeparatorChar = sep; - return this; - } - /// get a reference to the configuration section - std::string §ionRef() { return configSection; } - /// get the section - const std::string §ion() const { return configSection; } - /// specify a particular section of the configuration file to use - ConfigBase *section(const std::string §ionName) { - configSection = sectionName; - return this; - } - - /// get a reference to the configuration index - int16_t &indexRef() { return configIndex; } - /// get the section index - int16_t index() const { return configIndex; } - /// specify a particular index in the section to use (-1) for all sections to use - ConfigBase *index(int16_t sectionIndex) { - configIndex = sectionIndex; - return this; - } -}; - -/// the default Config is the TOML file format -using ConfigTOML = ConfigBase; - -/// ConfigINI generates a "standard" INI compliant output -class ConfigINI : public ConfigTOML { - - public: - ConfigINI() { - commentChar = ';'; - arrayStart = '\0'; - arrayEnd = '\0'; - arraySeparator = ' '; - valueDelimiter = '='; - } -}; - - - -class Option; - -/// @defgroup validator_group Validators - -/// @brief Some validators that are provided -/// -/// These are simple `std::string(const std::string&)` validators that are useful. They return -/// a string if the validation fails. A custom struct is provided, as well, with the same user -/// semantics, but with the ability to provide a new type name. -/// @{ - -/// -class Validator { - protected: - /// This is the description function, if empty the description_ will be used - std::function desc_function_{[]() { return std::string{}; }}; - - /// This is the base function that is to be called. - /// Returns a string error message if validation fails. - std::function func_{[](std::string &) { return std::string{}; }}; - /// The name for search purposes of the Validator - std::string name_{}; - /// A Validator will only apply to an indexed value (-1 is all elements) - int application_index_ = -1; - /// Enable for Validator to allow it to be disabled if need be - bool active_{true}; - /// specify that a validator should not modify the input - bool non_modifying_{false}; - - public: - Validator() = default; - /// Construct a Validator with just the description string - explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {} - /// Construct Validator from basic information - Validator(std::function op, std::string validator_desc, std::string validator_name = "") - : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)), - name_(std::move(validator_name)) {} - /// Set the Validator operation function - Validator &operation(std::function op) { - func_ = std::move(op); - return *this; - } - /// This is the required operator for a Validator - provided to help - /// users (CLI11 uses the member `func` directly) - std::string operator()(std::string &str) const { - std::string retstring; - if(active_) { - if(non_modifying_) { - std::string value = str; - retstring = func_(value); - } else { - retstring = func_(str); - } - } - return retstring; - } - - /// This is the required operator for a Validator - provided to help - /// users (CLI11 uses the member `func` directly) - std::string operator()(const std::string &str) const { - std::string value = str; - return (active_) ? func_(value) : std::string{}; - } - - /// Specify the type string - Validator &description(std::string validator_desc) { - desc_function_ = [validator_desc]() { return validator_desc; }; - return *this; - } - /// Specify the type string - Validator description(std::string validator_desc) const { - Validator newval(*this); - newval.desc_function_ = [validator_desc]() { return validator_desc; }; - return newval; - } - /// Generate type description information for the Validator - std::string get_description() const { - if(active_) { - return desc_function_(); - } - return std::string{}; - } - /// Specify the type string - Validator &name(std::string validator_name) { - name_ = std::move(validator_name); - return *this; - } - /// Specify the type string - Validator name(std::string validator_name) const { - Validator newval(*this); - newval.name_ = std::move(validator_name); - return newval; - } - /// Get the name of the Validator - const std::string &get_name() const { return name_; } - /// Specify whether the Validator is active or not - Validator &active(bool active_val = true) { - active_ = active_val; - return *this; - } - /// Specify whether the Validator is active or not - Validator active(bool active_val = true) const { - Validator newval(*this); - newval.active_ = active_val; - return newval; - } - - /// Specify whether the Validator can be modifying or not - Validator &non_modifying(bool no_modify = true) { - non_modifying_ = no_modify; - return *this; - } - /// Specify the application index of a validator - Validator &application_index(int app_index) { - application_index_ = app_index; - return *this; - } - /// Specify the application index of a validator - Validator application_index(int app_index) const { - Validator newval(*this); - newval.application_index_ = app_index; - return newval; - } - /// Get the current value of the application index - int get_application_index() const { return application_index_; } - /// Get a boolean if the validator is active - bool get_active() const { return active_; } - - /// Get a boolean if the validator is allowed to modify the input returns true if it can modify the input - bool get_modifying() const { return !non_modifying_; } - - /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the - /// same. - Validator operator&(const Validator &other) const { - Validator newval; - - newval._merge_description(*this, other, " AND "); - - // Give references (will make a copy in lambda function) - const std::function &f1 = func_; - const std::function &f2 = other.func_; - - newval.func_ = [f1, f2](std::string &input) { - std::string s1 = f1(input); - std::string s2 = f2(input); - if(!s1.empty() && !s2.empty()) - return std::string("(") + s1 + ") AND (" + s2 + ")"; - else - return s1 + s2; - }; - - newval.active_ = (active_ & other.active_); - newval.application_index_ = application_index_; - return newval; - } - - /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the - /// same. - Validator operator|(const Validator &other) const { - Validator newval; - - newval._merge_description(*this, other, " OR "); - - // Give references (will make a copy in lambda function) - const std::function &f1 = func_; - const std::function &f2 = other.func_; - - newval.func_ = [f1, f2](std::string &input) { - std::string s1 = f1(input); - std::string s2 = f2(input); - if(s1.empty() || s2.empty()) - return std::string(); - - return std::string("(") + s1 + ") OR (" + s2 + ")"; - }; - newval.active_ = (active_ & other.active_); - newval.application_index_ = application_index_; - return newval; - } - - /// Create a validator that fails when a given validator succeeds - Validator operator!() const { - Validator newval; - const std::function &dfunc1 = desc_function_; - newval.desc_function_ = [dfunc1]() { - auto str = dfunc1(); - return (!str.empty()) ? std::string("NOT ") + str : std::string{}; - }; - // Give references (will make a copy in lambda function) - const std::function &f1 = func_; - - newval.func_ = [f1, dfunc1](std::string &test) -> std::string { - std::string s1 = f1(test); - if(s1.empty()) { - return std::string("check ") + dfunc1() + " succeeded improperly"; - } - return std::string{}; - }; - newval.active_ = active_; - newval.application_index_ = application_index_; - return newval; - } - - private: - void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger) { - - const std::function &dfunc1 = val1.desc_function_; - const std::function &dfunc2 = val2.desc_function_; - - desc_function_ = [=]() { - std::string f1 = dfunc1(); - std::string f2 = dfunc2(); - if((f1.empty()) || (f2.empty())) { - return f1 + f2; - } - return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')'; - }; - } -}; // namespace CLI - -/// Class wrapping some of the accessors of Validator -class CustomValidator : public Validator { - public: -}; -// The implementation of the built in validators is using the Validator class; -// the user is only expected to use the const (static) versions (since there's no setup). -// Therefore, this is in detail. -namespace detail { - -/// CLI enumeration of different file types -enum class path_type { nonexistent, file, directory }; - -#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 -/// get the type of the path from a file name -inline path_type check_path(const char *file) noexcept { - std::error_code ec; - auto stat = std::filesystem::status(file, ec); - if(ec) { - return path_type::nonexistent; - } - switch(stat.type()) { - case std::filesystem::file_type::none: - case std::filesystem::file_type::not_found: - return path_type::nonexistent; - case std::filesystem::file_type::directory: - return path_type::directory; - case std::filesystem::file_type::symlink: - case std::filesystem::file_type::block: - case std::filesystem::file_type::character: - case std::filesystem::file_type::fifo: - case std::filesystem::file_type::socket: - case std::filesystem::file_type::regular: - case std::filesystem::file_type::unknown: - default: - return path_type::file; - } -} -#else -/// get the type of the path from a file name -inline path_type check_path(const char *file) noexcept { -#if defined(_MSC_VER) - struct __stat64 buffer; - if(_stat64(file, &buffer) == 0) { - return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; - } -#else - struct stat buffer; - if(stat(file, &buffer) == 0) { - return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; - } -#endif - return path_type::nonexistent; -} -#endif -/// Check for an existing file (returns error message if check fails) -class ExistingFileValidator : public Validator { - public: - ExistingFileValidator() : Validator("FILE") { - func_ = [](std::string &filename) { - auto path_result = check_path(filename.c_str()); - if(path_result == path_type::nonexistent) { - return "File does not exist: " + filename; - } - if(path_result == path_type::directory) { - return "File is actually a directory: " + filename; - } - return std::string(); - }; - } -}; - -/// Check for an existing directory (returns error message if check fails) -class ExistingDirectoryValidator : public Validator { - public: - ExistingDirectoryValidator() : Validator("DIR") { - func_ = [](std::string &filename) { - auto path_result = check_path(filename.c_str()); - if(path_result == path_type::nonexistent) { - return "Directory does not exist: " + filename; - } - if(path_result == path_type::file) { - return "Directory is actually a file: " + filename; - } - return std::string(); - }; - } -}; - -/// Check for an existing path -class ExistingPathValidator : public Validator { - public: - ExistingPathValidator() : Validator("PATH(existing)") { - func_ = [](std::string &filename) { - auto path_result = check_path(filename.c_str()); - if(path_result == path_type::nonexistent) { - return "Path does not exist: " + filename; - } - return std::string(); - }; - } -}; - -/// Check for an non-existing path -class NonexistentPathValidator : public Validator { - public: - NonexistentPathValidator() : Validator("PATH(non-existing)") { - func_ = [](std::string &filename) { - auto path_result = check_path(filename.c_str()); - if(path_result != path_type::nonexistent) { - return "Path already exists: " + filename; - } - return std::string(); - }; - } -}; - -/// Validate the given string is a legal ipv4 address -class IPV4Validator : public Validator { - public: - IPV4Validator() : Validator("IPV4") { - func_ = [](std::string &ip_addr) { - auto result = CLI::detail::split(ip_addr, '.'); - if(result.size() != 4) { - return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')'; - } - int num; - for(const auto &var : result) { - bool retval = detail::lexical_cast(var, num); - if(!retval) { - return std::string("Failed parsing number (") + var + ')'; - } - if(num < 0 || num > 255) { - return std::string("Each IP number must be between 0 and 255 ") + var; - } - } - return std::string(); - }; - } -}; - -} // namespace detail - -// Static is not needed here, because global const implies static. - -/// Check for existing file (returns error message if check fails) -const detail::ExistingFileValidator ExistingFile; - -/// Check for an existing directory (returns error message if check fails) -const detail::ExistingDirectoryValidator ExistingDirectory; - -/// Check for an existing path -const detail::ExistingPathValidator ExistingPath; - -/// Check for an non-existing path -const detail::NonexistentPathValidator NonexistentPath; - -/// Check for an IP4 address -const detail::IPV4Validator ValidIPV4; - -/// Validate the input as a particular type -template class TypeValidator : public Validator { - public: - explicit TypeValidator(const std::string &validator_name) : Validator(validator_name) { - func_ = [](std::string &input_string) { - auto val = DesiredType(); - if(!detail::lexical_cast(input_string, val)) { - return std::string("Failed parsing ") + input_string + " as a " + detail::type_name(); - } - return std::string(); - }; - } - TypeValidator() : TypeValidator(detail::type_name()) {} -}; - -/// Check for a number -const TypeValidator Number("NUMBER"); - -/// Modify a path if the file is a particular default location, can be used as Check or transform -/// with the error return optionally disabled -class FileOnDefaultPath : public Validator { - public: - explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true) : Validator("FILE") { - func_ = [default_path, enableErrorReturn](std::string &filename) { - auto path_result = detail::check_path(filename.c_str()); - if(path_result == detail::path_type::nonexistent) { - std::string test_file_path = default_path; - if(default_path.back() != '/' && default_path.back() != '\\') { - // Add folder separator - test_file_path += '/'; - } - test_file_path.append(filename); - path_result = detail::check_path(test_file_path.c_str()); - if(path_result == detail::path_type::file) { - filename = test_file_path; - } else { - if(enableErrorReturn) { - return "File does not exist: " + filename; - } - } - } - return std::string{}; - }; - } -}; - -/// Produce a range (factory). Min and max are inclusive. -class Range : public Validator { - public: - /// This produces a range with min and max inclusive. - /// - /// Note that the constructor is templated, but the struct is not, so C++17 is not - /// needed to provide nice syntax for Range(a,b). - template - Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) { - if(validator_name.empty()) { - std::stringstream out; - out << detail::type_name() << " in [" << min_val << " - " << max_val << "]"; - description(out.str()); - } - - func_ = [min_val, max_val](std::string &input) { - T val; - bool converted = detail::lexical_cast(input, val); - if((!converted) || (val < min_val || val > max_val)) { - std::stringstream out; - out << "Value " << input << " not in range ["; - out << min_val << " - " << max_val << "]"; - return out.str(); - } - return std::string{}; - }; - } - - /// Range of one value is 0 to value - template - explicit Range(T max_val, const std::string &validator_name = std::string{}) - : Range(static_cast(0), max_val, validator_name) {} -}; - -/// Check for a non negative number -const Range NonNegativeNumber((std::numeric_limits::max)(), "NONNEGATIVE"); - -/// Check for a positive valued number (val>0.0), min() her is the smallest positive number -const Range PositiveNumber((std::numeric_limits::min)(), (std::numeric_limits::max)(), "POSITIVE"); - -/// Produce a bounded range (factory). Min and max are inclusive. -class Bound : public Validator { - public: - /// This bounds a value with min and max inclusive. - /// - /// Note that the constructor is templated, but the struct is not, so C++17 is not - /// needed to provide nice syntax for Range(a,b). - template Bound(T min_val, T max_val) { - std::stringstream out; - out << detail::type_name() << " bounded to [" << min_val << " - " << max_val << "]"; - description(out.str()); - - func_ = [min_val, max_val](std::string &input) { - T val; - bool converted = detail::lexical_cast(input, val); - if(!converted) { - return std::string("Value ") + input + " could not be converted"; - } - if(val < min_val) - input = detail::to_string(min_val); - else if(val > max_val) - input = detail::to_string(max_val); - - return std::string{}; - }; - } - - /// Range of one value is 0 to value - template explicit Bound(T max_val) : Bound(static_cast(0), max_val) {} -}; - -namespace detail { -template ::type>::value, detail::enabler> = detail::dummy> -auto smart_deref(T value) -> decltype(*value) { - return *value; -} - -template < - typename T, - enable_if_t::type>::value, detail::enabler> = detail::dummy> -typename std::remove_reference::type &smart_deref(T &value) { - return value; -} -/// Generate a string representation of a set -template std::string generate_set(const T &set) { - using element_t = typename detail::element_type::type; - using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair - std::string out(1, '{'); - out.append(detail::join( - detail::smart_deref(set), - [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, - ",")); - out.push_back('}'); - return out; -} - -/// Generate a string representation of a map -template std::string generate_map(const T &map, bool key_only = false) { - using element_t = typename detail::element_type::type; - using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair - std::string out(1, '{'); - out.append(detail::join( - detail::smart_deref(map), - [key_only](const iteration_type_t &v) { - std::string res{detail::to_string(detail::pair_adaptor::first(v))}; - - if(!key_only) { - res.append("->"); - res += detail::to_string(detail::pair_adaptor::second(v)); - } - return res; - }, - ",")); - out.push_back('}'); - return out; -} - -template struct has_find { - template - static auto test(int) -> decltype(std::declval().find(std::declval()), std::true_type()); - template static auto test(...) -> decltype(std::false_type()); - - static const auto value = decltype(test(0))::value; - using type = std::integral_constant; -}; - -/// A search function -template ::value, detail::enabler> = detail::dummy> -auto search(const T &set, const V &val) -> std::pair { - using element_t = typename detail::element_type::type; - auto &setref = detail::smart_deref(set); - auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) { - return (detail::pair_adaptor::first(v) == val); - }); - return {(it != std::end(setref)), it}; -} - -/// A search function that uses the built in find function -template ::value, detail::enabler> = detail::dummy> -auto search(const T &set, const V &val) -> std::pair { - auto &setref = detail::smart_deref(set); - auto it = setref.find(val); - return {(it != std::end(setref)), it}; -} - -/// A search function with a filter function -template -auto search(const T &set, const V &val, const std::function &filter_function) - -> std::pair { - using element_t = typename detail::element_type::type; - // do the potentially faster first search - auto res = search(set, val); - if((res.first) || (!(filter_function))) { - return res; - } - // if we haven't found it do the longer linear search with all the element translations - auto &setref = detail::smart_deref(set); - auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) { - V a{detail::pair_adaptor::first(v)}; - a = filter_function(a); - return (a == val); - }); - return {(it != std::end(setref)), it}; -} - -// the following suggestion was made by Nikita Ofitserov(@himikof) -// done in templates to prevent compiler warnings on negation of unsigned numbers - -/// Do a check for overflow on signed numbers -template -inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { - if((a > 0) == (b > 0)) { - return ((std::numeric_limits::max)() / (std::abs)(a) < (std::abs)(b)); - } else { - return ((std::numeric_limits::min)() / (std::abs)(a) > -(std::abs)(b)); - } -} -/// Do a check for overflow on unsigned numbers -template -inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { - return ((std::numeric_limits::max)() / a < b); -} - -/// Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise. -template typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { - if(a == 0 || b == 0 || a == 1 || b == 1) { - a *= b; - return true; - } - if(a == (std::numeric_limits::min)() || b == (std::numeric_limits::min)()) { - return false; - } - if(overflowCheck(a, b)) { - return false; - } - a *= b; - return true; -} - -/// Performs a *= b; if it doesn't equal infinity. Returns false otherwise. -template -typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { - T c = a * b; - if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) { - return false; - } - a = c; - return true; -} - -} // namespace detail -/// Verify items are in a set -class IsMember : public Validator { - public: - using filter_fn_t = std::function; - - /// This allows in-place construction using an initializer list - template - IsMember(std::initializer_list values, Args &&...args) - : IsMember(std::vector(values), std::forward(args)...) {} - - /// This checks to see if an item is in a set (empty function) - template explicit IsMember(T &&set) : IsMember(std::forward(set), nullptr) {} - - /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter - /// both sides of the comparison before computing the comparison. - template explicit IsMember(T set, F filter_function) { - - // Get the type of the contained item - requires a container have ::value_type - // if the type does not have first_type and second_type, these are both value_type - using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed - using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map - - using local_item_t = typename IsMemberType::type; // This will convert bad types to good ones - // (const char * to std::string) - - // Make a local copy of the filter function, using a std::function if not one already - std::function filter_fn = filter_function; - - // This is the type name for help, it will take the current version of the set contents - desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); }; - - // This is the function that validates - // It stores a copy of the set pointer-like, so shared_ptr will stay alive - func_ = [set, filter_fn](std::string &input) { - local_item_t b; - if(!detail::lexical_cast(input, b)) { - throw ValidationError(input); // name is added later - } - if(filter_fn) { - b = filter_fn(b); - } - auto res = detail::search(set, b, filter_fn); - if(res.first) { - // Make sure the version in the input string is identical to the one in the set - if(filter_fn) { - input = detail::value_string(detail::pair_adaptor::first(*(res.second))); - } - - // Return empty error string (success) - return std::string{}; - } - - // If you reach this point, the result was not found - return input + " not in " + detail::generate_set(detail::smart_deref(set)); - }; - } - - /// You can pass in as many filter functions as you like, they nest (string only currently) - template - IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) - : IsMember( - std::forward(set), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} -}; - -/// definition of the default transformation object -template using TransformPairs = std::vector>; - -/// Translate named items to other or a value set -class Transformer : public Validator { - public: - using filter_fn_t = std::function; - - /// This allows in-place construction - template - Transformer(std::initializer_list> values, Args &&...args) - : Transformer(TransformPairs(values), std::forward(args)...) {} - - /// direct map of std::string to std::string - template explicit Transformer(T &&mapping) : Transformer(std::forward(mapping), nullptr) {} - - /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter - /// both sides of the comparison before computing the comparison. - template explicit Transformer(T mapping, F filter_function) { - - static_assert(detail::pair_adaptor::type>::value, - "mapping must produce value pairs"); - // Get the type of the contained item - requires a container have ::value_type - // if the type does not have first_type and second_type, these are both value_type - using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed - using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map - using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones - // (const char * to std::string) - - // Make a local copy of the filter function, using a std::function if not one already - std::function filter_fn = filter_function; - - // This is the type name for help, it will take the current version of the set contents - desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); }; - - func_ = [mapping, filter_fn](std::string &input) { - local_item_t b; - if(!detail::lexical_cast(input, b)) { - return std::string(); - // there is no possible way we can match anything in the mapping if we can't convert so just return - } - if(filter_fn) { - b = filter_fn(b); - } - auto res = detail::search(mapping, b, filter_fn); - if(res.first) { - input = detail::value_string(detail::pair_adaptor::second(*res.second)); - } - return std::string{}; - }; - } - - /// You can pass in as many filter functions as you like, they nest - template - Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) - : Transformer( - std::forward(mapping), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} -}; - -/// translate named items to other or a value set -class CheckedTransformer : public Validator { - public: - using filter_fn_t = std::function; - - /// This allows in-place construction - template - CheckedTransformer(std::initializer_list> values, Args &&...args) - : CheckedTransformer(TransformPairs(values), std::forward(args)...) {} - - /// direct map of std::string to std::string - template explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {} - - /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter - /// both sides of the comparison before computing the comparison. - template explicit CheckedTransformer(T mapping, F filter_function) { - - static_assert(detail::pair_adaptor::type>::value, - "mapping must produce value pairs"); - // Get the type of the contained item - requires a container have ::value_type - // if the type does not have first_type and second_type, these are both value_type - using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed - using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map - using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones - // (const char * to std::string) - using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair - - // Make a local copy of the filter function, using a std::function if not one already - std::function filter_fn = filter_function; - - auto tfunc = [mapping]() { - std::string out("value in "); - out += detail::generate_map(detail::smart_deref(mapping)) + " OR {"; - out += detail::join( - detail::smart_deref(mapping), - [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor::second(v)); }, - ","); - out.push_back('}'); - return out; - }; - - desc_function_ = tfunc; - - func_ = [mapping, tfunc, filter_fn](std::string &input) { - local_item_t b; - bool converted = detail::lexical_cast(input, b); - if(converted) { - if(filter_fn) { - b = filter_fn(b); - } - auto res = detail::search(mapping, b, filter_fn); - if(res.first) { - input = detail::value_string(detail::pair_adaptor::second(*res.second)); - return std::string{}; - } - } - for(const auto &v : detail::smart_deref(mapping)) { - auto output_string = detail::value_string(detail::pair_adaptor::second(v)); - if(output_string == input) { - return std::string(); - } - } - - return "Check " + input + " " + tfunc() + " FAILED"; - }; - } - - /// You can pass in as many filter functions as you like, they nest - template - CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) - : CheckedTransformer( - std::forward(mapping), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} -}; - -/// Helper function to allow ignore_case to be passed to IsMember or Transform -inline std::string ignore_case(std::string item) { return detail::to_lower(item); } - -/// Helper function to allow ignore_underscore to be passed to IsMember or Transform -inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); } - -/// Helper function to allow checks to ignore spaces to be passed to IsMember or Transform -inline std::string ignore_space(std::string item) { - item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item)); - item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item)); - return item; -} - -/// Multiply a number by a factor using given mapping. -/// Can be used to write transforms for SIZE or DURATION inputs. -/// -/// Example: -/// With mapping = `{"b"->1, "kb"->1024, "mb"->1024*1024}` -/// one can recognize inputs like "100", "12kb", "100 MB", -/// that will be automatically transformed to 100, 14448, 104857600. -/// -/// Output number type matches the type in the provided mapping. -/// Therefore, if it is required to interpret real inputs like "0.42 s", -/// the mapping should be of a type or . -class AsNumberWithUnit : public Validator { - public: - /// Adjust AsNumberWithUnit behavior. - /// CASE_SENSITIVE/CASE_INSENSITIVE controls how units are matched. - /// UNIT_OPTIONAL/UNIT_REQUIRED throws ValidationError - /// if UNIT_REQUIRED is set and unit literal is not found. - enum Options { - CASE_SENSITIVE = 0, - CASE_INSENSITIVE = 1, - UNIT_OPTIONAL = 0, - UNIT_REQUIRED = 2, - DEFAULT = CASE_INSENSITIVE | UNIT_OPTIONAL - }; - - template - explicit AsNumberWithUnit(std::map mapping, - Options opts = DEFAULT, - const std::string &unit_name = "UNIT") { - description(generate_description(unit_name, opts)); - validate_mapping(mapping, opts); - - // transform function - func_ = [mapping, opts](std::string &input) -> std::string { - Number num; - - detail::rtrim(input); - if(input.empty()) { - throw ValidationError("Input is empty"); - } - - // Find split position between number and prefix - auto unit_begin = input.end(); - while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) { - --unit_begin; - } - - std::string unit{unit_begin, input.end()}; - input.resize(static_cast(std::distance(input.begin(), unit_begin))); - detail::trim(input); - - if(opts & UNIT_REQUIRED && unit.empty()) { - throw ValidationError("Missing mandatory unit"); - } - if(opts & CASE_INSENSITIVE) { - unit = detail::to_lower(unit); - } - if(unit.empty()) { - if(!detail::lexical_cast(input, num)) { - throw ValidationError(std::string("Value ") + input + " could not be converted to " + - detail::type_name()); - } - // No need to modify input if no unit passed - return {}; - } - - // find corresponding factor - auto it = mapping.find(unit); - if(it == mapping.end()) { - throw ValidationError(unit + - " unit not recognized. " - "Allowed values: " + - detail::generate_map(mapping, true)); - } - - if(!input.empty()) { - bool converted = detail::lexical_cast(input, num); - if(!converted) { - throw ValidationError(std::string("Value ") + input + " could not be converted to " + - detail::type_name()); - } - // perform safe multiplication - bool ok = detail::checked_multiply(num, it->second); - if(!ok) { - throw ValidationError(detail::to_string(num) + " multiplied by " + unit + - " factor would cause number overflow. Use smaller value."); - } - } else { - num = static_cast(it->second); - } - - input = detail::to_string(num); - - return {}; - }; - } - - private: - /// Check that mapping contains valid units. - /// Update mapping for CASE_INSENSITIVE mode. - template static void validate_mapping(std::map &mapping, Options opts) { - for(auto &kv : mapping) { - if(kv.first.empty()) { - throw ValidationError("Unit must not be empty."); - } - if(!detail::isalpha(kv.first)) { - throw ValidationError("Unit must contain only letters."); - } - } - - // make all units lowercase if CASE_INSENSITIVE - if(opts & CASE_INSENSITIVE) { - std::map lower_mapping; - for(auto &kv : mapping) { - auto s = detail::to_lower(kv.first); - if(lower_mapping.count(s)) { - throw ValidationError(std::string("Several matching lowercase unit representations are found: ") + - s); - } - lower_mapping[detail::to_lower(kv.first)] = kv.second; - } - mapping = std::move(lower_mapping); - } - } - - /// Generate description like this: NUMBER [UNIT] - template static std::string generate_description(const std::string &name, Options opts) { - std::stringstream out; - out << detail::type_name() << ' '; - if(opts & UNIT_REQUIRED) { - out << name; - } else { - out << '[' << name << ']'; - } - return out.str(); - } -}; - -/// Converts a human-readable size string (with unit literal) to uin64_t size. -/// Example: -/// "100" => 100 -/// "1 b" => 100 -/// "10Kb" => 10240 // you can configure this to be interpreted as kilobyte (*1000) or kibibyte (*1024) -/// "10 KB" => 10240 -/// "10 kb" => 10240 -/// "10 kib" => 10240 // *i, *ib are always interpreted as *bibyte (*1024) -/// "10kb" => 10240 -/// "2 MB" => 2097152 -/// "2 EiB" => 2^61 // Units up to exibyte are supported -class AsSizeValue : public AsNumberWithUnit { - public: - using result_t = std::uint64_t; - - /// If kb_is_1000 is true, - /// interpret 'kb', 'k' as 1000 and 'kib', 'ki' as 1024 - /// (same applies to higher order units as well). - /// Otherwise, interpret all literals as factors of 1024. - /// The first option is formally correct, but - /// the second interpretation is more wide-spread - /// (see https://en.wikipedia.org/wiki/Binary_prefix). - explicit AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) { - if(kb_is_1000) { - description("SIZE [b, kb(=1000b), kib(=1024b), ...]"); - } else { - description("SIZE [b, kb(=1024b), ...]"); - } - } - - private: - /// Get mapping - static std::map init_mapping(bool kb_is_1000) { - std::map m; - result_t k_factor = kb_is_1000 ? 1000 : 1024; - result_t ki_factor = 1024; - result_t k = 1; - result_t ki = 1; - m["b"] = 1; - for(std::string p : {"k", "m", "g", "t", "p", "e"}) { - k *= k_factor; - ki *= ki_factor; - m[p] = k; - m[p + "b"] = k; - m[p + "i"] = ki; - m[p + "ib"] = ki; - } - return m; - } - - /// Cache calculated mapping - static std::map get_mapping(bool kb_is_1000) { - if(kb_is_1000) { - static auto m = init_mapping(true); - return m; - } else { - static auto m = init_mapping(false); - return m; - } - } -}; - -namespace detail { -/// Split a string into a program name and command line arguments -/// the string is assumed to contain a file name followed by other arguments -/// the return value contains is a pair with the first argument containing the program name and the second -/// everything else. -inline std::pair split_program_name(std::string commandline) { - // try to determine the programName - std::pair vals; - trim(commandline); - auto esp = commandline.find_first_of(' ', 1); - while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) { - esp = commandline.find_first_of(' ', esp + 1); - if(esp == std::string::npos) { - // if we have reached the end and haven't found a valid file just assume the first argument is the - // program name - if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') { - bool embeddedQuote = false; - auto keyChar = commandline[0]; - auto end = commandline.find_first_of(keyChar, 1); - while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes - end = commandline.find_first_of(keyChar, end + 1); - embeddedQuote = true; - } - if(end != std::string::npos) { - vals.first = commandline.substr(1, end - 1); - esp = end + 1; - if(embeddedQuote) { - vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar)); - } - } else { - esp = commandline.find_first_of(' ', 1); - } - } else { - esp = commandline.find_first_of(' ', 1); - } - - break; - } - } - if(vals.first.empty()) { - vals.first = commandline.substr(0, esp); - rtrim(vals.first); - } - - // strip the program name - vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{}; - ltrim(vals.second); - return vals; -} - -} // namespace detail -/// @} - - - - -class Option; -class App; - -/// This enum signifies the type of help requested -/// -/// This is passed in by App; all user classes must accept this as -/// the second argument. - -enum class AppFormatMode { - Normal, ///< The normal, detailed help - All, ///< A fully expanded help - Sub, ///< Used when printed as part of expanded subcommand -}; - -/// This is the minimum requirements to run a formatter. -/// -/// A user can subclass this is if they do not care at all -/// about the structure in CLI::Formatter. -class FormatterBase { - protected: - /// @name Options - ///@{ - - /// The width of the first column - std::size_t column_width_{30}; - - /// @brief The required help printout labels (user changeable) - /// Values are Needs, Excludes, etc. - std::map labels_{}; - - ///@} - /// @name Basic - ///@{ - - public: - FormatterBase() = default; - FormatterBase(const FormatterBase &) = default; - FormatterBase(FormatterBase &&) = default; - - /// Adding a destructor in this form to work around bug in GCC 4.7 - virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default) - - /// This is the key method that puts together help - virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0; - - ///@} - /// @name Setters - ///@{ - - /// Set the "REQUIRED" label - void label(std::string key, std::string val) { labels_[key] = val; } - - /// Set the column width - void column_width(std::size_t val) { column_width_ = val; } - - ///@} - /// @name Getters - ///@{ - - /// Get the current value of a name (REQUIRED, etc.) - std::string get_label(std::string key) const { - if(labels_.find(key) == labels_.end()) - return key; - else - return labels_.at(key); - } - - /// Get the current column width - std::size_t get_column_width() const { return column_width_; } - - ///@} -}; - -/// This is a specialty override for lambda functions -class FormatterLambda final : public FormatterBase { - using funct_t = std::function; - - /// The lambda to hold and run - funct_t lambda_; - - public: - /// Create a FormatterLambda with a lambda function - explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {} - - /// Adding a destructor (mostly to make GCC 4.7 happy) - ~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default) - - /// This will simply call the lambda function - std::string make_help(const App *app, std::string name, AppFormatMode mode) const override { - return lambda_(app, name, mode); - } -}; - -/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few -/// overridable methods, to be highly customizable with minimal effort. -class Formatter : public FormatterBase { - public: - Formatter() = default; - Formatter(const Formatter &) = default; - Formatter(Formatter &&) = default; - - /// @name Overridables - ///@{ - - /// This prints out a group of options with title - /// - virtual std::string make_group(std::string group, bool is_positional, std::vector opts) const; - - /// This prints out just the positionals "group" - virtual std::string make_positionals(const App *app) const; - - /// This prints out all the groups of options - std::string make_groups(const App *app, AppFormatMode mode) const; - - /// This prints out all the subcommands - virtual std::string make_subcommands(const App *app, AppFormatMode mode) const; - - /// This prints out a subcommand - virtual std::string make_subcommand(const App *sub) const; - - /// This prints out a subcommand in help-all - virtual std::string make_expanded(const App *sub) const; - - /// This prints out all the groups of options - virtual std::string make_footer(const App *app) const; - - /// This displays the description line - virtual std::string make_description(const App *app) const; - - /// This displays the usage line - virtual std::string make_usage(const App *app, std::string name) const; - - /// This puts everything together - std::string make_help(const App * /*app*/, std::string, AppFormatMode) const override; - - ///@} - /// @name Options - ///@{ - - /// This prints out an option help line, either positional or optional form - virtual std::string make_option(const Option *opt, bool is_positional) const { - std::stringstream out; - detail::format_help( - out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_); - return out.str(); - } - - /// @brief This is the name part of an option, Default: left column - virtual std::string make_option_name(const Option *, bool) const; - - /// @brief This is the options part of the name, Default: combined into left column - virtual std::string make_option_opts(const Option *) const; - - /// @brief This is the description. Default: Right column, on new line if left column too large - virtual std::string make_option_desc(const Option *) const; - - /// @brief This is used to print the name on the USAGE line - virtual std::string make_option_usage(const Option *opt) const; - - ///@} -}; - - - - -using results_t = std::vector; -/// callback function definition -using callback_t = std::function; - -class Option; -class App; - -using Option_p = std::unique_ptr