From f181bddc4f08f9bd599e84cae4d7d067e9ad4a8d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 3 Apr 2020 16:36:04 +0200 Subject: [PATCH 001/204] src/main.cpp: make changes for newer version of libeoskeygen --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8dfb1fd..d7834a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "cli_key_search_result.h" #include "console.h" @@ -73,7 +74,7 @@ int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& d #endif /* LIBEOSKEYGEN_HAVE_THREADS */ std::cout << "Searching for " << count - << " keys containing: " << eoskeygen::strjoin(ks.getList(), ",") + << " keys containing: " << eoskeygen::strlist::join(ks.getList(), ",") #ifdef LIBEOSKEYGEN_HAVE_THREADS << ", Using: " << option_num_threads << " threads" #endif /* LIBEOSKEYGEN_HAVE_THREADS */ @@ -250,7 +251,7 @@ int main(int argc, char **argv) { } // List else { - words = eoskeygen::strsplitwords(arg); + words = eoskeygen::strlist::splitw(arg); } if (p + 1 < argc) { From 654a53698f660c465d6cf8b803ad12d598c2f3bd Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 3 Apr 2020 16:39:43 +0200 Subject: [PATCH 002/204] Importing libeoskeygen as "common" module in this repo (the amount of git repos is too damn high!) --- common/.gitignore | 1 + common/CMakeLists.txt | 49 ++++++++ common/cmake/libeosio.cmake | 51 ++++++++ common/include/eoskeygen/config.h | 30 +++++ common/include/eoskeygen/core/dictionary.h | 72 +++++++++++ common/include/eoskeygen/core/file.h | 35 ++++++ common/include/eoskeygen/core/leet.h | 36 ++++++ common/include/eoskeygen/core/string.h | 41 ++++++ common/include/eoskeygen/core/strlist.h | 50 ++++++++ common/include/eoskeygen/key_search.h | 104 +++++++++++++++ common/include/eoskeygen/key_search_result.h | 40 ++++++ common/src/config.h.in | 30 +++++ common/src/core/dictionary.cpp | 125 +++++++++++++++++++ common/src/core/file.cpp | 49 ++++++++ common/src/core/leet.cpp | 82 ++++++++++++ common/src/core/string.cpp | 52 ++++++++ common/src/core/strlist.cpp | 75 +++++++++++ common/src/key_search.cpp | 115 +++++++++++++++++ common/src/key_search_mt.cpp | 106 ++++++++++++++++ 19 files changed, 1143 insertions(+) create mode 100644 common/.gitignore create mode 100644 common/CMakeLists.txt create mode 100644 common/cmake/libeosio.cmake create mode 100644 common/include/eoskeygen/config.h create mode 100644 common/include/eoskeygen/core/dictionary.h create mode 100644 common/include/eoskeygen/core/file.h create mode 100644 common/include/eoskeygen/core/leet.h create mode 100644 common/include/eoskeygen/core/string.h create mode 100644 common/include/eoskeygen/core/strlist.h create mode 100644 common/include/eoskeygen/key_search.h create mode 100644 common/include/eoskeygen/key_search_result.h create mode 100644 common/src/config.h.in create mode 100644 common/src/core/dictionary.cpp create mode 100644 common/src/core/file.cpp create mode 100644 common/src/core/leet.cpp create mode 100644 common/src/core/string.cpp create mode 100644 common/src/core/strlist.cpp create mode 100644 common/src/key_search.cpp create mode 100644 common/src/key_search_mt.cpp diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..9375aee --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +include/eoskeygen/config.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..fa9e2d5 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,49 @@ +# ------------------------------------------------------------ +# 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( EOSIOKEYGEN_HAVE_THREADS TRUE ) + set( COMMON_SOURCE ${COMMON_SOURCE} src/key_search_mt.cpp ) + endif (Threads_FOUND) +endif (USE_THREADS) + +# Project config file +configure_file(src/config.h.in "${CMAKE_CURRENT_LIST_DIR}/include/eoskeygen/config.h" @ONLY) + +add_library( ${COMMON_NAME} STATIC ${COMMON_SOURCE} ) + +target_include_directories( ${COMMON_NAME} PUBLIC include ) + +# Link with libeosio and threads library. +include( libeosio ) +target_link_libraries( ${COMMON_NAME} + PUBLIC + libeosio + ${CMAKE_THREAD_LIBS_INIT} +) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake new file mode 100644 index 0000000..6427170 --- /dev/null +++ b/common/cmake/libeosio.cmake @@ -0,0 +1,51 @@ +# -------------------------------- +# Variables +# -------------------------------- +set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) +set( LIBEOSIO_WANTED_VERSION 0.1.0 ) + +# -------------------------------- +# Macros +# -------------------------------- +macro(fromGit tag) + + message ("Using libeosio from: ${LIBEOSIO_GIT_URL}@${tag}") + + include(FetchContent) + FetchContent_Declare(libeosio + GIT_REPOSITORY ${LIBEOSIO_GIT_URL} + GIT_TAG ${tag} + ) + + FetchContent_GetProperties(libeosio) + if (NOT libeosio_POPULATED) + FetchContent_Populate(libeosio) + add_subdirectory(${libeosio_SOURCE_DIR} ${libeosio_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() +endmacro() + +macro(buildLocal src) + message ("Using local libeosio at: ${src}") + add_subdirectory(${src} ${src}/build EXCLUDE_FROM_ALL) +endmacro() + +# If we have a locallibeosio +if (LIBEOSIO_SOURCE_DIR) + buildLocal( ${LIBEOSIO_SOURCE_DIR} ) +else() + + # Check if version is in fact a version. + if (LIBEOSIO_WANTED_VERSION MATCHES "^[0-9]+(.[0-9]+)?(.[0-9]+)(-[a-zA-Z0-9]+)?$") + # Try finding the package on the system. + find_package(libeosio ${LIBEOSIO_WANTED_VERSION} QUIET) + if (libeoskeygen_FOUND) + message ("Using libeosio in: ${libeosio_DIR}") + # Not found, download from git. + else() + fromGit( v${LIBEOSIO_WANTED_VERSION} ) + endif() + # Assume version contains a git branch. + else() + fromGit( ${LIBEOSIO_WANTED_VERSION} ) + endif() +endif() diff --git a/common/include/eoskeygen/config.h b/common/include/eoskeygen/config.h new file mode 100644 index 0000000..5728f1f --- /dev/null +++ b/common/include/eoskeygen/config.h @@ -0,0 +1,30 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CONFIG_H +#define EOSIOKEYGEN_COMMON_CONFIG_H + +// Defined if we have thread support. +#define EOSIOKEYGEN_HAVE_THREADS + +#endif /* EOSIOKEYGEN_COMMON_CONFIG_H */ diff --git a/common/include/eoskeygen/core/dictionary.h b/common/include/eoskeygen/core/dictionary.h new file mode 100644 index 0000000..3197108 --- /dev/null +++ b/common/include/eoskeygen/core/dictionary.h @@ -0,0 +1,72 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CORE_DICTIONARY_H +#define EOSIOKEYGEN_COMMON_CORE_DICTIONARY_H + +#include +#include +#include + +namespace eoskeygen { + +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 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 eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_CORE_DICTIONARY_H */ diff --git a/common/include/eoskeygen/core/file.h b/common/include/eoskeygen/core/file.h new file mode 100644 index 0000000..fffebaa --- /dev/null +++ b/common/include/eoskeygen/core/file.h @@ -0,0 +1,35 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CORE_FILE_H +#define EOSIOKEYGEN_COMMON_CORE_FILE_H + +#include + +namespace eoskeygen { + +bool readLines(const std::string& filename, strlist_t& lines); + +} // namespace + +#endif /* EOSIOKEYGEN_COMMON_CORE_FILE_H */ diff --git a/common/include/eoskeygen/core/leet.h b/common/include/eoskeygen/core/leet.h new file mode 100644 index 0000000..01289fc --- /dev/null +++ b/common/include/eoskeygen/core/leet.h @@ -0,0 +1,36 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CORE_LEET_H +#define EOSIOKEYGEN_COMMON_CORE_LEET_H + +#include +#include + +namespace eoskeygen { + +strlist_t l33twords(std::string str); + +} // namespace eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_CORE_LEET_H */ diff --git a/common/include/eoskeygen/core/string.h b/common/include/eoskeygen/core/string.h new file mode 100644 index 0000000..b9ae23a --- /dev/null +++ b/common/include/eoskeygen/core/string.h @@ -0,0 +1,41 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CORE_STRING_H +#define EOSIOKEYGEN_COMMON_CORE_STRING_H + +#include +#include +#include + +namespace eoskeygen { + +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 eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_CORE_STRING_H */ diff --git a/common/include/eoskeygen/core/strlist.h b/common/include/eoskeygen/core/strlist.h new file mode 100644 index 0000000..b1e8d99 --- /dev/null +++ b/common/include/eoskeygen/core/strlist.h @@ -0,0 +1,50 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CORE_STRLIST_H +#define EOSIOKEYGEN_COMMON_CORE_STRLIST_H + +#include +#include + +namespace eoskeygen { + +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 eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_CORE_STRLIST_H */ diff --git a/common/include/eoskeygen/key_search.h b/common/include/eoskeygen/key_search.h new file mode 100644 index 0000000..226b9cc --- /dev/null +++ b/common/include/eoskeygen/key_search.h @@ -0,0 +1,104 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_KEY_SEARCH_H +#define EOSIOKEYGEN_COMMON_KEY_SEARCH_H + +#include +#include +#include +#include +#include + +namespace eoskeygen { + +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(); + + // 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 EOSIOKEYGEN_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); +#endif /* EOSIOKEYGEN_HAVE_THREADS */ + + // 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 libeosio::ec_keypair* key, struct result& result); + +#ifdef EOSIOKEYGEN_HAVE_THREADS + void _thr_proc(); + + void _search_mt(size_t n); +#endif /* EOSIOKEYGEN_HAVE_THREADS */ + + void _search_linear(size_t n); + +protected : + // List of words to search for. + strlist_t m_words; + +#ifdef EOSIOKEYGEN_HAVE_THREADS + // Number of threads to use. + size_t m_threads; +#endif /* EOSIOKEYGEN_HAVE_THREADS */ + + IKeySearchResult* m_callback; +}; + +} // namespace eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_KEY_SEARCH_H */ diff --git a/common/include/eoskeygen/key_search_result.h b/common/include/eoskeygen/key_search_result.h new file mode 100644 index 0000000..943e6d9 --- /dev/null +++ b/common/include/eoskeygen/key_search_result.h @@ -0,0 +1,40 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_KEY_SEARCH_RESULT_H +#define EOSIOKEYGEN_COMMON_KEY_SEARCH_RESULT_H + +#include + +namespace eoskeygen { + +class IKeySearchResult +{ +public : + + virtual void onResult(const struct libeosio::ec_keypair* key, const struct KeySearch::result& result) = 0; +}; + +} // namespace eoskeygen + +#endif /* EOSIOKEYGEN_COMMON_KEY_SEARCH_RESULT_H */ diff --git a/common/src/config.h.in b/common/src/config.h.in new file mode 100644 index 0000000..7871d9f --- /dev/null +++ b/common/src/config.h.in @@ -0,0 +1,30 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CONFIG_H +#define EOSIOKEYGEN_COMMON_CONFIG_H + +// Defined if we have thread support. +#cmakedefine EOSIOKEYGEN_HAVE_THREADS + +#endif /* EOSIOKEYGEN_COMMON_CONFIG_H */ diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp new file mode 100644 index 0000000..0e74906 --- /dev/null +++ b/common/src/core/dictionary.cpp @@ -0,0 +1,125 @@ +/** + * MIT License + * + * 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 + * 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 + +namespace eoskeygen { + +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()) + ); +} + +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 eoskeygen diff --git a/common/src/core/file.cpp b/common/src/core/file.cpp new file mode 100644 index 0000000..ac73356 --- /dev/null +++ b/common/src/core/file.cpp @@ -0,0 +1,49 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +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 eoskeygen diff --git a/common/src/core/leet.cpp b/common/src/core/leet.cpp new file mode 100644 index 0000000..bf0e7f1 --- /dev/null +++ b/common/src/core/leet.cpp @@ -0,0 +1,82 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +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 eoskeygen diff --git a/common/src/core/string.cpp b/common/src/core/string.cpp new file mode 100644 index 0000000..164e362 --- /dev/null +++ b/common/src/core/string.cpp @@ -0,0 +1,52 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +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 eoskeygen diff --git a/common/src/core/strlist.cpp b/common/src/core/strlist.cpp new file mode 100644 index 0000000..ea12151 --- /dev/null +++ b/common/src/core/strlist.cpp @@ -0,0 +1,75 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +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 eoskeygen::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 eoskeygen diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp new file mode 100644 index 0000000..e97e14a --- /dev/null +++ b/common/src/key_search.cpp @@ -0,0 +1,115 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +KeySearch::KeySearch() : +#ifdef EOSIOKEYGEN_HAVE_THREADS + m_threads(0), +#endif + m_callback(NULL) +{ +} + +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(size_t n) { + + size_t count = 0; + struct libeosio::ec_keypair pair; + + while (count < n) { + struct result res; + libeosio::ec_generate_key(&pair); + if (_contains_word(&pair, res)) { + m_callback->onResult(&pair, res); + count++; + } + } +} + +void KeySearch::find(size_t num_results) { + +#ifdef EOSIOKEYGEN_HAVE_THREADS + // Only do multithread if number of threads makes sense. + if (m_threads >= 2) { + _search_mt(num_results); + return; + } +#endif /* HAVE_THREADS */ + + _search_linear(num_results); +} + +bool KeySearch::_contains_word(const struct libeosio::ec_keypair* key, struct result& result) { + + // skip first 3 chars, as those are always "EOS" + std::string pubstr = libeosio::wif_pub_encode(key->pub).substr(3); + strtolower(pubstr); + + for(auto const& w: m_words) { + size_t p = pubstr.find(w); + if (p != std::string::npos) { + result.pos = p + 3; + result.len = w.length(); + return true; + } + } + return false; +} + +} // namespace eoskeygen diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp new file mode 100644 index 0000000..2e498ff --- /dev/null +++ b/common/src/key_search_mt.cpp @@ -0,0 +1,106 @@ +/** + * MIT License + * + * 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 + * 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 eoskeygen { + +// Max keys to search for, +std::size_t g_max; + +// How many keys we have found so far. +std::size_t g_count; + +// Mutex guard for g_count. +std::mutex g_count_mtx; + +// Thread process. +void KeySearch::_thr_proc() { + + struct libeosio::ec_keypair pair; + + while (g_count < g_max) { + struct result res; + + libeosio::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 g_count and res safely. + const std::lock_guard lock(g_count_mtx); + + // It is possible g_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 (g_count >= g_max) { + return; + } + + // Update count and call result function. + g_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(); +} + +void KeySearch::_search_mt(size_t n) +{ + std::vector t; + + t.resize(m_threads - 1); + + // Setup global variables for the threads. + g_max = n; + g_count = 0; + + // 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 eoskeygen From dd9dd484e378a079aceb37109da357009f0a03f9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 3 Apr 2020 16:53:32 +0200 Subject: [PATCH 003/204] Use the "common" subfolder instead of libeoskeygen repository. --- CMakeLists.txt | 9 ++++-- CMakeModules/libeoskeygen.cmake | 52 --------------------------------- src/benchmark.cpp | 6 ++-- src/cli_key_search_result.cpp | 8 ++--- src/cli_key_search_result.h | 4 +-- src/main.cpp | 38 ++++++++++++------------ 6 files changed, 34 insertions(+), 83 deletions(-) delete mode 100644 CMakeModules/libeoskeygen.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d5c1d1d..197a292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,6 @@ option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") -include(libeoskeygen) - # Use installpath from GNUInstallDirs as default. include(GNUInstallDirs) @@ -39,6 +37,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") add_definitions( "-D_CRT_SECURE_NO_WARNINGS=1" ) endif() +# -------------------------------- +# Common code +# -------------------------------- +add_subdirectory( common ) + # -------------------------------- # Program # -------------------------------- @@ -66,7 +69,7 @@ include_directories(${PROJECT_BINARY_DIR}) add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) -target_link_libraries( ${PROGRAM_EXE} PUBLIC eoskeygen ) +target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) # -------------------------------- # Install diff --git a/CMakeModules/libeoskeygen.cmake b/CMakeModules/libeoskeygen.cmake deleted file mode 100644 index d58803f..0000000 --- a/CMakeModules/libeoskeygen.cmake +++ /dev/null @@ -1,52 +0,0 @@ - -# -------------------------------- -# 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/src/benchmark.cpp b/src/benchmark.cpp index 43d8b35..da384a4 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include -#include +#include #include "benchmark.h" using std::chrono::steady_clock; @@ -43,8 +43,8 @@ void benchmark(size_t num_keys, struct benchmark_result* res) { start = steady_clock::now(); for(size_t i = 0; i < num_keys; i++) { - struct ec_keypair k; - ec_generate_key(&k); + struct libeosio::ec_keypair k; + libeosio::ec_generate_key(&k); } res->sec = duration(steady_clock::now() - start).count(); diff --git a/src/cli_key_search_result.cpp b/src/cli_key_search_result.cpp index b61ea3a..05d5b57 100644 --- a/src/cli_key_search_result.cpp +++ b/src/cli_key_search_result.cpp @@ -22,8 +22,8 @@ * SOFTWARE. */ #include +#include #include -#include #include "console.h" #include "cli_key_search_result.h" @@ -42,9 +42,9 @@ m_dict (dict) { } -void CliKeySearchResult::onResult(const struct ec_keypair* key, const struct KeySearch::result& result) { +void CliKeySearchResult::onResult(const struct libeosio::ec_keypair* key, const struct KeySearch::result& result) { - std::string pub = wif_pub_encode(key->pub); + std::string pub = libeosio::wif_pub_encode(key->pub); Dictionary::search_result_t dict_res = m_dict.search(pub); std::cout << "----" << std::endl; @@ -68,7 +68,7 @@ void CliKeySearchResult::onResult(const struct ec_keypair* key, const struct Key } std::cout << std::endl - << "Private: " << wif_priv_encode(key->secret) << std::endl; + << "Private: " << libeosio::wif_priv_encode(key->secret) << std::endl; } } // namespace eoskeygen diff --git a/src/cli_key_search_result.h b/src/cli_key_search_result.h index 2645aeb..0d7e6b2 100644 --- a/src/cli_key_search_result.h +++ b/src/cli_key_search_result.h @@ -24,8 +24,8 @@ #ifndef EOSIOKEYGEN_KEY_SEARCH_HELPERS_H #define EOSIOKEYGEN_KEY_SEARCH_HELPERS_H +#include #include -#include #include #include @@ -38,7 +38,7 @@ class CliKeySearchResult : public IKeySearchResult public: CliKeySearchResult(const Dictionary& dict); - virtual void onResult(const struct ec_keypair* key, const struct KeySearch::result& result); + virtual void onResult(const struct libeosio::ec_keypair* key, const struct KeySearch::result& result); protected : diff --git a/src/main.cpp b/src/main.cpp index d7834a7..eb74b8b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,13 +23,13 @@ */ #include #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include #include #include "cli_key_search_result.h" @@ -40,9 +40,9 @@ // Command line options. bool option_l33t = false; -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS size_t option_num_threads = eoskeygen::KeySearch::max_threads(); -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& dict, int count) { @@ -52,7 +52,7 @@ int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& d ks.setCallback(&rs); for(auto it = words.begin(); it != words.end(); it++) { - size_t p = eoskeygen::is_base58(*it); + size_t p = libeosio::is_base58(*it); if (p != std::string::npos) { std::cerr << "The word '" << *it << "' contains an invalid non-base58 character '" @@ -69,15 +69,15 @@ int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& d ks.addList(words); } -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS ks.setThreadCount(option_num_threads); -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ std::cout << "Searching for " << count << " keys containing: " << eoskeygen::strlist::join(ks.getList(), ",") -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS << ", Using: " << option_num_threads << " threads" -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ << std::endl; ks.find(count); @@ -89,9 +89,9 @@ void usage(const char *name) { std::cout << name << " [ -h | --help | -v | search [ -m | --l33t" -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS << " | --threads=" -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ << " | --dict= ... " << " | --lang= ... ] |file: [ ]" << " | benchmark [ ]" @@ -119,11 +119,11 @@ void usage(const char *name) { << std::endl << std::endl << " --l33t: Takes each word in and find all l33tspeak" << std::endl << " combinations of that word and uses the new list for the search." -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS << std::endl << std::endl << " --threads=: Use of parallel threads for searching." << std::endl << " Default is what the operating system recomend." -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ << std::endl << std::endl << " --dict=: Use words found in (separated by newline) to" << std::endl << " highlight words in the keys found (note that the words in this" << std::endl @@ -163,9 +163,9 @@ int main(int argc, char **argv) { // No args, just print a key. if (argc <= 1) { - struct eoskeygen::ec_keypair pair; - eoskeygen::ec_generate_key(&pair); - eoskeygen::wif_print_key(&pair); + struct libeosio::ec_keypair pair; + libeosio::ec_generate_key(&pair); + libeosio::wif_print_key(&pair); return 0; } @@ -191,7 +191,7 @@ int main(int argc, char **argv) { } else if (!strcmp(argv[p], "--l33t")) { option_l33t = true; } else if (!memcmp(argv[p], "--threads=", 10)) { -#ifdef LIBEOSKEYGEN_HAVE_THREADS +#ifdef EOSIOKEYGEN_HAVE_THREADS option_num_threads = atoi(argv[p] + 10); if (option_num_threads < 2) { std::cerr << "NOTICE: Number of threads less than 2 does not make sense." @@ -203,7 +203,7 @@ int main(int argc, char **argv) { // otherwise we might break scripts. Print a nice message instead. std::cerr << "NOTICE: eosio-keygen is not compiled with" << " thread support. this option is ignored." << std::endl; -#endif /* LIBEOSKEYGEN_HAVE_THREADS */ +#endif /* EOSIOKEYGEN_HAVE_THREADS */ } // Dictionary. else if (!memcmp(argv[p], "--dict=", 7)) { From 9a5f0cff1cd9e496af0f647c2b7570437b160470 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 7 Apr 2020 16:05:18 +0200 Subject: [PATCH 004/204] common/cmake/libeosio.cmake: Use commit 137d5cbe31666a748954dd233e54c5703480ebbf --- common/cmake/libeosio.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index 6427170..8373f2d 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION 0.1.0 ) +set( LIBEOSIO_WANTED_VERSION 137d5cbe31666a748954dd233e54c5703480ebbf ) # -------------------------------- # Macros From 526b87670be850987fd5a5d7b5ba5b25c51cba27 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 7 Apr 2020 17:16:07 +0200 Subject: [PATCH 005/204] remove LICENSE.bitcoin (this code exist in libeosio) --- CMakeLists.txt | 10 ++-------- LICENSE.bitcoin | 22 ---------------------- 2 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 LICENSE.bitcoin diff --git a/CMakeLists.txt b/CMakeLists.txt index 197a292..13db013 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) # Readme and license -install(FILES README.md LICENSE LICENSE.bitcoin +install(FILES README.md LICENSE DESTINATION ${CMAKE_INSTALL_SHAREDIR}) # Documentation @@ -95,13 +95,7 @@ endif (UNIX) # -------------------------------- if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") - 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} ) + set( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) endif() set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) diff --git a/LICENSE.bitcoin b/LICENSE.bitcoin deleted file mode 100644 index 9d54ecb..0000000 --- a/LICENSE.bitcoin +++ /dev/null @@ -1,22 +0,0 @@ -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. From ba0efa2dd7bec122fd41723f5e3b27a2794fc4a2 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 7 Apr 2020 22:37:05 +0200 Subject: [PATCH 006/204] move src dir to cli and add it's own cmake file. --- CMakeLists.txt | 49 ++++---------------------- cli/CMakeLists.txt | 42 ++++++++++++++++++++++ {src => cli}/benchmark.cpp | 0 {src => cli}/benchmark.h | 0 {src => cli}/cli_key_search_result.cpp | 0 {src => cli}/cli_key_search_result.h | 0 {src => cli}/console.cpp | 0 {src => cli}/console.h | 0 {src => cli}/console_ansi.cpp | 0 {src => cli}/console_win32.cpp | 0 {docs => cli/docs}/eosio-keygen.1.in | 0 {src => cli}/isatty.cpp | 0 {src => cli}/isatty.h | 0 {src => cli}/main.cpp | 0 src/config.h.in => config.h.in | 0 15 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 cli/CMakeLists.txt rename {src => cli}/benchmark.cpp (100%) rename {src => cli}/benchmark.h (100%) rename {src => cli}/cli_key_search_result.cpp (100%) rename {src => cli}/cli_key_search_result.h (100%) rename {src => cli}/console.cpp (100%) rename {src => cli}/console.h (100%) rename {src => cli}/console_ansi.cpp (100%) rename {src => cli}/console_win32.cpp (100%) rename {docs => cli/docs}/eosio-keygen.1.in (100%) rename {src => cli}/isatty.cpp (100%) rename {src => cli}/isatty.h (100%) rename {src => cli}/main.cpp (100%) rename src/config.h.in => config.h.in (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13db013..e81fa4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,6 @@ project(eosio-keygen set( PROJECT_MAINTAINER "Henrik Hautakoski ") -# Options -option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") # Use installpath from GNUInstallDirs as default. @@ -37,59 +34,25 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") add_definitions( "-D_CRT_SECURE_NO_WARNINGS=1" ) endif() -# -------------------------------- -# Common code -# -------------------------------- -add_subdirectory( common ) - -# -------------------------------- -# Program -# -------------------------------- - -set (PROGRAM_EXE ${CMAKE_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() - # Project config file -configure_file(src/config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) +configure_file(config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) include_directories(${PROJECT_BINARY_DIR}) -add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) +# -------------------------------- +# Subdirectories +# -------------------------------- -target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) +add_subdirectory( common ) +add_subdirectory( cli ) # -------------------------------- # Install # -------------------------------- -install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - # Readme and license install(FILES README.md LICENSE 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 # -------------------------------- diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt new file mode 100644 index 0000000..9080728 --- /dev/null +++ b/cli/CMakeLists.txt @@ -0,0 +1,42 @@ +# Options +option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) + +# -------------------------------- +# Program +# -------------------------------- + +set (PROGRAM_EXE ${CMAKE_PROJECT_NAME}) + +set (PROGRAM_SOURCE + isatty.cpp + cli_key_search_result.cpp + console.cpp + benchmark.cpp + main.cpp +) + +if (WIN32 AND NOT FORCE_ANSI) + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} console_win32.cpp) +else() + # *nix should have ansi support. + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} console_ansi.cpp) +endif() + +add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) + +target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) + +# -------------------------------- +# Install +# -------------------------------- + +install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +# 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) diff --git a/src/benchmark.cpp b/cli/benchmark.cpp similarity index 100% rename from src/benchmark.cpp rename to cli/benchmark.cpp diff --git a/src/benchmark.h b/cli/benchmark.h similarity index 100% rename from src/benchmark.h rename to cli/benchmark.h diff --git a/src/cli_key_search_result.cpp b/cli/cli_key_search_result.cpp similarity index 100% rename from src/cli_key_search_result.cpp rename to cli/cli_key_search_result.cpp diff --git a/src/cli_key_search_result.h b/cli/cli_key_search_result.h similarity index 100% rename from src/cli_key_search_result.h rename to cli/cli_key_search_result.h diff --git a/src/console.cpp b/cli/console.cpp similarity index 100% rename from src/console.cpp rename to cli/console.cpp diff --git a/src/console.h b/cli/console.h similarity index 100% rename from src/console.h rename to cli/console.h diff --git a/src/console_ansi.cpp b/cli/console_ansi.cpp similarity index 100% rename from src/console_ansi.cpp rename to cli/console_ansi.cpp diff --git a/src/console_win32.cpp b/cli/console_win32.cpp similarity index 100% rename from src/console_win32.cpp rename to cli/console_win32.cpp diff --git a/docs/eosio-keygen.1.in b/cli/docs/eosio-keygen.1.in similarity index 100% rename from docs/eosio-keygen.1.in rename to cli/docs/eosio-keygen.1.in diff --git a/src/isatty.cpp b/cli/isatty.cpp similarity index 100% rename from src/isatty.cpp rename to cli/isatty.cpp diff --git a/src/isatty.h b/cli/isatty.h similarity index 100% rename from src/isatty.h rename to cli/isatty.h diff --git a/src/main.cpp b/cli/main.cpp similarity index 100% rename from src/main.cpp rename to cli/main.cpp diff --git a/src/config.h.in b/config.h.in similarity index 100% rename from src/config.h.in rename to config.h.in From d9976c7f80a086499121af72f8774a33bf8dadc6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 7 Apr 2020 22:42:31 +0200 Subject: [PATCH 007/204] CMakeLists.txt: set default value for CMAKE_BUILD_TYPE --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e81fa4d..da803cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,11 @@ project(eosio-keygen set( PROJECT_MAINTAINER "Henrik Hautakoski ") +# Default to release build if none is set. +if (NOT CMAKE_BUILD_TYPE) + set( CMAKE_BUILD_TYPE Release ) +endif() + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") # Use installpath from GNUInstallDirs as default. From 70dee5611b9d0a8f97680d0fd3f3d71b8d090482 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 7 Apr 2020 22:43:19 +0200 Subject: [PATCH 008/204] CMakeLists.txt: Add c++ flags for the different types of builds. --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da803cd..9fe5d9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,11 +28,19 @@ if (WIN32) set( CMAKE_INSTALL_MANDIR "." ) endif (WIN32) -# Configure the compiler options +# -------------------------------- +# Compiler settings +# -------------------------------- + set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF ) +# c++ flags +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3" ) +set( CMAKE_CXX_FLAGS_MINSIZEREL "-Os" ) + 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") From fb85be4f1e629bd8d0eeda5d9a88b096afaa559c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 09:43:51 +0200 Subject: [PATCH 009/204] common/include/eoskeygen/core/string.h: don't include strlist.h --- common/include/eoskeygen/core/string.h | 1 - 1 file changed, 1 deletion(-) diff --git a/common/include/eoskeygen/core/string.h b/common/include/eoskeygen/core/string.h index b9ae23a..a0d8e03 100644 --- a/common/include/eoskeygen/core/string.h +++ b/common/include/eoskeygen/core/string.h @@ -26,7 +26,6 @@ #include #include -#include namespace eoskeygen { From 52474387ca01015453f3a0e977c894f0f3578815 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 09:48:58 +0200 Subject: [PATCH 010/204] common/include/eoskeygen/key_search.h: include libeosio/types.h --- common/include/eoskeygen/key_search.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/include/eoskeygen/key_search.h b/common/include/eoskeygen/key_search.h index 226b9cc..688def0 100644 --- a/common/include/eoskeygen/key_search.h +++ b/common/include/eoskeygen/key_search.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include From e80d8c5e34e48d1cfcdc9fe8a48a4b0e76cf5f6e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 09:55:14 +0200 Subject: [PATCH 011/204] rename "CMakeModules" directory to "cmake" --- CMakeLists.txt | 2 +- {CMakeModules => cmake}/cpack_custom.cmake | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {CMakeModules => cmake}/cpack_custom.cmake (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fe5d9d..3c6ce03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ if (NOT CMAKE_BUILD_TYPE) set( CMAKE_BUILD_TYPE Release ) endif() -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Use installpath from GNUInstallDirs as default. include(GNUInstallDirs) diff --git a/CMakeModules/cpack_custom.cmake b/cmake/cpack_custom.cmake similarity index 100% rename from CMakeModules/cpack_custom.cmake rename to cmake/cpack_custom.cmake From 4cc6f39da3cc74eeab9a444d0f31a3c224548ff7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 10:07:24 +0200 Subject: [PATCH 012/204] CMakeLists.txt: some restructure/cleanup. --- CMakeLists.txt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c6ce03..d6d36b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.15) -# Project name and version +# -------------------------------- +# Project Info +# -------------------------------- + project(eosio-keygen VERSION 1.0.4 DESCRIPTION "Keygenerator for EOSIO" @@ -8,14 +11,19 @@ project(eosio-keygen set( PROJECT_MAINTAINER "Henrik Hautakoski ") +# -------------------------------- +# CMake settings +# -------------------------------- + +# Append modules dir +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + # Default to release build if none is set. if (NOT CMAKE_BUILD_TYPE) set( CMAKE_BUILD_TYPE Release ) endif() -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -# Use installpath from GNUInstallDirs as default. +# Install path include(GNUInstallDirs) set( CMAKE_INSTALL_SHAREDIR ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME} ) From 0205e25afb9db1e681e2a44bf44505f3ec6b1733 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 09:50:30 +0200 Subject: [PATCH 013/204] Adding initial GUI code. --- CMakeLists.txt | 1 + gui/CMakeLists.txt | 22 +++++ gui/SearchWindow.cpp | 215 +++++++++++++++++++++++++++++++++++++++++++ gui/SearchWindow.h | 105 +++++++++++++++++++++ gui/main.cpp | 36 ++++++++ 5 files changed, 379 insertions(+) create mode 100644 gui/CMakeLists.txt create mode 100644 gui/SearchWindow.cpp create mode 100644 gui/SearchWindow.h create mode 100644 gui/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d6d36b3..12dedca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ include_directories(${PROJECT_BINARY_DIR}) add_subdirectory( common ) add_subdirectory( cli ) +add_subdirectory( gui ) # -------------------------------- # Install diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt new file mode 100644 index 0000000..01f46bb --- /dev/null +++ b/gui/CMakeLists.txt @@ -0,0 +1,22 @@ + +# Qt5 needs MOC,RCC and UIC +set( CMAKE_AUTOMOC ON ) +set( CMAKE_AUTORCC ON ) +set( CMAKE_AUTOUIC ON ) + +# -------------------------------- +# Program +# -------------------------------- + +set( PROGRAM_EXE ${CMAKE_PROJECT_NAME}-gui ) + +set( PROGRAM_SRC + main.cpp + SearchWindow.cpp +) + +add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) + +# Libraries +find_package( Qt5 COMPONENTS Core Widgets REQUIRED ) +target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp new file mode 100644 index 0000000..fae2321 --- /dev/null +++ b/gui/SearchWindow.cpp @@ -0,0 +1,215 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 "SearchWindow.h" + +SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : +QWidget (parent, flags), +m_worker (NULL), +m_status ("status"), +m_leet_cb ("L33t"), +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); + + // First row. + m_layout.addWidget(&m_leet_cb, 0, 1); + + m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); + m_num_threads.setRange(1, (int) eoskeygen::KeySearch::max_threads()); + m_num_threads.setSuffix(" Threads"); + m_layout.addWidget(&m_num_threads, 0, 2); + + m_num_results.setValue(10); + m_num_results.setRange(1, 99); + m_num_results.setSuffix(" Results"); + m_layout.addWidget(&m_num_results, 0, 3); + + // Second row. + m_layout.addWidget(&m_status, 1, 0, 1, 2); + m_layout.addWidget(&m_txt_search, 1, 0, 1, 2); + m_layout.addWidget(&m_btn_exec, 1, 2); + m_layout.addWidget(&m_btn_clear, 1, 3); + + + // Third row. + m_layout.addWidget(&m_output, 2, 0, 1, 0); + + // Search + // ------------------------ + + m_ksearch.setCallback(this); + + initSignals(); + + // Focus search field. + m_txt_search.setFocus(); +} + +SearchWindow::~SearchWindow() +{ + // Make sure worker thread exits. + if (m_worker) { + m_worker->quit(); + m_worker->wait(); + } +} + +void SearchWindow::initSignals() +{ + // Buttons + connect(&m_btn_exec, SIGNAL(released()), this, SLOT(search())); + connect(&m_btn_clear, SIGNAL(released()), &m_output, SLOT(clear())); + + connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); +} + +void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) +{ + int pos = (int) result.pos; + int len = (int) result.len; + QString pub = QString::fromStdString(libeosio::wif_pub_encode(key->pub)); + QString mid = pub.mid(pos, len); + QString left = pub.left(pos); + QString right = pub.mid(pos + len, pub.size() - pos); + + QString out = "Public: " + pub.left(3); + for(int i = 3; i < pub.length(); ) { + + if (i == pos) { + out += "" + pub.mid(pos, len) + ""; + i += pos; + continue; + } + + out += pub[i++]; + } + + out += "
Private: " + QString::fromStdString(libeosio::wif_priv_encode(key->secret)); + + // As this function could be called from a non-gui thread. we use signals. + emit addOutput("

" + out + "

"); +} + +// -------------------- +// Slots +// -------------------- + +void SearchWindow::search() +{ + if (m_worker && m_worker->isRunning()) { + return; + } + + const std::string& input = m_txt_search.text().toLocal8Bit().constData(); + eoskeygen::strlist_t list; + + if (m_leet_cb.isChecked()) { + list = eoskeygen::l33twords(input); + } else { + list = eoskeygen::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; + } + + m_ksearch.clear(); + m_ksearch.addList(list); + m_ksearch.setThreadCount(m_num_threads.value()); + + // Create search thread + m_worker = QThread::create([this] { + m_ksearch.find(m_num_results.value()); + }); + + connect(m_worker, SIGNAL(started()), this, SLOT(searchStarted())); + connect(m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); + + m_status.setText("Searching for: " + QString::fromStdString(eoskeygen::strlist::join(list, ", "))); + m_worker->start(); +} + +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); + } +} + +void SearchWindow::searchStarted() +{ + m_txt_search.setEnabled(false); + m_txt_search.setHidden(true); + m_btn_exec.setEnabled(false); + m_btn_clear.setEnabled(false); + m_num_threads.setEnabled(false); + m_num_results.setEnabled(false); +} + +void SearchWindow::searchFinished() +{ + m_txt_search.setEnabled(true); + m_txt_search.setHidden(false); + m_btn_exec.setEnabled(true); + m_btn_clear.setEnabled(true); + m_num_threads.setEnabled(true); + m_num_results.setEnabled(true); + + // We are done with the worker pointer. + if (m_worker) { + delete m_worker; + m_worker = NULL; + } +} diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h new file mode 100644 index 0000000..2959c02 --- /dev/null +++ b/gui/SearchWindow.h @@ -0,0 +1,105 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 + +class QThread; + +class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult +{ + Q_OBJECT +public: + explicit SearchWindow(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); + virtual ~SearchWindow(); + + void onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result); + +private : + void initSignals(); + +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(); + +signals: + void addOutput(const QString& line); + +private: + + // Search worker thread. + QThread* m_worker; + + eoskeygen::KeySearch m_ksearch; + + // Widgets + // ---------------- + + // Status text. + QLabel m_status; + + // Search input. + QLineEdit m_txt_search; + + // Number of Threads. + QSpinBox m_num_threads; + + // Number of Results + QSpinBox m_num_results; + + QCheckBox m_leet_cb; + + // 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/main.cpp b/gui/main.cpp new file mode 100644 index 0000000..73fe05f --- /dev/null +++ b/gui/main.cpp @@ -0,0 +1,36 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 "SearchWindow.h" + +int main(int argc, char **argv) { + + QApplication app(argc, argv); + + SearchWindow search_win; + + search_win.show(); + + return app.exec(); +} From 69017c7a213790cb3cb77300a3b57b65c6b05596 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 12:39:55 +0200 Subject: [PATCH 014/204] CMake: Adding BUILD_COMPONENT_GUI and BUILD_COMPONENT_CLI (so user's can build either one or both). --- CMakeLists.txt | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12dedca..b752918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,17 @@ project(eosio-keygen set( PROJECT_MAINTAINER "Henrik Hautakoski ") +# -------------------------------- +# Options +# -------------------------------- + +option(BUILD_COMPONENT_CLI "Build CLI Component" ON) +option(BUILD_COMPONENT_GUI "Build GUI Component (Qt5)" OFF) + +if (NOT BUILD_COMPONENT_CLI AND NOT BUILD_COMPONENT_GUI) + message(FATAL_ERROR "Atleast one of BUILD_COMPONENT_GUI,BUILD_COMPONENT_CLI must be set to ON") +endif() + # -------------------------------- # CMake settings # -------------------------------- @@ -60,12 +71,18 @@ configure_file(config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) include_directories(${PROJECT_BINARY_DIR}) # -------------------------------- -# Subdirectories +# Components # -------------------------------- add_subdirectory( common ) -add_subdirectory( cli ) -add_subdirectory( gui ) + +if (BUILD_COMPONENT_CLI) + add_subdirectory( cli ) +endif() + +if (BUILD_COMPONENT_GUI) + add_subdirectory( gui ) +endif() # -------------------------------- # Install From a2ec5eaaec7164b7ac65db2bb5368fb52934217a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 14:03:01 +0200 Subject: [PATCH 015/204] gui/CMakeLists.txt: Force Qt 5.11 or later. --- gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 01f46bb..fc02215 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -18,5 +18,5 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 COMPONENTS Core Widgets REQUIRED ) +find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) From 8cb3fad9b1b20818c4c95c3b74c828d3ec41c350 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 14:05:03 +0200 Subject: [PATCH 016/204] gui/CMakeLists.txt: Adding install target --- gui/CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index fc02215..94b0226 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -8,7 +8,9 @@ set( CMAKE_AUTOUIC ON ) # Program # -------------------------------- -set( PROGRAM_EXE ${CMAKE_PROJECT_NAME}-gui ) +set( COMPONENT_NAME ${CMAKE_PROJECT_NAME}-gui) + +set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp @@ -20,3 +22,11 @@ add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) + +# -------------------------------- +# Install +# -------------------------------- + +install(TARGETS ${PROGRAM_EXE} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT ${COMPONENT_NAME}) From 3c21e27f450a1446751fa26ef84d4019a0b4b8ff Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:45:19 +0200 Subject: [PATCH 017/204] gui/SearchWindow: Use QFutureWatcher instead of QThread. By removing the call to QThread::create() that requires version >= 5.11 we can have a lower version as requirement. This is useful because a lot of systems don't ship with 5.11 as default. --- gui/CMakeLists.txt | 4 ++-- gui/SearchWindow.cpp | 35 +++++++++-------------------------- gui/SearchWindow.h | 6 ++---- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 94b0226..8c330ed 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -20,8 +20,8 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) -target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) +find_package( Qt5 5.11 COMPONENTS Concurrent Core Widgets REQUIRED ) +target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets common ) # -------------------------------- # Install diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index fae2321..e34f556 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -32,7 +33,6 @@ SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), -m_worker (NULL), m_status ("status"), m_leet_cb ("L33t"), m_btn_exec ("Search"), @@ -86,21 +86,16 @@ m_btn_clear ("Clear") m_txt_search.setFocus(); } -SearchWindow::~SearchWindow() -{ - // Make sure worker thread exits. - if (m_worker) { - m_worker->quit(); - m_worker->wait(); - } -} - 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))); } @@ -137,7 +132,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct void SearchWindow::search() { - if (m_worker && m_worker->isRunning()) { + if (m_worker.isRunning()) { return; } @@ -162,16 +157,10 @@ void SearchWindow::search() m_ksearch.addList(list); m_ksearch.setThreadCount(m_num_threads.value()); - // Create search thread - m_worker = QThread::create([this] { - m_ksearch.find(m_num_results.value()); - }); - - connect(m_worker, SIGNAL(started()), this, SLOT(searchStarted())); - connect(m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); + QFuture future = QtConcurrent::run(m_ksearch, &eoskeygen::KeySearch::find, m_num_results.value()); + m_worker.setFuture(future); m_status.setText("Searching for: " + QString::fromStdString(eoskeygen::strlist::join(list, ", "))); - m_worker->start(); } void SearchWindow::output(const std::string& html) @@ -206,10 +195,4 @@ void SearchWindow::searchFinished() m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); m_num_results.setEnabled(true); - - // We are done with the worker pointer. - if (m_worker) { - delete m_worker; - m_worker = NULL; - } } diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 2959c02..0bc6a65 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -31,18 +31,16 @@ #include #include #include +#include #include #include #include -class QThread; - class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { Q_OBJECT public: explicit SearchWindow(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); - virtual ~SearchWindow(); void onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result); @@ -70,7 +68,7 @@ signals: private: // Search worker thread. - QThread* m_worker; + QFutureWatcher m_worker; eoskeygen::KeySearch m_ksearch; From 40ddff41dbaee9043804e0985296c6237aadedb1 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:48:26 +0200 Subject: [PATCH 018/204] gui/CMakeLists.txt: Drop the requirement for QT 5.11 --- gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 8c330ed..cb65710 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -20,7 +20,7 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 5.11 COMPONENTS Concurrent Core Widgets REQUIRED ) +find_package( Qt5 COMPONENTS Concurrent Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets common ) # -------------------------------- From 0d44bbc8f65a8cae78ae505a2fd4424ec8039942 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:49:26 +0200 Subject: [PATCH 019/204] .github/workflows/ci.yml: Build GUI --- .github/workflows/ci.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef1fafb..6f4e4a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,12 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] - build-opts: [ "-DFORCE_ANSI=ON", "-DFORCE_ANSI=OFF" ] + build-opts: [ + -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON, + -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF, + -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON + ] + name: ${{matrix.os}} (${{matrix.build-opts}}) runs-on: ${{matrix.os}} @@ -20,13 +25,24 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Dependancies + - name: OpenSSL shell: bash run: | if [ "$RUNNER_OS" == "macOS" ]; then brew install openssl fi + - name: Qt - Ubuntu + if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os == 'Linux' + shell: bash + run: sudo apt-get install qt5-default + + - name: Qt - Windows/Mac + if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os != 'Linux' + uses: jurplel/install-qt-action@v2 + with: + version: '5.9' + - name: Configure shell: bash run: | From bbd2959a0d2d243e12187c3f9ad61b94e0165eaa Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 16:57:58 +0200 Subject: [PATCH 020/204] CMakeLists.txt: adding DOWNLOAD_CACHE_DIR variable. --- .gitignore | 1 + CMakeLists.txt | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 6f31401..02e2c31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ .vscode/ +.cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index d6d36b3..3748b26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,10 @@ if (WIN32) 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 ) + # -------------------------------- # Compiler settings # -------------------------------- From eed3c1cfef22f5ad67f46c26f697af3bce8c7629 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 16:58:20 +0200 Subject: [PATCH 021/204] common/cmake/libeosio.cmake: download source to DOWNLOAD_CACHE_DIR --- common/cmake/libeosio.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index 8373f2d..b37b8a2 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -15,6 +15,7 @@ macro(fromGit tag) FetchContent_Declare(libeosio GIT_REPOSITORY ${LIBEOSIO_GIT_URL} GIT_TAG ${tag} + SOURCE_DIR ${DOWNLOAD_CACHE_DIR}/libeosio ) FetchContent_GetProperties(libeosio) From bc614da0e82c5b8dd1730fb3390a59e42d26e7ea Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 17:06:09 +0200 Subject: [PATCH 022/204] common/cmake/libeosio.cmake: also set stamp directory to DOWNLOAD_CACHE_DIR --- common/cmake/libeosio.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index b37b8a2..b739349 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -15,7 +15,8 @@ macro(fromGit tag) FetchContent_Declare(libeosio GIT_REPOSITORY ${LIBEOSIO_GIT_URL} GIT_TAG ${tag} - SOURCE_DIR ${DOWNLOAD_CACHE_DIR}/libeosio + SOURCE_DIR ${DOWNLOAD_CACHE_DIR}/libeosio/src + STAMP_DIR ${DOWNLOAD_CACHE_DIR}/libeosio/stamp ) FetchContent_GetProperties(libeosio) From 48eb7161654f01bc4d94faa1bfcfa4d187a1a390 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 17:44:19 +0200 Subject: [PATCH 023/204] .github/workflows/ci.yml: add abit more human friendly names than matrix.build-opts. and have the actual cmake flags as matrix includes. --- .github/workflows/ci.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f4e4a2..1f9186e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,14 +12,17 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] - build-opts: [ - -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON, - -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF, - -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON - ] + build: [ cli-force-ansi-on, cli-force-ansi-off, gui ] + include: + - build: cli-force-ansi-on + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON + - build: cli-force-ansi-off + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON + - build: gui + cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON - name: ${{matrix.os}} (${{matrix.build-opts}}) + name: ${{matrix.os}} (${{matrix.build}}) runs-on: ${{matrix.os}} steps: @@ -33,12 +36,12 @@ jobs: fi - name: Qt - Ubuntu - if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os == 'Linux' + if: matrix.build == 'gui' && runner.os == 'Linux' shell: bash run: sudo apt-get install qt5-default - name: Qt - Windows/Mac - if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os != 'Linux' + if: matrix.build == 'gui' && runner.os != 'Linux' uses: jurplel/install-qt-action@v2 with: version: '5.9' @@ -49,7 +52,7 @@ jobs: if [ "$RUNNER_OS" == "macOS" ]; then SSL_OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" fi - cmake ${SSL_OPTS} ${{matrix.build-opts}} -B build + cmake ${SSL_OPTS} ${{matrix.cmake-opts}} -B build - name: Build shell: bash @@ -58,5 +61,5 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v1 with: - name: ${{matrix.os}}_${{matrix.build-opts}}-build + name: ${{matrix.os}}_${{matrix.build}}-build path: build From c206ec764f4c138f3a6ae1897e3dacd4f85a3ece Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 17:47:45 +0200 Subject: [PATCH 024/204] .github/workflows/ci.yml: some minor cleanup. --- .github/workflows/ci.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f9186e..af10bb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,12 +28,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: OpenSSL + - name: OpenSSL OSX + if: runner.os == 'macOS' shell: bash - run: | - if [ "$RUNNER_OS" == "macOS" ]; then - brew install openssl - fi + run: brew install openssl - name: Qt - Ubuntu if: matrix.build == 'gui' && runner.os == 'Linux' @@ -49,10 +47,11 @@ jobs: - name: Configure shell: bash run: | + OPTS="${{matrix.cmake-opts}}" if [ "$RUNNER_OS" == "macOS" ]; then - SSL_OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" + OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1 ${OPTS}" fi - cmake ${SSL_OPTS} ${{matrix.cmake-opts}} -B build + cmake ${OPTS} -B build - name: Build shell: bash From bfc40bd3e70ccfaba6ed2908e53b41ac7275f49b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 11 Apr 2020 16:29:42 +0200 Subject: [PATCH 025/204] gui/SearchWindow.cpp: Force scrollbar to the bottom when adding text to m_output. --- gui/SearchWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index e34f556..ba3a757 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -23,6 +23,7 @@ */ #include #include +#include #include #include #include @@ -175,6 +176,9 @@ void SearchWindow::output(const QString& html) } else { m_output.setHtml(html); } + + // Force scrollbar to the bottom. + m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } void SearchWindow::searchStarted() From 6a53999c14196b30dda0a1f3972bfcbbb1dc927c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:24:56 +0200 Subject: [PATCH 026/204] Adding gui/MultiSelect module --- gui/CMakeLists.txt | 1 + gui/MultiSelect.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++ gui/MultiSelect.h | 89 ++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 gui/MultiSelect.cpp create mode 100644 gui/MultiSelect.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index cb65710..f681677 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -15,6 +15,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp SearchWindow.cpp + MultiSelect.cpp ) add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp new file mode 100644 index 0000000..6288b89 --- /dev/null +++ b/gui/MultiSelect.cpp @@ -0,0 +1,137 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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.h" + +MultiSelect::MultiSelect(const QString& text, 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*))); +} + +void MultiSelect::addItem(const QString& text) +{ + QListWidgetItem* item = new QListWidgetItem(text, m_list); + item->setFlags(Qt::ItemIsEnabled); + item->setCheckState(Qt::Unchecked); +} + +void MultiSelect::addItems(const QStringList& list) +{ + QStringList::const_iterator it; + + for(it = list.cbegin(); it != list.cend(); it++) { + addItem(*it); + } +} + +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::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/MultiSelect.h b/gui/MultiSelect.h new file mode 100644 index 0000000..fc40731 --- /dev/null +++ b/gui/MultiSelect.h @@ -0,0 +1,89 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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, QWidget *parent = 0); + + // Items. + + void addItem(const QString& text); + + void addItems(const QStringList& list); + + 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); + +private slots : + + // Called when the dialog is accepted. + void selectionConfirmed(); + + // Called when a list item is clicked on. + void listItemClicked(QListWidgetItem *item); + +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 */ From 45005c995073d17330ba36eb22dd12523d795f78 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:37:25 +0200 Subject: [PATCH 027/204] adding gui/helpers module --- gui/CMakeLists.txt | 1 + gui/helpers.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ gui/helpers.h | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 gui/helpers.cpp create mode 100644 gui/helpers.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index f681677..7dba68c 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -16,6 +16,7 @@ set( PROGRAM_SRC main.cpp SearchWindow.cpp MultiSelect.cpp + helpers.cpp ) add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) diff --git a/gui/helpers.cpp b/gui/helpers.cpp new file mode 100644 index 0000000..3b492b4 --- /dev/null +++ b/gui/helpers.cpp @@ -0,0 +1,42 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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.h" + +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/helpers.h b/gui/helpers.h new file mode 100644 index 0000000..ccb5218 --- /dev/null +++ b/gui/helpers.h @@ -0,0 +1,38 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 */ From 35706c9ba3712629cf03d641135239b5d12413e0 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:39:46 +0200 Subject: [PATCH 028/204] config.h.in: add CONFIG_DICT_PATH and CONFIG_DICT_FULL_PATH --- config.h.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.h.in b/config.h.in index ff5de16..a1b4356 100644 --- a/config.h.in +++ b/config.h.in @@ -31,4 +31,7 @@ #define CONFIG_SHARE_PATH "@CMAKE_INSTALL_DATADIR@/@CMAKE_PROJECT_NAME@" #define CONFIG_SHARE_FULL_PATH "@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@" +#define CONFIG_DICT_PATH "@CMAKE_INSTALL_DATADIR@/@CMAKE_PROJECT_NAME@/dict" +#define CONFIG_DICT_FULL_PATH "@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@/dict" + #endif /* EOSIOKEYGEN_CONFIG_H */ From 3b1ada9cb771e93ac4242e39d7b44d6aa84b48c8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:19:39 +0200 Subject: [PATCH 029/204] gui/SearchWindow.cpp: in onResult() should advance index by word length and not position. --- gui/SearchWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index ba3a757..9543467 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -114,7 +114,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct if (i == pos) { out += "" + pub.mid(pos, len) + ""; - i += pos; + i += len; continue; } From 1f8fbfc8caa843908d37e37c521905f1288922e6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:33:07 +0200 Subject: [PATCH 030/204] gui/SearchWindow: implement dictionary language --- gui/SearchWindow.cpp | 39 +++++++++++++++++++++++++++++++++++++++ gui/SearchWindow.h | 8 ++++++++ 2 files changed, 47 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 9543467..bc5d9b7 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -30,12 +30,15 @@ #include #include #include +#include "config.h" +#include "helpers.h" #include "SearchWindow.h" SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), m_status ("status"), m_leet_cb ("L33t"), +m_dict_lang ("Dictionary Language"), m_btn_exec ("Search"), m_btn_clear ("Clear") { @@ -54,6 +57,9 @@ m_btn_clear ("Clear") m_layout.setColumnStretch(0, 10); // First row. + m_dict_lang.addItems(get_files(CONFIG_DICT_FULL_PATH)); + m_layout.addWidget(&m_dict_lang, 0, 0); + m_layout.addWidget(&m_leet_cb, 0, 1); m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); @@ -98,6 +104,8 @@ void SearchWindow::initSignals() connect(&m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); + + connect(&m_dict_lang, SIGNAL(selectionChanged(QStringList)), this, SLOT(langSelected(QStringList))); } void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) @@ -108,6 +116,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct QString mid = pub.mid(pos, len); QString left = pub.left(pos); QString right = pub.mid(pos + len, pub.size() - pos); + eoskeygen::Dictionary::search_result_t dict_res = m_dict.search(pub.toStdString()); QString out = "Public: " + pub.left(3); for(int i = 3; i < pub.length(); ) { @@ -118,6 +127,16 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct 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++]; } @@ -181,10 +200,29 @@ void SearchWindow::output(const QString& html) m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } +void SearchWindow::langSelected(QStringList selected) +{ + std::string base_path(CONFIG_DICT_FULL_PATH); + + // Clear dictionary first. + m_dict.clear(); + + // Go through all selected languages. + for(QStringList::const_iterator it = selected.cbegin(); it != selected.cend(); it++) { + + // Load and add them to dictionary. + eoskeygen::Dictionary dict; + dict.loadFromFile(base_path + "/" + it->toStdString()); + + m_dict.add(dict); + } +} + void SearchWindow::searchStarted() { m_txt_search.setEnabled(false); m_txt_search.setHidden(true); + m_dict_lang.setEnabled(false); m_btn_exec.setEnabled(false); m_btn_clear.setEnabled(false); m_num_threads.setEnabled(false); @@ -195,6 +233,7 @@ void SearchWindow::searchFinished() { m_txt_search.setEnabled(true); m_txt_search.setHidden(false); + m_dict_lang.setEnabled(true); m_btn_exec.setEnabled(true); m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 0bc6a65..1aff8b1 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -35,6 +35,7 @@ #include #include #include +#include "MultiSelect.h" class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { @@ -62,6 +63,9 @@ private slots: // Called when a search is done. void searchFinished(); + // Called when dictionary language(s) are selected. + void langSelected(QStringList selected); + signals: void addOutput(const QString& line); @@ -72,6 +76,8 @@ private: eoskeygen::KeySearch m_ksearch; + eoskeygen::Dictionary m_dict; + // Widgets // ---------------- @@ -89,6 +95,8 @@ private: QCheckBox m_leet_cb; + MultiSelect m_dict_lang; + // Buttons QPushButton m_btn_exec; QPushButton m_btn_clear; From 3ca4631bbe2009d7cb040365012798d8b194c02f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:34:28 +0200 Subject: [PATCH 031/204] common/include/eoskeygen/core/dictionary.h: adding getWords() method. --- common/include/eoskeygen/core/dictionary.h | 3 +++ common/src/core/dictionary.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/common/include/eoskeygen/core/dictionary.h b/common/include/eoskeygen/core/dictionary.h index 3197108..bdd9cac 100644 --- a/common/include/eoskeygen/core/dictionary.h +++ b/common/include/eoskeygen/core/dictionary.h @@ -53,6 +53,9 @@ public : // 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; diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp index 0e74906..7446b34 100644 --- a/common/src/core/dictionary.cpp +++ b/common/src/core/dictionary.cpp @@ -79,6 +79,11 @@ void Dictionary::add(const Dictionary& dictionary) ); } +const std::set& Dictionary::getWords() const +{ + return m_words; +} + void Dictionary::clear() { m_words.clear(); From c14a453f01f45f31bda229cd0ba2c699f8a082c8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:38:17 +0200 Subject: [PATCH 032/204] gui/SearchWindow.cpp: disable m_leet_cb during search. --- gui/SearchWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index bc5d9b7..0ae0d5e 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -223,6 +223,7 @@ void SearchWindow::searchStarted() m_txt_search.setEnabled(false); m_txt_search.setHidden(true); m_dict_lang.setEnabled(false); + m_leet_cb.setEnabled(false); m_btn_exec.setEnabled(false); m_btn_clear.setEnabled(false); m_num_threads.setEnabled(false); @@ -234,6 +235,7 @@ void SearchWindow::searchFinished() m_txt_search.setEnabled(true); m_txt_search.setHidden(false); m_dict_lang.setEnabled(true); + m_leet_cb.setEnabled(true); m_btn_exec.setEnabled(true); m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); From 925ef7e8ad285071dafc2f7caaa6feded71980cf Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:49:40 +0200 Subject: [PATCH 033/204] gui/MultiSelect: add variable for default state for addItem() and addItems() --- gui/MultiSelect.cpp | 8 ++++---- gui/MultiSelect.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 6288b89..2578eba 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -54,19 +54,19 @@ QPushButton (text + ": none", parent) QObject::connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); } -void MultiSelect::addItem(const QString& text) +void MultiSelect::addItem(const QString& text, bool checked) { QListWidgetItem* item = new QListWidgetItem(text, m_list); item->setFlags(Qt::ItemIsEnabled); - item->setCheckState(Qt::Unchecked); + item->setCheckState(checked ? Qt::Checked : Qt::Unchecked); } -void MultiSelect::addItems(const QStringList& list) +void MultiSelect::addItems(const QStringList& list, bool checked) { QStringList::const_iterator it; for(it = list.cbegin(); it != list.cend(); it++) { - addItem(*it); + addItem(*it, checked); } } diff --git a/gui/MultiSelect.h b/gui/MultiSelect.h index fc40731..830c4d0 100644 --- a/gui/MultiSelect.h +++ b/gui/MultiSelect.h @@ -47,9 +47,9 @@ public: // Items. - void addItem(const QString& text); + void addItem(const QString& text, bool checked = false); - void addItems(const QStringList& list); + void addItems(const QStringList& list, bool checked = false); void clearItems(); From 50a2805c3fe1db9739d11090bda0cb3a3fa8ffdb Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:56:04 +0200 Subject: [PATCH 034/204] gui/MultiSelect: Add user_add_item parameter to constructor adds a button and signal to the MultiSelect, allowing client code to implement adding items from user input. --- gui/MultiSelect.cpp | 17 +++++++++++++++-- gui/MultiSelect.h | 9 ++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 2578eba..98c6dac 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -28,8 +28,8 @@ #include #include "MultiSelect.h" -MultiSelect::MultiSelect(const QString& text, QWidget *parent) : -QPushButton (text + ": none", parent) +MultiSelect::MultiSelect(const QString& text, bool user_can_add, QWidget *parent) : +QPushButton (text + ": none", parent) { QPushButton* btn; QVBoxLayout* layout; @@ -52,6 +52,13 @@ QPushButton (text + ": none", parent) 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) @@ -125,6 +132,12 @@ void MultiSelect::listItemClicked(QListWidgetItem *item) 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) { diff --git a/gui/MultiSelect.h b/gui/MultiSelect.h index 830c4d0..84ed207 100644 --- a/gui/MultiSelect.h +++ b/gui/MultiSelect.h @@ -43,7 +43,7 @@ class MultiSelect : public QPushButton { Q_OBJECT public: - MultiSelect(const QString& text, QWidget *parent = 0); + MultiSelect(const QString& text, bool user_add_item = false, QWidget *parent = 0); // Items. @@ -61,6 +61,10 @@ 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. @@ -69,6 +73,9 @@ private slots : // 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 From 769e56af2f3d4275fbcf70d9047886d2b947fdd3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:56:41 +0200 Subject: [PATCH 035/204] gui/SearchWindow: adding "Dictionary file" widget. --- gui/SearchWindow.cpp | 71 ++++++++++++++++++++++++++++++-------------- gui/SearchWindow.h | 8 +++-- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 0ae0d5e..cbfa290 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -22,6 +22,7 @@ * SOFTWARE. */ #include +#include #include #include #include @@ -39,6 +40,7 @@ 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") { @@ -55,29 +57,30 @@ m_btn_clear ("Clear") // ------------------------ 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_layout.addWidget(&m_dict_lang, 0, 0); + m_layout.addWidget(&m_dict_file, 0, 1); - m_layout.addWidget(&m_leet_cb, 0, 1); + m_layout.addWidget(&m_leet_cb, 0, 2); m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); m_num_threads.setRange(1, (int) eoskeygen::KeySearch::max_threads()); m_num_threads.setSuffix(" Threads"); - m_layout.addWidget(&m_num_threads, 0, 2); + m_layout.addWidget(&m_num_threads, 0, 3); m_num_results.setValue(10); m_num_results.setRange(1, 99); m_num_results.setSuffix(" Results"); - m_layout.addWidget(&m_num_results, 0, 3); + m_layout.addWidget(&m_num_results, 0, 4); // Second row. - m_layout.addWidget(&m_status, 1, 0, 1, 2); - m_layout.addWidget(&m_txt_search, 1, 0, 1, 2); - m_layout.addWidget(&m_btn_exec, 1, 2); - m_layout.addWidget(&m_btn_clear, 1, 3); - + 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); @@ -105,7 +108,35 @@ void SearchWindow::initSignals() connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); - connect(&m_dict_lang, SIGNAL(selectionChanged(QStringList)), this, SLOT(langSelected(QStringList))); + connect(&m_dict_file, SIGNAL(addNewItem()), this, SLOT(langFileAdd())); +} + +void SearchWindow::loadDictionaries() +{ + QStringList list; + eoskeygen::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 libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) @@ -173,6 +204,8 @@ void SearchWindow::search() return; } + loadDictionaries(); + m_ksearch.clear(); m_ksearch.addList(list); m_ksearch.setThreadCount(m_num_threads.value()); @@ -200,22 +233,12 @@ void SearchWindow::output(const QString& html) m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } -void SearchWindow::langSelected(QStringList selected) +void SearchWindow::langFileAdd() { - std::string base_path(CONFIG_DICT_FULL_PATH); + QStringList files = QFileDialog::getOpenFileNames(this, + "Select one or more language files"); - // Clear dictionary first. - m_dict.clear(); - - // Go through all selected languages. - for(QStringList::const_iterator it = selected.cbegin(); it != selected.cend(); it++) { - - // Load and add them to dictionary. - eoskeygen::Dictionary dict; - dict.loadFromFile(base_path + "/" + it->toStdString()); - - m_dict.add(dict); - } + m_dict_file.addItems(files, true); } void SearchWindow::searchStarted() @@ -223,6 +246,7 @@ void SearchWindow::searchStarted() 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_exec.setEnabled(false); m_btn_clear.setEnabled(false); @@ -235,6 +259,7 @@ void SearchWindow::searchFinished() 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_exec.setEnabled(true); m_btn_clear.setEnabled(true); diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 1aff8b1..c57f17f 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -48,6 +48,8 @@ public: private : void initSignals(); + void loadDictionaries(); + private slots: // Start a search @@ -63,8 +65,8 @@ private slots: // Called when a search is done. void searchFinished(); - // Called when dictionary language(s) are selected. - void langSelected(QStringList selected); + // Called when a new language file should be added + void langFileAdd(); signals: void addOutput(const QString& line); @@ -97,6 +99,8 @@ private: MultiSelect m_dict_lang; + MultiSelect m_dict_file; + // Buttons QPushButton m_btn_exec; QPushButton m_btn_clear; From e9dadc07acb668a23f5cdc582431ec5098dd86f8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 11:12:06 +0200 Subject: [PATCH 036/204] common/src/core/dictionary.cpp: get rid of iostream header --- common/src/core/dictionary.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp index 7446b34..12c8e42 100644 --- a/common/src/core/dictionary.cpp +++ b/common/src/core/dictionary.cpp @@ -22,7 +22,6 @@ * SOFTWARE. */ #include -#include #include #include #include From 3bd9e9856b1b3c5875db0db90258f45107e03977 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:15:39 +0200 Subject: [PATCH 037/204] GUI: Adding GenerateWindow class --- gui/CMakeLists.txt | 1 + gui/GenerateWindow.cpp | 116 +++++++++++++++++++++++++++++++++++++++++ gui/GenerateWindow.hpp | 62 ++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 gui/GenerateWindow.cpp create mode 100644 gui/GenerateWindow.hpp diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7dba68c..7e37389 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -14,6 +14,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp + GenerateWindow.cpp SearchWindow.cpp MultiSelect.cpp helpers.cpp diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp new file mode 100644 index 0000000..8ab00bb --- /dev/null +++ b/gui/GenerateWindow.cpp @@ -0,0 +1,116 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 "GenerateWindow.hpp" + +void _initKeyWidget(QLineEdit& w) { + w.setFixedWidth(450); + 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") +{ + QIcon copy_icon = QIcon::fromTheme("edit-copy"); + QGridLayout* layout; + + _initKeyWidget(m_pub); + _initKeyWidget(m_priv); + + _initKeyCopyButton(m_btn_copy_pub, copy_icon); + _initKeyCopyButton(m_btn_copy_priv, copy_icon); + + // Layout + layout = new QGridLayout(); + layout->setAlignment(Qt::AlignCenter); + + // Public key row + + layout->addWidget(new QLabel("Public:"), 0, 0); + layout->addWidget(&m_pub, 0, 1); + layout->addWidget(&m_btn_copy_pub, 0, 2); + + // Private key row + + layout->addWidget(new QLabel("Private:"), 1, 0); + layout->addWidget(&m_priv, 1, 1); + layout->addWidget(&m_btn_copy_priv, 1, 2); + + // Bottom row + + m_btn_copy_both.setFixedWidth(80); + + layout->addWidget(&m_btn_gen, 2, 1); + layout->addWidget(&m_btn_copy_both, 2, 2); + + 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, privstr; + struct libeosio::ec_keypair pair; + + libeosio::ec_generate_key(&pair); + + m_pub.setText(QString::fromStdString(libeosio::wif_pub_encode(pair.pub))); + m_priv.setText(QString::fromStdString(libeosio::wif_priv_encode(pair.secret))); +} + +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/GenerateWindow.hpp b/gui/GenerateWindow.hpp new file mode 100644 index 0000000..da2a110 --- /dev/null +++ b/gui/GenerateWindow.hpp @@ -0,0 +1,62 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 */ From 8f45d3707a9436348356cd55649220747c59e263 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:17:24 +0200 Subject: [PATCH 038/204] GUI: Adding MainWindow class --- gui/CMakeLists.txt | 1 + gui/MainWindow.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++ gui/MainWindow.hpp | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 gui/MainWindow.cpp create mode 100644 gui/MainWindow.hpp diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7e37389..a9f1f6a 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -14,6 +14,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp + MainWindow.cpp GenerateWindow.cpp SearchWindow.cpp MultiSelect.cpp diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp new file mode 100644 index 0000000..414ea0e --- /dev/null +++ b/gui/MainWindow.cpp @@ -0,0 +1,55 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 "GenerateWindow.hpp" +#include "SearchWindow.h" +#include "MainWindow.hpp" + +MainWindow::MainWindow(QWidget *parent) : +QMainWindow (parent) +{ + // Create sub windows and stacked widget. + m_stacked = new QStackedWidget(); + m_stacked->addWidget(new GenerateWindow()); + m_stacked->addWidget(new SearchWindow()); + + setCentralWidget(m_stacked); + + // Menu bar. + + menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); + menuBar()->addAction("Search", this, SLOT(switchToSearch())); +} + +void MainWindow::switchToGenerate() +{ + m_stacked->setCurrentIndex(0); +} + +void MainWindow::switchToSearch() +{ + m_stacked->setCurrentIndex(1); +} diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp new file mode 100644 index 0000000..1d5d695 --- /dev/null +++ b/gui/MainWindow.hpp @@ -0,0 +1,50 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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 + +class QStackedWidget; + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + +private slots : + + // Switch to generate window. + void switchToGenerate(); + + // Switch to search window. + void switchToSearch(); + +private : + + QStackedWidget* m_stacked; +}; + +#endif /* MAIN_WINDOW_H */ From f6dc9cd0b1bd74be0f72eb71b06a1384d2eb5e6a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:19:14 +0200 Subject: [PATCH 039/204] gui/main.cpp: use MainWindow class. --- gui/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/main.cpp b/gui/main.cpp index 73fe05f..ecd14e6 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -22,15 +22,15 @@ * SOFTWARE. */ #include -#include "SearchWindow.h" +#include "MainWindow.hpp" int main(int argc, char **argv) { QApplication app(argc, argv); - SearchWindow search_win; + MainWindow window; - search_win.show(); + window.show(); return app.exec(); } From 4a3e5a5f62f5809adff12ec39d5bf6a19d6b1fcd Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:24:39 +0200 Subject: [PATCH 040/204] GUI: rename all header files from .h to .hpp --- gui/MainWindow.cpp | 2 +- gui/MultiSelect.cpp | 2 +- gui/{MultiSelect.h => MultiSelect.hpp} | 0 gui/SearchWindow.cpp | 4 ++-- gui/{SearchWindow.h => SearchWindow.hpp} | 2 +- gui/helpers.cpp | 2 +- gui/{helpers.h => helpers.hpp} | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename gui/{MultiSelect.h => MultiSelect.hpp} (100%) rename gui/{SearchWindow.h => SearchWindow.hpp} (99%) rename gui/{helpers.h => helpers.hpp} (100%) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 414ea0e..e4f42a4 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -25,7 +25,7 @@ #include #include #include "GenerateWindow.hpp" -#include "SearchWindow.h" +#include "SearchWindow.hpp" #include "MainWindow.hpp" MainWindow::MainWindow(QWidget *parent) : diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 98c6dac..bccf803 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -26,7 +26,7 @@ #include #include #include -#include "MultiSelect.h" +#include "MultiSelect.hpp" MultiSelect::MultiSelect(const QString& text, bool user_can_add, QWidget *parent) : QPushButton (text + ": none", parent) diff --git a/gui/MultiSelect.h b/gui/MultiSelect.hpp similarity index 100% rename from gui/MultiSelect.h rename to gui/MultiSelect.hpp diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index cbfa290..3b962d5 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -32,8 +32,8 @@ #include #include #include "config.h" -#include "helpers.h" -#include "SearchWindow.h" +#include "helpers.hpp" +#include "SearchWindow.hpp" SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), diff --git a/gui/SearchWindow.h b/gui/SearchWindow.hpp similarity index 99% rename from gui/SearchWindow.h rename to gui/SearchWindow.hpp index c57f17f..49bc41b 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.hpp @@ -35,7 +35,7 @@ #include #include #include -#include "MultiSelect.h" +#include "MultiSelect.hpp" class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { diff --git a/gui/helpers.cpp b/gui/helpers.cpp index 3b492b4..d1574d4 100644 --- a/gui/helpers.cpp +++ b/gui/helpers.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "helpers.h" +#include "helpers.hpp" QStringList get_files(const QDir& directory) { diff --git a/gui/helpers.h b/gui/helpers.hpp similarity index 100% rename from gui/helpers.h rename to gui/helpers.hpp From 0503aa0f049639ea4c1d2acfb11d11041cc0b50d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:31:49 +0200 Subject: [PATCH 041/204] CMakeLists.txt: Add PROJECT_LICENSE_FILE variable. --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b752918..77ad630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ project(eosio-keygen HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) set( PROJECT_MAINTAINER "Henrik Hautakoski ") +set( PROJECT_LICENSE_FILE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) # -------------------------------- # Options @@ -89,7 +90,7 @@ endif() # -------------------------------- # Readme and license -install(FILES README.md LICENSE +install(FILES README.md ${PROJECT_LICENSE_FILE} DESTINATION ${CMAKE_INSTALL_SHAREDIR}) # -------------------------------- @@ -97,7 +98,7 @@ install(FILES README.md LICENSE # -------------------------------- if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") - set( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) + set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) endif() set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) From 54d46004c18eba0f3feef7670c5b8be24b53d911 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 12:59:03 +0200 Subject: [PATCH 042/204] cli: change .h to .hpp --- CMakeLists.txt | 2 +- cli/benchmark.cpp | 2 +- cli/{benchmark.h => benchmark.hpp} | 0 cli/cli_key_search_result.cpp | 4 ++-- ...{cli_key_search_result.h => cli_key_search_result.hpp} | 0 cli/console.cpp | 4 ++-- cli/{console.h => console.hpp} | 0 cli/console_ansi.cpp | 2 +- cli/console_win32.cpp | 2 +- cli/isatty.cpp | 2 +- cli/{isatty.h => isatty.hpp} | 0 cli/main.cpp | 8 ++++---- config.h.in => config.hpp.in | 0 13 files changed, 13 insertions(+), 13 deletions(-) rename cli/{benchmark.h => benchmark.hpp} (100%) rename cli/{cli_key_search_result.h => cli_key_search_result.hpp} (100%) rename cli/{console.h => console.hpp} (100%) rename cli/{isatty.h => isatty.hpp} (100%) rename config.h.in => config.hpp.in (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3748b26..7eac1f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endif() # Project config file -configure_file(config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) +configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) include_directories(${PROJECT_BINARY_DIR}) # -------------------------------- diff --git a/cli/benchmark.cpp b/cli/benchmark.cpp index da384a4..521184e 100644 --- a/cli/benchmark.cpp +++ b/cli/benchmark.cpp @@ -23,7 +23,7 @@ */ #include #include -#include "benchmark.h" +#include "benchmark.hpp" using std::chrono::steady_clock; using std::chrono::duration; diff --git a/cli/benchmark.h b/cli/benchmark.hpp similarity index 100% rename from cli/benchmark.h rename to cli/benchmark.hpp diff --git a/cli/cli_key_search_result.cpp b/cli/cli_key_search_result.cpp index 05d5b57..6817e59 100644 --- a/cli/cli_key_search_result.cpp +++ b/cli/cli_key_search_result.cpp @@ -24,8 +24,8 @@ #include #include #include -#include "console.h" -#include "cli_key_search_result.h" +#include "console.hpp" +#include "cli_key_search_result.hpp" namespace eoskeygen { diff --git a/cli/cli_key_search_result.h b/cli/cli_key_search_result.hpp similarity index 100% rename from cli/cli_key_search_result.h rename to cli/cli_key_search_result.hpp diff --git a/cli/console.cpp b/cli/console.cpp index 2208856..2ed20da 100644 --- a/cli/console.cpp +++ b/cli/console.cpp @@ -22,8 +22,8 @@ * SOFTWARE. */ #include -#include "isatty.h" -#include "console.h" +#include "isatty.hpp" +#include "console.hpp" namespace eoskeygen { namespace console { diff --git a/cli/console.h b/cli/console.hpp similarity index 100% rename from cli/console.h rename to cli/console.hpp diff --git a/cli/console_ansi.cpp b/cli/console_ansi.cpp index 2d34980..75b5412 100644 --- a/cli/console_ansi.cpp +++ b/cli/console_ansi.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include -#include "console.h" +#include "console.hpp" namespace eoskeygen { diff --git a/cli/console_win32.cpp b/cli/console_win32.cpp index d3b1614..813daa0 100644 --- a/cli/console_win32.cpp +++ b/cli/console_win32.cpp @@ -23,7 +23,7 @@ */ #include #include -#include "console.h" +#include "console.hpp" namespace eoskeygen { diff --git a/cli/isatty.cpp b/cli/isatty.cpp index e32fe19..5fdadfb 100644 --- a/cli/isatty.cpp +++ b/cli/isatty.cpp @@ -5,7 +5,7 @@ #define _isatty isatty #define _fileno fileno #endif -#include "isatty.h" +#include "isatty.hpp" namespace eoskeygen { diff --git a/cli/isatty.h b/cli/isatty.hpp similarity index 100% rename from cli/isatty.h rename to cli/isatty.hpp diff --git a/cli/main.cpp b/cli/main.cpp index eb74b8b..ff3c527 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -32,10 +32,10 @@ #include #include #include -#include "cli_key_search_result.h" -#include "console.h" -#include "benchmark.h" -#include "config.h" +#include "cli_key_search_result.hpp" +#include "console.hpp" +#include "benchmark.hpp" +#include "config.hpp" // Command line options. bool option_l33t = false; diff --git a/config.h.in b/config.hpp.in similarity index 100% rename from config.h.in rename to config.hpp.in From 2f16accbba7d40a7b8d9ed17ce6f927e420ef429 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:32:39 +0200 Subject: [PATCH 043/204] Adding gui/gui_about.h.in --- gui/gui_about.h.in | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 gui/gui_about.h.in diff --git a/gui/gui_about.h.in b/gui/gui_about.h.in new file mode 100644 index 0000000..1f6ab9f --- /dev/null +++ b/gui/gui_about.h.in @@ -0,0 +1,37 @@ +/** + * MIT License + * + * Copyright (c) 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 + * 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_ABOUT_H +#define EOSIOKEYGEN_GUI_ABOUT_H + +#define EOSIOKEYGEN_GUI_ABOUT_TITLE "@PROJECT_NAME@ - About" + +#define EOSIOKEYGEN_GUI_ABOUT_TEXT \ + "

@PROJECT_NAME@ - v@PROJECT_VERSION@

" \ + "

@PROJECT_DESCRIPTION@

" \ + "

@PROJECT_HOMEPAGE_URL@

" \ + "@GUI_ABOUT_LICENSE@" \ + "

Author

" \ + "

@GUI_ABOUT_AUTHOR@

" + +#endif /* EOSIOKEYGEN_CONFIG_ABOUT_H */ From 099d6b30083d61e2ce77ff0c2f2bb02f8141308c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:33:02 +0200 Subject: [PATCH 044/204] gui/CMakeLists.txt: Autogenerate gui_config.h from gui_config.h.in --- gui/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index a9f1f6a..3a32d08 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -4,6 +4,18 @@ 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_about.h.in "${CMAKE_CURRENT_BINARY_DIR}/gui_about.h" @ONLY ESCAPE_QUOTES) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + # -------------------------------- # Program # -------------------------------- From c98ed34e6e7e75dd99a6889b09cde432a33ca77f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:33:59 +0200 Subject: [PATCH 045/204] GUI: Implement about dialog in MainWindow. --- gui/MainWindow.cpp | 8 ++++++++ gui/MainWindow.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index e4f42a4..ce2d579 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -21,9 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#include #include #include #include +#include "gui_about.h" #include "GenerateWindow.hpp" #include "SearchWindow.hpp" #include "MainWindow.hpp" @@ -42,6 +44,7 @@ QMainWindow (parent) menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); menuBar()->addAction("Search", this, SLOT(switchToSearch())); + menuBar()->addAction("About", this, SLOT(showAbout())); } void MainWindow::switchToGenerate() @@ -53,3 +56,8 @@ void MainWindow::switchToSearch() { m_stacked->setCurrentIndex(1); } + +void MainWindow::showAbout() +{ + QMessageBox::about(this, EOSIOKEYGEN_GUI_ABOUT_TITLE, EOSIOKEYGEN_GUI_ABOUT_TEXT); +} diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp index 1d5d695..704fa1f 100644 --- a/gui/MainWindow.hpp +++ b/gui/MainWindow.hpp @@ -42,6 +42,8 @@ private slots : // Switch to search window. void switchToSearch(); + void showAbout(); + private : QStackedWidget* m_stacked; From d3e8cc2814007af60ae9f894bf256ba85ecebaac Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 13:51:34 +0200 Subject: [PATCH 046/204] gui/GenerateWindow.cpp: Align labels to the right. --- gui/GenerateWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp index 8ab00bb..6d6c8e9 100644 --- a/gui/GenerateWindow.cpp +++ b/gui/GenerateWindow.cpp @@ -60,13 +60,13 @@ m_btn_copy_both ("Copy keys") // Public key row - layout->addWidget(new QLabel("Public:"), 0, 0); + layout->addWidget(new QLabel("Public:"), 0, 0, Qt::AlignRight); layout->addWidget(&m_pub, 0, 1); layout->addWidget(&m_btn_copy_pub, 0, 2); // Private key row - layout->addWidget(new QLabel("Private:"), 1, 0); + layout->addWidget(new QLabel("Private:"), 1, 0, Qt::AlignRight); layout->addWidget(&m_priv, 1, 1); layout->addWidget(&m_btn_copy_priv, 1, 2); From 460e8149fd074a5380bdfffb421db5bb6180f6f3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 13:58:49 +0200 Subject: [PATCH 047/204] gui/GenerateWindow.cpp: Fix horizontal centering of widget's using QGridLayout::setColumnStretch() --- gui/GenerateWindow.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp index 6d6c8e9..898281c 100644 --- a/gui/GenerateWindow.cpp +++ b/gui/GenerateWindow.cpp @@ -58,24 +58,27 @@ m_btn_copy_both ("Copy keys") layout = new QGridLayout(); layout->setAlignment(Qt::AlignCenter); - // Public key row + // Stretch first and last column to make the widgets horizontally centered. + layout->setColumnStretch(0, 1); + layout->setColumnStretch(4, 1); - layout->addWidget(new QLabel("Public:"), 0, 0, Qt::AlignRight); - layout->addWidget(&m_pub, 0, 1); - layout->addWidget(&m_btn_copy_pub, 0, 2); + // 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, 0, Qt::AlignRight); - layout->addWidget(&m_priv, 1, 1); - layout->addWidget(&m_btn_copy_priv, 1, 2); + 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, 1); - layout->addWidget(&m_btn_copy_both, 2, 2); + layout->addWidget(&m_btn_gen, 2, 2); + layout->addWidget(&m_btn_copy_both, 2, 3); setLayout(layout); From 94686cc4f68ebf5344e91a93b18b7cdfb980e14f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 14:43:36 +0200 Subject: [PATCH 048/204] gui/SearchWindow.cpp: change config.h to config.hpp --- gui/SearchWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 3b962d5..3e7042f 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -31,7 +31,7 @@ #include #include #include -#include "config.h" +#include "config.hpp" #include "helpers.hpp" #include "SearchWindow.hpp" From 9e9e96b9540bba3cd814d9b1de531879f21e10ff Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 19 Apr 2020 11:04:45 +0200 Subject: [PATCH 049/204] README.md: Replace the old libeoskeygen info with libeosio. --- README.md | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 3b72adf..ef8c295 100644 --- a/README.md +++ b/README.md @@ -25,31 +25,6 @@ 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: @@ -134,6 +109,32 @@ These compile options are available: For more details about options run `./build.sh -l` or `mkdir build && cmake build -LA` +### libeosio + +To speed up the build process, you can install `libeosio` + +#### Ubuntu + +You can use [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 libeosio-dev +``` + +or manually via `.deb` file from [github](https://github.com/eosswedenorg/libeosio/releases) + +```sh +$ wget +$ sudo apt install ./libeosio-dev-.deb +``` + +#### Other + +Consult [libeosio's github](https://github.com/eosswedenorg/libeosio) + ## Install After the project has been compiled. run `sudo ./install.sh` or the following code if you dont want to use that: From e5cb4a72f6085268b1d2e404801047402fd07dc9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 19 Apr 2020 11:17:15 +0200 Subject: [PATCH 050/204] libeosio .h files are renamed to .hpp --- cli/benchmark.cpp | 2 +- cli/cli_key_search_result.cpp | 2 +- cli/cli_key_search_result.hpp | 2 +- cli/main.cpp | 6 +++--- common/cmake/libeosio.cmake | 2 +- common/include/eoskeygen/key_search.h | 2 +- common/src/key_search.cpp | 4 ++-- common/src/key_search_mt.cpp | 2 +- gui/GenerateWindow.cpp | 4 ++-- gui/SearchWindow.cpp | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cli/benchmark.cpp b/cli/benchmark.cpp index 521184e..b25fbae 100644 --- a/cli/benchmark.cpp +++ b/cli/benchmark.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include -#include +#include #include "benchmark.hpp" using std::chrono::steady_clock; diff --git a/cli/cli_key_search_result.cpp b/cli/cli_key_search_result.cpp index 6817e59..24cf8c3 100644 --- a/cli/cli_key_search_result.cpp +++ b/cli/cli_key_search_result.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include -#include +#include #include #include "console.hpp" #include "cli_key_search_result.hpp" diff --git a/cli/cli_key_search_result.hpp b/cli/cli_key_search_result.hpp index 0d7e6b2..dcb749c 100644 --- a/cli/cli_key_search_result.hpp +++ b/cli/cli_key_search_result.hpp @@ -24,7 +24,7 @@ #ifndef EOSIOKEYGEN_KEY_SEARCH_HELPERS_H #define EOSIOKEYGEN_KEY_SEARCH_HELPERS_H -#include +#include #include #include #include diff --git a/cli/main.cpp b/cli/main.cpp index ff3c527..a68a894 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -23,9 +23,9 @@ */ #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index b739349..5c1499b 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION 137d5cbe31666a748954dd233e54c5703480ebbf ) +set( LIBEOSIO_WANTED_VERSION aa7f3041185e5c28b03279636d1ba2446ed740ab ) # -------------------------------- # Macros diff --git a/common/include/eoskeygen/key_search.h b/common/include/eoskeygen/key_search.h index 688def0..94bbd79 100644 --- a/common/include/eoskeygen/key_search.h +++ b/common/include/eoskeygen/key_search.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp index e97e14a..d849d78 100644 --- a/common/src/key_search.cpp +++ b/common/src/key_search.cpp @@ -21,8 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include -#include +#include +#include #include #include #include diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp index 2e498ff..abd74c3 100644 --- a/common/src/key_search_mt.cpp +++ b/common/src/key_search_mt.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp index 898281c..ffefda0 100644 --- a/gui/GenerateWindow.cpp +++ b/gui/GenerateWindow.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include "GenerateWindow.hpp" void _initKeyWidget(QLineEdit& w) { diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 3e7042f..bdc77c4 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include "config.hpp" From 9dacf00c7f09d1b827cbe74a532580ff8bb7939b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 19 Apr 2020 15:35:50 +0200 Subject: [PATCH 051/204] common/cmake/libeosio.cmake: use v0.1.0 --- common/cmake/libeosio.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index 5c1499b..4dbdcc5 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION aa7f3041185e5c28b03279636d1ba2446ed740ab ) +set( LIBEOSIO_WANTED_VERSION v0.1.0 ) # -------------------------------- # Macros From a85c9b50902ecba0a8d30f184fcd1efdebf34231 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 19 Apr 2020 15:44:07 +0200 Subject: [PATCH 052/204] change remaining .h files to .hpp --- cli/cli_key_search_result.cpp | 2 +- cli/cli_key_search_result.hpp | 6 ++-- cli/main.cpp | 12 ++++---- common/CMakeLists.txt | 2 +- common/{src/config.h.in => config.hpp.in} | 0 common/include/eoskeygen/config.hpp | 30 +++++++++++++++++++ .../core/{dictionary.h => dictionary.hpp} | 0 .../eoskeygen/core/{file.h => file.hpp} | 2 +- .../eoskeygen/core/{leet.h => leet.hpp} | 2 +- .../eoskeygen/core/{string.h => string.hpp} | 0 .../eoskeygen/core/{strlist.h => strlist.hpp} | 0 .../{key_search.h => key_search.hpp} | 6 ++-- ..._search_result.h => key_search_result.hpp} | 2 +- common/src/core/dictionary.cpp | 6 ++-- common/src/core/file.cpp | 4 +-- common/src/core/leet.cpp | 2 +- common/src/core/string.cpp | 2 +- common/src/core/strlist.cpp | 4 +-- common/src/key_search.cpp | 8 ++--- common/src/key_search_mt.cpp | 4 +-- gui/SearchWindow.cpp | 4 +-- gui/SearchWindow.hpp | 4 +-- 22 files changed, 66 insertions(+), 36 deletions(-) rename common/{src/config.h.in => config.hpp.in} (100%) create mode 100644 common/include/eoskeygen/config.hpp rename common/include/eoskeygen/core/{dictionary.h => dictionary.hpp} (100%) rename common/include/eoskeygen/core/{file.h => file.hpp} (97%) rename common/include/eoskeygen/core/{leet.h => leet.hpp} (97%) rename common/include/eoskeygen/core/{string.h => string.hpp} (100%) rename common/include/eoskeygen/core/{strlist.h => strlist.hpp} (100%) rename common/include/eoskeygen/{key_search.h => key_search.hpp} (96%) rename common/include/eoskeygen/{key_search_result.h => key_search_result.hpp} (97%) diff --git a/cli/cli_key_search_result.cpp b/cli/cli_key_search_result.cpp index 24cf8c3..7ec6b18 100644 --- a/cli/cli_key_search_result.cpp +++ b/cli/cli_key_search_result.cpp @@ -23,7 +23,7 @@ */ #include #include -#include +#include #include "console.hpp" #include "cli_key_search_result.hpp" diff --git a/cli/cli_key_search_result.hpp b/cli/cli_key_search_result.hpp index dcb749c..c9a2e15 100644 --- a/cli/cli_key_search_result.hpp +++ b/cli/cli_key_search_result.hpp @@ -25,9 +25,9 @@ #define EOSIOKEYGEN_KEY_SEARCH_HELPERS_H #include -#include -#include -#include +#include +#include +#include namespace eoskeygen { diff --git a/cli/main.cpp b/cli/main.cpp index a68a894..aa34553 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -26,12 +26,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "cli_key_search_result.hpp" #include "console.hpp" #include "benchmark.hpp" diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index fa9e2d5..e268a16 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -34,7 +34,7 @@ if (USE_THREADS) endif (USE_THREADS) # Project config file -configure_file(src/config.h.in "${CMAKE_CURRENT_LIST_DIR}/include/eoskeygen/config.h" @ONLY) +configure_file(config.hpp.in "${CMAKE_CURRENT_LIST_DIR}/include/eoskeygen/config.hpp" @ONLY) add_library( ${COMMON_NAME} STATIC ${COMMON_SOURCE} ) diff --git a/common/src/config.h.in b/common/config.hpp.in similarity index 100% rename from common/src/config.h.in rename to common/config.hpp.in diff --git a/common/include/eoskeygen/config.hpp b/common/include/eoskeygen/config.hpp new file mode 100644 index 0000000..5728f1f --- /dev/null +++ b/common/include/eoskeygen/config.hpp @@ -0,0 +1,30 @@ +/** + * MIT License + * + * 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 + * 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_COMMON_CONFIG_H +#define EOSIOKEYGEN_COMMON_CONFIG_H + +// Defined if we have thread support. +#define EOSIOKEYGEN_HAVE_THREADS + +#endif /* EOSIOKEYGEN_COMMON_CONFIG_H */ diff --git a/common/include/eoskeygen/core/dictionary.h b/common/include/eoskeygen/core/dictionary.hpp similarity index 100% rename from common/include/eoskeygen/core/dictionary.h rename to common/include/eoskeygen/core/dictionary.hpp diff --git a/common/include/eoskeygen/core/file.h b/common/include/eoskeygen/core/file.hpp similarity index 97% rename from common/include/eoskeygen/core/file.h rename to common/include/eoskeygen/core/file.hpp index fffebaa..6f5c7e3 100644 --- a/common/include/eoskeygen/core/file.h +++ b/common/include/eoskeygen/core/file.hpp @@ -24,7 +24,7 @@ #ifndef EOSIOKEYGEN_COMMON_CORE_FILE_H #define EOSIOKEYGEN_COMMON_CORE_FILE_H -#include +#include namespace eoskeygen { diff --git a/common/include/eoskeygen/core/leet.h b/common/include/eoskeygen/core/leet.hpp similarity index 97% rename from common/include/eoskeygen/core/leet.h rename to common/include/eoskeygen/core/leet.hpp index 01289fc..7631052 100644 --- a/common/include/eoskeygen/core/leet.h +++ b/common/include/eoskeygen/core/leet.hpp @@ -25,7 +25,7 @@ #define EOSIOKEYGEN_COMMON_CORE_LEET_H #include -#include +#include namespace eoskeygen { diff --git a/common/include/eoskeygen/core/string.h b/common/include/eoskeygen/core/string.hpp similarity index 100% rename from common/include/eoskeygen/core/string.h rename to common/include/eoskeygen/core/string.hpp diff --git a/common/include/eoskeygen/core/strlist.h b/common/include/eoskeygen/core/strlist.hpp similarity index 100% rename from common/include/eoskeygen/core/strlist.h rename to common/include/eoskeygen/core/strlist.hpp diff --git a/common/include/eoskeygen/key_search.h b/common/include/eoskeygen/key_search.hpp similarity index 96% rename from common/include/eoskeygen/key_search.h rename to common/include/eoskeygen/key_search.hpp index 94bbd79..f757002 100644 --- a/common/include/eoskeygen/key_search.h +++ b/common/include/eoskeygen/key_search.hpp @@ -27,9 +27,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include namespace eoskeygen { diff --git a/common/include/eoskeygen/key_search_result.h b/common/include/eoskeygen/key_search_result.hpp similarity index 97% rename from common/include/eoskeygen/key_search_result.h rename to common/include/eoskeygen/key_search_result.hpp index 943e6d9..825ebae 100644 --- a/common/include/eoskeygen/key_search_result.h +++ b/common/include/eoskeygen/key_search_result.hpp @@ -24,7 +24,7 @@ #ifndef EOSIOKEYGEN_COMMON_KEY_SEARCH_RESULT_H #define EOSIOKEYGEN_COMMON_KEY_SEARCH_RESULT_H -#include +#include namespace eoskeygen { diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp index 12c8e42..11bd50b 100644 --- a/common/src/core/dictionary.cpp +++ b/common/src/core/dictionary.cpp @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include namespace eoskeygen { diff --git a/common/src/core/file.cpp b/common/src/core/file.cpp index ac73356..74f4c5e 100644 --- a/common/src/core/file.cpp +++ b/common/src/core/file.cpp @@ -22,8 +22,8 @@ * SOFTWARE. */ #include -#include -#include +#include +#include namespace eoskeygen { diff --git a/common/src/core/leet.cpp b/common/src/core/leet.cpp index bf0e7f1..75bed31 100644 --- a/common/src/core/leet.cpp +++ b/common/src/core/leet.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include -#include +#include namespace eoskeygen { diff --git a/common/src/core/string.cpp b/common/src/core/string.cpp index 164e362..1851a01 100644 --- a/common/src/core/string.cpp +++ b/common/src/core/string.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace eoskeygen { diff --git a/common/src/core/strlist.cpp b/common/src/core/strlist.cpp index ea12151..6212a35 100644 --- a/common/src/core/strlist.cpp +++ b/common/src/core/strlist.cpp @@ -22,8 +22,8 @@ * SOFTWARE. */ #include -#include -#include +#include +#include namespace eoskeygen { diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp index d849d78..810f884 100644 --- a/common/src/key_search.cpp +++ b/common/src/key_search.cpp @@ -23,10 +23,10 @@ */ #include #include -#include -#include -#include -#include +#include +#include +#include +#include namespace eoskeygen { diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp index abd74c3..00e50e3 100644 --- a/common/src/key_search_mt.cpp +++ b/common/src/key_search_mt.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include namespace eoskeygen { diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index bdc77c4..3a71a5d 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -29,8 +29,8 @@ #include #include #include -#include -#include +#include +#include #include "config.hpp" #include "helpers.hpp" #include "SearchWindow.hpp" diff --git a/gui/SearchWindow.hpp b/gui/SearchWindow.hpp index 49bc41b..a918d0b 100644 --- a/gui/SearchWindow.hpp +++ b/gui/SearchWindow.hpp @@ -33,8 +33,8 @@ #include #include #include -#include -#include +#include +#include #include "MultiSelect.hpp" class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult From 4741eb684f064b0cbff47ce3486cbf99c82f12b1 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 16:54:35 +0200 Subject: [PATCH 053/204] common/.gitignore: ignore correct header file. --- common/.gitignore | 2 +- common/include/eoskeygen/config.hpp | 30 ----------------------------- 2 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 common/include/eoskeygen/config.hpp diff --git a/common/.gitignore b/common/.gitignore index 9375aee..3d2564d 100644 --- a/common/.gitignore +++ b/common/.gitignore @@ -1 +1 @@ -include/eoskeygen/config.h +include/eoskeygen/config.h* diff --git a/common/include/eoskeygen/config.hpp b/common/include/eoskeygen/config.hpp deleted file mode 100644 index 5728f1f..0000000 --- a/common/include/eoskeygen/config.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - * MIT License - * - * 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 - * 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_COMMON_CONFIG_H -#define EOSIOKEYGEN_COMMON_CONFIG_H - -// Defined if we have thread support. -#define EOSIOKEYGEN_HAVE_THREADS - -#endif /* EOSIOKEYGEN_COMMON_CONFIG_H */ From c1b2bfce0d8d79917118bb777989a9425985e7f5 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 16:57:10 +0200 Subject: [PATCH 054/204] README.md: adding --disabled-threads documentation again. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef8c295..c8db1d0 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,8 @@ C:\repo\build> cmake --build . --config Release These compile options are available: | Cmake | build.sh | Description | -|--------------------------- | ----------------- | ------------------------------------------| +|--------------------------- | ----------------- | ----------------------------------------- | +| -DUSE_THREADS=`OFF` | --disable-threads | Disable thread support | | -DCMAKE_BUILD_TYPE=`value` | -t `value` | Type of build | | -DFORCE_ANSI=`ON` | --force-ansi | Force ANSI console colors even on windows | From 22222c1d7c6b5731750255d4b408eeca919f4233 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 17:11:07 +0200 Subject: [PATCH 055/204] gui/SearchWindow: Respect EOSIOKEYGEN_HAVE_THREADS define. --- gui/SearchWindow.cpp | 8 ++++++++ gui/SearchWindow.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 3a71a5d..2f36d81 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -66,10 +66,12 @@ m_btn_clear ("Clear") m_layout.addWidget(&m_leet_cb, 0, 2); +#ifdef EOSIOKEYGEN_HAVE_THREADS m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); m_num_threads.setRange(1, (int) eoskeygen::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); @@ -208,7 +210,9 @@ void SearchWindow::search() 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, &eoskeygen::KeySearch::find, m_num_results.value()); m_worker.setFuture(future); @@ -250,7 +254,9 @@ void SearchWindow::searchStarted() m_leet_cb.setEnabled(false); m_btn_exec.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); } @@ -263,6 +269,8 @@ void SearchWindow::searchFinished() m_leet_cb.setEnabled(true); m_btn_exec.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/SearchWindow.hpp b/gui/SearchWindow.hpp index a918d0b..bd622d7 100644 --- a/gui/SearchWindow.hpp +++ b/gui/SearchWindow.hpp @@ -89,8 +89,10 @@ private: // 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; From 6181af62120c23316377e8ad30ecc96eae5a449e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 17:11:43 +0200 Subject: [PATCH 056/204] README.md: Document --no-cli,--gui build flags. --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c8db1d0..5e154aa 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,13 @@ C:\repo\build> cmake --build . --config Release These compile options are available: -| Cmake | build.sh | Description | -|--------------------------- | ----------------- | ----------------------------------------- | -| -DUSE_THREADS=`OFF` | --disable-threads | Disable thread support | -| -DCMAKE_BUILD_TYPE=`value` | -t `value` | Type of build | -| -DFORCE_ANSI=`ON` | --force-ansi | Force ANSI console colors even on windows | +| Cmake | build.sh | Description | +|---------------------------- | ----------------- | ----------------------------------------- | +| -DBUILD_COMPONENT_CLI=`OFF` | --no-cli | Do not build cli program | +| -DBUILD_COMPONENT_GUI=`ON` | --gui | Build gui program (Qt5) | +| -DUSE_THREADS=`OFF` | --disable-threads | Disable thread support | +| -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` From 7a8867bb3c8779f0b10159d4a0e97b8dcecf19b7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 17:15:38 +0200 Subject: [PATCH 057/204] build.sh: Adding --no-cli,--gui flags --- build.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 05ef766..06da719 100755 --- a/build.sh +++ b/build.sh @@ -1,11 +1,11 @@ #!/bin/bash function usage() { - echo "Usage: ${0##*/} [ -h|--help ] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" + echo "Usage: ${0##*/} [ -h|--help ] [ --no-cli ] [ --gui] [ -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,type:,pkg-type:,disable-threads,force-ansi" -- "$@") +options=$(getopt -n "${0##*/}" -o "lht:" -l "help,no-cli,gui,type:,pkg-type:,disable-threads,force-ansi" -- "$@") [ $? -eq 0 ] || usage @@ -33,6 +33,10 @@ while true; do TARGET="package" ARGS="${ARGS} -DCPACK_GENERATOR=${1^^}" ;; + --no-cli) + ARGS="${ARGS} -DBUILD_COMPONENT_CLI=OFF" ;; + --gui) + ARGS="${ARGS} -DBUILD_COMPONENT_GUI=ON" ;; --disable-threads) ARGS="${ARGS} -DUSE_THREADS=OFF" ;; --force-ansi) @@ -48,6 +52,9 @@ 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 --clean-first --target ${TARGET} From 54e493de1f50b652777d70b31e48c4c97215dcba Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 20 Apr 2020 18:11:46 +0200 Subject: [PATCH 058/204] .github/workflows/ci.yml: update build matrix to cover all configurations. --- .github/workflows/ci.yml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af10bb7..cec2909 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,15 +12,20 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] - build: [ cli-force-ansi-on, cli-force-ansi-off, gui ] + build: [ cli, cli-mt, cli-ansi, cli-ansi-mt, gui, gui-mt ] include: - - build: cli-force-ansi-on - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON - - build: cli-force-ansi-off - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON + - build: cli + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=OFF + - build: cli-mt + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=ON + - build: cli-ansi + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=OFF + - build: cli-ansi-mt + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=ON - build: gui - cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON - + cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON -DUSE_THREADS=OFF + - build: gui-mt + cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON -DUSE_THREADS=ON name: ${{matrix.os}} (${{matrix.build}}) runs-on: ${{matrix.os}} @@ -34,12 +39,12 @@ jobs: run: brew install openssl - name: Qt - Ubuntu - if: matrix.build == 'gui' && runner.os == 'Linux' + if: startsWith(matrix.build, 'gui') && runner.os == 'Linux' shell: bash run: sudo apt-get install qt5-default - name: Qt - Windows/Mac - if: matrix.build == 'gui' && runner.os != 'Linux' + if: startsWith(matrix.build, 'gui') && runner.os != 'Linux' uses: jurplel/install-qt-action@v2 with: version: '5.9' From 884f8a612518635465c5f0989bfcc5e12ed6a5b0 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 21 Apr 2020 10:06:10 +0200 Subject: [PATCH 059/204] cli: move source files. --- cli/CMakeLists.txt | 14 +++++++------- cli/{ => src}/benchmark.cpp | 0 cli/{ => src}/benchmark.hpp | 0 cli/{ => src}/cli_key_search_result.cpp | 0 cli/{ => src}/cli_key_search_result.hpp | 0 cli/{ => src}/console.cpp | 0 cli/{ => src}/console.hpp | 0 cli/{ => src}/console_ansi.cpp | 0 cli/{ => src}/console_win32.cpp | 0 cli/{ => src}/isatty.cpp | 0 cli/{ => src}/isatty.hpp | 0 cli/{ => src}/main.cpp | 0 12 files changed, 7 insertions(+), 7 deletions(-) rename cli/{ => src}/benchmark.cpp (100%) rename cli/{ => src}/benchmark.hpp (100%) rename cli/{ => src}/cli_key_search_result.cpp (100%) rename cli/{ => src}/cli_key_search_result.hpp (100%) rename cli/{ => src}/console.cpp (100%) rename cli/{ => src}/console.hpp (100%) rename cli/{ => src}/console_ansi.cpp (100%) rename cli/{ => src}/console_win32.cpp (100%) rename cli/{ => src}/isatty.cpp (100%) rename cli/{ => src}/isatty.hpp (100%) rename cli/{ => src}/main.cpp (100%) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 9080728..f08a281 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -8,18 +8,18 @@ option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) set (PROGRAM_EXE ${CMAKE_PROJECT_NAME}) set (PROGRAM_SOURCE - isatty.cpp - cli_key_search_result.cpp - console.cpp - benchmark.cpp - main.cpp + 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} console_win32.cpp) + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_win32.cpp) else() # *nix should have ansi support. - set (PROGRAM_SOURCE ${PROGRAM_SOURCE} console_ansi.cpp) + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_ansi.cpp) endif() add_executable( ${PROGRAM_EXE} ${PROGRAM_SOURCE} ) diff --git a/cli/benchmark.cpp b/cli/src/benchmark.cpp similarity index 100% rename from cli/benchmark.cpp rename to cli/src/benchmark.cpp diff --git a/cli/benchmark.hpp b/cli/src/benchmark.hpp similarity index 100% rename from cli/benchmark.hpp rename to cli/src/benchmark.hpp diff --git a/cli/cli_key_search_result.cpp b/cli/src/cli_key_search_result.cpp similarity index 100% rename from cli/cli_key_search_result.cpp rename to cli/src/cli_key_search_result.cpp diff --git a/cli/cli_key_search_result.hpp b/cli/src/cli_key_search_result.hpp similarity index 100% rename from cli/cli_key_search_result.hpp rename to cli/src/cli_key_search_result.hpp diff --git a/cli/console.cpp b/cli/src/console.cpp similarity index 100% rename from cli/console.cpp rename to cli/src/console.cpp diff --git a/cli/console.hpp b/cli/src/console.hpp similarity index 100% rename from cli/console.hpp rename to cli/src/console.hpp diff --git a/cli/console_ansi.cpp b/cli/src/console_ansi.cpp similarity index 100% rename from cli/console_ansi.cpp rename to cli/src/console_ansi.cpp diff --git a/cli/console_win32.cpp b/cli/src/console_win32.cpp similarity index 100% rename from cli/console_win32.cpp rename to cli/src/console_win32.cpp diff --git a/cli/isatty.cpp b/cli/src/isatty.cpp similarity index 100% rename from cli/isatty.cpp rename to cli/src/isatty.cpp diff --git a/cli/isatty.hpp b/cli/src/isatty.hpp similarity index 100% rename from cli/isatty.hpp rename to cli/src/isatty.hpp diff --git a/cli/main.cpp b/cli/src/main.cpp similarity index 100% rename from cli/main.cpp rename to cli/src/main.cpp From 4a83b06ef20e192de0ba208f717221588133925d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 21 Apr 2020 14:22:42 +0200 Subject: [PATCH 060/204] CMake: new CPack structure with config defined in sub directories. --- CMakeLists.txt | 44 +++++++++++-------- cli/CMakeLists.txt | 26 +++++++++-- cli/cmake/CPackComponentConfig.cmake.in | 13 ++++++ .../{cpack_custom.cmake => CPackConfig.cmake} | 13 +----- cmake/CPackProperties.cmake.in | 7 +++ gui/CMakeLists.txt | 19 ++++++-- gui/cmake/CPackComponentConfig.cmake.in | 16 +++++++ 7 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 cli/cmake/CPackComponentConfig.cmake.in rename cmake/{cpack_custom.cmake => CPackConfig.cmake} (88%) create mode 100644 cmake/CPackProperties.cmake.in create mode 100644 gui/cmake/CPackComponentConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c48bb2..97d5d09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,29 @@ endif() configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) include_directories(${PROJECT_BINARY_DIR}) +# -------------------------------- +# Install +# -------------------------------- + +# Readme and license +install(FILES README.md ${PROJECT_LICENSE_FILE} + DESTINATION ${CMAKE_INSTALL_SHAREDIR}) + +# -------------------------------- +# Package +# -------------------------------- + +include(CPackConfig) + +set( CPACK_COMPONENTS_ALL cli gui ) + +if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") + set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) +endif() + +set (CPACK_PROPERTIES_FILE ${PROJECT_BINARY_DIR}/CPackComponentsInclude.cmake) +configure_file(cmake/CPackProperties.cmake.in ${CPACK_PROPERTIES_FILE} @ONLY) + # -------------------------------- # Components # -------------------------------- @@ -90,23 +113,6 @@ if (BUILD_COMPONENT_GUI) endif() # -------------------------------- -# Install +# CPack # -------------------------------- - -# Readme and license -install(FILES README.md ${PROJECT_LICENSE_FILE} - DESTINATION ${CMAKE_INSTALL_SHAREDIR}) - -# -------------------------------- -# Package -# -------------------------------- - -if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") - set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) -endif() - -set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) -set( CPACK_DEBIAN_PACKAGE_SECTION "misc" ) -set( CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON ) - -include( cpack_custom ) +include (CPack) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index f08a281..76c8621 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,3 +1,13 @@ +cmake_minimum_required(VERSION 3.15) + +# -------------------------------- +# Project Info +# -------------------------------- + +project(eosio-keygen + VERSION ${CMAKE_PROJECT_VERSION} + LANGUAGES CXX) + # Options option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) @@ -5,7 +15,7 @@ option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) # Program # -------------------------------- -set (PROGRAM_EXE ${CMAKE_PROJECT_NAME}) +set (PROGRAM_EXE ${PROJECT_NAME}) set (PROGRAM_SOURCE src/isatty.cpp @@ -30,7 +40,9 @@ target_link_libraries( ${PROGRAM_EXE} PUBLIC common ) # Install # -------------------------------- -install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(TARGETS ${PROGRAM_EXE} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT cli) # Documentation @@ -38,5 +50,13 @@ 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}) + 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 new file mode 100644 index 0000000..d1b5c1b --- /dev/null +++ b/cli/cmake/CPackComponentConfig.cmake.in @@ -0,0 +1,13 @@ + +# -------------------------------- +# CPack Component Config +# -------------------------------- + +set( CPACK_PACKAGE_CLI_NAME "${PROJECT_NAME}" ) +set( CPACK_PACKAGE_CLI_CONTACT "${PROJECT_MAINTAINER}" ) + +# 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_PRIORITY "optional" ) +set( CPACK_DEBIAN_CLI_PACKAGE_SECTION "misc" ) +set( CPACK_DEBIAN_CLI_PACKAGE_DEPENDS "libssl1.1 (>= 1.1.0), libstdc++6 (>= 6)") diff --git a/cmake/cpack_custom.cmake b/cmake/CPackConfig.cmake similarity index 88% rename from cmake/cpack_custom.cmake rename to cmake/CPackConfig.cmake index d4fad9b..9dd5e7a 100644 --- a/cmake/cpack_custom.cmake +++ b/cmake/CPackConfig.cmake @@ -93,10 +93,8 @@ 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}" ) -# 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" -) +# Always build components for deb packages +set( CPACK_DEB_COMPONENT_INSTALL ON ) # -------------------------------- @@ -112,10 +110,3 @@ if (NOT CPACK_GENERATOR) set( CPACK_GENERATOR "ZIP" ) endif() endif() - - -# -------------------------------- -# Include original CPack module. -# -------------------------------- - -include( CPack ) diff --git a/cmake/CPackProperties.cmake.in b/cmake/CPackProperties.cmake.in new file mode 100644 index 0000000..6a75e0c --- /dev/null +++ b/cmake/CPackProperties.cmake.in @@ -0,0 +1,7 @@ + +# 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/gui/CMakeLists.txt b/gui/CMakeLists.txt index 3a32d08..7d7911e 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -1,3 +1,9 @@ +cmake_minimum_required(VERSION 3.15) + +project(eosio-keygen-gui + VERSION ${CMAKE_PROJECT_VERSION} + DESCRIPTION "Keygenerator for EOSIO (gui)" + LANGUAGES CXX) # Qt5 needs MOC,RCC and UIC set( CMAKE_AUTOMOC ON ) @@ -20,9 +26,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) # Program # -------------------------------- -set( COMPONENT_NAME ${CMAKE_PROJECT_NAME}-gui) - -set( PROGRAM_EXE ${COMPONENT_NAME} ) +set( PROGRAM_EXE ${PROJECT_NAME} ) set( PROGRAM_SRC main.cpp @@ -45,4 +49,11 @@ target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets com install(TARGETS ${PROGRAM_EXE} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT ${COMPONENT_NAME}) + COMPONENT gui) + +# -------------------------------- +# Package +# -------------------------------- + +configure_file(cmake/CPackComponentConfig.cmake.in + ${PROJECT_BINARY_DIR}/CPackProperties.cmake) diff --git a/gui/cmake/CPackComponentConfig.cmake.in b/gui/cmake/CPackComponentConfig.cmake.in new file mode 100644 index 0000000..ff52fc4 --- /dev/null +++ b/gui/cmake/CPackComponentConfig.cmake.in @@ -0,0 +1,16 @@ + +# -------------------------------- +# 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_PRIORITY "optional" ) +set( CPACK_DEBIAN_GUI_PACKAGE_SECTION "misc" ) +set( CPACK_DEBIAN_GUI_PACKAGE_SHLIBDEPS ON ) From 404c203488d67cc735388155f358bea8fe22f16d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 22 Apr 2020 12:17:54 +0200 Subject: [PATCH 061/204] README.md: Change libeoskeygen to libeosio --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5e154aa..f1ce300 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This program generates public and private keypair for [EOS](https://eos.io/) ## Compile -You will need `libeoskeygen` and `cmake 3.15` or later to compile this project. +You will need `libeosio` and `cmake 3.15` or later to compile this project. ### Linux/MacOS @@ -56,7 +56,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. -`libeoskeygen` needs to be compiled and installed from source. [Go here](https://github.com/eosswedenorg/libeoskeygen) +`libeosio` needs to be compiled and installed from source. [Go here](https://github.com/eosswedenorg/libeosio) #### Build From a350dd5846ecfd49bc58459d362b114213144efe Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 22 Apr 2020 15:37:04 +0200 Subject: [PATCH 062/204] CMakeLists.txt: Fixing compile flags for MSVC Use set_compile_options() with cmake generator expression to define flags for all configurations and compilers in a compact way. --- CMakeLists.txt | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97d5d09..4697bc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,15 +61,22 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF ) # c++ flags -set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g" ) -set( CMAKE_CXX_FLAGS_RELEASE "-O3" ) -set( CMAKE_CXX_FLAGS_MINSIZEREL "-Os" ) +add_compile_options( + "$<$:-Werror;-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>>" + + # Release + "$<$:$<$:-O3>>" + "$<$:$<$:/O2>>" + + # MinSizeRel + "$<$:$<$:-Os>>" + "$<$:$<$:/O1>>" +) # Project config file configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) From 8d925536bab0c824962cb54069dc37a105c9d89c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 22 Apr 2020 18:01:40 +0200 Subject: [PATCH 063/204] build.sh: add nsis to --pkg-type --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 06da719..b623cdc 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash function usage() { - echo "Usage: ${0##*/} [ -h|--help ] [ --no-cli ] [ --gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" + echo "Usage: ${0##*/} [ -h|--help ] [ --no-cli ] [ --gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type nsis|deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" exit 1 } @@ -26,7 +26,7 @@ while true; do ;; --pkg-type) shift - [[ ! "$1" =~ ^(deb|zip|tgz)$ ]] && { + [[ ! "$1" =~ ^(nsis|deb|zip|tgz)$ ]] && { echo "Incorrect package type '$1' provided" usage } From 00b9177f3aae13aab5d50b42349e6a748c8cfd04 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 23 Apr 2020 10:00:23 +0200 Subject: [PATCH 064/204] gui/CMakeLists.txt: add "WIN32" flag to add_executable This makes cmake configure the compiler to create a gui app (e.g. not opening a console window that spawns a gui window as a child process) --- gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7d7911e..17e3166 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -37,7 +37,7 @@ set( PROGRAM_SRC helpers.cpp ) -add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) +add_executable( ${PROGRAM_EXE} WIN32 ${PROGRAM_SRC} ) # Libraries find_package( Qt5 COMPONENTS Concurrent Core Widgets REQUIRED ) From bfd254f48404edfd83df0e05dcb2c5c3706b9082 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 23 Apr 2020 16:30:30 +0200 Subject: [PATCH 065/204] CMake: Adding alot of code to handle .ddl's on windows using windeployqt --- gui/cmake/QtUtils.cmake | 110 ++++++++++++++++++++++++++++ gui/cmake/cmake_install_qt.cmake.in | 23 ++++++ 2 files changed, 133 insertions(+) create mode 100644 gui/cmake/QtUtils.cmake create mode 100644 gui/cmake/cmake_install_qt.cmake.in diff --git a/gui/cmake/QtUtils.cmake b/gui/cmake/QtUtils.cmake new file mode 100644 index 0000000..694d1be --- /dev/null +++ b/gui/cmake/QtUtils.cmake @@ -0,0 +1,110 @@ + +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 new file mode 100644 index 0000000..da01764 --- /dev/null +++ b/gui/cmake/cmake_install_qt.cmake.in @@ -0,0 +1,23 @@ + +# 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() From 4436f769e652d5f165cc2d455a205593a74024ca Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 23 Apr 2020 16:31:24 +0200 Subject: [PATCH 066/204] gui/CMakeLists.txt: use the new Qt stuff. --- gui/CMakeLists.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 17e3166..9734e0d 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -5,6 +5,11 @@ project(eosio-keygen-gui DESCRIPTION "Keygenerator for EOSIO (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 ) @@ -40,8 +45,14 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} WIN32 ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 COMPONENTS Concurrent Core Widgets REQUIRED ) -target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets common ) +target_link_libraries( ${PROGRAM_EXE} common ) + +# QT +qt5_app(TARGET ${PROGRAM_EXE} + SKIP_TRANSLATIONS + MODULES Core Gui Widgets Concurrent + INSTALL_COMPONENT gui +) # -------------------------------- # Install From a390d4226f5ab227a74bfb2f79b4e722b4184c7c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 23 Apr 2020 16:35:23 +0200 Subject: [PATCH 067/204] CMakeLists.txt: Set CMAKE_INSTALL_BINDIR to "bin" on windows With Qt we have alot more files then just the two .exe's --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4697bc4..7664ef3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ set( CMAKE_INSTALL_SHAREDIR ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME} ) if (WIN32) # "Flat" install on windows. - set( CMAKE_INSTALL_BINDIR "." ) + set( CMAKE_INSTALL_BINDIR "bin" ) set( CMAKE_INSTALL_DATADIR "." ) set( CMAKE_INSTALL_SHAREDIR "." ) set( CMAKE_INSTALL_MANDIR "." ) From 56c188688084526cbcf23e134de286daf4782e86 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 23 Apr 2020 16:57:48 +0200 Subject: [PATCH 068/204] gui/cmake/QtUtils.cmake: the value _install_args should not be in quotes. --- gui/cmake/QtUtils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/cmake/QtUtils.cmake b/gui/cmake/QtUtils.cmake index 694d1be..7d91a73 100644 --- a/gui/cmake/QtUtils.cmake +++ b/gui/cmake/QtUtils.cmake @@ -70,7 +70,7 @@ function(qt5_win_deploy) configure_file(${_QT_INSTALL_CONFIG_TEMPLATE} ${_QT_INSTALL_CONFIG} @ONLY) if (_deploy_INSTALL_COMPONENT) - set(_install_args "COMPONENT ${_deploy_INSTALL_COMPONENT}") + set(_install_args COMPONENT ${_deploy_INSTALL_COMPONENT}) endif() install(SCRIPT ${_QT_INSTALL_CONFIG} ${_install_args}) From 2d1c0d078528c466844436fdf2502ffdc6fadcb9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 12:01:24 +0200 Subject: [PATCH 069/204] CMake: rename BUILD_COMPONENT_* options to COMPONENT_* --- .github/workflows/ci.yml | 12 ++++++------ CMakeLists.txt | 10 +++++----- README.md | 14 +++++++------- build.sh | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cec2909..9ff243d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,17 +15,17 @@ jobs: build: [ cli, cli-mt, cli-ansi, cli-ansi-mt, gui, gui-mt ] include: - build: cli - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=OFF + cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=OFF - build: cli-mt - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=ON + cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=OFF -DUSE_THREADS=ON - build: cli-ansi - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=OFF + cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=OFF - build: cli-ansi-mt - cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=ON + cmake-opts: -DCOMPONENT_CLI=ON -DCOMPONENT_GUI=OFF -DFORCE_ANSI=ON -DUSE_THREADS=ON - build: gui - cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON -DUSE_THREADS=OFF + cmake-opts: -DCOMPONENT_CLI=OFF -DCOMPONENT_GUI=ON -DUSE_THREADS=OFF - build: gui-mt - cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON -DUSE_THREADS=ON + cmake-opts: -DCOMPONENT_CLI=OFF -DCOMPONENT_GUI=ON -DUSE_THREADS=ON name: ${{matrix.os}} (${{matrix.build}}) runs-on: ${{matrix.os}} diff --git a/CMakeLists.txt b/CMakeLists.txt index 7664ef3..58a5c4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,10 +16,10 @@ set( PROJECT_LICENSE_FILE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) # Options # -------------------------------- -option(BUILD_COMPONENT_CLI "Build CLI Component" ON) -option(BUILD_COMPONENT_GUI "Build GUI Component (Qt5)" OFF) +option(COMPONENT_CLI "Build CLI Component" ON) +option(COMPONENT_GUI "Build GUI Component (Qt5)" OFF) -if (NOT BUILD_COMPONENT_CLI AND NOT BUILD_COMPONENT_GUI) +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() @@ -111,11 +111,11 @@ configure_file(cmake/CPackProperties.cmake.in ${CPACK_PROPERTIES_FILE} @ONLY) add_subdirectory( common ) -if (BUILD_COMPONENT_CLI) +if (COMPONENT_CLI) add_subdirectory( cli ) endif() -if (BUILD_COMPONENT_GUI) +if (COMPONENT_GUI) add_subdirectory( gui ) endif() diff --git a/README.md b/README.md index f1ce300..cb68cd3 100644 --- a/README.md +++ b/README.md @@ -102,13 +102,13 @@ C:\repo\build> cmake --build . --config Release These compile options are available: -| Cmake | build.sh | Description | -|---------------------------- | ----------------- | ----------------------------------------- | -| -DBUILD_COMPONENT_CLI=`OFF` | --no-cli | Do not build cli program | -| -DBUILD_COMPONENT_GUI=`ON` | --gui | Build gui program (Qt5) | -| -DUSE_THREADS=`OFF` | --disable-threads | Disable thread support | -| -DCMAKE_BUILD_TYPE=`value` | -t `value` | Type of build | -| -DFORCE_ANSI=`ON` | --force-ansi | Force ANSI console colors even on windows | +| 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 | +| -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` diff --git a/build.sh b/build.sh index b623cdc..7bab057 100755 --- a/build.sh +++ b/build.sh @@ -34,9 +34,9 @@ while true; do ARGS="${ARGS} -DCPACK_GENERATOR=${1^^}" ;; --no-cli) - ARGS="${ARGS} -DBUILD_COMPONENT_CLI=OFF" ;; + ARGS="${ARGS} -DCOMPONENT_CLI=OFF" ;; --gui) - ARGS="${ARGS} -DBUILD_COMPONENT_GUI=ON" ;; + ARGS="${ARGS} -DCOMPONENT_GUI=ON" ;; --disable-threads) ARGS="${ARGS} -DUSE_THREADS=OFF" ;; --force-ansi) From 2d150a2e8bc7b97d3c1bcf417709efca7248d5aa Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 12:02:40 +0200 Subject: [PATCH 070/204] .github/workflows/package.yml: pass CMAKE_BUILD_TYPE=Release to cmake on windows. --- .github/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 8398b5e..309649c 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -50,7 +50,7 @@ jobs: } else { $PLATFORM="${{matrix.arch}}" } - cmake -A $PLATFORM -D CPACK_GENERATOR=NSIS -S . -B build + cmake -A $PLATFORM -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build - name: Build run: cmake --build build --config Release From cad11e591220c09a2b72269d03848bf25c5fc3b3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 13:37:52 +0200 Subject: [PATCH 071/204] gui: move source files to "src" subdirectory --- gui/CMakeLists.txt | 12 ++++++------ gui/{ => src}/GenerateWindow.cpp | 0 gui/{ => src}/GenerateWindow.hpp | 0 gui/{ => src}/MainWindow.cpp | 0 gui/{ => src}/MainWindow.hpp | 0 gui/{ => src}/MultiSelect.cpp | 0 gui/{ => src}/MultiSelect.hpp | 0 gui/{ => src}/SearchWindow.cpp | 0 gui/{ => src}/SearchWindow.hpp | 0 gui/{ => src}/helpers.cpp | 0 gui/{ => src}/helpers.hpp | 0 gui/{ => src}/main.cpp | 0 12 files changed, 6 insertions(+), 6 deletions(-) rename gui/{ => src}/GenerateWindow.cpp (100%) rename gui/{ => src}/GenerateWindow.hpp (100%) rename gui/{ => src}/MainWindow.cpp (100%) rename gui/{ => src}/MainWindow.hpp (100%) rename gui/{ => src}/MultiSelect.cpp (100%) rename gui/{ => src}/MultiSelect.hpp (100%) rename gui/{ => src}/SearchWindow.cpp (100%) rename gui/{ => src}/SearchWindow.hpp (100%) rename gui/{ => src}/helpers.cpp (100%) rename gui/{ => src}/helpers.hpp (100%) rename gui/{ => src}/main.cpp (100%) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 9734e0d..0b6c940 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -34,12 +34,12 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) set( PROGRAM_EXE ${PROJECT_NAME} ) set( PROGRAM_SRC - main.cpp - MainWindow.cpp - GenerateWindow.cpp - SearchWindow.cpp - MultiSelect.cpp - helpers.cpp + src/main.cpp + src/MainWindow.cpp + src/GenerateWindow.cpp + src/SearchWindow.cpp + src/MultiSelect.cpp + src/helpers.cpp ) add_executable( ${PROGRAM_EXE} WIN32 ${PROGRAM_SRC} ) diff --git a/gui/GenerateWindow.cpp b/gui/src/GenerateWindow.cpp similarity index 100% rename from gui/GenerateWindow.cpp rename to gui/src/GenerateWindow.cpp diff --git a/gui/GenerateWindow.hpp b/gui/src/GenerateWindow.hpp similarity index 100% rename from gui/GenerateWindow.hpp rename to gui/src/GenerateWindow.hpp diff --git a/gui/MainWindow.cpp b/gui/src/MainWindow.cpp similarity index 100% rename from gui/MainWindow.cpp rename to gui/src/MainWindow.cpp diff --git a/gui/MainWindow.hpp b/gui/src/MainWindow.hpp similarity index 100% rename from gui/MainWindow.hpp rename to gui/src/MainWindow.hpp diff --git a/gui/MultiSelect.cpp b/gui/src/MultiSelect.cpp similarity index 100% rename from gui/MultiSelect.cpp rename to gui/src/MultiSelect.cpp diff --git a/gui/MultiSelect.hpp b/gui/src/MultiSelect.hpp similarity index 100% rename from gui/MultiSelect.hpp rename to gui/src/MultiSelect.hpp diff --git a/gui/SearchWindow.cpp b/gui/src/SearchWindow.cpp similarity index 100% rename from gui/SearchWindow.cpp rename to gui/src/SearchWindow.cpp diff --git a/gui/SearchWindow.hpp b/gui/src/SearchWindow.hpp similarity index 100% rename from gui/SearchWindow.hpp rename to gui/src/SearchWindow.hpp diff --git a/gui/helpers.cpp b/gui/src/helpers.cpp similarity index 100% rename from gui/helpers.cpp rename to gui/src/helpers.cpp diff --git a/gui/helpers.hpp b/gui/src/helpers.hpp similarity index 100% rename from gui/helpers.hpp rename to gui/src/helpers.hpp diff --git a/gui/main.cpp b/gui/src/main.cpp similarity index 100% rename from gui/main.cpp rename to gui/src/main.cpp From 2084a66dbf6a61a5ef2c8d74255fcb4ff1c6313b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 13:38:20 +0200 Subject: [PATCH 072/204] CMakeLists.txt: set CMAKE_BUILD_TYPE to Debug per default. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58a5c4a..7a97b2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,9 +30,9 @@ endif() # Append modules dir list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -# Default to release build if none is set. +# Default to debug build if none is set. if (NOT CMAKE_BUILD_TYPE) - set( CMAKE_BUILD_TYPE Release ) + set( CMAKE_BUILD_TYPE Debug ) endif() # Install path From e1bda4b846eb8a37552321b6569e479cec603f2e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 14:43:02 +0200 Subject: [PATCH 073/204] cli/cmake/CPackComponentConfig.cmake.in: Set description. --- cli/cmake/CPackComponentConfig.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/cmake/CPackComponentConfig.cmake.in b/cli/cmake/CPackComponentConfig.cmake.in index d1b5c1b..aabca32 100644 --- a/cli/cmake/CPackComponentConfig.cmake.in +++ b/cli/cmake/CPackComponentConfig.cmake.in @@ -6,6 +6,8 @@ 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_PRIORITY "optional" ) From 178e71fbc75d00217c67262e8aa56e545f1f598c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 15:54:49 +0200 Subject: [PATCH 074/204] cli/cmake/CPackComponentConfig.cmake.in: Set debian package name --- cli/cmake/CPackComponentConfig.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/cmake/CPackComponentConfig.cmake.in b/cli/cmake/CPackComponentConfig.cmake.in index aabca32..30d60da 100644 --- a/cli/cmake/CPackComponentConfig.cmake.in +++ b/cli/cmake/CPackComponentConfig.cmake.in @@ -10,6 +10,7 @@ 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), libstdc++6 (>= 6)") From c5e9222abed7df876a01fb3319e6b615190ffae0 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 15:55:13 +0200 Subject: [PATCH 075/204] gui/cmake/CPackComponentConfig.cmake.in: Set debian package name --- gui/cmake/CPackComponentConfig.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/cmake/CPackComponentConfig.cmake.in b/gui/cmake/CPackComponentConfig.cmake.in index ff52fc4..3269f8b 100644 --- a/gui/cmake/CPackComponentConfig.cmake.in +++ b/gui/cmake/CPackComponentConfig.cmake.in @@ -11,6 +11,7 @@ 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_SHLIBDEPS ON ) From 37647685ea29e836aa70bc7fa8c5bf873fec9e35 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 16:35:10 +0200 Subject: [PATCH 076/204] CMake: install license file for both cli and gui --- CMakeLists.txt | 8 -------- cli/CMakeLists.txt | 5 +++++ gui/CMakeLists.txt | 5 +++++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a97b2b..c0212a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,14 +82,6 @@ add_compile_options( configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) include_directories(${PROJECT_BINARY_DIR}) -# -------------------------------- -# Install -# -------------------------------- - -# Readme and license -install(FILES README.md ${PROJECT_LICENSE_FILE} - DESTINATION ${CMAKE_INSTALL_SHAREDIR}) - # -------------------------------- # Package # -------------------------------- diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 76c8621..4ff100c 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -44,6 +44,11 @@ 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) + # Documentation if (UNIX) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 0b6c940..ce70fca 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -62,6 +62,11 @@ 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) + # -------------------------------- # Package # -------------------------------- From e0d4fbbdb7d72958dc5e267a874bf3ecdfd2c4ae Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 16:53:38 +0200 Subject: [PATCH 077/204] cli/docs/eosio-keygen.1.in: Spelling fix. --- cli/docs/eosio-keygen.1.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/docs/eosio-keygen.1.in b/cli/docs/eosio-keygen.1.in index ef12205..c7ef574 100644 --- a/cli/docs/eosio-keygen.1.in +++ b/cli/docs/eosio-keygen.1.in @@ -68,7 +68,7 @@ and find all l33tspeak combinations of that word and uses the new list for the s .B --threads= Use .I -of parallel threads for searching. Default is what the operating system recomends. +of parallel threads for searching. Default is what the operating system recommends. .TP 20 .B --dict= Use words found in From f1f5e50e9aeecca2e52d0e61700a5c1ee1068e42 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 17:04:49 +0200 Subject: [PATCH 078/204] Adding cli/docs/README.md.in --- cli/docs/README.md.in | 105 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 cli/docs/README.md.in diff --git a/cli/docs/README.md.in b/cli/docs/README.md.in new file mode 100644 index 0000000..2e38c01 --- /dev/null +++ b/cli/docs/README.md.in @@ -0,0 +1,105 @@ + +# eosio-keygen (cli) + +Generate public and private keypair for [EOSIO](https://eos.io/) + +## 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 EOSIO 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 + +`eosio-keygen 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 + +`eosio-keygen 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 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. + +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. + +``` +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 - [henrik@eossweden.org](mailto:henrik@eossweden.org) From c173c002f50ba91cd7dc3ee3652f044a285369a1 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 17:05:26 +0200 Subject: [PATCH 079/204] CMake: configure and install cli/docs/README.md.in --- cli/CMakeLists.txt | 5 +++++ cli/docs/README.md.in | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 4ff100c..610425c 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -51,6 +51,11 @@ install(FILES ${PROJECT_LICENSE_FILE} # 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/eosio-keygen.1.in ${PROJECT_BINARY_DIR}/man1/eosio-keygen.1 ) diff --git a/cli/docs/README.md.in b/cli/docs/README.md.in index 2e38c01..6b6fb67 100644 --- a/cli/docs/README.md.in +++ b/cli/docs/README.md.in @@ -3,6 +3,8 @@ Generate public and private keypair for [EOSIO](https://eos.io/) +Source code is available at [github.com](https://github.com/eosswedenorg/eosio-keygen) + ## Synopsis ```shell @@ -89,7 +91,7 @@ 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. +Please read the `LICENSE.cli` file. ``` THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, From 7cb70bd9a456964d6c9cfdff94669e8d3d8471f5 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 17:49:16 +0200 Subject: [PATCH 080/204] Adding a basic gui/README.md --- gui/README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 gui/README.md diff --git a/gui/README.md b/gui/README.md new file mode 100644 index 0000000..c3b9a22 --- /dev/null +++ b/gui/README.md @@ -0,0 +1,33 @@ + +# eosio-keygen (gui) + +This is the graphical version of [eosio-keygen](https://github.com/eosswedenorg/eosio-keygen) project. + +The program generates public and private keypairs for [EOSIO](https://eos.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 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. + +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.gui` 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 - [henrik@eossweden.org](mailto:henrik@eossweden.org) From e3d5176caef832b5461210939a31b2ff6f7e0659 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 17:50:38 +0200 Subject: [PATCH 081/204] CMake: install gui/README.md --- gui/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index ce70fca..6e35e94 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -67,6 +67,11 @@ install(FILES ${PROJECT_LICENSE_FILE} COMPONENT gui RENAME LICENSE.gui) +install(FILES README.md + DESTINATION ${CMAKE_INSTALL_SHAREDIR} + COMPONENT gui + RENAME README.gui.md) + # -------------------------------- # Package # -------------------------------- From 8bc9a87cc9069a956d06c5269b53dd94bde22978 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 17:54:27 +0200 Subject: [PATCH 082/204] Adding Sw/eden homepage to all my author lines. --- README.md | 2 +- cli/docs/README.md.in | 2 +- gui/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb68cd3..65d3121 100644 --- a/README.md +++ b/README.md @@ -179,4 +179,4 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Author -Henrik Hautakoski - [henrik@eossweden.org](mailto:henrik@eossweden.org) +Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) diff --git a/cli/docs/README.md.in b/cli/docs/README.md.in index 6b6fb67..d387386 100644 --- a/cli/docs/README.md.in +++ b/cli/docs/README.md.in @@ -104,4 +104,4 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Author -Henrik Hautakoski - [henrik@eossweden.org](mailto:henrik@eossweden.org) +Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) diff --git a/gui/README.md b/gui/README.md index c3b9a22..cf078bf 100644 --- a/gui/README.md +++ b/gui/README.md @@ -30,4 +30,4 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Author -Henrik Hautakoski - [henrik@eossweden.org](mailto:henrik@eossweden.org) +Henrik Hautakoski - [Sw/eden](https://eossweden.org/) - [henrik@eossweden.org](mailto:henrik@eossweden.org) From 9e048c7175c7cbe117fe476309b07259c3fcc306 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 18:16:18 +0200 Subject: [PATCH 083/204] .github/workflows/package.yml: build both gui and cli on windows. --- .github/workflows/package.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 309649c..9bbb714 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -43,6 +43,11 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Qt + uses: jurplel/install-qt-action@v2 + with: + version: '5.9' + - name: Configure run: | if ("${{matrix.arch}}" -eq "x86") { @@ -50,7 +55,7 @@ jobs: } else { $PLATFORM="${{matrix.arch}}" } - cmake -A $PLATFORM -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build + cmake -A $PLATFORM -DCOMPONENT_GUI=ON -DCOMPONENT_CLI=ON -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build - name: Build run: cmake --build build --config Release From 0cb00ae734219e1ace4b1c9b80d35d37d2afaab6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 18:30:23 +0200 Subject: [PATCH 084/204] build.sh: adding --cli and --no-gui flags to compliment --no-cli and --gui --- build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 7bab057..4988843 100755 --- a/build.sh +++ b/build.sh @@ -1,11 +1,11 @@ #!/bin/bash function usage() { - echo "Usage: ${0##*/} [ -h|--help ] [ --no-cli ] [ --gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type nsis|deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" + echo "Usage: ${0##*/} [ -h|--help ] [ --cli|--no-cli ] [ --gui|--no-gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type nsis|deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" exit 1 } -options=$(getopt -n "${0##*/}" -o "lht:" -l "help,no-cli,gui,type:,pkg-type:,disable-threads,force-ansi" -- "$@") +options=$(getopt -n "${0##*/}" -o "lht:" -l "help,cli,no-cli,gui,no-gui,type:,pkg-type:,disable-threads,force-ansi" -- "$@") [ $? -eq 0 ] || usage @@ -33,10 +33,14 @@ while true; do TARGET="package" ARGS="${ARGS} -DCPACK_GENERATOR=${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) From 54f0fc206f13e2d8ce80f63ecdc984c3cc09269d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 18:39:01 +0200 Subject: [PATCH 085/204] build.sh: need to pass --config flag to cmake build (for multiconfig generators like Visual Studio/xcode) --- build.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 4988843..679d90f 100755 --- a/build.sh +++ b/build.sh @@ -13,6 +13,7 @@ eval set -- "$options" ONLY_CONFIG=0 ARGS="" +BUILD_ARGS="--clean-first" while true; do case $1 in @@ -23,6 +24,7 @@ while true; do usage } ARGS="${ARGS} -DCMAKE_BUILD_TYPE=${1}" + BUILD_ARGS="${BUILD_ARGS} --config ${1}" ;; --pkg-type) shift @@ -61,5 +63,5 @@ rm build/CMakeCache.txt 2> /dev/null cmake -B build $ARGS . if [ ${ONLY_CONFIG} -eq 0 ]; then - cmake --build build --clean-first --target ${TARGET} + cmake --build build ${BUILD_ARGS} --target ${TARGET} fi From 63c7212fad10e80284f6793bbc8d60836115374a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 18:42:36 +0200 Subject: [PATCH 086/204] install.sh: don't assume we have generated Makefiles with cmake. use cmake --install --- install.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 927f1c7..33dde09 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,3 @@ #!/bin/bash -pushd build > /dev/null -make install $@ -popd > /dev/null +cmake --install build $@ From 8b8ba4c2c60895607f639a4196dc96e81777c821 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 24 Apr 2020 18:46:13 +0200 Subject: [PATCH 087/204] .github/workflows/package.yml: build both cli and gui on ubuntu. --- .github/workflows/package.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 9bbb714..85e1a80 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -10,16 +10,27 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04 ] - name: ${{matrix.os}} + component: [ cli, gui ] + include: + - 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: ${{matrix.os}} (${{matrix.component}}) runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v1 + - name: Qt + if: startsWith(matrix.component, 'gui') + shell: bash + run: sudo apt-get install qt5-default + - name: Package id: package run: | - ./build.sh -t Release --pkg-type deb - FILE=$(ls build/*.deb | head -1) + ./build.sh ${{matrix.build-opts}} + FILE=$(ls build/eosio-*.deb | head -1) echo "::set-output name=filename::$FILE" echo "::set-output name=name::$(basename $FILE)" From df2b40d1c6b1f0e5973079fed3c9d90f523060f9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 25 Apr 2020 10:52:49 +0200 Subject: [PATCH 088/204] CMake: only pack components that are configured. --- CMakeLists.txt | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0212a9..432c804 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,15 @@ endif (WIN32) # 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 # -------------------------------- @@ -88,7 +97,7 @@ include_directories(${PROJECT_BINARY_DIR}) include(CPackConfig) -set( CPACK_COMPONENTS_ALL cli gui ) +set( CPACK_COMPONENTS_ALL ${components} ) if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) @@ -103,13 +112,9 @@ configure_file(cmake/CPackProperties.cmake.in ${CPACK_PROPERTIES_FILE} @ONLY) add_subdirectory( common ) -if (COMPONENT_CLI) - add_subdirectory( cli ) -endif() - -if (COMPONENT_GUI) - add_subdirectory( gui ) -endif() +foreach(comp ${components}) + add_subdirectory( ${comp} ) +endforeach() # -------------------------------- # CPack From 8a9d594d3788194aeabd553634d28e510e851df6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 25 Apr 2020 12:50:58 +0200 Subject: [PATCH 089/204] CMake: Install gui/LICENSE.qt5 --- gui/CMakeLists.txt | 4 ++ gui/LICENSE.qt5 | 165 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 gui/LICENSE.qt5 diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 6e35e94..1ec2ead 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -72,6 +72,10 @@ install(FILES README.md COMPONENT gui RENAME README.gui.md) +install(FILES LICENSE.qt5 + DESTINATION ${CMAKE_INSTALL_SHAREDIR} + COMPONENT gui) + # -------------------------------- # Package # -------------------------------- diff --git a/gui/LICENSE.qt5 b/gui/LICENSE.qt5 new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/gui/LICENSE.qt5 @@ -0,0 +1,165 @@ + 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. From 0b101728b67fbca2941387681d5941c471e1a477 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 25 Apr 2020 20:24:55 +0200 Subject: [PATCH 090/204] .github/workflows/package.yml: we can set arch "directly" on windows. --- .github/workflows/package.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 85e1a80..ccd6895 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -48,7 +48,7 @@ jobs: windows: strategy: matrix: - arch: [ x86, x64 ] + arch: [ Win32, x64 ] name: Windows (${{matrix.arch}}) runs-on: windows-latest steps: @@ -60,13 +60,7 @@ jobs: version: '5.9' - name: Configure - run: | - if ("${{matrix.arch}}" -eq "x86") { - $PLATFORM="Win32" - } else { - $PLATFORM="${{matrix.arch}}" - } - cmake -A $PLATFORM -DCOMPONENT_GUI=ON -DCOMPONENT_CLI=ON -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build + run: cmake -A ${{matrix.arch}} -DCOMPONENT_GUI=ON -DCOMPONENT_CLI=ON -D CMAKE_BUILD_TYPE=Release -D CPACK_GENERATOR=NSIS -S . -B build - name: Build run: cmake --build build --config Release From e19982aceeafea0a77e0fd4dca2e22f6c9599349 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 25 Apr 2020 20:31:23 +0200 Subject: [PATCH 091/204] .github/workflows/package.yml: set qt arch correctly on windows. --- .github/workflows/package.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index ccd6895..6554a33 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -49,6 +49,11 @@ jobs: strategy: matrix: arch: [ Win32, x64 ] + include: + - arch: Win32 + qt-arch: win32_msvc2015 + - arch: x64 + qt-arch: win64_msvc2015_64 name: Windows (${{matrix.arch}}) runs-on: windows-latest steps: @@ -57,6 +62,7 @@ jobs: - name: Qt uses: jurplel/install-qt-action@v2 with: + arch: ${{ matrix.qt-arch }} version: '5.9' - name: Configure From beeba58cee1d0341aca8f9a7d2ac6a0066ec0b76 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 25 Apr 2020 21:47:10 +0200 Subject: [PATCH 092/204] Github Actions: use Qt 5.11.0 on windows. qt < 5.11 has a bug in qCountLeadingZeroBits function (QtCore/qalgorithms.h). This function is marked constexpr but returns a non-const value. MSVC compilers will pick this up as an C3615 error. See https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c3615 --- .github/workflows/ci.yml | 2 +- .github/workflows/package.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ff243d..9242f69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: if: startsWith(matrix.build, 'gui') && runner.os != 'Linux' uses: jurplel/install-qt-action@v2 with: - version: '5.9' + version: '5.11.0' - name: Configure shell: bash diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 6554a33..5e36c7a 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -63,7 +63,7 @@ jobs: uses: jurplel/install-qt-action@v2 with: arch: ${{ matrix.qt-arch }} - version: '5.9' + version: '5.11.0' - 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 From 6f1359444a58891e3ad6309371525e9950095cc0 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 26 Apr 2020 10:42:33 +0200 Subject: [PATCH 093/204] .github/workflows/package.yml: fixing windows build (must have --config Release everywhere) --- .github/workflows/package.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 5e36c7a..8ff79a5 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -68,13 +68,10 @@ jobs: - 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 - - name: Build - run: cmake --build build --config Release - - name: Package id: package run: | - cmake --build build --target package + cmake --build build --config Release --target package $FILE=(ls build/*.exe) echo "::set-output name=filename::$FILE" echo "::set-output name=name::$(([io.fileinfo]"$FILE").basename).exe" From dce6f586078ad039c92169f97e2d533dd856752c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 26 Apr 2020 13:04:22 +0200 Subject: [PATCH 094/204] Github Actions: skip building for Ubuntu 16.04 First, 16.04 only supports libssl 1.0 (officially) that links fine but will not find the library at runtime. Second, 16.04 is old (LTS is still valid tho). If requested, we could consider supporting it but no point going through the hassle if it has no users. --- .github/workflows/ci.yml | 2 +- .github/workflows/package.yml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9242f69..f699ed4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: compile: strategy: matrix: - os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] + os: [ ubuntu-18.04, macos-latest, windows-latest ] build: [ cli, cli-mt, cli-ansi, cli-ansi-mt, gui, gui-mt ] include: - build: cli diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 8ff79a5..ae34287 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -9,7 +9,6 @@ jobs: ubuntu: strategy: matrix: - os: [ ubuntu-16.04, ubuntu-18.04 ] component: [ cli, gui ] include: - component: cli @@ -17,7 +16,7 @@ jobs: - component: gui build-opts: --no-cli --gui -t Release --pkg-type deb name: ${{matrix.os}} (${{matrix.component}}) - runs-on: ${{matrix.os}} + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 From 2ec874607f17b4125a4520c15914139c1a13a08c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 26 Apr 2020 13:05:18 +0200 Subject: [PATCH 095/204] Github Actions: pin qt5-default to 5.9.5 on ubuntu. --- .github/workflows/ci.yml | 2 +- .github/workflows/package.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f699ed4..d4571bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: - name: Qt - Ubuntu if: startsWith(matrix.build, 'gui') && runner.os == 'Linux' shell: bash - run: sudo apt-get install qt5-default + run: sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 - name: Qt - Windows/Mac if: startsWith(matrix.build, 'gui') && runner.os != 'Linux' diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index ae34287..367b32b 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -23,7 +23,7 @@ jobs: - name: Qt if: startsWith(matrix.component, 'gui') shell: bash - run: sudo apt-get install qt5-default + run: sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 - name: Package id: package From b7c3fc0506ac9fa8f84e85eaeab8bc533cafb424 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 26 Apr 2020 13:22:39 +0200 Subject: [PATCH 096/204] gui/cmake/CPackComponentConfig.cmake.in: explicitly depend on qt >= 5.9.5 and libssl >= 1.1 --- gui/cmake/CPackComponentConfig.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/cmake/CPackComponentConfig.cmake.in b/gui/cmake/CPackComponentConfig.cmake.in index 3269f8b..4167b21 100644 --- a/gui/cmake/CPackComponentConfig.cmake.in +++ b/gui/cmake/CPackComponentConfig.cmake.in @@ -14,4 +14,4 @@ set( CPACK_DEBIAN_GUI_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${CPACK_DEBI 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_SHLIBDEPS ON ) +set( CPACK_DEBIAN_GUI_PACKAGE_DEPENDS "libqt5core5a (>= 5.9.5), libqt5concurrent5 (>= 5.9.5), libqt5gui5 (>= 5.9.5), libqt5widgets5 (>= 5.9.5), libssl1.1") From e20023cf31de9fbf6984e4185f74cc18823ea53c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 11:56:08 +0200 Subject: [PATCH 097/204] adding cmake/extras.cmake --- cmake/extras.cmake | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 cmake/extras.cmake diff --git a/cmake/extras.cmake b/cmake/extras.cmake new file mode 100644 index 0000000..a23a1fe --- /dev/null +++ b/cmake/extras.cmake @@ -0,0 +1,43 @@ + +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" ) From 282028793becd1a8b67959981d0aa11675b5f9d2 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 11:56:32 +0200 Subject: [PATCH 098/204] CMake: bundle eosio-extras on windows. --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 432c804..0d8120f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,12 @@ add_compile_options( configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config.hpp" @ONLY) include_directories(${PROJECT_BINARY_DIR}) +# Bundle eosio-extras on windows. +if (WIN32) + include(extras) + list(APPEND components extras ) +endif() + # -------------------------------- # Package # -------------------------------- @@ -113,7 +119,9 @@ configure_file(cmake/CPackProperties.cmake.in ${CPACK_PROPERTIES_FILE} @ONLY) add_subdirectory( common ) foreach(comp ${components}) - add_subdirectory( ${comp} ) + if ( EXISTS ${CMAKE_CURRENT_LIST_DIR}/${comp} ) + add_subdirectory( ${comp} ) + endif() endforeach() # -------------------------------- From 38263a421c222885ac3db294f8a842c858f2564c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 12:33:24 +0200 Subject: [PATCH 099/204] README.md: Adding a note about Ubuntu 18.04 support. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 65d3121..44c8193 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ You will need `libeosio` and `cmake 3.15` or later to compile this project. ### Linux/MacOS +**NOTE:** Only Ubuntu 18.04 is officially supported. + +The project should compile fine on most versions/distros but it is only tested +and distributed for Ubuntu 18.04 by [Sw/eden](www.eossweden.org). + #### Dependencies #### Linux From a6c0cbcc4e075b07472b127312f90f8de804651d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 13:00:09 +0200 Subject: [PATCH 100/204] README.md: Adding notice about MacOS support. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 44c8193..059f98b 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Other methods is documanted at https://cmake.org/download #### 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: From e26bc8097f34c28c9abafb2a7a7788cf8775d1c6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 13:11:46 +0200 Subject: [PATCH 101/204] README.md: Adding documentation for Qt. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 059f98b..8bea272 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ This program generates public and private keypair for [EOS](https://eos.io/) You will need `libeosio` and `cmake 3.15` or later to compile this project. +`Qt 5.9.0` or later is required for the graphical program. + ### Linux/MacOS **NOTE:** Only Ubuntu 18.04 is officially supported. @@ -50,6 +52,19 @@ $ 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. @@ -65,6 +80,14 @@ If you need a newer version of cmake, you can download the official `.dmg` file: `libeosio` needs to be compiled and installed from source. [Go here](https://github.com/eosswedenorg/libeosio) +**Qt (only for gui program)** + +This can be installed with brew. + +```sh +$ brew install qt +``` + #### Build Run `./build.sh` to trigger cmake. @@ -87,7 +110,9 @@ 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. @@ -105,6 +130,14 @@ C:\repo\build> cmake -D OPENSSL_ROOT_DIR="C:/path/to/openssl-1.1/x86" .. C:\repo\build> cmake --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" +``` + ## Compile options These compile options are available: From 464a0c18013fe40997b1be1796e9786c19c9cac4 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 13:12:47 +0200 Subject: [PATCH 102/204] README.md: simplify windows example. --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8bea272..e4ac358 100644 --- a/README.md +++ b/README.md @@ -124,10 +124,8 @@ you need to set `OPENSSL_ROOT_DIR` to the directory where you unpacked For example: ``` -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 +C:\repo> cmake -D OPENSSL_ROOT_DIR="C:/path/to/openssl-1.1/x86" -B build +C:\repo> cmake --build build --config Release ``` **Qt** From 4c67cbf905ea709cec5f6765a595af8d1793cdfc Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 14:26:00 +0200 Subject: [PATCH 103/204] Version 1.0.5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d8120f..92c9c1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.15) # -------------------------------- project(eosio-keygen - VERSION 1.0.4 + VERSION 1.0.5 DESCRIPTION "Keygenerator for EOSIO" HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) From a3be286579f8a8ffffb420c1ca1dce594d03ae46 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 27 Apr 2020 14:29:15 +0200 Subject: [PATCH 104/204] .github/workflows/package.yml: fix job name for ubuntu. --- .github/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 367b32b..036e97e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -15,7 +15,7 @@ jobs: build-opts: --cli --no-gui -t Release --pkg-type deb - component: gui build-opts: --no-cli --gui -t Release --pkg-type deb - name: ${{matrix.os}} (${{matrix.component}}) + name: Ubuntu (${{matrix.component}}) runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 From 3cc6a2530ea8b5679daaf49a08563f3c95e6ef6d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 28 Apr 2020 09:48:04 +0200 Subject: [PATCH 105/204] gui/src/SearchWindow.cpp: Pass a pointer to m_ksearch in call to QtConocurrent::run() It's not passed by reference otherwise. so it will copy the whole object. --- gui/src/SearchWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp index 2f36d81..95375a4 100644 --- a/gui/src/SearchWindow.cpp +++ b/gui/src/SearchWindow.cpp @@ -214,7 +214,7 @@ void SearchWindow::search() m_ksearch.setThreadCount(m_num_threads.value()); #endif /* EOSIOKEYGEN_HAVE_THREADS */ - QFuture future = QtConcurrent::run(m_ksearch, &eoskeygen::KeySearch::find, m_num_results.value()); + QFuture future = QtConcurrent::run(&m_ksearch, &eoskeygen::KeySearch::find, m_num_results.value()); m_worker.setFuture(future); m_status.setText("Searching for: " + QString::fromStdString(eoskeygen::strlist::join(list, ", "))); From 2a528e0eb094743dbb41c9d47f906eb986189b2a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 28 Apr 2020 10:02:35 +0200 Subject: [PATCH 106/204] common/include/eoskeygen/key_search.hpp: add max and count variables to the class. This is done so that m_max can be set to zero from another method. stopping a find() operation. (for threaded operations) --- common/include/eoskeygen/key_search.hpp | 10 +++++++-- common/src/key_search.cpp | 24 ++++++++++++--------- common/src/key_search_mt.cpp | 28 ++++++++----------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/common/include/eoskeygen/key_search.hpp b/common/include/eoskeygen/key_search.hpp index f757002..eb358da 100644 --- a/common/include/eoskeygen/key_search.hpp +++ b/common/include/eoskeygen/key_search.hpp @@ -83,15 +83,21 @@ protected : #ifdef EOSIOKEYGEN_HAVE_THREADS void _thr_proc(); - void _search_mt(size_t n); + void _search_mt(); #endif /* EOSIOKEYGEN_HAVE_THREADS */ - void _search_linear(size_t n); + void _search_linear(); protected : // 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 EOSIOKEYGEN_HAVE_THREADS // Number of threads to use. size_t m_threads; diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp index 810f884..68803a9 100644 --- a/common/src/key_search.cpp +++ b/common/src/key_search.cpp @@ -31,10 +31,12 @@ namespace eoskeygen { KeySearch::KeySearch() : + m_max (0), + m_count (0), #ifdef EOSIOKEYGEN_HAVE_THREADS - m_threads(0), + m_threads (0), #endif - m_callback(NULL) + m_callback (NULL) { } @@ -67,32 +69,34 @@ void KeySearch::setCallback(IKeySearchResult* callback) m_callback = callback; } -void KeySearch::_search_linear(size_t n) { - - size_t count = 0; +void KeySearch::_search_linear() +{ struct libeosio::ec_keypair pair; - while (count < n) { + while (m_count < m_max) { struct result res; libeosio::ec_generate_key(&pair); if (_contains_word(&pair, res)) { m_callback->onResult(&pair, res); - count++; + m_count++; } } } -void KeySearch::find(size_t num_results) { +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(num_results); + _search_mt(); return; } #endif /* HAVE_THREADS */ - _search_linear(num_results); + _search_linear(); } bool KeySearch::_contains_word(const struct libeosio::ec_keypair* key, struct result& result) { diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp index 00e50e3..fc643b0 100644 --- a/common/src/key_search_mt.cpp +++ b/common/src/key_search_mt.cpp @@ -31,39 +31,33 @@ namespace eoskeygen { -// Max keys to search for, -std::size_t g_max; - -// How many keys we have found so far. -std::size_t g_count; - -// Mutex guard for g_count. +// Mutex guard for m_count. std::mutex g_count_mtx; // Thread process. -void KeySearch::_thr_proc() { - +void KeySearch::_thr_proc() +{ struct libeosio::ec_keypair pair; - while (g_count < g_max) { + while (m_count < m_max) { struct result res; libeosio::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 g_count and res safely. + // interrupted mid write and can write to m_count and res safely. const std::lock_guard lock(g_count_mtx); - // It is possible g_count was updated by another thread + // 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 (g_count >= g_max) { + if (m_count >= m_max) { return; } // Update count and call result function. - g_count++; + m_count++; m_callback->onResult(&pair, res); } } @@ -79,16 +73,12 @@ size_t KeySearch::max_threads() return std::thread::hardware_concurrency(); } -void KeySearch::_search_mt(size_t n) +void KeySearch::_search_mt() { std::vector t; t.resize(m_threads - 1); - // Setup global variables for the threads. - g_max = n; - g_count = 0; - // Launch them. for(std::size_t i = 0; i < t.size(); i++) { t[i] = std::thread(&KeySearch::_thr_proc, this); From 7c2545cdc28f0eecfff028250a7171dc29fa06e7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 28 Apr 2020 10:10:36 +0200 Subject: [PATCH 107/204] common/include/eoskeygen/key_search.hpp: adding abort() --- common/include/eoskeygen/key_search.hpp | 6 ++++++ common/src/key_search.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/common/include/eoskeygen/key_search.hpp b/common/include/eoskeygen/key_search.hpp index eb358da..3e3975a 100644 --- a/common/include/eoskeygen/key_search.hpp +++ b/common/include/eoskeygen/key_search.hpp @@ -71,6 +71,12 @@ public : void setThreadCount(size_t num); #endif /* EOSIOKEYGEN_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); diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp index 68803a9..506ee84 100644 --- a/common/src/key_search.cpp +++ b/common/src/key_search.cpp @@ -83,6 +83,12 @@ void KeySearch::_search_linear() } } +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; From 1cb6ddabd6d23189c03496250334cc96f26a5299 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 28 Apr 2020 10:11:47 +0200 Subject: [PATCH 108/204] gui/src/SearchWindow.cpp: implement "Cancel" button. stopping the search operation. --- gui/src/SearchWindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp index 95375a4..42b54ff 100644 --- a/gui/src/SearchWindow.cpp +++ b/gui/src/SearchWindow.cpp @@ -186,6 +186,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct void SearchWindow::search() { if (m_worker.isRunning()) { + m_ksearch.abort(); return; } @@ -247,12 +248,13 @@ void SearchWindow::langFileAdd() void SearchWindow::searchStarted() { + 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_exec.setEnabled(false); m_btn_clear.setEnabled(false); #ifdef EOSIOKEYGEN_HAVE_THREADS m_num_threads.setEnabled(false); @@ -262,12 +264,13 @@ void SearchWindow::searchStarted() 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_exec.setEnabled(true); m_btn_clear.setEnabled(true); #ifdef EOSIOKEYGEN_HAVE_THREADS m_num_threads.setEnabled(true); From cf6c1a4854549b1a5248fdb3febc8b0964274783 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 15 May 2020 13:54:07 +0200 Subject: [PATCH 109/204] remove common/include/eoskeygen/config.h (old autogenerated file) --- common/include/eoskeygen/config.h | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 common/include/eoskeygen/config.h diff --git a/common/include/eoskeygen/config.h b/common/include/eoskeygen/config.h deleted file mode 100644 index 5728f1f..0000000 --- a/common/include/eoskeygen/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * MIT License - * - * 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 - * 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_COMMON_CONFIG_H -#define EOSIOKEYGEN_COMMON_CONFIG_H - -// Defined if we have thread support. -#define EOSIOKEYGEN_HAVE_THREADS - -#endif /* EOSIOKEYGEN_COMMON_CONFIG_H */ From 0a2ad127006777a359a41ad40e6b72c94cb23a9e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 15 May 2020 14:04:35 +0200 Subject: [PATCH 110/204] .github/workflows/ci.yml: trigger on pull requests also. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4571bc..2cf3fd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,8 @@ on: - '*' - '*/*' - '!master' + pull_request: + branches: [ develop ] jobs: compile: From f6554a924aed29e537a5d1fd729305c0ddfc5709 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 14 May 2020 14:14:54 +0200 Subject: [PATCH 111/204] gui/gui_about.h.in: rename to gui_text.h.in --- gui/CMakeLists.txt | 2 +- gui/{gui_about.h.in => gui_text.h.in} | 10 +++++----- gui/src/MainWindow.cpp | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) rename gui/{gui_about.h.in => gui_text.h.in} (86%) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 1ec2ead..3628f7a 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -24,7 +24,7 @@ string(REGEX REPLACE "\n\n([^\n]+)" "

\\1

" GUI_ABOUT_LICENSE ${GUI_ABOUT_L string(REGEX REPLACE "\n" "" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) string(REGEX REPLACE "\<(.+)\>" "- \\1" GUI_ABOUT_AUTHOR ${PROJECT_MAINTAINER}) -configure_file(gui_about.h.in "${CMAKE_CURRENT_BINARY_DIR}/gui_about.h" @ONLY ESCAPE_QUOTES) +configure_file(gui_text.h.in "${CMAKE_CURRENT_BINARY_DIR}/gui_text.h" @ONLY ESCAPE_QUOTES) include_directories(${CMAKE_CURRENT_BINARY_DIR}) # -------------------------------- diff --git a/gui/gui_about.h.in b/gui/gui_text.h.in similarity index 86% rename from gui/gui_about.h.in rename to gui/gui_text.h.in index 1f6ab9f..4c81c9d 100644 --- a/gui/gui_about.h.in +++ b/gui/gui_text.h.in @@ -21,12 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef EOSIOKEYGEN_GUI_ABOUT_H -#define EOSIOKEYGEN_GUI_ABOUT_H +#ifndef EOSIOKEYGEN_GUI_TEXT_H +#define EOSIOKEYGEN_GUI_TEXT_H -#define EOSIOKEYGEN_GUI_ABOUT_TITLE "@PROJECT_NAME@ - About" +#define EOSIOKEYGEN_GUI_TEXT_ABOUT_TITLE "@PROJECT_NAME@ - About" -#define EOSIOKEYGEN_GUI_ABOUT_TEXT \ +#define EOSIOKEYGEN_GUI_TEXT_ABOUT_BODY \ "

@PROJECT_NAME@ - v@PROJECT_VERSION@

" \ "

@PROJECT_DESCRIPTION@

" \ "

@PROJECT_HOMEPAGE_URL@

" \ @@ -34,4 +34,4 @@ "

Author

" \ "

@GUI_ABOUT_AUTHOR@

" -#endif /* EOSIOKEYGEN_CONFIG_ABOUT_H */ +#endif /* EOSIOKEYGEN_GUI_TEXT_H */ diff --git a/gui/src/MainWindow.cpp b/gui/src/MainWindow.cpp index ce2d579..cfed710 100644 --- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -25,7 +25,7 @@ #include #include #include -#include "gui_about.h" +#include "gui_text.h" #include "GenerateWindow.hpp" #include "SearchWindow.hpp" #include "MainWindow.hpp" @@ -59,5 +59,7 @@ void MainWindow::switchToSearch() void MainWindow::showAbout() { - QMessageBox::about(this, EOSIOKEYGEN_GUI_ABOUT_TITLE, EOSIOKEYGEN_GUI_ABOUT_TEXT); + QMessageBox::about(this, + EOSIOKEYGEN_GUI_TEXT_ABOUT_TITLE, + EOSIOKEYGEN_GUI_TEXT_ABOUT_BODY); } From 88bd1217babe512acf3648f1011e15140ae5ecc8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 15 May 2020 13:38:19 +0200 Subject: [PATCH 112/204] gui/gui_text.h.in: define tooltip text for dictionary widgets. --- gui/gui_text.h.in | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/gui/gui_text.h.in b/gui/gui_text.h.in index 4c81c9d..a8a1cff 100644 --- a/gui/gui_text.h.in +++ b/gui/gui_text.h.in @@ -24,6 +24,8 @@ #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 \ @@ -34,4 +36,19 @@ "

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 */ From e0a388dac192a2001773d3e95cd7c82ee6beda4f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 15 May 2020 13:38:41 +0200 Subject: [PATCH 113/204] gui/src/SearchWindow.cpp: show tooltip for dictionary widgets. --- gui/src/SearchWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp index 42b54ff..2128fed 100644 --- a/gui/src/SearchWindow.cpp +++ b/gui/src/SearchWindow.cpp @@ -31,6 +31,7 @@ #include #include #include +#include "gui_text.h" #include "config.hpp" #include "helpers.hpp" #include "SearchWindow.hpp" @@ -61,6 +62,9 @@ m_btn_clear ("Clear") // 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); From cb181bea212e5ee7ba71edeaac2407390ad3fa67 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 15 May 2020 14:48:55 +0200 Subject: [PATCH 114/204] Version 1.0.6 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92c9c1a..f7bdb17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.15) # -------------------------------- project(eosio-keygen - VERSION 1.0.5 + VERSION 1.0.6 DESCRIPTION "Keygenerator for EOSIO" HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) From 73ccd4be0255fd929530e79e048c0c316c95e05a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 22 May 2020 16:23:55 +0200 Subject: [PATCH 115/204] common/cmake/libeosio.cmake: use v0.1.1 --- common/cmake/libeosio.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index 4dbdcc5..c72cbb6 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION v0.1.0 ) +set( LIBEOSIO_WANTED_VERSION v0.1.1 ) # -------------------------------- # Macros From 51883f42ca3963f45f8dcfa4847afffd0b4a0e53 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 4 Jan 2021 13:05:08 +0100 Subject: [PATCH 116/204] cli/src/main.cpp: move usage() function to the top. --- cli/src/main.cpp | 82 ++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/cli/src/main.cpp b/cli/src/main.cpp index aa34553..7602e29 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -44,47 +44,6 @@ bool option_l33t = false; size_t option_num_threads = eoskeygen::KeySearch::max_threads(); #endif /* EOSIOKEYGEN_HAVE_THREADS */ -int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& dict, int count) { - - eoskeygen::KeySearch ks; - eoskeygen::CliKeySearchResult rs(dict); - - ks.setCallback(&rs); - - for(auto it = words.begin(); it != words.end(); it++) { - size_t p = libeosio::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(eoskeygen::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: " << eoskeygen::strlist::join(ks.getList(), ",") -#ifdef EOSIOKEYGEN_HAVE_THREADS - << ", Using: " << option_num_threads << " threads" -#endif /* EOSIOKEYGEN_HAVE_THREADS */ - << std::endl; - - ks.find(count); - - return 0; -} - void usage(const char *name) { std::cout << name @@ -142,6 +101,47 @@ void usage(const char *name) { << std::endl; } +int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& dict, int count) { + + eoskeygen::KeySearch ks; + eoskeygen::CliKeySearchResult rs(dict); + + ks.setCallback(&rs); + + for(auto it = words.begin(); it != words.end(); it++) { + size_t p = libeosio::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(eoskeygen::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: " << eoskeygen::strlist::join(ks.getList(), ",") +#ifdef EOSIOKEYGEN_HAVE_THREADS + << ", Using: " << option_num_threads << " threads" +#endif /* EOSIOKEYGEN_HAVE_THREADS */ + << std::endl; + + ks.find(count); + + return 0; +} + void cmd_benchmark(size_t num_keys) { struct eoskeygen::benchmark_result res; From 56a5c226bd55c5457d41d45051519e0cf79e3917 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 4 Jan 2021 13:11:49 +0100 Subject: [PATCH 117/204] Updated year in headers. --- LICENSE | 2 +- cli/src/benchmark.cpp | 2 +- cli/src/benchmark.hpp | 2 +- cli/src/cli_key_search_result.cpp | 2 +- cli/src/cli_key_search_result.hpp | 2 +- cli/src/console.cpp | 2 +- cli/src/console.hpp | 2 +- cli/src/console_ansi.cpp | 2 +- cli/src/console_win32.cpp | 2 +- cli/src/isatty.cpp | 24 +++++++++++++++++++ cli/src/isatty.hpp | 2 +- cli/src/main.cpp | 2 +- common/config.hpp.in | 2 +- common/include/eoskeygen/core/dictionary.hpp | 2 +- common/include/eoskeygen/core/file.hpp | 2 +- common/include/eoskeygen/core/leet.hpp | 2 +- common/include/eoskeygen/core/string.hpp | 2 +- common/include/eoskeygen/core/strlist.hpp | 2 +- common/include/eoskeygen/key_search.hpp | 2 +- .../include/eoskeygen/key_search_result.hpp | 2 +- common/src/core/dictionary.cpp | 2 +- common/src/core/file.cpp | 2 +- common/src/core/leet.cpp | 2 +- common/src/core/string.cpp | 2 +- common/src/core/strlist.cpp | 2 +- common/src/key_search.cpp | 2 +- common/src/key_search_mt.cpp | 2 +- config.hpp.in | 2 +- gui/gui_text.h.in | 2 +- gui/src/GenerateWindow.cpp | 2 +- gui/src/GenerateWindow.hpp | 2 +- gui/src/MainWindow.cpp | 2 +- gui/src/MainWindow.hpp | 2 +- gui/src/MultiSelect.cpp | 2 +- gui/src/MultiSelect.hpp | 2 +- gui/src/SearchWindow.cpp | 2 +- gui/src/SearchWindow.hpp | 2 +- gui/src/helpers.cpp | 2 +- gui/src/helpers.hpp | 2 +- gui/src/main.cpp | 2 +- 40 files changed, 63 insertions(+), 39 deletions(-) diff --git a/LICENSE b/LICENSE index ea09337..81ee5da 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2020 EOS Sw/eden +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 diff --git a/cli/src/benchmark.cpp b/cli/src/benchmark.cpp index b25fbae..e7dafd6 100644 --- a/cli/src/benchmark.cpp +++ b/cli/src/benchmark.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/benchmark.hpp b/cli/src/benchmark.hpp index 8b1f57b..9300cc3 100644 --- a/cli/src/benchmark.hpp +++ b/cli/src/benchmark.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/cli_key_search_result.cpp b/cli/src/cli_key_search_result.cpp index 7ec6b18..0d527de 100644 --- a/cli/src/cli_key_search_result.cpp +++ b/cli/src/cli_key_search_result.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/cli_key_search_result.hpp b/cli/src/cli_key_search_result.hpp index c9a2e15..ac75cb1 100644 --- a/cli/src/cli_key_search_result.hpp +++ b/cli/src/cli_key_search_result.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/console.cpp b/cli/src/console.cpp index 2ed20da..ebcfe1f 100644 --- a/cli/src/console.cpp +++ b/cli/src/console.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/console.hpp b/cli/src/console.hpp index 65da9aa..f847f75 100644 --- a/cli/src/console.hpp +++ b/cli/src/console.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/console_ansi.cpp b/cli/src/console_ansi.cpp index 75b5412..5cf5850 100644 --- a/cli/src/console_ansi.cpp +++ b/cli/src/console_ansi.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/console_win32.cpp b/cli/src/console_win32.cpp index 813daa0..3b13f5a 100644 --- a/cli/src/console_win32.cpp +++ b/cli/src/console_win32.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/isatty.cpp b/cli/src/isatty.cpp index 5fdadfb..ea03397 100644 --- a/cli/src/isatty.cpp +++ b/cli/src/isatty.cpp @@ -1,3 +1,27 @@ +/** + * 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 diff --git a/cli/src/isatty.hpp b/cli/src/isatty.hpp index 0cf40c9..0b724af 100644 --- a/cli/src/isatty.hpp +++ b/cli/src/isatty.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/cli/src/main.cpp b/cli/src/main.cpp index 7602e29..ddd8768 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/config.hpp.in b/common/config.hpp.in index 7871d9f..8b1d7f9 100644 --- a/common/config.hpp.in +++ b/common/config.hpp.in @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/core/dictionary.hpp b/common/include/eoskeygen/core/dictionary.hpp index bdd9cac..4a939c0 100644 --- a/common/include/eoskeygen/core/dictionary.hpp +++ b/common/include/eoskeygen/core/dictionary.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/core/file.hpp b/common/include/eoskeygen/core/file.hpp index 6f5c7e3..330c974 100644 --- a/common/include/eoskeygen/core/file.hpp +++ b/common/include/eoskeygen/core/file.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/core/leet.hpp b/common/include/eoskeygen/core/leet.hpp index 7631052..29eea80 100644 --- a/common/include/eoskeygen/core/leet.hpp +++ b/common/include/eoskeygen/core/leet.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/core/string.hpp b/common/include/eoskeygen/core/string.hpp index a0d8e03..4e008c0 100644 --- a/common/include/eoskeygen/core/string.hpp +++ b/common/include/eoskeygen/core/string.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/core/strlist.hpp b/common/include/eoskeygen/core/strlist.hpp index b1e8d99..96f509e 100644 --- a/common/include/eoskeygen/core/strlist.hpp +++ b/common/include/eoskeygen/core/strlist.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/key_search.hpp b/common/include/eoskeygen/key_search.hpp index 3e3975a..902716f 100644 --- a/common/include/eoskeygen/key_search.hpp +++ b/common/include/eoskeygen/key_search.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/include/eoskeygen/key_search_result.hpp b/common/include/eoskeygen/key_search_result.hpp index 825ebae..e174d18 100644 --- a/common/include/eoskeygen/key_search_result.hpp +++ b/common/include/eoskeygen/key_search_result.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/core/dictionary.cpp b/common/src/core/dictionary.cpp index 11bd50b..806922b 100644 --- a/common/src/core/dictionary.cpp +++ b/common/src/core/dictionary.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/core/file.cpp b/common/src/core/file.cpp index 74f4c5e..6cbdac5 100644 --- a/common/src/core/file.cpp +++ b/common/src/core/file.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/core/leet.cpp b/common/src/core/leet.cpp index 75bed31..e30e54d 100644 --- a/common/src/core/leet.cpp +++ b/common/src/core/leet.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/core/string.cpp b/common/src/core/string.cpp index 1851a01..6186556 100644 --- a/common/src/core/string.cpp +++ b/common/src/core/string.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/core/strlist.cpp b/common/src/core/strlist.cpp index 6212a35..8c8f874 100644 --- a/common/src/core/strlist.cpp +++ b/common/src/core/strlist.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/key_search.cpp b/common/src/key_search.cpp index 506ee84..f7af039 100644 --- a/common/src/key_search.cpp +++ b/common/src/key_search.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/common/src/key_search_mt.cpp b/common/src/key_search_mt.cpp index fc643b0..8c1585b 100644 --- a/common/src/key_search_mt.cpp +++ b/common/src/key_search_mt.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/config.hpp.in b/config.hpp.in index a1b4356..95b3526 100644 --- a/config.hpp.in +++ b/config.hpp.in @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2019-2020 EOS Sw/eden + * 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 diff --git a/gui/gui_text.h.in b/gui/gui_text.h.in index a8a1cff..e119cb1 100644 --- a/gui/gui_text.h.in +++ b/gui/gui_text.h.in @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/GenerateWindow.cpp b/gui/src/GenerateWindow.cpp index ffefda0..00fa48f 100644 --- a/gui/src/GenerateWindow.cpp +++ b/gui/src/GenerateWindow.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/GenerateWindow.hpp b/gui/src/GenerateWindow.hpp index da2a110..63a3c99 100644 --- a/gui/src/GenerateWindow.hpp +++ b/gui/src/GenerateWindow.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/MainWindow.cpp b/gui/src/MainWindow.cpp index cfed710..3648bf7 100644 --- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/MainWindow.hpp b/gui/src/MainWindow.hpp index 704fa1f..c42e574 100644 --- a/gui/src/MainWindow.hpp +++ b/gui/src/MainWindow.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/MultiSelect.cpp b/gui/src/MultiSelect.cpp index bccf803..1b2ea89 100644 --- a/gui/src/MultiSelect.cpp +++ b/gui/src/MultiSelect.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/MultiSelect.hpp b/gui/src/MultiSelect.hpp index 84ed207..5fe5d8a 100644 --- a/gui/src/MultiSelect.hpp +++ b/gui/src/MultiSelect.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp index 2128fed..758ff43 100644 --- a/gui/src/SearchWindow.cpp +++ b/gui/src/SearchWindow.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/SearchWindow.hpp b/gui/src/SearchWindow.hpp index bd622d7..a161628 100644 --- a/gui/src/SearchWindow.hpp +++ b/gui/src/SearchWindow.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/helpers.cpp b/gui/src/helpers.cpp index d1574d4..dc70b2f 100644 --- a/gui/src/helpers.cpp +++ b/gui/src/helpers.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/helpers.hpp b/gui/src/helpers.hpp index ccb5218..da76ed2 100644 --- a/gui/src/helpers.hpp +++ b/gui/src/helpers.hpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 diff --git a/gui/src/main.cpp b/gui/src/main.cpp index ecd14e6..4d8ee5b 100644 --- a/gui/src/main.cpp +++ b/gui/src/main.cpp @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2020 EOS Sw/eden + * 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 From 32967fdaac1c27c5145a51362e38101eb87cd04b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 4 Jan 2021 16:16:34 +0100 Subject: [PATCH 118/204] cli/src/benchmark.cpp: Minor cleanup, stop using the keyword "using" :) --- cli/src/benchmark.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/cli/src/benchmark.cpp b/cli/src/benchmark.cpp index e7dafd6..9c65375 100644 --- a/cli/src/benchmark.cpp +++ b/cli/src/benchmark.cpp @@ -25,29 +25,25 @@ #include #include "benchmark.hpp" -using std::chrono::steady_clock; -using std::chrono::duration; -using std::chrono::time_point; - namespace eoskeygen { -void benchmark(size_t num_keys, struct benchmark_result* res) { +std::chrono::duration _run_benchmark(size_t num_keys) { + auto start = std::chrono::steady_clock::now(); + for(size_t i = 0; i < num_keys; i++) { + struct libeosio::ec_keypair k; + libeosio::ec_generate_key(&k); + } + return std::chrono::steady_clock::now() - start; +} - time_point start; +void benchmark(size_t num_keys, struct benchmark_result* res) { if (num_keys < 1) { res->sec = res->kps = 0; return; } - start = steady_clock::now(); - - for(size_t i = 0; i < num_keys; i++) { - struct libeosio::ec_keypair k; - libeosio::ec_generate_key(&k); - } - - res->sec = duration(steady_clock::now() - start).count(); + res->sec = _run_benchmark(num_keys).count(); res->kps = static_cast(num_keys) / res->sec; } From 5bd72cec1958a189de2ea0f969f544379f1327f6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 24 Feb 2021 14:05:42 +0100 Subject: [PATCH 119/204] common/cmake/libeosio.cmake: use v0.1.2 --- common/cmake/libeosio.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index c72cbb6..91f1485 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION v0.1.1 ) +set( LIBEOSIO_WANTED_VERSION v0.1.2 ) # -------------------------------- # Macros From 145769970f7362dad83fbfc3181c104d36457ace Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 24 Feb 2021 13:33:27 +0100 Subject: [PATCH 120/204] .github/workflows/ci.yml: Adding support for Ubuntu 20.04 --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cf3fd0..869dcd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: compile: strategy: matrix: - os: [ ubuntu-18.04, macos-latest, windows-latest ] + os: [ ubuntu-20.04, ubuntu-18.04, macos-latest, windows-latest ] build: [ cli, cli-mt, cli-ansi, cli-ansi-mt, gui, gui-mt ] include: - build: cli @@ -43,7 +43,12 @@ jobs: - name: Qt - Ubuntu if: startsWith(matrix.build, 'gui') && runner.os == 'Linux' shell: bash - run: sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 + run: | + if [ "${{matrix.os}}" == "ubuntu-20.04" ]; then + sudo apt-get install qt5-default=5.12.8+dfsg-0ubuntu1 + else : + sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 + fi - name: Qt - Windows/Mac if: startsWith(matrix.build, 'gui') && runner.os != 'Linux' From 09e287733ca8363aa0ba967ff6d35d455fbca867 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 24 Feb 2021 14:17:30 +0100 Subject: [PATCH 121/204] .github/workflows/package.yml: Build package for Ubuntu 20.04 --- .github/workflows/package.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 036e97e..fa972d5 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -9,21 +9,27 @@ jobs: ubuntu: strategy: matrix: + os: [ ubuntu-18.04, ubuntu-20.04 ] component: [ cli, gui ] include: - 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: Ubuntu (${{matrix.component}}) - runs-on: ubuntu-18.04 + name: ${{matrix.os}} (${{matrix.component}}) + runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v1 - name: Qt if: startsWith(matrix.component, 'gui') shell: bash - run: sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 + run: | + if [ "${{matrix.os}}" == "ubuntu-20.04" ]; then + sudo apt-get install qt5-default=5.12.8+dfsg-0ubuntu1 + else : + sudo apt-get install qt5-default=5.9.5+dfsg-0ubuntu2.5 + fi - name: Package id: package From e4dbcbdc0a213839f6301658df2072ccafdd879a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 24 Feb 2021 14:23:40 +0100 Subject: [PATCH 122/204] Version 1.0.7 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7bdb17..1a84cb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.15) # -------------------------------- project(eosio-keygen - VERSION 1.0.6 + VERSION 1.0.7 DESCRIPTION "Keygenerator for EOSIO" HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) From 010edeb2f568dc95bf69e33170d975bafe33d6c5 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 14:53:28 +0200 Subject: [PATCH 123/204] cli/src/main.cpp: Improve usage text format. --- cli/src/main.cpp | 56 +++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/cli/src/main.cpp b/cli/src/main.cpp index ddd8768..3d1f3f8 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -46,57 +46,65 @@ size_t option_num_threads = eoskeygen::KeySearch::max_threads(); void usage(const char *name) { - std::cout << name - << " [ -h | --help | -v | search [ -m | --l33t" + std::cout << std::endl + << "Usage:" << std::endl + << " " << name << std::endl; + + std::cout << " " << name + << " search [ -m | --l33t" #ifdef EOSIOKEYGEN_HAVE_THREADS << " | --threads=" #endif /* EOSIOKEYGEN_HAVE_THREADS */ << " | --dict= ... " << " | --lang= ... ] |file: [ ]" - << " | benchmark [ ]" << " ]" - << std::endl << std::endl; + << std::endl; - std::cout << " - Output one EOSIO key pair if no arguments are given" << std::endl << std::endl; + std::cout << " " << name << " benchmark [ ]" << std::endl; + + std::cout << " " << name << " -h | --help" << std::endl; + std::cout << " " << name << " -v" << std::endl; + + std::cout << std::endl << " - Output one EOSIO key pair if no arguments are given" << std::endl << std::endl; // Options std::cout - << " Options:" << std::endl - << " -h, --help Shows this help text." + << "Options:" << std::endl + << " -h --help Shows this help text." << std::endl << std::endl - << " -v Shows version." + << " -v Shows version." << std::endl << std::endl; - std::cout << " search: " << std::endl + std::cout << "search: " << std::endl << " performs a search, finding public keys containing" << std::endl << " one or more words from (separated with ',')." << std::endl << std::endl << " Instead of a list it is possible to specify a file with words" << std::endl << " (separated with newline '\\n') using file:" << std::endl << std::endl - << " -m: Monochrome, disables all color output." + << " -m Monochrome, disables all color output." << std::endl << std::endl - << " --l33t: Takes each word in and find all l33tspeak" << std::endl - << " combinations of that word and uses the new list for the search." + << " --l33t Takes each word in and find all l33tspeak" << std::endl + << " combinations of that word and uses the new list for the search." #ifdef EOSIOKEYGEN_HAVE_THREADS << std::endl << std::endl - << " --threads=: Use of parallel threads for searching." << std::endl - << " Default is what the operating system recomend." + << " --threads= Use of parallel threads for searching." << std::endl + << " Default is what the operating system recomends." #endif /* EOSIOKEYGEN_HAVE_THREADS */ << std::endl << std::endl - << " --dict=: Use words found in (separated by newline) to" << std::endl - << " highlight words in the keys found (note that the words in this" << std::endl - << " file are not used for search. only for highlight output)." << std::endl - << " There can be more then one --dict flag. In that case contents" << std::endl - << " of all files are merged into one dictionary." << std::endl + << " --dict= Use words found in (separated by newline) to" << std::endl + << " highlight words in the keys found (note that the words in this" << std::endl + << " file are not used for search. only for highlight output)." << std::endl + << " There can be more then one --dict flag. In that case contents" << std::endl + << " of all files are merged into one dictionary." << std::endl << std::endl << std::endl - << " --lang=: Same as --dict but will use " << std::endl - << " to find a file in " << CONFIG_SHARE_FULL_PATH << "/dict." << std::endl - << " There can be more then one --lang flag. In that case contents" << std::endl - << " of all files are merged into one dictionary." << std::endl + << " --lang= Same as --dict but will use " << std::endl + << " to find a file in " << CONFIG_SHARE_FULL_PATH << "/dict." << std::endl + << " There can be more then one --lang flag. In that case contents" << std::endl + << " of all files are merged into one dictionary." << std::endl << std::endl; - std::cout << " Benchmark: " << std::endl + std::cout << "benchmark: " << std::endl << " performs a benchmark test, generating keys and measuring the time." << std::endl << std::endl; } From 95849b1e326364e49df8b81c91264bd3f33b0e8b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 18:04:33 +0200 Subject: [PATCH 124/204] build.sh: adding --libeosio flag --- build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 679d90f..a58395c 100755 --- a/build.sh +++ b/build.sh @@ -1,11 +1,11 @@ #!/bin/bash function usage() { - echo "Usage: ${0##*/} [ -h|--help ] [ --cli|--no-cli ] [ --gui|--no-gui] [ -t|--type Debug|Release|RelWithDebInfo|MinSizeRel ] [--pkg-type nsis|deb|zip|tgz] [ --disable-threads ] [ --force-ansi ]" + 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 ]" exit 1 } -options=$(getopt -n "${0##*/}" -o "lht:" -l "help,cli,no-cli,gui,no-gui,type:,pkg-type:,disable-threads,force-ansi" -- "$@") +options=$(getopt -n "${0##*/}" -o "lht:" -l "help,cli,no-cli,gui,no-gui,type:,libeosio:,pkg-type:,disable-threads,force-ansi" -- "$@") [ $? -eq 0 ] || usage @@ -35,6 +35,10 @@ while true; do TARGET="package" ARGS="${ARGS} -DCPACK_GENERATOR=${1^^}" ;; + --libeosio) + shift + ARGS="${ARGS} -DLIBEOSIO_SOURCE_DIR=${1}" + ;; --cli) ARGS="${ARGS} -DCOMPONENT_CLI=ON" ;; --no-cli) From 554cfd588497c46a07a11169018684ca61378791 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 16:44:12 +0200 Subject: [PATCH 125/204] common/cmake/libeosio.cmake: set v0.1.3 needed for prefix parameter to wif_print_key() --- common/cmake/libeosio.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmake/libeosio.cmake b/common/cmake/libeosio.cmake index 91f1485..f741c08 100644 --- a/common/cmake/libeosio.cmake +++ b/common/cmake/libeosio.cmake @@ -2,7 +2,7 @@ # Variables # -------------------------------- set( LIBEOSIO_GIT_URL "https://github.com/eosswedenorg/libeosio.git" ) -set( LIBEOSIO_WANTED_VERSION v0.1.2 ) +set( LIBEOSIO_WANTED_VERSION v0.1.3 ) # -------------------------------- # Macros From 52e255850a599a723716336207256df4568ae52d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 16:45:59 +0200 Subject: [PATCH 126/204] cli/src/cli_key_search_result: Add prefix parameter to constructor. --- cli/src/cli_key_search_result.cpp | 8 +++++--- cli/src/cli_key_search_result.hpp | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cli/src/cli_key_search_result.cpp b/cli/src/cli_key_search_result.cpp index 0d527de..fa3d009 100644 --- a/cli/src/cli_key_search_result.cpp +++ b/cli/src/cli_key_search_result.cpp @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#include #include #include #include @@ -37,8 +38,9 @@ static size_t highlight(console::Color color, const std::string& str, size_t pos return len; } -CliKeySearchResult::CliKeySearchResult(const Dictionary& dict) : -m_dict (dict) +CliKeySearchResult::CliKeySearchResult(const Dictionary& dict, const std::string& prefix) : +m_dict (dict), +m_prefix (prefix) { } @@ -50,7 +52,7 @@ void CliKeySearchResult::onResult(const struct libeosio::ec_keypair* key, const std::cout << "----" << std::endl; std::cout << "Found: " << pub.substr(result.pos, result.len) << std::endl; - std::cout << "Public: EOS"; + std::cout << "Public: " << m_prefix.substr(0, 3); for(size_t i = 3; i < pub.length(); ) { if (i == result.pos) { diff --git a/cli/src/cli_key_search_result.hpp b/cli/src/cli_key_search_result.hpp index ac75cb1..4f1e47b 100644 --- a/cli/src/cli_key_search_result.hpp +++ b/cli/src/cli_key_search_result.hpp @@ -24,6 +24,7 @@ #ifndef EOSIOKEYGEN_KEY_SEARCH_HELPERS_H #define EOSIOKEYGEN_KEY_SEARCH_HELPERS_H +#include #include #include #include @@ -36,13 +37,15 @@ class Dictionary; class CliKeySearchResult : public IKeySearchResult { public: - CliKeySearchResult(const Dictionary& dict); + CliKeySearchResult(const Dictionary& dict, const std::string& prefix); virtual void onResult(const struct libeosio::ec_keypair* key, const struct KeySearch::result& result); protected : const Dictionary& m_dict; + + std::string m_prefix; }; } // namespace eoskeygen From 486d2c5030858bab7c31a1782b86a8e15f9bb0bb Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 16:47:18 +0200 Subject: [PATCH 127/204] cli/src/main.cpp: implement "--fio" option to generate FIO keys. --- cli/src/main.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cli/src/main.cpp b/cli/src/main.cpp index 3d1f3f8..19248ac 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -39,6 +39,7 @@ // Command line options. bool option_l33t = false; +std::string key_prefix = "EOS"; #ifdef EOSIOKEYGEN_HAVE_THREADS size_t option_num_threads = eoskeygen::KeySearch::max_threads(); @@ -48,10 +49,10 @@ void usage(const char *name) { std::cout << std::endl << "Usage:" << std::endl - << " " << name << std::endl; + << " " << name << " [ options ]" << std::endl; std::cout << " " << name - << " search [ -m | --l33t" + << " [ options ] search [ -m | --l33t" #ifdef EOSIOKEYGEN_HAVE_THREADS << " | --threads=" #endif /* EOSIOKEYGEN_HAVE_THREADS */ @@ -60,7 +61,7 @@ void usage(const char *name) { << " ]" << std::endl; - std::cout << " " << name << " benchmark [ ]" << std::endl; + std::cout << " " << name << " [ options ] benchmark [ ]" << std::endl; std::cout << " " << name << " -h | --help" << std::endl; std::cout << " " << name << " -v" << std::endl; @@ -73,6 +74,8 @@ void usage(const char *name) { << " -h --help Shows this help text." << std::endl << std::endl << " -v Shows version." + << std::endl << std::endl + << " --fio Generate keys from FIO network instead of EOSIO." << std::endl << std::endl; std::cout << "search: " << std::endl @@ -112,7 +115,7 @@ void usage(const char *name) { int cmd_search(const eoskeygen::strlist_t& words, const eoskeygen::Dictionary& dict, int count) { eoskeygen::KeySearch ks; - eoskeygen::CliKeySearchResult rs(dict); + eoskeygen::CliKeySearchResult rs(dict, key_prefix); ks.setCallback(&rs); @@ -169,11 +172,16 @@ int main(int argc, char **argv) { // when parsing command line. int p = 1; + if (p < argc && !strcmp(argv[p], "--fio")) { + p++; + key_prefix = "FIO"; + } + // No args, just print a key. - if (argc <= 1) { + if (p >= argc) { struct libeosio::ec_keypair pair; libeosio::ec_generate_key(&pair); - libeosio::wif_print_key(&pair); + libeosio::wif_print_key(&pair, key_prefix); return 0; } From f7b84c7752395bb12e363b344a01c52080e4043b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 6 May 2021 18:05:01 +0200 Subject: [PATCH 128/204] GUI: Adding Settings Component. --- gui/CMakeLists.txt | 1 + gui/src/Settings.cpp | 39 +++++++++++++++++++++++++++++++++++++++ gui/src/Settings.hpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 gui/src/Settings.cpp create mode 100644 gui/src/Settings.hpp diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 3628f7a..361dfeb 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -39,6 +39,7 @@ set( PROGRAM_SRC src/GenerateWindow.cpp src/SearchWindow.cpp src/MultiSelect.cpp + src/Settings.cpp src/helpers.cpp ) diff --git a/gui/src/Settings.cpp b/gui/src/Settings.cpp new file mode 100644 index 0000000..d49c408 --- /dev/null +++ b/gui/src/Settings.cpp @@ -0,0 +1,39 @@ +/** + * 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 { + bool fio_keys = false; + +} // namespace priv + +bool Settings::shouldGenerateFioKeys() +{ + return priv::fio_keys; +} + +void Settings::setGenerateFioKeys(bool value) +{ + priv::fio_keys = value; +} diff --git a/gui/src/Settings.hpp b/gui/src/Settings.hpp new file mode 100644 index 0000000..d47c26f --- /dev/null +++ b/gui/src/Settings.hpp @@ -0,0 +1,34 @@ +/** + * 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 + +namespace Settings +{ + bool shouldGenerateFioKeys(); + + void setGenerateFioKeys(bool value); +}; + +#endif /* SEARCH_WINDOW_H */ From 8c9047d71600aed1e41aaa52d25980c9b2e2f4be Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 7 May 2021 13:38:17 +0200 Subject: [PATCH 129/204] gui/src/SearchWindow.cpp: Check Settings::shouldGenerateFioKeys() to know if we should use "FIO" or "EOS" prefix. --- gui/src/SearchWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/src/SearchWindow.cpp b/gui/src/SearchWindow.cpp index 758ff43..23e2cf3 100644 --- a/gui/src/SearchWindow.cpp +++ b/gui/src/SearchWindow.cpp @@ -31,6 +31,7 @@ #include #include #include +#include "Settings.hpp" #include "gui_text.h" #include "config.hpp" #include "helpers.hpp" @@ -149,7 +150,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct { int pos = (int) result.pos; int len = (int) result.len; - QString pub = QString::fromStdString(libeosio::wif_pub_encode(key->pub)); + QString pub = QString::fromStdString(libeosio::wif_pub_encode(key->pub, Settings::shouldGenerateFioKeys() ? "FIO" : "EOS")); QString mid = pub.mid(pos, len); QString left = pub.left(pos); QString right = pub.mid(pos + len, pub.size() - pos); From 6bd84b1d8d4db1ea35f0390d59961e739dbd3299 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 7 May 2021 13:38:32 +0200 Subject: [PATCH 130/204] gui/src/GenerateWindow.cpp: Check Settings::shouldGenerateFioKeys() if we should use "FIO" or "EOS" prefix. --- gui/src/GenerateWindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gui/src/GenerateWindow.cpp b/gui/src/GenerateWindow.cpp index 00fa48f..8880ffb 100644 --- a/gui/src/GenerateWindow.cpp +++ b/gui/src/GenerateWindow.cpp @@ -28,6 +28,7 @@ #include #include #include +#include "Settings.hpp" #include "GenerateWindow.hpp" void _initKeyWidget(QLineEdit& w) { @@ -91,12 +92,13 @@ m_btn_copy_both ("Copy keys") void GenerateWindow::generate_key() { - std::string pubstr, privstr; + std::string pubstr; struct libeosio::ec_keypair pair; libeosio::ec_generate_key(&pair); - m_pub.setText(QString::fromStdString(libeosio::wif_pub_encode(pair.pub))); + pubstr = libeosio::wif_pub_encode(pair.pub, Settings::shouldGenerateFioKeys() ? "FIO" : "EOS"); + m_pub.setText(QString::fromStdString(pubstr)); m_priv.setText(QString::fromStdString(libeosio::wif_priv_encode(pair.secret))); } From 7fb1774359fe7baf67eefc01c21487883d6678ff Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 7 May 2021 13:40:47 +0200 Subject: [PATCH 131/204] gui/src/MainWindow: Add menu item to switch between FIO/EOS key prefixes. --- gui/src/MainWindow.cpp | 22 ++++++++++++++++++++-- gui/src/MainWindow.hpp | 6 ++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/gui/src/MainWindow.cpp b/gui/src/MainWindow.cpp index 3648bf7..8000ac1 100644 --- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -26,12 +26,14 @@ #include #include #include "gui_text.h" +#include "Settings.hpp" #include "GenerateWindow.hpp" #include "SearchWindow.hpp" #include "MainWindow.hpp" MainWindow::MainWindow(QWidget *parent) : -QMainWindow (parent) +QMainWindow (parent), +m_fio_action (nullptr) { // Create sub windows and stacked widget. m_stacked = new QStackedWidget(); @@ -40,10 +42,21 @@ QMainWindow (parent) setCentralWidget(m_stacked); - // Menu bar. + // Add to menu bar. menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); menuBar()->addAction("Search", this, SLOT(switchToSearch())); + + // Settings + + m_fio_action = new QAction("FIO Keys", this); + m_fio_action->setCheckable(true); + connect(m_fio_action, SIGNAL(triggered()), this, SLOT(fioKeysCheckboxChanged())); + + QMenu *settings_menu = menuBar()->addMenu("Settings"); + settings_menu->addAction(m_fio_action); + + // About menuBar()->addAction("About", this, SLOT(showAbout())); } @@ -63,3 +76,8 @@ void MainWindow::showAbout() EOSIOKEYGEN_GUI_TEXT_ABOUT_TITLE, EOSIOKEYGEN_GUI_TEXT_ABOUT_BODY); } + +void MainWindow::fioKeysCheckboxChanged() +{ + Settings::setGenerateFioKeys(m_fio_action ? m_fio_action->isChecked() : false); +} diff --git a/gui/src/MainWindow.hpp b/gui/src/MainWindow.hpp index c42e574..1658195 100644 --- a/gui/src/MainWindow.hpp +++ b/gui/src/MainWindow.hpp @@ -24,6 +24,8 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H +#include +#include #include class QStackedWidget; @@ -44,9 +46,13 @@ private slots : void showAbout(); + void fioKeysCheckboxChanged(); + private : QStackedWidget* m_stacked; + + QPointer m_fio_action; }; #endif /* MAIN_WINDOW_H */ From 0e4a574f7ae23556db1fb4feecb5f1df2fd67b1f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 20 Sep 2022 11:09:07 +0200 Subject: [PATCH 132/204] cli/src/main.cpp: fix indent in usage string. --- cli/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/main.cpp b/cli/src/main.cpp index 19248ac..911635c 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -49,7 +49,7 @@ void usage(const char *name) { std::cout << std::endl << "Usage:" << std::endl - << " " << name << " [ options ]" << std::endl; + << " " << name << " [ options ]" << std::endl; std::cout << " " << name << " [ options ] search [ -m | --l33t" From 1d923d3dd8da56368c2d7361da92bae521fb461b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 20 Sep 2022 15:18:03 +0200 Subject: [PATCH 133/204] Adding lib/CLI11 --- lib/CLI11/CMakeLists.txt | 2 + lib/CLI11/LICENSE | 25 + lib/CLI11/include/CLI11/CLI11.hpp | 9190 +++++++++++++++++++++++++++++ 3 files changed, 9217 insertions(+) create mode 100644 lib/CLI11/CMakeLists.txt create mode 100644 lib/CLI11/LICENSE create mode 100644 lib/CLI11/include/CLI11/CLI11.hpp diff --git a/lib/CLI11/CMakeLists.txt b/lib/CLI11/CMakeLists.txt new file mode 100644 index 0000000..fb43efb --- /dev/null +++ b/lib/CLI11/CMakeLists.txt @@ -0,0 +1,2 @@ +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 new file mode 100644 index 0000000..f618d95 --- /dev/null +++ b/lib/CLI11/LICENSE @@ -0,0 +1,25 @@ +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 new file mode 100644 index 0000000..f29a5c4 --- /dev/null +++ b/lib/CLI11/include/CLI11/CLI11.hpp @@ -0,0 +1,9190 @@ +// 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