├── .gitignore ├── img ├── demo_help.png ├── demo_print.png └── demo_invalid_param.png ├── paramkit ├── include │ ├── paramkit.h │ ├── color_scheme.h │ ├── term_colors.h │ ├── strings_util.h │ ├── pk_util.h │ ├── param_group.h │ ├── param.h │ └── params.h ├── CMakeLists.txt ├── pk_util.cpp └── strings_util.cpp ├── CMakeLists.txt ├── demo ├── CMakeLists.txt └── main.cpp ├── .appveyor.yml ├── .github └── workflows │ └── main.yml ├── README.md └── Doxyfile /.gitignore: -------------------------------------------------------------------------------- 1 | docs 2 | -------------------------------------------------------------------------------- /img/demo_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/paramkit/HEAD/img/demo_help.png -------------------------------------------------------------------------------- /img/demo_print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/paramkit/HEAD/img/demo_print.png -------------------------------------------------------------------------------- /img/demo_invalid_param.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/paramkit/HEAD/img/demo_invalid_param.png -------------------------------------------------------------------------------- /paramkit/include/paramkit.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief The main header, responsible for including all the other headers 4 | */ 5 | 6 | #ifndef _PARAMKIT_ 7 | #define _PARAMKIT_ 8 | 9 | #include "pk_util.h" 10 | #include "param.h" 11 | #include "params.h" 12 | #include "term_colors.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /paramkit/include/color_scheme.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "term_colors.h" 4 | 5 | namespace paramkit { 6 | 7 | const WORD ERROR_COLOR = RED; 8 | const WORD WARNING_COLOR = RED; 9 | const WORD HILIGHTED_COLOR = WHITE; 10 | 11 | const WORD HEADER_COLOR = YELLOW; 12 | const WORD SEPARATOR_COLOR = BROWN; 13 | const WORD INACTIVE_COLOR = GRAY; 14 | 15 | const WORD PARAM_SIMILAR_NAME = MAKE_COLOR(MAGENTA, BLACK); 16 | const WORD PARAM_SIMILAR_DESC = MAKE_COLOR(BLACK, MAGENTA); 17 | }; 18 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required ( VERSION 3.0 ) 2 | 3 | project ( ParamKit ) 4 | 5 | # modules: 6 | set ( M_PARAMKIT_LIB "paramkit" ) 7 | set ( M_PARAMKIT_DEMO "demo" ) 8 | 9 | # modules paths: 10 | set ( PARAMKIT_DIR "${CMAKE_SOURCE_DIR}/${M_PARAMKIT_LIB}" CACHE PATH "ParamKit main path" ) 11 | 12 | # Add sub-directories 13 | # 14 | # libs 15 | add_subdirectory ( paramkit ) 16 | set ( PARAMKIT_LIB $ CACHE PATH "ParamKit library path" ) 17 | 18 | #demos: 19 | add_subdirectory ( demo ) 20 | add_dependencies ( demo paramkit ) 21 | -------------------------------------------------------------------------------- /paramkit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required ( VERSION 3.12 ) 2 | 3 | project ( paramkit ) 4 | 5 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 6 | 7 | include_directories ( 8 | include 9 | ) 10 | 11 | set (srcs 12 | pk_util.cpp 13 | strings_util.cpp 14 | ) 15 | 16 | set (hdrs 17 | include/paramkit.h 18 | include/param.h 19 | include/params.h 20 | include/term_colors.h 21 | include/color_scheme.h 22 | include/pk_util.h 23 | include/strings_util.h 24 | include/param_group.h 25 | ) 26 | 27 | add_library ( ${PROJECT_NAME} STATIC ${hdrs} ${srcs} ) 28 | -------------------------------------------------------------------------------- /demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required ( VERSION 3.0 ) 2 | 3 | project (demo) 4 | 5 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 6 | 7 | message (STATUS "paramkit_dir='${PARAMKIT_DIR}'") 8 | message (STATUS "paramkit_lib='${PARAMKIT_LIB}'") 9 | 10 | include_directories ( ${PARAMKIT_DIR}/include ) 11 | 12 | set (srcs 13 | main.cpp 14 | ) 15 | 16 | set (hdrs 17 | ) 18 | 19 | add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs} ) 20 | target_link_libraries ( ${PROJECT_NAME} ${PARAMKIT_LIB} ) 21 | add_dependencies( ${PROJECT_NAME} paramkit ) 22 | 23 | INSTALL( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT ${PROJECT_NAME} ) 24 | -------------------------------------------------------------------------------- /paramkit/include/term_colors.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief Definitions of the colors used on the terminal 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #define BLACK 0 12 | #define DARK_BLUE 1 13 | #define DARK_GREEN 2 14 | #define DARK_CYAN 3 15 | #define DARK_RED 4 16 | #define DARK_MAGENTA 5 17 | #define BROWN 6 18 | #define SILVER 7 19 | #define GRAY 8 20 | #define BLUE 9 21 | #define LIME 0xA 22 | #define CYAN 0xB 23 | #define RED 0xC 24 | #define MAGENTA 0xD 25 | #define YELLOW 0xE 26 | #define WHITE 0xF 27 | 28 | #define MAKE_COLOR(fg_color, bg_color) (fg_color | (bg_color << 4)) 29 | #define GET_BG_COLOR(color) (color >> 4) 30 | 31 | #define YELLOW_ON_BLACK MAKE_COLOR(YELLOW, BLACK) 32 | #define RED_ON_BLACK MAKE_COLOR(RED, BLACK) 33 | 34 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - Visual Studio 2015 3 | 4 | platform: x64 5 | - x64 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | install: 12 | - set PATH=C:\Program Files\CMake\bin;%PATH% 13 | 14 | build: 15 | verbosity: detailed 16 | 17 | configuration: 18 | - Release 19 | - Debug 20 | 21 | environment: 22 | artifactName: $(APPVEYOR_PROJECT_NAME)-$(APPVEYOR_REPO_COMMIT)-$(CONFIGURATION) 23 | matrix: 24 | - env_arch: "x64" 25 | - env_arch: "x86" 26 | 27 | before_build: 28 | - mkdir build 29 | - cd build 30 | - if [%env_arch%]==[x64] ( 31 | cmake .. -A x64 ) 32 | - if [%env_arch%]==[x86] ( 33 | cmake .. -A Win32 ) 34 | - cmake -DCMAKE_INSTALL_PREFIX:PATH=%APPVEYOR_BUILD_FOLDER%/%APPVEYOR_REPO_COMMIT% .. 35 | 36 | build_script: 37 | - cmake --build . --config %CONFIGURATION% --target install 38 | 39 | after_build: 40 | - mkdir %artifactName% 41 | - cp %APPVEYOR_BUILD_FOLDER%/%APPVEYOR_REPO_COMMIT%/* %artifactName% 42 | 43 | artifacts: 44 | - path: build\%artifactName% 45 | -------------------------------------------------------------------------------- /paramkit/include/strings_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief The set of utility functions related with string processing, and finding similarity between strings 4 | */ 5 | 6 | #pragma once 7 | #include 8 | 9 | namespace paramkit { 10 | 11 | namespace util { 12 | 13 | enum stringsim_type { 14 | SIM_NONE = 0, 15 | SIM_SUBSTR = 1, 16 | SIM_LAV_DIST, 17 | SIM_HIST 18 | }; 19 | 20 | std::string to_lowercase(std::string); 21 | 22 | bool is_cstr_equal(char const *a, char const *b, const size_t max_len, bool ignoreCase = true); 23 | bool strequals(const std::string& a, const std::string& b, bool ignoreCase = true); 24 | 25 | // Calculate Levenshtein distance of two strings 26 | size_t levenshtein_distance(const char s1[], const char s2[]); 27 | 28 | // Check a similarity in strings histograms 29 | bool has_similar_histogram(const char s1[], const char s2[]); 30 | 31 | stringsim_type has_keyword(const std::string param, const std::string filter); 32 | 33 | stringsim_type is_string_similar(const std::string ¶m, const std::string &filter); 34 | }; //namespace util 35 | 36 | }; // namespace paramkit 37 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Doxygen Action 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | # This workflow contains a single job called "build" 17 | build: 18 | # The type of runner that the job will run on 19 | runs-on: ubuntu-latest 20 | 21 | # Steps represent a sequence of tasks that will be executed as part of the job 22 | steps: 23 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 24 | - uses: actions/checkout@v2 25 | 26 | - name: Doxygen Action 27 | uses: mattnotmitt/doxygen-action@v1.3.1 28 | with: 29 | # Path to Doxyfile 30 | doxyfile-path: "./Doxyfile" # default is ./Doxyfile 31 | # Working directory 32 | working-directory: "." # default is . 33 | 34 | - name: Deploy 35 | uses: peaceiris/actions-gh-pages@v3 36 | with: 37 | github_token: ${{ secrets.GITHUB_TOKEN }} 38 | publish_dir: ./docs/html 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ParamKit 2 | [![Build status](https://ci.appveyor.com/api/projects/status/dw7xwgd9isgvsair?svg=true)](https://ci.appveyor.com/project/hasherezade/paramkit) 3 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/eb0766850dbf4a389b54aa04ae92906d)](https://app.codacy.com/gh/hasherezade/paramkit/dashboard?branch=master) 4 | [![Commit activity](https://img.shields.io/github/commit-activity/m/hasherezade/paramkit)](https://github.com/hasherezade/paramkit/commits) 5 | [![Last Commit](https://img.shields.io/github/last-commit/hasherezade/paramkit/master)](https://github.com/hasherezade/paramkit/commits) 6 | 7 | A small library helping to parse commandline parameters (for Windows). 8 | 9 | Objectives 10 | - 11 | + "like Python's `argparse` but for C/C++" 12 | + compact and minimalistic 13 | + easy to use 14 | + extendable 15 | 16 | You can quickly create a project using ParamKit basing on the given template: 17 | 18 | + [Project template](https://github.com/hasherezade/paramkit_tpl) 19 | 20 | Docs 21 | - 22 | 📚 [https://hasherezade.github.io/paramkit/](https://hasherezade.github.io/paramkit/) 23 | 24 | Demo 25 | - 26 | 27 | Print help for each parameter: 28 | 29 | demo: print help 30 | 31 | Paramkit allows you to cluster your parameters into custom groups. 32 | 33 | You can use predefined, popular parameter types, or add your custom ones. 34 | 35 | Easily parse and store values, and verify if all required parameters are filled: 36 | 37 | demo: print filled params 38 | 39 | Verify if no invalid parameter was passed, and eventually suggest similar parameters: 40 | 41 | demo: print invalid param 42 | 43 | See [the demo code](https://github.com/hasherezade/paramkit/tree/master/demo) 44 | -------------------------------------------------------------------------------- /paramkit/include/pk_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief The set of utility functions used by the ParamKit 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "strings_util.h" 17 | 18 | #define GETNAME(x) (#x) 19 | 20 | namespace paramkit { 21 | 22 | bool is_hex(const char *buf, size_t len); 23 | bool is_hex_with_prefix(const char *buf); 24 | bool is_dec(const char *buf, size_t len); 25 | bool is_number(const char* my_buf); 26 | long get_number(const char *my_buf); 27 | 28 | size_t strip_to_list(IN std::string s, IN std::string delim, OUT std::set &elements_list); 29 | std::string& trim(std::string& str, const std::string& chars = "\t\n\v\f\r "); 30 | 31 | bool get_console_color(HANDLE hConsole, int& color); 32 | void print_in_color(int color, const std::string &text); 33 | //-- 34 | 35 | template 36 | std::string to_string(T_CHAR *str1) 37 | { 38 | if (str1 == nullptr) return ""; 39 | std::string val; 40 | 41 | for (size_t i = 0; ; i++) { 42 | if (str1[i] == 0) break; 43 | val.push_back((char)str1[i]); 44 | } 45 | return val; 46 | } 47 | 48 | template 49 | int loadInt(const T_CHAR *str1, bool isHex = false) 50 | { 51 | std::string str = to_string(str1); 52 | int intVal = 0; 53 | std::stringstream ss; 54 | if (isHex) { 55 | ss << std::hex << str; 56 | } 57 | else { 58 | ss << std::dec << str; 59 | } 60 | ss >> intVal; 61 | return intVal; 62 | } 63 | 64 | template 65 | bool loadBoolean(IN const T_CHAR *str1, OUT bool &value) 66 | { 67 | std::string str = to_string(str1); 68 | if (util::strequals(str, "True") || util::strequals(str, "on") || util::strequals(str, "yes")) { 69 | value = true; 70 | return true; 71 | } 72 | if (util::strequals(str, "False") || util::strequals(str, "off") || util::strequals(str, "no")) { 73 | value = false; 74 | return true; 75 | } 76 | if (!is_dec(str.c_str(), str.length())) { 77 | return false; 78 | } 79 | const int val = loadInt(str.c_str(), false); 80 | if (val == 0) { 81 | value = false; 82 | return true; 83 | } 84 | if (val == 1) { 85 | value = true; 86 | return true; 87 | } 88 | return false; 89 | } 90 | 91 | //! Copy the std::string/std::wstring value into an buffer of a given character count 92 | template 93 | size_t copy_to_cstr(T_STR value, T_CHAR *buf, size_t buf_count) 94 | { 95 | size_t val_len = value.length() + 1; 96 | if (val_len > buf_count) { 97 | val_len = buf_count; 98 | } 99 | memcpy(buf, value.c_str(), val_len * sizeof(T_CHAR)); 100 | buf[val_len - 1] = '\0'; 101 | return val_len; 102 | } 103 | 104 | }; 105 | -------------------------------------------------------------------------------- /demo/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define PARAM_MY_DEC "pdec" 5 | #define PARAM_MY_HEX "phex" 6 | 7 | #define PARAM_MY_ASTRING "pastr" 8 | #define PARAM_MY_WSTRING "pwstr" 9 | 10 | #define PARAM_MY_BOOL "pbool" 11 | #define PARAM_MY_ENUM "penum" 12 | 13 | #define MAX_BUF 50 14 | 15 | typedef enum { 16 | FRUIT_APPLE = 0, 17 | FRUIT_ORANGE = 1, 18 | FRUIT_STRAWBERY, 19 | FRUIT_COUNT 20 | } t_fruits; 21 | 22 | //--- 23 | 24 | using namespace paramkit; 25 | 26 | typedef struct { 27 | DWORD myDec; 28 | DWORD myHex; 29 | bool myBool; 30 | char myABuf[MAX_BUF]; 31 | wchar_t myWBuf[MAX_BUF]; 32 | t_fruits myEnum; 33 | } t_params_struct; 34 | 35 | void print_params(t_params_struct &p) 36 | { 37 | std::cout << "myDec : [" << std::dec << p.myDec << "] = " << std::hex << "[0x" << p.myDec << "]\n"; 38 | std::cout << "myHex : [" << std::hex << "0x" << p.myHex << "] = [" << std::dec << p.myHex << "]\n"; 39 | std::cout << "myBool: [" << std::dec << p.myBool << "]\n"; 40 | std::cout << "myABuf: [" << p.myABuf << "]\n"; 41 | std::wcout << "myWBuf: [" << p.myWBuf << "]\n"; 42 | std::cout << "myEnum: [" << std::dec << p.myEnum << "]\n"; 43 | } 44 | 45 | class DemoParams : public Params 46 | { 47 | public: 48 | DemoParams() 49 | : Params() 50 | { 51 | this->addParam(new IntParam(PARAM_MY_DEC, true, IntParam::INT_BASE_DEC)); 52 | this->setInfo(PARAM_MY_DEC, "Sample decimal Integer param"); 53 | 54 | this->addParam(new IntParam(PARAM_MY_HEX, true, IntParam::INT_BASE_HEX)); 55 | this->setInfo(PARAM_MY_HEX, "Sample hexadecimal Integer param"); 56 | 57 | this->addParam(new BoolParam(PARAM_MY_BOOL, false)); 58 | this->setInfo(PARAM_MY_BOOL, "Sample boolean param"); 59 | 60 | this->addParam(new StringParam(PARAM_MY_ASTRING, false)); 61 | this->setInfo(PARAM_MY_ASTRING, "Sample string param"); 62 | 63 | this->addParam(new WStringParam(PARAM_MY_WSTRING, false)); 64 | this->setInfo(PARAM_MY_WSTRING, "Sample wide string param"); 65 | 66 | EnumParam *myEnum = new EnumParam(PARAM_MY_ENUM, GETNAME(t_fruits), false); 67 | this->addParam(myEnum); 68 | this->setInfo(PARAM_MY_ENUM, "Sample enum param"); 69 | myEnum->addEnumValue(t_fruits::FRUIT_APPLE, "A", "green apples"); 70 | myEnum->addEnumValue(t_fruits::FRUIT_ORANGE, "O", "oranges"); 71 | myEnum->addEnumValue(t_fruits::FRUIT_STRAWBERY, "S", "fresh strawberries"); 72 | 73 | //optional: group parameters 74 | std::string str_group = "string params"; 75 | this->addGroup(new ParamGroup(str_group)); 76 | this->addParamToGroup(PARAM_MY_ASTRING, str_group); 77 | this->addParamToGroup(PARAM_MY_WSTRING, str_group); 78 | 79 | str_group = "enums"; 80 | this->addGroup(new ParamGroup(str_group)); 81 | this->addParamToGroup(PARAM_MY_ENUM, str_group); 82 | } 83 | 84 | bool fillStruct(t_params_struct ¶msStruct) 85 | { 86 | copyVal(PARAM_MY_BOOL, paramsStruct.myBool); 87 | copyVal(PARAM_MY_DEC, paramsStruct.myDec); 88 | copyVal(PARAM_MY_HEX, paramsStruct.myHex); 89 | copyVal(PARAM_MY_ENUM, paramsStruct.myEnum); 90 | 91 | copyCStr(PARAM_MY_ASTRING, paramsStruct.myABuf, _countof(paramsStruct.myABuf)); 92 | copyCStr(PARAM_MY_WSTRING, paramsStruct.myWBuf, _countof(paramsStruct.myWBuf)); 93 | return true; 94 | } 95 | 96 | void printBanner() 97 | { 98 | paramkit::print_in_color(CYAN, "Welcome to ParamKit Demo!"); 99 | std::cout << std::endl; 100 | } 101 | }; 102 | 103 | int main(int argc, char* argv[]) 104 | { 105 | DemoParams params; 106 | if (argc < 2) { 107 | params.printBanner(); 108 | params.printInfo(false); 109 | return 0; 110 | } 111 | if (!params.parse(argc, argv)) { 112 | return 0; 113 | } 114 | std::cout << "\nPrinting the filled params:\n"; 115 | params.print(); 116 | 117 | t_params_struct p = { 0 }; 118 | params.fillStruct(p); 119 | 120 | std::cout << "\nConverted to the structure:\n"; 121 | print_params(p); 122 | std::cout << std::endl; 123 | 124 | if (!params.hasRequiredFilled()) { 125 | std::cout << "[!] Some of the required parameters are not filled!\n"; 126 | } 127 | else { 128 | std::cout << "[+] All the required parameters filled!\n"; 129 | } 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /paramkit/pk_util.cpp: -------------------------------------------------------------------------------- 1 | #include "pk_util.h" 2 | #include "strings_util.h" 3 | 4 | bool paramkit::is_hex(const char *buf, size_t len) 5 | { 6 | if (!buf || len == 0) return false; 7 | for (size_t i = 0; i < len; i++) { 8 | if (buf[i] >= '0' && buf[i] <= '9') continue; 9 | if (buf[i] >= 'A' && buf[i] <= 'F') continue; 10 | if (buf[i] >= 'a' && buf[i] <= 'f') continue; 11 | return false; 12 | } 13 | return true; 14 | } 15 | 16 | bool paramkit::is_dec(const char *buf, size_t len) 17 | { 18 | if (!buf || len == 0) return false; 19 | for (size_t i = 0; i < len; i++) { 20 | if (buf[i] >= '0' && buf[i] <= '9') continue; 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | bool paramkit::is_hex_with_prefix(const char *my_buf) 27 | { 28 | if (!my_buf) return false; 29 | 30 | const char hex_pattern[] = "0x"; 31 | size_t hex_pattern_len = strlen(hex_pattern); 32 | 33 | const size_t len = strlen(my_buf); 34 | if (len == 0) return false; 35 | 36 | if (len > hex_pattern_len) { 37 | if (util::is_cstr_equal(my_buf, hex_pattern, hex_pattern_len)) { 38 | if (!is_hex(my_buf + hex_pattern_len, len - hex_pattern_len)) return false; 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | bool paramkit::is_number(const char* my_buf) 46 | { 47 | if (!my_buf) return false; 48 | 49 | const size_t len = strlen(my_buf); 50 | if (is_hex_with_prefix(my_buf)) return true; 51 | if (is_dec(my_buf, len)) return true; 52 | return false; 53 | } 54 | 55 | long paramkit::get_number(const char *my_buf) 56 | { 57 | if (!my_buf) return false; 58 | 59 | const char hex_pattern[] = "0x"; 60 | size_t hex_pattern_len = strlen(hex_pattern); 61 | 62 | const size_t len = strlen(my_buf); 63 | if (len == 0) return 0; 64 | 65 | long out = 0; 66 | const size_t min_length = 1; //tolerate number with at least 1 character 67 | if (len > hex_pattern_len) { 68 | if (util::is_cstr_equal(my_buf, hex_pattern, hex_pattern_len)) { 69 | if (!is_hex(my_buf + hex_pattern_len, min_length)) return 0; 70 | 71 | std::stringstream ss; 72 | ss << std::hex << my_buf; 73 | ss >> out; 74 | return out; 75 | } 76 | } 77 | if (!is_dec(my_buf, min_length)) return 0; 78 | 79 | std::stringstream ss; 80 | ss << std::dec << my_buf; 81 | ss >> out; 82 | return out; 83 | } 84 | 85 | bool paramkit::get_console_color(HANDLE hConsole, int& color) { 86 | CONSOLE_SCREEN_BUFFER_INFO info; 87 | if (!GetConsoleScreenBufferInfo(hConsole, &info)) 88 | return false; 89 | color = info.wAttributes; 90 | return true; 91 | } 92 | 93 | void paramkit::print_in_color(int color, const std::string &text) 94 | { 95 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 96 | int prev = 7; 97 | get_console_color(hConsole, prev); // get the previous color 98 | 99 | FlushConsoleInputBuffer(hConsole); 100 | SetConsoleTextAttribute(hConsole, color); // back to default color 101 | std::cout << text; 102 | FlushConsoleInputBuffer(hConsole); 103 | 104 | SetConsoleTextAttribute(hConsole, prev); // back to previous color 105 | } 106 | 107 | namespace paramkit { 108 | std::string& ltrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") 109 | { 110 | str.erase(0, str.find_first_not_of(chars)); 111 | return str; 112 | } 113 | 114 | std::string& rtrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") 115 | { 116 | str.erase(str.find_last_not_of(chars) + 1); 117 | return str; 118 | } 119 | }; 120 | 121 | std::string& paramkit::trim(std::string& str, const std::string& chars) 122 | { 123 | return ltrim(rtrim(str, chars), chars); 124 | } 125 | 126 | size_t paramkit::strip_to_list(IN std::string s, IN std::string delim, OUT std::set &elements_list) 127 | { 128 | size_t start = 0; 129 | size_t end = s.find(delim); 130 | while (end != std::string::npos) 131 | { 132 | std::string next_str = s.substr(start, end - start); 133 | trim(next_str); 134 | if (next_str.length() > 0) { 135 | elements_list.insert(next_str); 136 | } 137 | start = end + delim.length(); 138 | end = s.find(delim, start); 139 | } 140 | std::string next_str = s.substr(start, end); 141 | trim(next_str); 142 | if (next_str.length() > 0) { 143 | elements_list.insert(next_str); 144 | } 145 | return elements_list.size(); 146 | } 147 | -------------------------------------------------------------------------------- /paramkit/strings_util.cpp: -------------------------------------------------------------------------------- 1 | #include "strings_util.h" 2 | 3 | #include 4 | #include 5 | 6 | #define MIN(x,y) ((x) < (y) ? (x) : (y)) 7 | 8 | std::string paramkit::util::to_lowercase(std::string str) 9 | { 10 | std::transform(str.begin(), str.end(), str.begin(), tolower); 11 | return str; 12 | } 13 | 14 | bool paramkit::util::is_cstr_equal(char const *a, char const *b, const size_t max_len, bool ignoreCase) 15 | { 16 | if (a == b) return true; 17 | if (!a || !b) return false; 18 | for (size_t i = 0; i < max_len; ++i) { 19 | if (ignoreCase) { 20 | if (tolower(a[i]) != tolower(b[i])) { 21 | return false; 22 | } 23 | } 24 | else { 25 | if (a[i] != b[i]) { 26 | return false; 27 | } 28 | } 29 | if (a[i] == '\0') break; 30 | } 31 | return true; 32 | } 33 | 34 | bool paramkit::util::strequals(const std::string& a, const std::string& b, bool ignoreCase) 35 | { 36 | size_t aLen = a.size(); 37 | if (b.size() != aLen) return false; 38 | 39 | for (size_t i = 0; i < aLen; ++i) { 40 | if (!ignoreCase) { 41 | if (a[i] != b[i]) return false; 42 | } 43 | else { 44 | if (tolower(a[i]) != tolower(b[i])) return false; 45 | } 46 | } 47 | return true; 48 | } 49 | 50 | size_t paramkit::util::levenshtein_distance(const char s1[], const char s2[]) 51 | { 52 | const size_t MAX_LEN = 100; 53 | const size_t len1 = strlen(s1); 54 | const size_t len2 = strlen(s2); 55 | 56 | if (len1 >= MAX_LEN || len2 >= MAX_LEN) return(-1); 57 | 58 | //init the distance matrix 59 | int dist[MAX_LEN][MAX_LEN] = { 0 }; 60 | for (int i = 0;i <= len1;i++) { 61 | dist[0][i] = i; 62 | } 63 | for (int j = 0;j <= len2; j++) { 64 | dist[j][0] = j; 65 | } 66 | // calculate 67 | for (int j = 1;j <= len1; j++) { 68 | for (int i = 1;i <= len2; i++) { 69 | int track = 1; 70 | if (s1[i - 1] == s2[j - 1]) { 71 | track = 0; 72 | } 73 | int t = MIN((dist[i - 1][j] + 1), (dist[i][j - 1] + 1)); 74 | dist[i][j] = MIN(t, (dist[i - 1][j - 1] + track)); 75 | } 76 | } 77 | return dist[len2][len1]; 78 | } 79 | 80 | inline void calc_histogram(const char s1[], size_t hist1[255]) 81 | { 82 | memset(hist1, 0, 255); 83 | const size_t len1 = strlen(s1); 84 | for (size_t i = 0; i < len1; i++) { 85 | const char c = tolower(s1[i]); 86 | hist1[c]++; 87 | } 88 | } 89 | 90 | inline size_t calc_unique_chars(size_t hist1[255]) 91 | { 92 | size_t count = 0; 93 | for (size_t i = 0; i < 255; i++) { 94 | if (hist1[i] != 0) count++; 95 | } 96 | return count; 97 | } 98 | 99 | bool paramkit::util::has_similar_histogram(const char s1[], const char s2[]) 100 | { 101 | const size_t MAX_LEN = 255; 102 | size_t hist1[MAX_LEN] = { 0 }; 103 | size_t hist2[MAX_LEN] = { 0 }; 104 | 105 | calc_histogram(s1, hist1); 106 | calc_histogram(s2, hist2); 107 | 108 | size_t sim = 0; 109 | for (size_t i = 0; i < MAX_LEN; i++) { 110 | if (hist1[i] != 0 && hist2[i] != 0 ) sim++; 111 | } 112 | const size_t uniq1 = calc_unique_chars(hist1); 113 | const size_t uniq2 = calc_unique_chars(hist2); 114 | if (sim == uniq1 && sim == uniq2) { 115 | return true; 116 | } 117 | // 118 | return false; 119 | } 120 | 121 | paramkit::util::stringsim_type paramkit::util::has_keyword( std::string param, std::string filter) 122 | { 123 | if (param.empty() || filter.empty()) { 124 | return SIM_NONE; 125 | } 126 | param = to_lowercase(param); 127 | filter = to_lowercase(filter); 128 | const bool sim_found = (param.find(filter) != std::string::npos) || (filter.find(param) != std::string::npos); 129 | if (sim_found) return SIM_SUBSTR; 130 | return SIM_NONE; 131 | } 132 | 133 | paramkit::util::stringsim_type paramkit::util::is_string_similar(const std::string ¶m, const std::string &filter) 134 | { 135 | if (param.empty() || filter.empty()) { 136 | return SIM_NONE; 137 | } 138 | bool sim_found = false; 139 | if (has_keyword(param, filter) != SIM_NONE) { 140 | return SIM_SUBSTR; 141 | } 142 | size_t dist = util::levenshtein_distance(filter.c_str(), param.c_str()); 143 | if (dist == 1 || dist <= (param.length() / 2)) { 144 | sim_found = true; 145 | } 146 | if (dist >= param.length() || dist >= filter.length()) { 147 | sim_found = false; 148 | } 149 | if (sim_found) return SIM_LAV_DIST; 150 | 151 | sim_found = util::has_similar_histogram(filter.c_str(), param.c_str()); 152 | if (sim_found) return SIM_HIST; 153 | 154 | return SIM_NONE; 155 | } 156 | -------------------------------------------------------------------------------- /paramkit/include/param_group.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief The group of parameters 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "color_scheme.h" 17 | #include "param.h" 18 | #include "strings_util.h" 19 | 20 | namespace paramkit { 21 | 22 | //--- 23 | //! The class responsible for grouping parameters (objects of the type Param) 24 | class ParamGroup { 25 | public: 26 | //! A constructor of a ParamGroup 27 | /** 28 | \param _name : a name of the group that will be used to identify it 29 | */ 30 | ParamGroup(const std::string& _name) 31 | : hdrColor(HEADER_COLOR), paramColor(HILIGHTED_COLOR), separatorColor(SEPARATOR_COLOR) 32 | { 33 | this->name = _name; 34 | } 35 | 36 | //! Prints the whole group of parameters (their names and descriptions), optionally with the group name 37 | /** 38 | \param printGroupName : a flag indicating if the group name will be printed 39 | \param printRequired : a flag indicating if the required parameters should be printed. If true, only required are printed. If false, only optional are printed. 40 | \param hilightMissing : a flag indicating if the required parameters that are not filled should be hiligted. 41 | \param filter : a string that will be searched among the parameters. If filled, only the parameters that are similar to the given string are printed. 42 | \param isExtended : print extended info about each parameter 43 | \return number of printed parameters 44 | */ 45 | size_t printGroup(bool printGroupName, bool printRequired, bool hilightMissing, const std::string &filter = "", bool isExtended = false) 46 | { 47 | if (countParams(printRequired, hilightMissing, filter) == 0) { 48 | return 0; 49 | } 50 | const bool has_filter = filter.length() > 0 ? true : false; 51 | size_t printed = 0; 52 | 53 | if (printGroupName && name.length()) { 54 | print_in_color(separatorColor, "\n---" + name + "---\n"); 55 | } 56 | std::set::iterator itr; 57 | for (itr = params.begin(); itr != params.end(); ++itr) { 58 | Param* param = (*itr); 59 | 60 | if (!param) continue; 61 | if (printRequired != param->isRequired) continue; 62 | 63 | bool should_print = hilightMissing ? false : true; 64 | int color = paramColor; 65 | if (hilightMissing && param->isRequired && !param->isSet()) { 66 | color = WARNING_COLOR; 67 | should_print = true; 68 | } 69 | if (has_filter) { 70 | bool has_any = param->isNameSimilar(filter); 71 | color = has_any ? PARAM_SIMILAR_NAME : paramColor; 72 | if (!has_any) { 73 | has_any = param->isKeywordInDescription(filter); 74 | color = has_any ? PARAM_SIMILAR_DESC : paramColor; 75 | } 76 | if (!has_any) continue; 77 | } 78 | if (should_print) { 79 | if (!param->isActive()) { 80 | color = INACTIVE_COLOR; 81 | } 82 | param->printInColor(color); 83 | param->printDesc(isExtended); 84 | printed++; 85 | } 86 | } 87 | return printed; 88 | } 89 | 90 | protected: 91 | 92 | size_t countParams(bool printRequired, bool hilightMissing, const std::string &filter) 93 | { 94 | const bool has_filter = filter.length() > 0 ? true : false; 95 | size_t printed = 0; 96 | std::set::iterator itr; 97 | for (itr = params.begin(); itr != params.end(); ++itr) { 98 | Param* param = (*itr); 99 | 100 | if (!param) continue; 101 | if (printRequired != param->isRequired) continue; 102 | bool should_print = hilightMissing ? false : true; 103 | if (hilightMissing && param->isRequired && !param->isSet()) { 104 | should_print = true; 105 | } 106 | if (has_filter) { 107 | should_print = false; 108 | if (param->isNameSimilar(filter) || param->isKeywordInDescription(filter)) { 109 | should_print = true; 110 | } 111 | } 112 | if (should_print) { 113 | printed++; 114 | } 115 | } 116 | return printed; 117 | } 118 | 119 | bool hasParam(Param *param) 120 | { 121 | std::set::iterator itr = params.find(param); 122 | if (itr != params.end()) { 123 | return true; 124 | } 125 | return false; 126 | } 127 | 128 | bool addParam(Param *param) 129 | { 130 | if (hasParam(param)) return false; 131 | this->params.insert(param); 132 | return false; 133 | } 134 | 135 | bool removeParam(Param *param) 136 | { 137 | std::set::iterator itr = params.find(param); 138 | if (itr != params.end()) { 139 | params.erase(itr); 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | std::string name; 146 | std::set params; 147 | 148 | const int hdrColor; 149 | const int paramColor; 150 | const int separatorColor; 151 | 152 | friend class Params; 153 | }; 154 | 155 | }; 156 | -------------------------------------------------------------------------------- /paramkit/include/param.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief Basic parameter types 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "pk_util.h" 17 | #include "strings_util.h" 18 | 19 | #define PARAM_UNINITIALIZED (-1) 20 | #define INFO_SPACER "\t " 21 | 22 | #define PARAM_SWITCH1 '/' ///< The switch used to recognize that the given string should be treated as a parameter (variant 1) 23 | #define PARAM_SWITCH2 '-' ///< The switch used to recognize that the given string should be treated as a parameter (variant 2) 24 | 25 | typedef unsigned __int64 uint64_t; 26 | 27 | namespace paramkit { 28 | 29 | //! The base class of a parameter 30 | class Param { 31 | public: 32 | 33 | //! A constructor of a parameter 34 | /** 35 | \param _argStr : the name of the parameter 36 | \param _isRequired : the flag if this is a required parameter (if false, the parameter is optional) 37 | */ 38 | Param(const std::string& _argStr, bool _isRequired) 39 | { 40 | isRequired = _isRequired; 41 | argStr = _argStr; 42 | requiredArg = false; 43 | active = true; 44 | } 45 | 46 | //! A constructor of a parameter 47 | /** 48 | \param _argStr : the name of the parameter 49 | \param _typeDescStr : a description of the parameter type 50 | \param _isRequired : the flag if this is a required parameter (if false, the parameter is optional) 51 | */ 52 | Param(const std::string& _argStr, const std::string& _typeDescStr, bool _isRequired) 53 | { 54 | isRequired = _isRequired; 55 | argStr = _argStr; 56 | typeDescStr = _typeDescStr; 57 | requiredArg = false; 58 | active = true; 59 | } 60 | 61 | //! Returns the string representation of the parameter's value 62 | virtual std::string valToString() const = 0; 63 | 64 | //! Returns the string representation of the parameter's type 65 | virtual std::string type() const = 0; 66 | 67 | //! Parses the parameter from the given string 68 | virtual bool parse(const char *arg) = 0; 69 | 70 | //! Parses the parameter from the given wide string 71 | virtual bool parse(const wchar_t *arg) 72 | { 73 | std::wstring value = arg; 74 | std::string str(value.begin(), value.end()); 75 | return parse(str.c_str()); 76 | } 77 | 78 | void setActive(bool _active) 79 | { 80 | this->active = _active; 81 | } 82 | 83 | //! Returns true if the parameter is active, false otherwise. 84 | virtual bool isActive() const 85 | { 86 | return this->active; 87 | } 88 | 89 | //! Returns true if the parameter is filled, false otherwise. 90 | virtual bool isSet() const = 0; 91 | 92 | virtual std::string info(bool isExtended) const 93 | { 94 | std::stringstream ss; 95 | ss << m_info; 96 | if (isExtended) { 97 | const std::string eInfo = extendedInfo(); 98 | if (eInfo.length()) { 99 | ss << "\n" << eInfo; 100 | } 101 | } 102 | return ss.str(); 103 | } 104 | 105 | //! Prints the parameter using the given color. Appends the parameter switch to the name. 106 | void printInColor(int color) 107 | { 108 | print_in_color(color, PARAM_SWITCH1 + this->argStr); 109 | } 110 | 111 | protected: 112 | 113 | //! Prints a formatted description of the parameter, including its unique name, type, and the info. 114 | void printDesc(bool isExtended = true) const 115 | { 116 | if (requiredArg) { 117 | if (typeDescStr.length()) { 118 | std::cout << " <" << typeDescStr << ">"; 119 | } 120 | else { 121 | std::cout << " <" << type() << ">"; 122 | } 123 | } 124 | std::cout << "\n\t"; 125 | std::cout << " : " << info(isExtended); 126 | std::cout << "\n"; 127 | } 128 | 129 | //! Checks if the param name is similar to the given filter 130 | virtual bool isNameSimilar(const std::string &filter) 131 | { 132 | util::stringsim_type sim_type = util::is_string_similar(argStr, filter); 133 | return (sim_type != util::SIM_NONE) ? true : false; 134 | } 135 | 136 | //! Checks if the parameter type contains the keyword 137 | virtual bool isKeywordInType(const std::string &keyword) 138 | { 139 | if (util::has_keyword(this->type(), keyword)) { 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | //! Checks if the description contains the keyword 146 | virtual bool isKeywordInDescription(const std::string &keyword) 147 | { 148 | if (util::has_keyword(m_info, keyword)) return true; 149 | 150 | util::stringsim_type sim_type = util::has_keyword(m_extInfo, keyword); 151 | return (sim_type != util::SIM_NONE) ? true : false; 152 | } 153 | 154 | //! Extended information 155 | virtual std::string extendedInfo() const 156 | { 157 | return m_extInfo; 158 | } 159 | 160 | std::string argStr; ///< a unique name of the parameter 161 | 162 | std::string typeDescStr; ///< a description of the type of the parameter: what type of values are allowed 163 | std::string m_info; ///< a basic information about the the parameter's purpose 164 | std::string m_extInfo; ///< an extended information about the the parameter's purpose 165 | 166 | bool isRequired; ///< a flag indicating if this parameter is required 167 | bool requiredArg; ///< a flag indicating if this parameter needs to be followed by a value 168 | bool active; ///< a flag indicating if this parameter is available 169 | 170 | friend class Params; 171 | friend class ParamCompare; 172 | friend class ParamGroup; 173 | }; 174 | 175 | //! A comparator class for Param class 176 | class ParamCompare 177 | { 178 | public: 179 | bool operator()(Param* param1, Param* param2) const 180 | { 181 | if (!param1 || !param2) return false; 182 | bool val = ((param1->argStr.compare(param2->argStr) < 0)); 183 | return val; 184 | } 185 | }; 186 | 187 | //! A parameter storing an integer value 188 | class IntParam : public Param { 189 | public: 190 | 191 | typedef enum 192 | { 193 | INT_BASE_ANY = 0, 194 | INT_BASE_DEC = 1, 195 | INT_BASE_HEX = 2, 196 | INT_BASE_COUNT 197 | } t_int_base; 198 | 199 | IntParam(const std::string& _argStr, bool _isRequired, t_int_base _base = INT_BASE_ANY) 200 | : Param(_argStr, _isRequired), 201 | base(_base) 202 | { 203 | requiredArg = true; 204 | value = PARAM_UNINITIALIZED; 205 | } 206 | 207 | virtual std::string valToString() const 208 | { 209 | std::stringstream stream; 210 | if (base == INT_BASE_HEX) { 211 | stream << std::hex; 212 | } 213 | else { 214 | stream << std::dec; 215 | } 216 | stream << value; 217 | return stream.str(); 218 | } 219 | 220 | virtual std::string type() const { 221 | if (base == INT_BASE_HEX) { 222 | return "integer: hex"; 223 | } 224 | if (base == INT_BASE_DEC) { 225 | return "integer: dec"; 226 | } 227 | return "integer: decimal, or hexadecimal with '0x' prefix"; 228 | } 229 | 230 | virtual bool isSet() const 231 | { 232 | return value != PARAM_UNINITIALIZED; 233 | } 234 | 235 | virtual bool parse(const char *arg) 236 | { 237 | if (!arg) return false; 238 | const size_t len = strlen(arg); 239 | 240 | if (!isValidNumber(arg, len)) { 241 | return false; 242 | } 243 | bool isHex = (base == INT_BASE_HEX); 244 | if (base == INT_BASE_ANY) { 245 | if (paramkit::is_hex_with_prefix(arg)) { 246 | isHex = true; 247 | } 248 | } 249 | this->value = loadInt(arg, isHex); 250 | return true; 251 | } 252 | 253 | bool isValidNumber(const char *arg, const size_t len) 254 | { 255 | if (base == INT_BASE_ANY) { 256 | if (paramkit::is_hex_with_prefix(arg) || paramkit::is_dec(arg, len)) { 257 | return true; 258 | } 259 | } 260 | if (base == INT_BASE_HEX) { 261 | if (paramkit::is_hex(arg, len) || paramkit::is_hex_with_prefix(arg)) { 262 | return true; 263 | } 264 | } 265 | if (base == INT_BASE_DEC) { 266 | if (paramkit::is_dec(arg, len)) return true; 267 | } 268 | return false; 269 | } 270 | 271 | t_int_base base; 272 | uint64_t value; 273 | }; 274 | 275 | //! A parameter storing a string value 276 | class StringParam : public Param { 277 | public: 278 | StringParam(const std::string& _argStr, bool _isRequired) 279 | : Param(_argStr, _isRequired) 280 | { 281 | requiredArg = true; 282 | value = ""; 283 | } 284 | 285 | virtual std::string valToString() const 286 | { 287 | return "\"" + value + "\""; 288 | } 289 | 290 | virtual std::string type() const { 291 | return "string"; 292 | } 293 | 294 | virtual bool isSet() const 295 | { 296 | return value.length() > 0; 297 | } 298 | 299 | virtual bool parse(const char *arg) 300 | { 301 | if (!arg) return false; 302 | 303 | this->value = arg; 304 | return true; 305 | } 306 | 307 | //! Copy the stored string value into an external buffer of a given length 308 | size_t copyToCStr(char *buf, size_t buf_max) const 309 | { 310 | return copy_to_cstr(value, buf, buf_max); 311 | } 312 | 313 | std::string value; 314 | }; 315 | 316 | //! A parameter storing a wide string value 317 | class WStringParam : public Param { 318 | public: 319 | WStringParam(const std::string& _argStr, bool _isRequired) 320 | : Param(_argStr, _isRequired) 321 | { 322 | requiredArg = true; 323 | value = L""; 324 | } 325 | 326 | virtual std::string valToString() const 327 | { 328 | std::string str(value.begin(), value.end()); 329 | return "\"" + str + "\""; 330 | } 331 | 332 | virtual std::string type() const 333 | { 334 | return "wstring"; 335 | } 336 | 337 | virtual bool isSet() const 338 | { 339 | return value.length() > 0; 340 | } 341 | 342 | virtual bool parse(const wchar_t *arg) 343 | { 344 | if (!arg) return false; 345 | 346 | this->value = arg; 347 | return true; 348 | } 349 | 350 | virtual bool parse(const char *arg) 351 | { 352 | if (!arg) return false; 353 | 354 | std::string value = arg; 355 | std::wstring str(value.begin(), value.end()); 356 | 357 | this->value = str; 358 | return true; 359 | } 360 | 361 | //! Copy the stored string value into an external buffer of a given length 362 | size_t copyToCStr(wchar_t *buf, size_t buf_len) const 363 | { 364 | return copy_to_cstr(value, buf, buf_len); 365 | } 366 | 367 | std::wstring value; 368 | }; 369 | 370 | //! A parameter storing a boolean value 371 | class BoolParam : public Param { 372 | public: 373 | BoolParam(const std::string& _argStr, bool _isRequired) 374 | : Param(_argStr, _isRequired) 375 | { 376 | requiredArg = false; 377 | value = false; 378 | isParsed = false; 379 | } 380 | 381 | virtual std::string type() const 382 | { 383 | return "bool"; 384 | } 385 | 386 | virtual std::string valToString() const 387 | { 388 | std::stringstream stream; 389 | stream << std::dec; 390 | if (value) { 391 | stream << "true"; 392 | } 393 | else { 394 | stream << "false"; 395 | } 396 | return stream.str(); 397 | } 398 | 399 | virtual bool isSet() const 400 | { 401 | return isParsed; 402 | } 403 | 404 | virtual bool parse(const char *arg = nullptr) 405 | { 406 | if (!arg) { 407 | this->value = true; 408 | this->isParsed = true; 409 | return true; 410 | } 411 | this->isParsed = loadBoolean(arg, this->value); 412 | return this->isParsed; 413 | } 414 | 415 | bool value; 416 | bool isParsed; 417 | }; 418 | 419 | 420 | //! A parameter storing an enum value 421 | class EnumParam : public Param { 422 | public: 423 | EnumParam(const std::string& _argStr, const std::string _enumName, bool _isRequired) 424 | : Param(_argStr, _isRequired), enumName(_enumName), m_isSet(false) 425 | { 426 | requiredArg = true; 427 | value = PARAM_UNINITIALIZED; 428 | } 429 | 430 | bool addEnumValue(int value, const std::string &info) 431 | { 432 | enumToInfo[value] = info; 433 | return true; 434 | } 435 | 436 | bool addEnumValue(int value, const std::string &str_val, const std::string &info) 437 | { 438 | if (addEnumValue(value, info)) { 439 | enumToString[value] = str_val; 440 | } 441 | return true; 442 | } 443 | 444 | virtual std::string valToString() const 445 | { 446 | if (!isSet()) { 447 | return "(undefined)"; 448 | } 449 | std::map::const_iterator foundString = enumToString.find(value); 450 | if (foundString != enumToString.end()) { 451 | return foundString->second; 452 | } 453 | std::stringstream stream; 454 | stream << std::dec << value; 455 | return stream.str(); 456 | } 457 | 458 | virtual std::string type() const 459 | { 460 | return "*" + enumName; 461 | } 462 | 463 | virtual bool isSet() const 464 | { 465 | if (!m_isSet) return false; 466 | if (!isInEnumScope(value)) { 467 | return false; 468 | } 469 | return true; 470 | } 471 | 472 | virtual bool isKeywordInType(const std::string &keyword) 473 | { 474 | if (util::has_keyword(enumName, keyword) != util::SIM_NONE) { 475 | return true; 476 | } 477 | return false; 478 | } 479 | 480 | bool isKeywordInDescription(const std::string &keyword) 481 | { 482 | if (Param::isKeywordInDescription(keyword)) { 483 | return true; 484 | } 485 | if (isKeywordInType(keyword)) { 486 | return true; 487 | } 488 | // search the keyword also in the descriptions of particulat options: 489 | std::map::const_iterator itr; 490 | for (itr = enumToInfo.begin(); itr != enumToInfo.end(); ++itr) { 491 | const std::string valDesc = itr->second; 492 | util::stringsim_type sim_type = util::has_keyword(valDesc, keyword); 493 | if (sim_type != util::SIM_NONE) return true; 494 | } 495 | return false; 496 | } 497 | 498 | virtual bool parse(const char *arg) 499 | { 500 | if (!arg) return false; 501 | 502 | //try to find by the string representation first: 503 | const std::string strVal = arg; 504 | std::map::iterator itr; 505 | for (itr = enumToString.begin(); itr != enumToString.end(); ++itr) { 506 | if (strVal == itr->second) { 507 | this->value = itr->first; 508 | m_isSet = true; 509 | return true; 510 | } 511 | } 512 | //try to find by the integer representation: 513 | if (!is_number(arg)) { 514 | return false; 515 | } 516 | int intVal = loadInt(arg); 517 | if (!isInEnumScope(intVal)) { 518 | // out of the enum scope 519 | return false; 520 | } 521 | this->value = intVal; 522 | m_isSet = true; 523 | return true; 524 | } 525 | 526 | int value; 527 | 528 | protected: 529 | 530 | std::string extendedInfo() const 531 | { 532 | std::stringstream stream; 533 | stream << Param::extendedInfo(); 534 | stream << optionsInfo(); 535 | return stream.str(); 536 | } 537 | 538 | std::string optionsInfo() const 539 | { 540 | std::stringstream stream; 541 | std::map::const_iterator itr; 542 | stream << type() << ":\n"; 543 | for (itr = enumToInfo.begin(); itr != enumToInfo.end(); ) { 544 | int val = itr->first; 545 | std::map::const_iterator foundString = enumToString.find(itr->first); 546 | 547 | stream << "\t" << std::dec << val; 548 | if (foundString != enumToString.end()) { 549 | stream << " (" << foundString->second << ")"; 550 | } 551 | stream << " - "; 552 | stream << itr->second; 553 | ++itr; 554 | if (itr != enumToInfo.end()) { 555 | stream << "\n"; 556 | } 557 | } 558 | return stream.str(); 559 | } 560 | 561 | bool isInEnumScope(int intVal)const 562 | { 563 | if (enumToInfo.find(intVal) != enumToInfo.end()) { 564 | return true; 565 | } 566 | return false; 567 | } 568 | 569 | std::map enumToString; ///< optional: string representation of the enum parameter 570 | std::map enumToInfo; ///< required: info about the enum parameter 571 | 572 | std::string enumName; 573 | bool m_isSet; 574 | }; 575 | 576 | 577 | class StringListParam : public StringParam { 578 | public: 579 | StringListParam(const std::string& _argStr, bool _isRequired, char _delimiter) 580 | : StringParam(_argStr, _isRequired), 581 | delimiter(std::string(1, _delimiter)) 582 | { 583 | } 584 | 585 | StringListParam(const std::string& _argStr, bool _isRequired, std::string _delimiter) 586 | : StringParam(_argStr, _isRequired), 587 | delimiter(_delimiter) 588 | { 589 | } 590 | 591 | virtual std::string type() const 592 | { 593 | return "list: separated by \'" + delimiter + "\'"; 594 | } 595 | 596 | size_t stripToElements(OUT std::set &elements_list) 597 | { 598 | return strip_to_list(this->value, this->delimiter, elements_list); 599 | } 600 | 601 | const std::string delimiter; 602 | }; 603 | 604 | class IntListParam : public StringListParam { 605 | public: 606 | IntListParam(const std::string& _argStr, bool _isRequired, char _delimiter) 607 | : StringListParam(_argStr, _isRequired, _delimiter) 608 | { 609 | } 610 | 611 | IntListParam(const std::string& _argStr, bool _isRequired, std::string _delimiter) 612 | : StringListParam(_argStr, _isRequired, _delimiter) 613 | { 614 | } 615 | 616 | virtual std::string type() const 617 | { 618 | return "list: dec or hex, separated by \'" + delimiter + "\'"; 619 | } 620 | 621 | virtual bool parse(const char *arg) 622 | { 623 | if (!arg) return false; 624 | 625 | std::set str_list; 626 | if (!strip_to_list(arg, this->delimiter, str_list)) { 627 | return false; 628 | } 629 | std::set::iterator itr; 630 | for (itr = str_list.begin(); itr != str_list.end(); ++itr) { 631 | std::string nextEl = *itr; 632 | if (!paramkit::is_number(nextEl.c_str())) return false; 633 | } 634 | this->value = arg; 635 | return true; 636 | } 637 | 638 | size_t stripToIntElements(OUT std::set &elements_list) 639 | { 640 | std::set str_list; 641 | if (!stripToElements(str_list)) { 642 | return 0; 643 | } 644 | std::set::iterator itr; 645 | for (itr = str_list.begin(); itr != str_list.end(); ++itr) { 646 | std::string nextEl = *itr; 647 | if (!paramkit::is_number(nextEl.c_str())) continue; 648 | 649 | long number = paramkit::get_number(nextEl.c_str()); 650 | elements_list.insert(number); 651 | } 652 | return elements_list.size(); 653 | } 654 | 655 | }; 656 | }; 657 | 658 | -------------------------------------------------------------------------------- /paramkit/include/params.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief The main parameters container and parser 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "pk_util.h" 16 | #include "color_scheme.h" 17 | #include "param.h" 18 | #include "param_group.h" 19 | //-- 20 | 21 | #define PARAM_HELP1 "?" 22 | #define PARAM_HELP2 "help" 23 | #define PARAM_VERSION "version" 24 | #define PARAM_VERSION2 "ver" 25 | 26 | namespace paramkit { 27 | 28 | //! The class responsible for storing and parsing parameters (objects of the type Param), possibly divided into groups (ParamGroup) 29 | class Params { 30 | public: 31 | Params(const std::string &version = "") 32 | : generalGroup(nullptr), versionStr(version), 33 | paramHelp(PARAM_HELP2, false), paramHelpP(PARAM_HELP2, false), paramInfoP(" ?", false), 34 | paramVersion(PARAM_VERSION, false), 35 | hdrColor(HEADER_COLOR), paramColor(HILIGHTED_COLOR) 36 | { 37 | paramHelp.m_info = "Print complete help."; 38 | paramHelpP.m_info = "Print help about a given keyword."; 39 | paramInfoP.m_info = "Print details of a given parameter."; 40 | paramVersion.m_info = "Print version info."; 41 | } 42 | 43 | virtual ~Params() 44 | { 45 | releaseGroups(); 46 | releaseParams(); 47 | } 48 | 49 | virtual void printBanner() 50 | { 51 | return; 52 | } 53 | 54 | virtual void printVersionInfo() 55 | { 56 | if (versionStr.length()) { 57 | std::cout << versionStr << std::endl; 58 | } 59 | } 60 | 61 | bool addGroup(ParamGroup *group) 62 | { 63 | if(!group) return false; 64 | if (this->paramGroups.find(group->name) != this->paramGroups.end()) { 65 | return false; 66 | } 67 | this->paramGroups[group->name] = group; 68 | return true; 69 | } 70 | 71 | ParamGroup* getParamGroup(const std::string &str) 72 | { 73 | std::map::iterator itr = this->paramGroups.find(str); 74 | if (itr != this->paramGroups.end()) { 75 | return itr->second; 76 | } 77 | return nullptr; 78 | } 79 | 80 | bool addParamToGroup(const std::string paramName, const std::string groupName) 81 | { 82 | Param* param = this->getParam(paramName); 83 | ParamGroup *group = this->getParamGroup(groupName); 84 | return addParamToGroup(param, group); 85 | } 86 | 87 | //! Adds a parameter into the storage 88 | /** 89 | \param param : an object inheriting from the class Param 90 | */ 91 | void addParam(Param* param) 92 | { 93 | if (!param) return; 94 | const std::string argStr = param->argStr; 95 | this->myParams[argStr] = param; 96 | if (!generalGroup) { 97 | generalGroup = new ParamGroup(""); 98 | this->addGroup(generalGroup); 99 | } 100 | this->addParamToGroup(param, this->generalGroup); 101 | } 102 | 103 | //! Sets the information about the parameter, defined by its name 104 | /** 105 | \param paramName : a unique name of the parameter 106 | \param basic_info : basic description of the parameter 107 | \param extended_info : additional description of the parameter 108 | \return true if setting the info was successful 109 | */ 110 | bool setInfo(const std::string& paramName, const std::string& basic_info, const std::string& extended_info = "") 111 | { 112 | Param *p = getParam(paramName); 113 | if (!p) return false; 114 | 115 | p->m_info = basic_info; 116 | p->m_extInfo = extended_info; 117 | return false; 118 | } 119 | 120 | //! Prints info about all the parameters. Optionally hilights the required ones that are missing. 121 | /** 122 | \param hilightMissing : if set, the required parameters that were not filled are printed in red. 123 | \param filter : display only parameters similar to the given string 124 | \param isExtended : display extended info about each parameter 125 | */ 126 | void printInfo(bool hilightMissing=false, const std::string &filter = "", bool isExtended = true) 127 | { 128 | std::cout << "---" << std::endl; 129 | _info(true, hilightMissing, filter, isExtended); 130 | _info(false, hilightMissing, filter, isExtended); 131 | const bool extendedInfoS = (filter.empty() && !hilightMissing) ? isExtended : false; 132 | printInfoSection(extendedInfoS); 133 | std::cout << "---" << std::endl; 134 | } 135 | 136 | //! Prints brief info about all the parameters. Wrapper for printInfo. 137 | void printBriefInfo() 138 | { 139 | printInfo(false, "", false); 140 | } 141 | 142 | //! Fills an IntParam defined by its name with the given value. If such parameter does not exist, or is not of the type IntParam, returns false. Otherwise returns true. 143 | /** 144 | \param paramName : a name of the parameter (of the type IntParam) that is to be filled 145 | \param val : the value to be set into the parameter 146 | \return true if setting the value was successful 147 | */ 148 | bool setIntValue(const std::string& paramName, uint64_t val) 149 | { 150 | Param *p = getParam(paramName); 151 | if (!p) return false; 152 | 153 | IntParam *param = dynamic_cast(p); 154 | if (!param) { 155 | return false; 156 | } 157 | param->value = val; 158 | return true; 159 | } 160 | 161 | //! Gets an integer value of the IntParam defined by its name. If such parameter does not exist, or is not of IntParam type, returns PARAM_UNINITIALIZED. 162 | /** 163 | \param paramName : a name of the parameter (of the type IntParam) which's value is to be retrieved 164 | */ 165 | uint64_t getIntValue(const std::string& paramName) 166 | { 167 | std::map::iterator itr = this->myParams.find(paramName); 168 | if (itr == this->myParams.end()) return PARAM_UNINITIALIZED; 169 | 170 | IntParam *param = dynamic_cast(itr->second); 171 | if (!param) { 172 | return 0; 173 | } 174 | return param->value; 175 | } 176 | 177 | //! Checks if the parameter with the given name is set (filled). 178 | /** 179 | \param paramName : a name of the parameter 180 | \return true if the parameter with the given name exists and is set 181 | */ 182 | virtual bool isSet(const std::string& paramName) 183 | { 184 | std::map::iterator itr = this->myParams.find(paramName); 185 | if (itr == this->myParams.end()) return false; 186 | 187 | Param *param = itr->second; 188 | if (!param) { 189 | return false; 190 | } 191 | return param->isSet(); 192 | } 193 | 194 | //! Checks if all the required parameters are filled. 195 | virtual bool hasRequiredFilled() 196 | { 197 | std::map::iterator itr; 198 | for (itr = myParams.begin(); itr != myParams.end(); itr++) { 199 | Param *param = itr->second; 200 | if (param->isRequired && param->isActive() && !param->isSet()) { 201 | return false; 202 | } 203 | } 204 | return true; 205 | } 206 | 207 | //! Deletes all the parameters groups. 208 | void releaseGroups() 209 | { 210 | paramToGroup.clear(); 211 | this->generalGroup = nullptr; 212 | std::map::iterator itr; 213 | for (itr = paramGroups.begin(); itr != paramGroups.end(); ++itr) { 214 | ParamGroup *group = itr->second; 215 | group->params.clear(); 216 | delete group; 217 | } 218 | paramGroups.clear(); 219 | } 220 | 221 | //! Deletes all the added parameters. 222 | void releaseParams() 223 | { 224 | std::map::iterator itr; 225 | for (itr = myParams.begin(); itr != myParams.end(); itr++) { 226 | Param *param = itr->second; 227 | delete param; 228 | } 229 | myParams.clear(); 230 | } 231 | 232 | //! Parses the parameters. Prints a warning if an undefined parameter was supplied. 233 | template 234 | bool parse(int argc, T_CHAR* argv[]) 235 | { 236 | bool helpRequested = false; 237 | size_t count = 0; 238 | for (int i = 1; i < argc; i++) { 239 | std::string param_str = to_string(argv[i]); 240 | if (!isParam(param_str)) { 241 | printUnknownArgument(param_str); 242 | continue; 243 | } 244 | bool found = false; 245 | param_str = skipParamPrefix(param_str); 246 | 247 | std::map::iterator itr; 248 | for (itr = myParams.begin(); itr != myParams.end(); ++itr) { 249 | bool paramHelp = false; 250 | Param *param = itr->second; 251 | if (param_str == PARAM_HELP2 || param_str == PARAM_HELP1) { 252 | if (param_str == PARAM_HELP2) { 253 | const bool hasArg = (i + 1) < argc && !(isParam(to_string(argv[i + 1]))); 254 | if (hasArg) { 255 | const std::string nextVal = to_string(argv[i + 1]); 256 | printHelp(nextVal, true); 257 | return false; 258 | } 259 | } 260 | const bool shouldExpand = (param_str == PARAM_HELP1) ? false : true; 261 | printHelp("", shouldExpand); 262 | return false; 263 | } 264 | if (this->versionStr.length()) { 265 | if (param_str == PARAM_VERSION || param_str == PARAM_VERSION2) { 266 | this->printVersionInfo(); 267 | return false; 268 | } 269 | } 270 | if (param_str == param->argStr) { 271 | if (!param->isActive()) { 272 | paramkit::print_in_color(RED, "WARNING: chosen inactive parameter: " + param_str + "\n"); 273 | } 274 | // has an argument: 275 | const bool hasArg = (i + 1) < argc && 276 | ( param->requiredArg || !(isParam(to_string(argv[i + 1]))) ); 277 | if (hasArg) { 278 | const std::string nextVal = to_string(argv[i + 1]); 279 | i++; // increment index: move to the next argument 280 | found = true; 281 | bool isParsed = false; 282 | 283 | if (nextVal == PARAM_HELP1) { 284 | paramHelp = true; 285 | helpRequested = true; 286 | isParsed = true; 287 | } 288 | else { 289 | isParsed = param->parse(nextVal.c_str()); 290 | if (!isParsed) { 291 | paramHelp = true; 292 | helpRequested = true; 293 | } 294 | } 295 | 296 | //help requested explicitly or parsing failed 297 | if (paramHelp) { 298 | if (!isParsed) { 299 | paramkit::print_in_color(RED, "Parsing the parameter failed. Correct options:\n"); 300 | } 301 | paramkit::print_in_color(RED, param_str); 302 | param->printDesc(); 303 | break; 304 | } 305 | break; 306 | } 307 | // does not require an argument: 308 | if (!param->requiredArg) { 309 | param->parse((char*)nullptr); 310 | found = true; 311 | break; 312 | } 313 | // requires an argument, but it is missing: 314 | paramkit::print_in_color(RED, param_str); 315 | paramHelp = true; 316 | helpRequested = true; 317 | param->printDesc(); 318 | found = true; 319 | break; 320 | } 321 | } 322 | if (found) { 323 | count++; 324 | } 325 | else { 326 | printUnknownParam(param_str); 327 | print_in_color(HILIGHTED_COLOR, "Similar parameters:\n"); 328 | this->printInfo(false, param_str, true); 329 | return false; 330 | } 331 | } 332 | if (helpRequested) { 333 | return false; 334 | } 335 | if (!this->hasRequiredFilled()) { 336 | print_in_color(WARNING_COLOR, "Missing required parameters:\n"); 337 | this->printInfo(true, "", true); 338 | return false; 339 | } 340 | if (this->countCategory(true) == 0 && countFilled(false) == 0) { 341 | std::stringstream ss1; 342 | ss1 << "Run with parameter " << PARAM_SWITCH1 << PARAM_HELP1 << " or " << PARAM_SWITCH1 << PARAM_HELP2 << " to see the options...\n"; 343 | print_in_color(YELLOW, ss1.str()); 344 | } 345 | return true; 346 | } 347 | 348 | //! Prints the values of all the parameters that are currently set. 349 | void print() 350 | { 351 | const int paramColor = HILIGHTED_COLOR; 352 | std::map::iterator itr; 353 | for (itr = myParams.begin(); itr != myParams.end(); itr++) { 354 | if (!isSet(itr->first)) continue; 355 | 356 | Param *param = itr->second; 357 | if (!param) continue; //should never happen 358 | 359 | param->printInColor(paramColor); 360 | std::cout << ": "; 361 | std::cout << std::hex << param->valToString() << "\n"; 362 | } 363 | } 364 | 365 | template 366 | bool copyVal(const std::string ¶mId, FIELD_T &toFill) 367 | { 368 | PARAM_T *myParam = dynamic_cast(this->getParam(paramId)); 369 | if (!myParam) { 370 | return false; 371 | } 372 | if (!myParam->isSet()) { 373 | return false; 374 | } 375 | toFill = static_cast(myParam->value); 376 | return true; 377 | } 378 | 379 | template 380 | bool copyCStr(const std::string ¶mId, FIELD_T &toFill, size_t toFillLen) 381 | { 382 | PARAM_T *myStr = dynamic_cast(this->getParam(paramId)); 383 | if (!myStr || !myStr->isSet()) { 384 | return false; 385 | } 386 | myStr->copyToCStr(toFill, toFillLen); 387 | return true; 388 | } 389 | 390 | protected: 391 | 392 | virtual size_t countFilled(bool isRequired) 393 | { 394 | size_t count = 0; 395 | std::map::iterator itr; 396 | for (itr = myParams.begin(); itr != myParams.end(); itr++) { 397 | Param *param = itr->second; 398 | if (param->isRequired != isRequired) continue; 399 | if (param->isSet()) { 400 | count++; 401 | } 402 | } 403 | return count; 404 | } 405 | 406 | size_t _info(bool isRequired, bool hilightMissing, const std::string &filter, bool isExtended) 407 | { 408 | const bool has_filter = filter.length() > 0 ? true : false; 409 | std::map::iterator itr; 410 | size_t printed = 0; 411 | if (countCategory(isRequired) > 0) { 412 | const std::string desc = isRequired ? "Required:" : "Optional:"; 413 | print_in_color(hdrColor, "\n"+ desc + "\n"); 414 | 415 | size_t total_count = 0; 416 | bool printGroupName = (countGroups(isRequired, hilightMissing, filter)) ? true : false; 417 | if (paramGroups.size() > 0) { 418 | std::map::iterator groupItr; 419 | for (groupItr = this->paramGroups.begin(); groupItr != paramGroups.end(); ++groupItr) { 420 | ParamGroup* group = groupItr->second; 421 | if (!group) continue; //should never happen 422 | printed += group->printGroup(printGroupName, isRequired, hilightMissing, filter, isExtended); 423 | total_count += group->countParams(isRequired, false, ""); 424 | } 425 | if (printed < total_count) { 426 | print_in_color(INACTIVE_COLOR, "\n[...]\n"); 427 | } 428 | } 429 | } 430 | return printed; 431 | } 432 | 433 | bool printHelp(const std::string helpArg, bool shouldExpand) 434 | { 435 | if (helpArg.empty()) { 436 | this->printBanner(); 437 | this->printInfo(false, "", shouldExpand); 438 | return false; 439 | } 440 | if (helpArg == PARAM_HELP1 || helpArg == PARAM_HELP2) { 441 | printBanner(); 442 | printInfoSection(true); 443 | return true; 444 | } 445 | if (helpArg == PARAM_VERSION || helpArg == PARAM_VERSION2) { 446 | if (this->versionStr.length()) { 447 | paramVersion.printInColor(paramColor); 448 | paramVersion.printDesc(true); 449 | } 450 | else { 451 | std::cout << "Application version is not set\n"; 452 | } 453 | return true; 454 | } 455 | this->printInfo(false, helpArg, shouldExpand); 456 | return true; 457 | } 458 | 459 | void printInfoSection(bool isExtended) 460 | { 461 | if (isExtended) { 462 | // make an example: 463 | if (myParams.size()) { 464 | std::map::iterator itr = myParams.begin(); 465 | std::stringstream ss1; 466 | ss1 << INFO_SPACER << "Example: " << PARAM_SWITCH1 << itr->first << " ?"; 467 | paramInfoP.m_extInfo = ss1.str(); 468 | } 469 | } 470 | print_in_color(hdrColor, "\nInfo:\n"); 471 | paramHelp.printInColor(paramColor); 472 | paramHelp.printDesc(isExtended); 473 | paramHelpP.printInColor(paramColor); 474 | paramHelpP.printDesc(isExtended); 475 | paramInfoP.printInColor(paramColor); 476 | paramInfoP.printDesc(isExtended); 477 | if (this->versionStr.length()) { 478 | paramVersion.printInColor(paramColor); 479 | paramVersion.printDesc(isExtended); 480 | } 481 | } 482 | 483 | bool addParamToGroup(Param *param, ParamGroup *group) 484 | { 485 | if (!param || !group) { 486 | return false; 487 | } 488 | std::map::iterator itr = paramToGroup.find(param); 489 | if (itr != paramToGroup.end()) { 490 | ParamGroup* currentGroup = itr->second; 491 | if (currentGroup != group) { 492 | currentGroup->removeParam(param); 493 | paramToGroup.erase(param); 494 | } 495 | } 496 | group->params.insert(param); 497 | paramToGroup[param] = group; 498 | return true; 499 | } 500 | 501 | size_t countGroups(bool required, bool hilightMissing, const std::string &filter) const 502 | { 503 | size_t groups_count = 0; 504 | std::map::const_iterator itr; 505 | for (itr = paramGroups.begin(); itr != paramGroups.end(); ++itr) { 506 | ParamGroup *group = itr->second; 507 | if (group == this->generalGroup) continue; //skip the general 508 | if (group->countParams(required, hilightMissing, filter) > 0) { 509 | groups_count++; 510 | } 511 | } 512 | return groups_count; 513 | } 514 | 515 | //! Returns the number of parameters of particular category: required or optional. 516 | size_t countCategory(bool isRequired) 517 | { 518 | size_t count = 0; 519 | std::map::iterator itr; 520 | for (itr = myParams.begin(); itr != myParams.end(); itr++) { 521 | Param *param = itr->second; 522 | if (param->isRequired == isRequired) count++; 523 | } 524 | return count; 525 | } 526 | 527 | void printUnknownParam(const std::string ¶m) 528 | { 529 | print_in_color(WARNING_COLOR, "Invalid parameter: "); 530 | std::cout << param << "\n"; 531 | } 532 | 533 | void printUnknownArgument(const std::string &str) 534 | { 535 | print_in_color(WARNING_COLOR, "Redundant argument: "); 536 | std::cout << str << "\n"; 537 | } 538 | 539 | //! Retrieve the parameter by its unique name. Returns nullptr if such parameter does not exist. 540 | Param* getParam(const std::string &str) 541 | { 542 | std::map::iterator itr = this->myParams.find(str); 543 | if (itr != this->myParams.end()) { 544 | return itr->second; 545 | } 546 | return nullptr; 547 | } 548 | 549 | //! Checks if the string starts from the parameter switch. 550 | static bool isParam(const std::string &str) 551 | { 552 | const size_t prefixLen = 1; 553 | const size_t len = str.length(); 554 | if (len <= prefixLen) return false; 555 | 556 | if (str[0] == PARAM_SWITCH1 || str[0] == PARAM_SWITCH2) { 557 | return true; 558 | } 559 | return false; 560 | } 561 | 562 | //! Skip the parameter prefix. Example: "/param", '-param', or "--param" is converted to "param". 563 | std::string skipParamPrefix(std::string &str) 564 | { 565 | size_t prefixLen = 1; 566 | const size_t len = str.length(); 567 | if (len < prefixLen) return str; 568 | 569 | if (str[0] != PARAM_SWITCH1 && str[0] != PARAM_SWITCH2) { 570 | return str; 571 | } 572 | if (len > 2 && str[0] == PARAM_SWITCH2) { 573 | if (str[1] == PARAM_SWITCH2) { // double prefix: "--", i.e. "--param" 574 | prefixLen = 2; 575 | } 576 | } 577 | return str.substr(prefixLen); // skip the first char 578 | } 579 | 580 | std::string versionStr; 581 | std::map myParams; 582 | 583 | BoolParam paramHelp; 584 | StringParam paramHelpP; 585 | BoolParam paramInfoP; 586 | 587 | BoolParam paramVersion; 588 | ParamGroup *generalGroup; 589 | std::map paramToGroup; 590 | std::map paramGroups; 591 | 592 | const int hdrColor; 593 | const int paramColor; 594 | }; 595 | }; 596 | 597 | -------------------------------------------------------------------------------- /Doxyfile: -------------------------------------------------------------------------------- 1 | # Doxyfile 1.9.2 2 | 3 | # This file describes the settings to be used by the documentation system 4 | # doxygen (www.doxygen.org) for a project. 5 | # 6 | # All text after a double hash (##) is considered a comment and is placed in 7 | # front of the TAG it is preceding. 8 | # 9 | # All text after a single hash (#) is considered a comment and will be ignored. 10 | # The format is: 11 | # TAG = value [value, ...] 12 | # For lists, items can also be appended using: 13 | # TAG += value [value, ...] 14 | # Values that contain spaces should be placed between quotes (\" \"). 15 | 16 | #--------------------------------------------------------------------------- 17 | # Project related configuration options 18 | #--------------------------------------------------------------------------- 19 | 20 | # This tag specifies the encoding used for all characters in the configuration 21 | # file that follow. The default is UTF-8 which is also the encoding used for all 22 | # text before the first occurrence of this tag. Doxygen uses libiconv (or the 23 | # iconv built into libc) for the transcoding. See 24 | # https://www.gnu.org/software/libiconv/ for the list of possible encodings. 25 | # The default value is: UTF-8. 26 | 27 | DOXYFILE_ENCODING = UTF-8 28 | 29 | # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by 30 | # double-quotes, unless you are using Doxywizard) that should identify the 31 | # project for which the documentation is generated. This name is used in the 32 | # title of most generated pages and in a few other places. 33 | # The default value is: My Project. 34 | 35 | PROJECT_NAME = ParamKit 36 | 37 | # The PROJECT_NUMBER tag can be used to enter a project or revision number. This 38 | # could be handy for archiving the generated documentation or if some version 39 | # control system is used. 40 | 41 | PROJECT_NUMBER = 42 | 43 | # Using the PROJECT_BRIEF tag one can provide an optional one line description 44 | # for a project that appears at the top of each page and should give viewer a 45 | # quick idea about the purpose of the project. Keep the description short. 46 | 47 | PROJECT_BRIEF = "A small library helping to parse commandline parameters (for Windows)." 48 | 49 | # With the PROJECT_LOGO tag one can specify a logo or an icon that is included 50 | # in the documentation. The maximum height of the logo should not exceed 55 51 | # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy 52 | # the logo to the output directory. 53 | 54 | PROJECT_LOGO = 55 | 56 | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path 57 | # into which the generated documentation will be written. If a relative path is 58 | # entered, it will be relative to the location where doxygen was started. If 59 | # left blank the current directory will be used. 60 | 61 | OUTPUT_DIRECTORY = docs 62 | 63 | # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- 64 | # directories (in 2 levels) under the output directory of each output format and 65 | # will distribute the generated files over these directories. Enabling this 66 | # option can be useful when feeding doxygen a huge amount of source files, where 67 | # putting all generated files in the same directory would otherwise causes 68 | # performance problems for the file system. 69 | # The default value is: NO. 70 | 71 | CREATE_SUBDIRS = NO 72 | 73 | # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII 74 | # characters to appear in the names of generated files. If set to NO, non-ASCII 75 | # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode 76 | # U+3044. 77 | # The default value is: NO. 78 | 79 | ALLOW_UNICODE_NAMES = NO 80 | 81 | # The OUTPUT_LANGUAGE tag is used to specify the language in which all 82 | # documentation generated by doxygen is written. Doxygen will use this 83 | # information to generate all constant output in the proper language. 84 | # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, 85 | # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), 86 | # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, 87 | # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), 88 | # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, 89 | # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, 90 | # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, 91 | # Ukrainian and Vietnamese. 92 | # The default value is: English. 93 | 94 | OUTPUT_LANGUAGE = English 95 | 96 | # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member 97 | # descriptions after the members that are listed in the file and class 98 | # documentation (similar to Javadoc). Set to NO to disable this. 99 | # The default value is: YES. 100 | 101 | BRIEF_MEMBER_DESC = YES 102 | 103 | # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief 104 | # description of a member or function before the detailed description 105 | # 106 | # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 107 | # brief descriptions will be completely suppressed. 108 | # The default value is: YES. 109 | 110 | REPEAT_BRIEF = YES 111 | 112 | # This tag implements a quasi-intelligent brief description abbreviator that is 113 | # used to form the text in various listings. Each string in this list, if found 114 | # as the leading text of the brief description, will be stripped from the text 115 | # and the result, after processing the whole list, is used as the annotated 116 | # text. Otherwise, the brief description is used as-is. If left blank, the 117 | # following values are used ($name is automatically replaced with the name of 118 | # the entity):The $name class, The $name widget, The $name file, is, provides, 119 | # specifies, contains, represents, a, an and the. 120 | 121 | ABBREVIATE_BRIEF = "The $name class" \ 122 | "The $name widget" \ 123 | "The $name file" \ 124 | is \ 125 | provides \ 126 | specifies \ 127 | contains \ 128 | represents \ 129 | a \ 130 | an \ 131 | the 132 | 133 | # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 134 | # doxygen will generate a detailed section even if there is only a brief 135 | # description. 136 | # The default value is: NO. 137 | 138 | ALWAYS_DETAILED_SEC = NO 139 | 140 | # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 141 | # inherited members of a class in the documentation of that class as if those 142 | # members were ordinary class members. Constructors, destructors and assignment 143 | # operators of the base classes will not be shown. 144 | # The default value is: NO. 145 | 146 | INLINE_INHERITED_MEMB = NO 147 | 148 | # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path 149 | # before files name in the file list and in the header files. If set to NO the 150 | # shortest path that makes the file name unique will be used 151 | # The default value is: YES. 152 | 153 | FULL_PATH_NAMES = YES 154 | 155 | # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. 156 | # Stripping is only done if one of the specified strings matches the left-hand 157 | # part of the path. The tag can be used to show relative paths in the file list. 158 | # If left blank the directory from which doxygen is run is used as the path to 159 | # strip. 160 | # 161 | # Note that you can specify absolute paths here, but also relative paths, which 162 | # will be relative from the directory where doxygen is started. 163 | # This tag requires that the tag FULL_PATH_NAMES is set to YES. 164 | 165 | STRIP_FROM_PATH = 166 | 167 | # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the 168 | # path mentioned in the documentation of a class, which tells the reader which 169 | # header file to include in order to use a class. If left blank only the name of 170 | # the header file containing the class definition is used. Otherwise one should 171 | # specify the list of include paths that are normally passed to the compiler 172 | # using the -I flag. 173 | 174 | STRIP_FROM_INC_PATH = 175 | 176 | # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but 177 | # less readable) file names. This can be useful is your file systems doesn't 178 | # support long names like on DOS, Mac, or CD-ROM. 179 | # The default value is: NO. 180 | 181 | SHORT_NAMES = NO 182 | 183 | # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the 184 | # first line (until the first dot) of a Javadoc-style comment as the brief 185 | # description. If set to NO, the Javadoc-style will behave just like regular Qt- 186 | # style comments (thus requiring an explicit @brief command for a brief 187 | # description.) 188 | # The default value is: NO. 189 | 190 | JAVADOC_AUTOBRIEF = NO 191 | 192 | # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line 193 | # such as 194 | # /*************** 195 | # as being the beginning of a Javadoc-style comment "banner". If set to NO, the 196 | # Javadoc-style will behave just like regular comments and it will not be 197 | # interpreted by doxygen. 198 | # The default value is: NO. 199 | 200 | JAVADOC_BANNER = NO 201 | 202 | # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first 203 | # line (until the first dot) of a Qt-style comment as the brief description. If 204 | # set to NO, the Qt-style will behave just like regular Qt-style comments (thus 205 | # requiring an explicit \brief command for a brief description.) 206 | # The default value is: NO. 207 | 208 | QT_AUTOBRIEF = NO 209 | 210 | # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a 211 | # multi-line C++ special comment block (i.e. a block of //! or /// comments) as 212 | # a brief description. This used to be the default behavior. The new default is 213 | # to treat a multi-line C++ comment block as a detailed description. Set this 214 | # tag to YES if you prefer the old behavior instead. 215 | # 216 | # Note that setting this tag to YES also means that rational rose comments are 217 | # not recognized any more. 218 | # The default value is: NO. 219 | 220 | MULTILINE_CPP_IS_BRIEF = NO 221 | 222 | # By default Python docstrings are displayed as preformatted text and doxygen's 223 | # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the 224 | # doxygen's special commands can be used and the contents of the docstring 225 | # documentation blocks is shown as doxygen documentation. 226 | # The default value is: YES. 227 | 228 | PYTHON_DOCSTRING = YES 229 | 230 | # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the 231 | # documentation from any documented member that it re-implements. 232 | # The default value is: YES. 233 | 234 | INHERIT_DOCS = YES 235 | 236 | # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new 237 | # page for each member. If set to NO, the documentation of a member will be part 238 | # of the file/class/namespace that contains it. 239 | # The default value is: NO. 240 | 241 | SEPARATE_MEMBER_PAGES = NO 242 | 243 | # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen 244 | # uses this value to replace tabs by spaces in code fragments. 245 | # Minimum value: 1, maximum value: 16, default value: 4. 246 | 247 | TAB_SIZE = 4 248 | 249 | # This tag can be used to specify a number of aliases that act as commands in 250 | # the documentation. An alias has the form: 251 | # name=value 252 | # For example adding 253 | # "sideeffect=@par Side Effects:^^" 254 | # will allow you to put the command \sideeffect (or @sideeffect) in the 255 | # documentation, which will result in a user-defined paragraph with heading 256 | # "Side Effects:". Note that you cannot put \n's in the value part of an alias 257 | # to insert newlines (in the resulting output). You can put ^^ in the value part 258 | # of an alias to insert a newline as if a physical newline was in the original 259 | # file. When you need a literal { or } or , in the value part of an alias you 260 | # have to escape them by means of a backslash (\), this can lead to conflicts 261 | # with the commands \{ and \} for these it is advised to use the version @{ and 262 | # @} or use a double escape (\\{ and \\}) 263 | 264 | ALIASES = 265 | 266 | # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 267 | # only. Doxygen will then generate output that is more tailored for C. For 268 | # instance, some of the names that are used will be different. The list of all 269 | # members will be omitted, etc. 270 | # The default value is: NO. 271 | 272 | OPTIMIZE_OUTPUT_FOR_C = NO 273 | 274 | # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or 275 | # Python sources only. Doxygen will then generate output that is more tailored 276 | # for that language. For instance, namespaces will be presented as packages, 277 | # qualified scopes will look different, etc. 278 | # The default value is: NO. 279 | 280 | OPTIMIZE_OUTPUT_JAVA = NO 281 | 282 | # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 283 | # sources. Doxygen will then generate output that is tailored for Fortran. 284 | # The default value is: NO. 285 | 286 | OPTIMIZE_FOR_FORTRAN = NO 287 | 288 | # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 289 | # sources. Doxygen will then generate output that is tailored for VHDL. 290 | # The default value is: NO. 291 | 292 | OPTIMIZE_OUTPUT_VHDL = NO 293 | 294 | # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice 295 | # sources only. Doxygen will then generate output that is more tailored for that 296 | # language. For instance, namespaces will be presented as modules, types will be 297 | # separated into more groups, etc. 298 | # The default value is: NO. 299 | 300 | OPTIMIZE_OUTPUT_SLICE = NO 301 | 302 | # Doxygen selects the parser to use depending on the extension of the files it 303 | # parses. With this tag you can assign which parser to use for a given 304 | # extension. Doxygen has a built-in mapping, but you can override or extend it 305 | # using this tag. The format is ext=language, where ext is a file extension, and 306 | # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, 307 | # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, 308 | # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: 309 | # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser 310 | # tries to guess whether the code is fixed or free formatted code, this is the 311 | # default for Fortran type files). For instance to make doxygen treat .inc files 312 | # as Fortran files (default is PHP), and .f files as C (default is Fortran), 313 | # use: inc=Fortran f=C. 314 | # 315 | # Note: For files without extension you can use no_extension as a placeholder. 316 | # 317 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise 318 | # the files are not read by doxygen. When specifying no_extension you should add 319 | # * to the FILE_PATTERNS. 320 | # 321 | # Note see also the list of default file extension mappings. 322 | 323 | EXTENSION_MAPPING = 324 | 325 | # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments 326 | # according to the Markdown format, which allows for more readable 327 | # documentation. See https://daringfireball.net/projects/markdown/ for details. 328 | # The output of markdown processing is further processed by doxygen, so you can 329 | # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in 330 | # case of backward compatibilities issues. 331 | # The default value is: YES. 332 | 333 | MARKDOWN_SUPPORT = YES 334 | 335 | # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up 336 | # to that level are automatically included in the table of contents, even if 337 | # they do not have an id attribute. 338 | # Note: This feature currently applies only to Markdown headings. 339 | # Minimum value: 0, maximum value: 99, default value: 5. 340 | # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. 341 | 342 | TOC_INCLUDE_HEADINGS = 0 343 | 344 | # When enabled doxygen tries to link words that correspond to documented 345 | # classes, or namespaces to their corresponding documentation. Such a link can 346 | # be prevented in individual cases by putting a % sign in front of the word or 347 | # globally by setting AUTOLINK_SUPPORT to NO. 348 | # The default value is: YES. 349 | 350 | AUTOLINK_SUPPORT = YES 351 | 352 | # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 353 | # to include (a tag file for) the STL sources as input, then you should set this 354 | # tag to YES in order to let doxygen match functions declarations and 355 | # definitions whose arguments contain STL classes (e.g. func(std::string); 356 | # versus func(std::string) {}). This also make the inheritance and collaboration 357 | # diagrams that involve STL classes more complete and accurate. 358 | # The default value is: NO. 359 | 360 | BUILTIN_STL_SUPPORT = NO 361 | 362 | # If you use Microsoft's C++/CLI language, you should set this option to YES to 363 | # enable parsing support. 364 | # The default value is: NO. 365 | 366 | CPP_CLI_SUPPORT = NO 367 | 368 | # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: 369 | # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen 370 | # will parse them like normal C++ but will assume all classes use public instead 371 | # of private inheritance when no explicit protection keyword is present. 372 | # The default value is: NO. 373 | 374 | SIP_SUPPORT = NO 375 | 376 | # For Microsoft's IDL there are propget and propput attributes to indicate 377 | # getter and setter methods for a property. Setting this option to YES will make 378 | # doxygen to replace the get and set methods by a property in the documentation. 379 | # This will only work if the methods are indeed getting or setting a simple 380 | # type. If this is not the case, or you want to show the methods anyway, you 381 | # should set this option to NO. 382 | # The default value is: YES. 383 | 384 | IDL_PROPERTY_SUPPORT = YES 385 | 386 | # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 387 | # tag is set to YES then doxygen will reuse the documentation of the first 388 | # member in the group (if any) for the other members of the group. By default 389 | # all members of a group must be documented explicitly. 390 | # The default value is: NO. 391 | 392 | DISTRIBUTE_GROUP_DOC = NO 393 | 394 | # If one adds a struct or class to a group and this option is enabled, then also 395 | # any nested class or struct is added to the same group. By default this option 396 | # is disabled and one has to add nested compounds explicitly via \ingroup. 397 | # The default value is: NO. 398 | 399 | GROUP_NESTED_COMPOUNDS = NO 400 | 401 | # Set the SUBGROUPING tag to YES to allow class member groups of the same type 402 | # (for instance a group of public functions) to be put as a subgroup of that 403 | # type (e.g. under the Public Functions section). Set it to NO to prevent 404 | # subgrouping. Alternatively, this can be done per class using the 405 | # \nosubgrouping command. 406 | # The default value is: YES. 407 | 408 | SUBGROUPING = YES 409 | 410 | # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions 411 | # are shown inside the group in which they are included (e.g. using \ingroup) 412 | # instead of on a separate page (for HTML and Man pages) or section (for LaTeX 413 | # and RTF). 414 | # 415 | # Note that this feature does not work in combination with 416 | # SEPARATE_MEMBER_PAGES. 417 | # The default value is: NO. 418 | 419 | INLINE_GROUPED_CLASSES = NO 420 | 421 | # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions 422 | # with only public data fields or simple typedef fields will be shown inline in 423 | # the documentation of the scope in which they are defined (i.e. file, 424 | # namespace, or group documentation), provided this scope is documented. If set 425 | # to NO, structs, classes, and unions are shown on a separate page (for HTML and 426 | # Man pages) or section (for LaTeX and RTF). 427 | # The default value is: NO. 428 | 429 | INLINE_SIMPLE_STRUCTS = NO 430 | 431 | # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or 432 | # enum is documented as struct, union, or enum with the name of the typedef. So 433 | # typedef struct TypeS {} TypeT, will appear in the documentation as a struct 434 | # with name TypeT. When disabled the typedef will appear as a member of a file, 435 | # namespace, or class. And the struct will be named TypeS. This can typically be 436 | # useful for C code in case the coding convention dictates that all compound 437 | # types are typedef'ed and only the typedef is referenced, never the tag name. 438 | # The default value is: NO. 439 | 440 | TYPEDEF_HIDES_STRUCT = NO 441 | 442 | # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This 443 | # cache is used to resolve symbols given their name and scope. Since this can be 444 | # an expensive process and often the same symbol appears multiple times in the 445 | # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small 446 | # doxygen will become slower. If the cache is too large, memory is wasted. The 447 | # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range 448 | # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 449 | # symbols. At the end of a run doxygen will report the cache usage and suggest 450 | # the optimal cache size from a speed point of view. 451 | # Minimum value: 0, maximum value: 9, default value: 0. 452 | 453 | LOOKUP_CACHE_SIZE = 0 454 | 455 | # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use 456 | # during processing. When set to 0 doxygen will based this on the number of 457 | # cores available in the system. You can set it explicitly to a value larger 458 | # than 0 to get more control over the balance between CPU load and processing 459 | # speed. At this moment only the input processing can be done using multiple 460 | # threads. Since this is still an experimental feature the default is set to 1, 461 | # which effectively disables parallel processing. Please report any issues you 462 | # encounter. Generating dot graphs in parallel is controlled by the 463 | # DOT_NUM_THREADS setting. 464 | # Minimum value: 0, maximum value: 32, default value: 1. 465 | 466 | NUM_PROC_THREADS = 1 467 | 468 | #--------------------------------------------------------------------------- 469 | # Build related configuration options 470 | #--------------------------------------------------------------------------- 471 | 472 | # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in 473 | # documentation are documented, even if no documentation was available. Private 474 | # class members and static file members will be hidden unless the 475 | # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. 476 | # Note: This will also disable the warnings about undocumented members that are 477 | # normally produced when WARNINGS is set to YES. 478 | # The default value is: NO. 479 | 480 | EXTRACT_ALL = YES 481 | 482 | # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will 483 | # be included in the documentation. 484 | # The default value is: NO. 485 | 486 | EXTRACT_PRIVATE = NO 487 | 488 | # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual 489 | # methods of a class will be included in the documentation. 490 | # The default value is: NO. 491 | 492 | EXTRACT_PRIV_VIRTUAL = NO 493 | 494 | # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal 495 | # scope will be included in the documentation. 496 | # The default value is: NO. 497 | 498 | EXTRACT_PACKAGE = NO 499 | 500 | # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be 501 | # included in the documentation. 502 | # The default value is: NO. 503 | 504 | EXTRACT_STATIC = NO 505 | 506 | # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined 507 | # locally in source files will be included in the documentation. If set to NO, 508 | # only classes defined in header files are included. Does not have any effect 509 | # for Java sources. 510 | # The default value is: YES. 511 | 512 | EXTRACT_LOCAL_CLASSES = YES 513 | 514 | # This flag is only useful for Objective-C code. If set to YES, local methods, 515 | # which are defined in the implementation section but not in the interface are 516 | # included in the documentation. If set to NO, only methods in the interface are 517 | # included. 518 | # The default value is: NO. 519 | 520 | EXTRACT_LOCAL_METHODS = NO 521 | 522 | # If this flag is set to YES, the members of anonymous namespaces will be 523 | # extracted and appear in the documentation as a namespace called 524 | # 'anonymous_namespace{file}', where file will be replaced with the base name of 525 | # the file that contains the anonymous namespace. By default anonymous namespace 526 | # are hidden. 527 | # The default value is: NO. 528 | 529 | EXTRACT_ANON_NSPACES = NO 530 | 531 | # If this flag is set to YES, the name of an unnamed parameter in a declaration 532 | # will be determined by the corresponding definition. By default unnamed 533 | # parameters remain unnamed in the output. 534 | # The default value is: YES. 535 | 536 | RESOLVE_UNNAMED_PARAMS = YES 537 | 538 | # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all 539 | # undocumented members inside documented classes or files. If set to NO these 540 | # members will be included in the various overviews, but no documentation 541 | # section is generated. This option has no effect if EXTRACT_ALL is enabled. 542 | # The default value is: NO. 543 | 544 | HIDE_UNDOC_MEMBERS = NO 545 | 546 | # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all 547 | # undocumented classes that are normally visible in the class hierarchy. If set 548 | # to NO, these classes will be included in the various overviews. This option 549 | # has no effect if EXTRACT_ALL is enabled. 550 | # The default value is: NO. 551 | 552 | HIDE_UNDOC_CLASSES = NO 553 | 554 | # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend 555 | # declarations. If set to NO, these declarations will be included in the 556 | # documentation. 557 | # The default value is: NO. 558 | 559 | HIDE_FRIEND_COMPOUNDS = NO 560 | 561 | # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any 562 | # documentation blocks found inside the body of a function. If set to NO, these 563 | # blocks will be appended to the function's detailed documentation block. 564 | # The default value is: NO. 565 | 566 | HIDE_IN_BODY_DOCS = NO 567 | 568 | # The INTERNAL_DOCS tag determines if documentation that is typed after a 569 | # \internal command is included. If the tag is set to NO then the documentation 570 | # will be excluded. Set it to YES to include the internal documentation. 571 | # The default value is: NO. 572 | 573 | INTERNAL_DOCS = NO 574 | 575 | # With the correct setting of option CASE_SENSE_NAMES doxygen will better be 576 | # able to match the capabilities of the underlying filesystem. In case the 577 | # filesystem is case sensitive (i.e. it supports files in the same directory 578 | # whose names only differ in casing), the option must be set to YES to properly 579 | # deal with such files in case they appear in the input. For filesystems that 580 | # are not case sensitive the option should be be set to NO to properly deal with 581 | # output files written for symbols that only differ in casing, such as for two 582 | # classes, one named CLASS and the other named Class, and to also support 583 | # references to files without having to specify the exact matching casing. On 584 | # Windows (including Cygwin) and MacOS, users should typically set this option 585 | # to NO, whereas on Linux or other Unix flavors it should typically be set to 586 | # YES. 587 | # The default value is: system dependent. 588 | 589 | CASE_SENSE_NAMES = NO 590 | 591 | # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with 592 | # their full class and namespace scopes in the documentation. If set to YES, the 593 | # scope will be hidden. 594 | # The default value is: NO. 595 | 596 | HIDE_SCOPE_NAMES = NO 597 | 598 | # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will 599 | # append additional text to a page's title, such as Class Reference. If set to 600 | # YES the compound reference will be hidden. 601 | # The default value is: NO. 602 | 603 | HIDE_COMPOUND_REFERENCE= NO 604 | 605 | # If the SHOW_HEADERFILE tag is set to YES then the documentation for a class 606 | # will show which file needs to be included to use the class. 607 | # The default value is: YES. 608 | 609 | SHOW_HEADERFILE = YES 610 | 611 | # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of 612 | # the files that are included by a file in the documentation of that file. 613 | # The default value is: YES. 614 | 615 | SHOW_INCLUDE_FILES = YES 616 | 617 | # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each 618 | # grouped member an include statement to the documentation, telling the reader 619 | # which file to include in order to use the member. 620 | # The default value is: NO. 621 | 622 | SHOW_GROUPED_MEMB_INC = NO 623 | 624 | # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include 625 | # files with double quotes in the documentation rather than with sharp brackets. 626 | # The default value is: NO. 627 | 628 | FORCE_LOCAL_INCLUDES = NO 629 | 630 | # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the 631 | # documentation for inline members. 632 | # The default value is: YES. 633 | 634 | INLINE_INFO = YES 635 | 636 | # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the 637 | # (detailed) documentation of file and class members alphabetically by member 638 | # name. If set to NO, the members will appear in declaration order. 639 | # The default value is: YES. 640 | 641 | SORT_MEMBER_DOCS = YES 642 | 643 | # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief 644 | # descriptions of file, namespace and class members alphabetically by member 645 | # name. If set to NO, the members will appear in declaration order. Note that 646 | # this will also influence the order of the classes in the class list. 647 | # The default value is: NO. 648 | 649 | SORT_BRIEF_DOCS = NO 650 | 651 | # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the 652 | # (brief and detailed) documentation of class members so that constructors and 653 | # destructors are listed first. If set to NO the constructors will appear in the 654 | # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. 655 | # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief 656 | # member documentation. 657 | # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting 658 | # detailed member documentation. 659 | # The default value is: NO. 660 | 661 | SORT_MEMBERS_CTORS_1ST = NO 662 | 663 | # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy 664 | # of group names into alphabetical order. If set to NO the group names will 665 | # appear in their defined order. 666 | # The default value is: NO. 667 | 668 | SORT_GROUP_NAMES = NO 669 | 670 | # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by 671 | # fully-qualified names, including namespaces. If set to NO, the class list will 672 | # be sorted only by class name, not including the namespace part. 673 | # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 674 | # Note: This option applies only to the class list, not to the alphabetical 675 | # list. 676 | # The default value is: NO. 677 | 678 | SORT_BY_SCOPE_NAME = NO 679 | 680 | # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper 681 | # type resolution of all parameters of a function it will reject a match between 682 | # the prototype and the implementation of a member function even if there is 683 | # only one candidate or it is obvious which candidate to choose by doing a 684 | # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still 685 | # accept a match between prototype and implementation in such cases. 686 | # The default value is: NO. 687 | 688 | STRICT_PROTO_MATCHING = NO 689 | 690 | # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo 691 | # list. This list is created by putting \todo commands in the documentation. 692 | # The default value is: YES. 693 | 694 | GENERATE_TODOLIST = YES 695 | 696 | # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test 697 | # list. This list is created by putting \test commands in the documentation. 698 | # The default value is: YES. 699 | 700 | GENERATE_TESTLIST = YES 701 | 702 | # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug 703 | # list. This list is created by putting \bug commands in the documentation. 704 | # The default value is: YES. 705 | 706 | GENERATE_BUGLIST = YES 707 | 708 | # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) 709 | # the deprecated list. This list is created by putting \deprecated commands in 710 | # the documentation. 711 | # The default value is: YES. 712 | 713 | GENERATE_DEPRECATEDLIST= YES 714 | 715 | # The ENABLED_SECTIONS tag can be used to enable conditional documentation 716 | # sections, marked by \if ... \endif and \cond 717 | # ... \endcond blocks. 718 | 719 | ENABLED_SECTIONS = 720 | 721 | # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the 722 | # initial value of a variable or macro / define can have for it to appear in the 723 | # documentation. If the initializer consists of more lines than specified here 724 | # it will be hidden. Use a value of 0 to hide initializers completely. The 725 | # appearance of the value of individual variables and macros / defines can be 726 | # controlled using \showinitializer or \hideinitializer command in the 727 | # documentation regardless of this setting. 728 | # Minimum value: 0, maximum value: 10000, default value: 30. 729 | 730 | MAX_INITIALIZER_LINES = 30 731 | 732 | # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at 733 | # the bottom of the documentation of classes and structs. If set to YES, the 734 | # list will mention the files that were used to generate the documentation. 735 | # The default value is: YES. 736 | 737 | SHOW_USED_FILES = YES 738 | 739 | # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This 740 | # will remove the Files entry from the Quick Index and from the Folder Tree View 741 | # (if specified). 742 | # The default value is: YES. 743 | 744 | SHOW_FILES = YES 745 | 746 | # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces 747 | # page. This will remove the Namespaces entry from the Quick Index and from the 748 | # Folder Tree View (if specified). 749 | # The default value is: YES. 750 | 751 | SHOW_NAMESPACES = YES 752 | 753 | # The FILE_VERSION_FILTER tag can be used to specify a program or script that 754 | # doxygen should invoke to get the current version for each file (typically from 755 | # the version control system). Doxygen will invoke the program by executing (via 756 | # popen()) the command command input-file, where command is the value of the 757 | # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided 758 | # by doxygen. Whatever the program writes to standard output is used as the file 759 | # version. For an example see the documentation. 760 | 761 | FILE_VERSION_FILTER = 762 | 763 | # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 764 | # by doxygen. The layout file controls the global structure of the generated 765 | # output files in an output format independent way. To create the layout file 766 | # that represents doxygen's defaults, run doxygen with the -l option. You can 767 | # optionally specify a file name after the option, if omitted DoxygenLayout.xml 768 | # will be used as the name of the layout file. See also section "Changing the 769 | # layout of pages" for information. 770 | # 771 | # Note that if you run doxygen from a directory containing a file called 772 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE 773 | # tag is left empty. 774 | 775 | LAYOUT_FILE = 776 | 777 | # The CITE_BIB_FILES tag can be used to specify one or more bib files containing 778 | # the reference definitions. This must be a list of .bib files. The .bib 779 | # extension is automatically appended if omitted. This requires the bibtex tool 780 | # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. 781 | # For LaTeX the style of the bibliography can be controlled using 782 | # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the 783 | # search path. See also \cite for info how to create references. 784 | 785 | CITE_BIB_FILES = 786 | 787 | #--------------------------------------------------------------------------- 788 | # Configuration options related to warning and progress messages 789 | #--------------------------------------------------------------------------- 790 | 791 | # The QUIET tag can be used to turn on/off the messages that are generated to 792 | # standard output by doxygen. If QUIET is set to YES this implies that the 793 | # messages are off. 794 | # The default value is: NO. 795 | 796 | QUIET = NO 797 | 798 | # The WARNINGS tag can be used to turn on/off the warning messages that are 799 | # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES 800 | # this implies that the warnings are on. 801 | # 802 | # Tip: Turn warnings on while writing the documentation. 803 | # The default value is: YES. 804 | 805 | WARNINGS = YES 806 | 807 | # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate 808 | # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag 809 | # will automatically be disabled. 810 | # The default value is: YES. 811 | 812 | WARN_IF_UNDOCUMENTED = YES 813 | 814 | # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for 815 | # potential errors in the documentation, such as documenting some parameters in 816 | # a documented function twice, or documenting parameters that don't exist or 817 | # using markup commands wrongly. 818 | # The default value is: YES. 819 | 820 | WARN_IF_DOC_ERROR = YES 821 | 822 | # If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete 823 | # function parameter documentation. If set to NO, doxygen will accept that some 824 | # parameters have no documentation without warning. 825 | # The default value is: YES. 826 | 827 | WARN_IF_INCOMPLETE_DOC = YES 828 | 829 | # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that 830 | # are documented, but have no documentation for their parameters or return 831 | # value. If set to NO, doxygen will only warn about wrong parameter 832 | # documentation, but not about the absence of documentation. If EXTRACT_ALL is 833 | # set to YES then this flag will automatically be disabled. See also 834 | # WARN_IF_INCOMPLETE_DOC 835 | # The default value is: NO. 836 | 837 | WARN_NO_PARAMDOC = NO 838 | 839 | # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when 840 | # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS 841 | # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but 842 | # at the end of the doxygen process doxygen will return with a non-zero status. 843 | # Possible values are: NO, YES and FAIL_ON_WARNINGS. 844 | # The default value is: NO. 845 | 846 | WARN_AS_ERROR = NO 847 | 848 | # The WARN_FORMAT tag determines the format of the warning messages that doxygen 849 | # can produce. The string should contain the $file, $line, and $text tags, which 850 | # will be replaced by the file and line number from which the warning originated 851 | # and the warning text. Optionally the format may contain $version, which will 852 | # be replaced by the version of the file (if it could be obtained via 853 | # FILE_VERSION_FILTER) 854 | # The default value is: $file:$line: $text. 855 | 856 | WARN_FORMAT = "$file:$line: $text" 857 | 858 | # The WARN_LOGFILE tag can be used to specify a file to which warning and error 859 | # messages should be written. If left blank the output is written to standard 860 | # error (stderr). 861 | 862 | WARN_LOGFILE = 863 | 864 | #--------------------------------------------------------------------------- 865 | # Configuration options related to the input files 866 | #--------------------------------------------------------------------------- 867 | 868 | # The INPUT tag is used to specify the files and/or directories that contain 869 | # documented source files. You may enter file names like myfile.cpp or 870 | # directories like /usr/src/myproject. Separate the files or directories with 871 | # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING 872 | # Note: If this tag is empty the current directory is searched. 873 | 874 | INPUT = ./README.md \ 875 | paramkit 876 | 877 | # This tag can be used to specify the character encoding of the source files 878 | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses 879 | # libiconv (or the iconv built into libc) for the transcoding. See the libiconv 880 | # documentation (see: 881 | # https://www.gnu.org/software/libiconv/) for the list of possible encodings. 882 | # The default value is: UTF-8. 883 | 884 | INPUT_ENCODING = UTF-8 885 | 886 | # If the value of the INPUT tag contains directories, you can use the 887 | # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and 888 | # *.h) to filter out the source-files in the directories. 889 | # 890 | # Note that for custom extensions or not directly supported extensions you also 891 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not 892 | # read by doxygen. 893 | # 894 | # Note the list of default checked file patterns might differ from the list of 895 | # default file extension mappings. 896 | # 897 | # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, 898 | # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, 899 | # *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, 900 | # *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C 901 | # comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, 902 | # *.vhdl, *.ucf, *.qsf and *.ice. 903 | 904 | FILE_PATTERNS = *.c \ 905 | *.cc \ 906 | *.cxx \ 907 | *.cpp \ 908 | *.c++ \ 909 | *.java \ 910 | *.ii \ 911 | *.ixx \ 912 | *.ipp \ 913 | *.i++ \ 914 | *.inl \ 915 | *.idl \ 916 | *.ddl \ 917 | *.odl \ 918 | *.h \ 919 | *.hh \ 920 | *.hxx \ 921 | *.hpp \ 922 | *.h++ \ 923 | *.cs \ 924 | *.d \ 925 | *.php \ 926 | *.php4 \ 927 | *.php5 \ 928 | *.phtml \ 929 | *.inc \ 930 | *.m \ 931 | *.markdown \ 932 | *.md \ 933 | *.mm \ 934 | *.dox \ 935 | *.py \ 936 | *.pyw \ 937 | *.f90 \ 938 | *.f95 \ 939 | *.f03 \ 940 | *.f08 \ 941 | *.f \ 942 | *.for \ 943 | *.tcl \ 944 | *.vhd \ 945 | *.vhdl \ 946 | *.ucf \ 947 | *.qsf \ 948 | *.ice 949 | 950 | # The RECURSIVE tag can be used to specify whether or not subdirectories should 951 | # be searched for input files as well. 952 | # The default value is: NO. 953 | 954 | RECURSIVE = YES 955 | 956 | # The EXCLUDE tag can be used to specify files and/or directories that should be 957 | # excluded from the INPUT source files. This way you can easily exclude a 958 | # subdirectory from a directory tree whose root is specified with the INPUT tag. 959 | # 960 | # Note that relative paths are relative to the directory from which doxygen is 961 | # run. 962 | 963 | EXCLUDE = 964 | 965 | # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 966 | # directories that are symbolic links (a Unix file system feature) are excluded 967 | # from the input. 968 | # The default value is: NO. 969 | 970 | EXCLUDE_SYMLINKS = NO 971 | 972 | # If the value of the INPUT tag contains directories, you can use the 973 | # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 974 | # certain files from those directories. 975 | # 976 | # Note that the wildcards are matched against the file with absolute path, so to 977 | # exclude all test directories for example use the pattern */test/* 978 | 979 | EXCLUDE_PATTERNS = 980 | 981 | # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 982 | # (namespaces, classes, functions, etc.) that should be excluded from the 983 | # output. The symbol name can be a fully qualified name, a word, or if the 984 | # wildcard * is used, a substring. Examples: ANamespace, AClass, 985 | # AClass::ANamespace, ANamespace::*Test 986 | # 987 | # Note that the wildcards are matched against the file with absolute path, so to 988 | # exclude all test directories use the pattern */test/* 989 | 990 | EXCLUDE_SYMBOLS = 991 | 992 | # The EXAMPLE_PATH tag can be used to specify one or more files or directories 993 | # that contain example code fragments that are included (see the \include 994 | # command). 995 | 996 | EXAMPLE_PATH = ./demo 997 | 998 | # If the value of the EXAMPLE_PATH tag contains directories, you can use the 999 | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and 1000 | # *.h) to filter out the source-files in the directories. If left blank all 1001 | # files are included. 1002 | 1003 | EXAMPLE_PATTERNS = * 1004 | 1005 | # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 1006 | # searched for input files to be used with the \include or \dontinclude commands 1007 | # irrespective of the value of the RECURSIVE tag. 1008 | # The default value is: NO. 1009 | 1010 | EXAMPLE_RECURSIVE = NO 1011 | 1012 | # The IMAGE_PATH tag can be used to specify one or more files or directories 1013 | # that contain images that are to be included in the documentation (see the 1014 | # \image command). 1015 | 1016 | IMAGE_PATH = 1017 | 1018 | # The INPUT_FILTER tag can be used to specify a program that doxygen should 1019 | # invoke to filter for each input file. Doxygen will invoke the filter program 1020 | # by executing (via popen()) the command: 1021 | # 1022 | # 1023 | # 1024 | # where is the value of the INPUT_FILTER tag, and is the 1025 | # name of an input file. Doxygen will then use the output that the filter 1026 | # program writes to standard output. If FILTER_PATTERNS is specified, this tag 1027 | # will be ignored. 1028 | # 1029 | # Note that the filter must not add or remove lines; it is applied before the 1030 | # code is scanned, but not when the output code is generated. If lines are added 1031 | # or removed, the anchors will not be placed correctly. 1032 | # 1033 | # Note that for custom extensions or not directly supported extensions you also 1034 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not 1035 | # properly processed by doxygen. 1036 | 1037 | INPUT_FILTER = 1038 | 1039 | # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 1040 | # basis. Doxygen will compare the file name with each pattern and apply the 1041 | # filter if there is a match. The filters are a list of the form: pattern=filter 1042 | # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how 1043 | # filters are used. If the FILTER_PATTERNS tag is empty or if none of the 1044 | # patterns match the file name, INPUT_FILTER is applied. 1045 | # 1046 | # Note that for custom extensions or not directly supported extensions you also 1047 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not 1048 | # properly processed by doxygen. 1049 | 1050 | FILTER_PATTERNS = 1051 | 1052 | # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 1053 | # INPUT_FILTER) will also be used to filter the input files that are used for 1054 | # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). 1055 | # The default value is: NO. 1056 | 1057 | FILTER_SOURCE_FILES = NO 1058 | 1059 | # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 1060 | # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and 1061 | # it is also possible to disable source filtering for a specific pattern using 1062 | # *.ext= (so without naming a filter). 1063 | # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. 1064 | 1065 | FILTER_SOURCE_PATTERNS = 1066 | 1067 | # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that 1068 | # is part of the input, its contents will be placed on the main page 1069 | # (index.html). This can be useful if you have a project on for instance GitHub 1070 | # and want to reuse the introduction page also for the doxygen output. 1071 | 1072 | USE_MDFILE_AS_MAINPAGE = README.md 1073 | 1074 | #--------------------------------------------------------------------------- 1075 | # Configuration options related to source browsing 1076 | #--------------------------------------------------------------------------- 1077 | 1078 | # If the SOURCE_BROWSER tag is set to YES then a list of source files will be 1079 | # generated. Documented entities will be cross-referenced with these sources. 1080 | # 1081 | # Note: To get rid of all source code in the generated output, make sure that 1082 | # also VERBATIM_HEADERS is set to NO. 1083 | # The default value is: NO. 1084 | 1085 | SOURCE_BROWSER = YES 1086 | 1087 | # Setting the INLINE_SOURCES tag to YES will include the body of functions, 1088 | # classes and enums directly into the documentation. 1089 | # The default value is: NO. 1090 | 1091 | INLINE_SOURCES = NO 1092 | 1093 | # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any 1094 | # special comment blocks from generated source code fragments. Normal C, C++ and 1095 | # Fortran comments will always remain visible. 1096 | # The default value is: YES. 1097 | 1098 | STRIP_CODE_COMMENTS = YES 1099 | 1100 | # If the REFERENCED_BY_RELATION tag is set to YES then for each documented 1101 | # entity all documented functions referencing it will be listed. 1102 | # The default value is: NO. 1103 | 1104 | REFERENCED_BY_RELATION = NO 1105 | 1106 | # If the REFERENCES_RELATION tag is set to YES then for each documented function 1107 | # all documented entities called/used by that function will be listed. 1108 | # The default value is: NO. 1109 | 1110 | REFERENCES_RELATION = NO 1111 | 1112 | # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set 1113 | # to YES then the hyperlinks from functions in REFERENCES_RELATION and 1114 | # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will 1115 | # link to the documentation. 1116 | # The default value is: YES. 1117 | 1118 | REFERENCES_LINK_SOURCE = YES 1119 | 1120 | # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the 1121 | # source code will show a tooltip with additional information such as prototype, 1122 | # brief description and links to the definition and documentation. Since this 1123 | # will make the HTML file larger and loading of large files a bit slower, you 1124 | # can opt to disable this feature. 1125 | # The default value is: YES. 1126 | # This tag requires that the tag SOURCE_BROWSER is set to YES. 1127 | 1128 | SOURCE_TOOLTIPS = YES 1129 | 1130 | # If the USE_HTAGS tag is set to YES then the references to source code will 1131 | # point to the HTML generated by the htags(1) tool instead of doxygen built-in 1132 | # source browser. The htags tool is part of GNU's global source tagging system 1133 | # (see https://www.gnu.org/software/global/global.html). You will need version 1134 | # 4.8.6 or higher. 1135 | # 1136 | # To use it do the following: 1137 | # - Install the latest version of global 1138 | # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file 1139 | # - Make sure the INPUT points to the root of the source tree 1140 | # - Run doxygen as normal 1141 | # 1142 | # Doxygen will invoke htags (and that will in turn invoke gtags), so these 1143 | # tools must be available from the command line (i.e. in the search path). 1144 | # 1145 | # The result: instead of the source browser generated by doxygen, the links to 1146 | # source code will now point to the output of htags. 1147 | # The default value is: NO. 1148 | # This tag requires that the tag SOURCE_BROWSER is set to YES. 1149 | 1150 | USE_HTAGS = NO 1151 | 1152 | # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a 1153 | # verbatim copy of the header file for each class for which an include is 1154 | # specified. Set to NO to disable this. 1155 | # See also: Section \class. 1156 | # The default value is: YES. 1157 | 1158 | VERBATIM_HEADERS = YES 1159 | 1160 | # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the 1161 | # clang parser (see: 1162 | # http://clang.llvm.org/) for more accurate parsing at the cost of reduced 1163 | # performance. This can be particularly helpful with template rich C++ code for 1164 | # which doxygen's built-in parser lacks the necessary type information. 1165 | # Note: The availability of this option depends on whether or not doxygen was 1166 | # generated with the -Duse_libclang=ON option for CMake. 1167 | # The default value is: NO. 1168 | 1169 | CLANG_ASSISTED_PARSING = NO 1170 | 1171 | # If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS 1172 | # tag is set to YES then doxygen will add the directory of each input to the 1173 | # include path. 1174 | # The default value is: YES. 1175 | # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. 1176 | 1177 | CLANG_ADD_INC_PATHS = YES 1178 | 1179 | # If clang assisted parsing is enabled you can provide the compiler with command 1180 | # line options that you would normally use when invoking the compiler. Note that 1181 | # the include paths will already be set by doxygen for the files and directories 1182 | # specified with INPUT and INCLUDE_PATH. 1183 | # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. 1184 | 1185 | CLANG_OPTIONS = 1186 | 1187 | # If clang assisted parsing is enabled you can provide the clang parser with the 1188 | # path to the directory containing a file called compile_commands.json. This 1189 | # file is the compilation database (see: 1190 | # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the 1191 | # options used when the source files were built. This is equivalent to 1192 | # specifying the -p option to a clang tool, such as clang-check. These options 1193 | # will then be passed to the parser. Any options specified with CLANG_OPTIONS 1194 | # will be added as well. 1195 | # Note: The availability of this option depends on whether or not doxygen was 1196 | # generated with the -Duse_libclang=ON option for CMake. 1197 | 1198 | CLANG_DATABASE_PATH = 1199 | 1200 | #--------------------------------------------------------------------------- 1201 | # Configuration options related to the alphabetical class index 1202 | #--------------------------------------------------------------------------- 1203 | 1204 | # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all 1205 | # compounds will be generated. Enable this if the project contains a lot of 1206 | # classes, structs, unions or interfaces. 1207 | # The default value is: YES. 1208 | 1209 | ALPHABETICAL_INDEX = YES 1210 | 1211 | # In case all classes in a project start with a common prefix, all classes will 1212 | # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag 1213 | # can be used to specify a prefix (or a list of prefixes) that should be ignored 1214 | # while generating the index headers. 1215 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. 1216 | 1217 | IGNORE_PREFIX = 1218 | 1219 | #--------------------------------------------------------------------------- 1220 | # Configuration options related to the HTML output 1221 | #--------------------------------------------------------------------------- 1222 | 1223 | # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output 1224 | # The default value is: YES. 1225 | 1226 | GENERATE_HTML = YES 1227 | 1228 | # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a 1229 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of 1230 | # it. 1231 | # The default directory is: html. 1232 | # This tag requires that the tag GENERATE_HTML is set to YES. 1233 | 1234 | HTML_OUTPUT = html 1235 | 1236 | # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each 1237 | # generated HTML page (for example: .htm, .php, .asp). 1238 | # The default value is: .html. 1239 | # This tag requires that the tag GENERATE_HTML is set to YES. 1240 | 1241 | HTML_FILE_EXTENSION = .html 1242 | 1243 | # The HTML_HEADER tag can be used to specify a user-defined HTML header file for 1244 | # each generated HTML page. If the tag is left blank doxygen will generate a 1245 | # standard header. 1246 | # 1247 | # To get valid HTML the header file that includes any scripts and style sheets 1248 | # that doxygen needs, which is dependent on the configuration options used (e.g. 1249 | # the setting GENERATE_TREEVIEW). It is highly recommended to start with a 1250 | # default header using 1251 | # doxygen -w html new_header.html new_footer.html new_stylesheet.css 1252 | # YourConfigFile 1253 | # and then modify the file new_header.html. See also section "Doxygen usage" 1254 | # for information on how to generate the default header that doxygen normally 1255 | # uses. 1256 | # Note: The header is subject to change so you typically have to regenerate the 1257 | # default header when upgrading to a newer version of doxygen. For a description 1258 | # of the possible markers and block names see the documentation. 1259 | # This tag requires that the tag GENERATE_HTML is set to YES. 1260 | 1261 | HTML_HEADER = 1262 | 1263 | # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each 1264 | # generated HTML page. If the tag is left blank doxygen will generate a standard 1265 | # footer. See HTML_HEADER for more information on how to generate a default 1266 | # footer and what special commands can be used inside the footer. See also 1267 | # section "Doxygen usage" for information on how to generate the default footer 1268 | # that doxygen normally uses. 1269 | # This tag requires that the tag GENERATE_HTML is set to YES. 1270 | 1271 | HTML_FOOTER = 1272 | 1273 | # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style 1274 | # sheet that is used by each HTML page. It can be used to fine-tune the look of 1275 | # the HTML output. If left blank doxygen will generate a default style sheet. 1276 | # See also section "Doxygen usage" for information on how to generate the style 1277 | # sheet that doxygen normally uses. 1278 | # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as 1279 | # it is more robust and this tag (HTML_STYLESHEET) will in the future become 1280 | # obsolete. 1281 | # This tag requires that the tag GENERATE_HTML is set to YES. 1282 | 1283 | HTML_STYLESHEET = 1284 | 1285 | # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined 1286 | # cascading style sheets that are included after the standard style sheets 1287 | # created by doxygen. Using this option one can overrule certain style aspects. 1288 | # This is preferred over using HTML_STYLESHEET since it does not replace the 1289 | # standard style sheet and is therefore more robust against future updates. 1290 | # Doxygen will copy the style sheet files to the output directory. 1291 | # Note: The order of the extra style sheet files is of importance (e.g. the last 1292 | # style sheet in the list overrules the setting of the previous ones in the 1293 | # list). For an example see the documentation. 1294 | # This tag requires that the tag GENERATE_HTML is set to YES. 1295 | 1296 | HTML_EXTRA_STYLESHEET = 1297 | 1298 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 1299 | # other source files which should be copied to the HTML output directory. Note 1300 | # that these files will be copied to the base HTML output directory. Use the 1301 | # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these 1302 | # files. In the HTML_STYLESHEET file, use the file name only. Also note that the 1303 | # files will be copied as-is; there are no commands or markers available. 1304 | # This tag requires that the tag GENERATE_HTML is set to YES. 1305 | 1306 | HTML_EXTRA_FILES = 1307 | 1308 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen 1309 | # will adjust the colors in the style sheet and background images according to 1310 | # this color. Hue is specified as an angle on a color-wheel, see 1311 | # https://en.wikipedia.org/wiki/Hue for more information. For instance the value 1312 | # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 1313 | # purple, and 360 is red again. 1314 | # Minimum value: 0, maximum value: 359, default value: 220. 1315 | # This tag requires that the tag GENERATE_HTML is set to YES. 1316 | 1317 | HTML_COLORSTYLE_HUE = 220 1318 | 1319 | # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors 1320 | # in the HTML output. For a value of 0 the output will use gray-scales only. A 1321 | # value of 255 will produce the most vivid colors. 1322 | # Minimum value: 0, maximum value: 255, default value: 100. 1323 | # This tag requires that the tag GENERATE_HTML is set to YES. 1324 | 1325 | HTML_COLORSTYLE_SAT = 100 1326 | 1327 | # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the 1328 | # luminance component of the colors in the HTML output. Values below 100 1329 | # gradually make the output lighter, whereas values above 100 make the output 1330 | # darker. The value divided by 100 is the actual gamma applied, so 80 represents 1331 | # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not 1332 | # change the gamma. 1333 | # Minimum value: 40, maximum value: 240, default value: 80. 1334 | # This tag requires that the tag GENERATE_HTML is set to YES. 1335 | 1336 | HTML_COLORSTYLE_GAMMA = 80 1337 | 1338 | # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 1339 | # page will contain the date and time when the page was generated. Setting this 1340 | # to YES can help to show when doxygen was last run and thus if the 1341 | # documentation is up to date. 1342 | # The default value is: NO. 1343 | # This tag requires that the tag GENERATE_HTML is set to YES. 1344 | 1345 | HTML_TIMESTAMP = NO 1346 | 1347 | # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML 1348 | # documentation will contain a main index with vertical navigation menus that 1349 | # are dynamically created via JavaScript. If disabled, the navigation index will 1350 | # consists of multiple levels of tabs that are statically embedded in every HTML 1351 | # page. Disable this option to support browsers that do not have JavaScript, 1352 | # like the Qt help browser. 1353 | # The default value is: YES. 1354 | # This tag requires that the tag GENERATE_HTML is set to YES. 1355 | 1356 | HTML_DYNAMIC_MENUS = YES 1357 | 1358 | # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 1359 | # documentation will contain sections that can be hidden and shown after the 1360 | # page has loaded. 1361 | # The default value is: NO. 1362 | # This tag requires that the tag GENERATE_HTML is set to YES. 1363 | 1364 | HTML_DYNAMIC_SECTIONS = NO 1365 | 1366 | # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries 1367 | # shown in the various tree structured indices initially; the user can expand 1368 | # and collapse entries dynamically later on. Doxygen will expand the tree to 1369 | # such a level that at most the specified number of entries are visible (unless 1370 | # a fully collapsed tree already exceeds this amount). So setting the number of 1371 | # entries 1 will produce a full collapsed tree by default. 0 is a special value 1372 | # representing an infinite number of entries and will result in a full expanded 1373 | # tree by default. 1374 | # Minimum value: 0, maximum value: 9999, default value: 100. 1375 | # This tag requires that the tag GENERATE_HTML is set to YES. 1376 | 1377 | HTML_INDEX_NUM_ENTRIES = 100 1378 | 1379 | # If the GENERATE_DOCSET tag is set to YES, additional index files will be 1380 | # generated that can be used as input for Apple's Xcode 3 integrated development 1381 | # environment (see: 1382 | # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To 1383 | # create a documentation set, doxygen will generate a Makefile in the HTML 1384 | # output directory. Running make will produce the docset in that directory and 1385 | # running make install will install the docset in 1386 | # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at 1387 | # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy 1388 | # genXcode/_index.html for more information. 1389 | # The default value is: NO. 1390 | # This tag requires that the tag GENERATE_HTML is set to YES. 1391 | 1392 | GENERATE_DOCSET = NO 1393 | 1394 | # This tag determines the name of the docset feed. A documentation feed provides 1395 | # an umbrella under which multiple documentation sets from a single provider 1396 | # (such as a company or product suite) can be grouped. 1397 | # The default value is: Doxygen generated docs. 1398 | # This tag requires that the tag GENERATE_DOCSET is set to YES. 1399 | 1400 | DOCSET_FEEDNAME = "Doxygen generated docs" 1401 | 1402 | # This tag specifies a string that should uniquely identify the documentation 1403 | # set bundle. This should be a reverse domain-name style string, e.g. 1404 | # com.mycompany.MyDocSet. Doxygen will append .docset to the name. 1405 | # The default value is: org.doxygen.Project. 1406 | # This tag requires that the tag GENERATE_DOCSET is set to YES. 1407 | 1408 | DOCSET_BUNDLE_ID = org.doxygen.Project 1409 | 1410 | # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify 1411 | # the documentation publisher. This should be a reverse domain-name style 1412 | # string, e.g. com.mycompany.MyDocSet.documentation. 1413 | # The default value is: org.doxygen.Publisher. 1414 | # This tag requires that the tag GENERATE_DOCSET is set to YES. 1415 | 1416 | DOCSET_PUBLISHER_ID = org.doxygen.Publisher 1417 | 1418 | # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. 1419 | # The default value is: Publisher. 1420 | # This tag requires that the tag GENERATE_DOCSET is set to YES. 1421 | 1422 | DOCSET_PUBLISHER_NAME = Publisher 1423 | 1424 | # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three 1425 | # additional HTML index files: index.hhp, index.hhc, and index.hhk. The 1426 | # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop 1427 | # on Windows. In the beginning of 2021 Microsoft took the original page, with 1428 | # a.o. the download links, offline the HTML help workshop was already many years 1429 | # in maintenance mode). You can download the HTML help workshop from the web 1430 | # archives at Installation executable (see: 1431 | # http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo 1432 | # ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). 1433 | # 1434 | # The HTML Help Workshop contains a compiler that can convert all HTML output 1435 | # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML 1436 | # files are now used as the Windows 98 help format, and will replace the old 1437 | # Windows help format (.hlp) on all Windows platforms in the future. Compressed 1438 | # HTML files also contain an index, a table of contents, and you can search for 1439 | # words in the documentation. The HTML workshop also contains a viewer for 1440 | # compressed HTML files. 1441 | # The default value is: NO. 1442 | # This tag requires that the tag GENERATE_HTML is set to YES. 1443 | 1444 | GENERATE_HTMLHELP = NO 1445 | 1446 | # The CHM_FILE tag can be used to specify the file name of the resulting .chm 1447 | # file. You can add a path in front of the file if the result should not be 1448 | # written to the html output directory. 1449 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1450 | 1451 | CHM_FILE = 1452 | 1453 | # The HHC_LOCATION tag can be used to specify the location (absolute path 1454 | # including file name) of the HTML help compiler (hhc.exe). If non-empty, 1455 | # doxygen will try to run the HTML help compiler on the generated index.hhp. 1456 | # The file has to be specified with full path. 1457 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1458 | 1459 | HHC_LOCATION = 1460 | 1461 | # The GENERATE_CHI flag controls if a separate .chi index file is generated 1462 | # (YES) or that it should be included in the main .chm file (NO). 1463 | # The default value is: NO. 1464 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1465 | 1466 | GENERATE_CHI = NO 1467 | 1468 | # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) 1469 | # and project file content. 1470 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1471 | 1472 | CHM_INDEX_ENCODING = 1473 | 1474 | # The BINARY_TOC flag controls whether a binary table of contents is generated 1475 | # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it 1476 | # enables the Previous and Next buttons. 1477 | # The default value is: NO. 1478 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1479 | 1480 | BINARY_TOC = NO 1481 | 1482 | # The TOC_EXPAND flag can be set to YES to add extra items for group members to 1483 | # the table of contents of the HTML help documentation and to the tree view. 1484 | # The default value is: NO. 1485 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. 1486 | 1487 | TOC_EXPAND = NO 1488 | 1489 | # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 1490 | # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that 1491 | # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help 1492 | # (.qch) of the generated HTML documentation. 1493 | # The default value is: NO. 1494 | # This tag requires that the tag GENERATE_HTML is set to YES. 1495 | 1496 | GENERATE_QHP = NO 1497 | 1498 | # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify 1499 | # the file name of the resulting .qch file. The path specified is relative to 1500 | # the HTML output folder. 1501 | # This tag requires that the tag GENERATE_QHP is set to YES. 1502 | 1503 | QCH_FILE = 1504 | 1505 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help 1506 | # Project output. For more information please see Qt Help Project / Namespace 1507 | # (see: 1508 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). 1509 | # The default value is: org.doxygen.Project. 1510 | # This tag requires that the tag GENERATE_QHP is set to YES. 1511 | 1512 | QHP_NAMESPACE = org.doxygen.Project 1513 | 1514 | # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt 1515 | # Help Project output. For more information please see Qt Help Project / Virtual 1516 | # Folders (see: 1517 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). 1518 | # The default value is: doc. 1519 | # This tag requires that the tag GENERATE_QHP is set to YES. 1520 | 1521 | QHP_VIRTUAL_FOLDER = doc 1522 | 1523 | # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom 1524 | # filter to add. For more information please see Qt Help Project / Custom 1525 | # Filters (see: 1526 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). 1527 | # This tag requires that the tag GENERATE_QHP is set to YES. 1528 | 1529 | QHP_CUST_FILTER_NAME = 1530 | 1531 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the 1532 | # custom filter to add. For more information please see Qt Help Project / Custom 1533 | # Filters (see: 1534 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). 1535 | # This tag requires that the tag GENERATE_QHP is set to YES. 1536 | 1537 | QHP_CUST_FILTER_ATTRS = 1538 | 1539 | # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 1540 | # project's filter section matches. Qt Help Project / Filter Attributes (see: 1541 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). 1542 | # This tag requires that the tag GENERATE_QHP is set to YES. 1543 | 1544 | QHP_SECT_FILTER_ATTRS = 1545 | 1546 | # The QHG_LOCATION tag can be used to specify the location (absolute path 1547 | # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to 1548 | # run qhelpgenerator on the generated .qhp file. 1549 | # This tag requires that the tag GENERATE_QHP is set to YES. 1550 | 1551 | QHG_LOCATION = 1552 | 1553 | # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be 1554 | # generated, together with the HTML files, they form an Eclipse help plugin. To 1555 | # install this plugin and make it available under the help contents menu in 1556 | # Eclipse, the contents of the directory containing the HTML and XML files needs 1557 | # to be copied into the plugins directory of eclipse. The name of the directory 1558 | # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. 1559 | # After copying Eclipse needs to be restarted before the help appears. 1560 | # The default value is: NO. 1561 | # This tag requires that the tag GENERATE_HTML is set to YES. 1562 | 1563 | GENERATE_ECLIPSEHELP = NO 1564 | 1565 | # A unique identifier for the Eclipse help plugin. When installing the plugin 1566 | # the directory name containing the HTML and XML files should also have this 1567 | # name. Each documentation set should have its own identifier. 1568 | # The default value is: org.doxygen.Project. 1569 | # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. 1570 | 1571 | ECLIPSE_DOC_ID = org.doxygen.Project 1572 | 1573 | # If you want full control over the layout of the generated HTML pages it might 1574 | # be necessary to disable the index and replace it with your own. The 1575 | # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top 1576 | # of each HTML page. A value of NO enables the index and the value YES disables 1577 | # it. Since the tabs in the index contain the same information as the navigation 1578 | # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. 1579 | # The default value is: NO. 1580 | # This tag requires that the tag GENERATE_HTML is set to YES. 1581 | 1582 | DISABLE_INDEX = NO 1583 | 1584 | # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 1585 | # structure should be generated to display hierarchical information. If the tag 1586 | # value is set to YES, a side panel will be generated containing a tree-like 1587 | # index structure (just like the one that is generated for HTML Help). For this 1588 | # to work a browser that supports JavaScript, DHTML, CSS and frames is required 1589 | # (i.e. any modern browser). Windows users are probably better off using the 1590 | # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can 1591 | # further fine tune the look of the index (see "Fine-tuning the output"). As an 1592 | # example, the default style sheet generated by doxygen has an example that 1593 | # shows how to put an image at the root of the tree instead of the PROJECT_NAME. 1594 | # Since the tree basically has the same information as the tab index, you could 1595 | # consider setting DISABLE_INDEX to YES when enabling this option. 1596 | # The default value is: NO. 1597 | # This tag requires that the tag GENERATE_HTML is set to YES. 1598 | 1599 | GENERATE_TREEVIEW = NO 1600 | 1601 | # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the 1602 | # FULL_SIDEBAR option determines if the side bar is limited to only the treeview 1603 | # area (value NO) or if it should extend to the full height of the window (value 1604 | # YES). Setting this to YES gives a layout similar to 1605 | # https://docs.readthedocs.io with more room for contents, but less room for the 1606 | # project logo, title, and description. If either GENERATOR_TREEVIEW or 1607 | # DISABLE_INDEX is set to NO, this option has no effect. 1608 | # The default value is: NO. 1609 | # This tag requires that the tag GENERATE_HTML is set to YES. 1610 | 1611 | FULL_SIDEBAR = NO 1612 | 1613 | # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that 1614 | # doxygen will group on one line in the generated HTML documentation. 1615 | # 1616 | # Note that a value of 0 will completely suppress the enum values from appearing 1617 | # in the overview section. 1618 | # Minimum value: 0, maximum value: 20, default value: 4. 1619 | # This tag requires that the tag GENERATE_HTML is set to YES. 1620 | 1621 | ENUM_VALUES_PER_LINE = 4 1622 | 1623 | # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used 1624 | # to set the initial width (in pixels) of the frame in which the tree is shown. 1625 | # Minimum value: 0, maximum value: 1500, default value: 250. 1626 | # This tag requires that the tag GENERATE_HTML is set to YES. 1627 | 1628 | TREEVIEW_WIDTH = 250 1629 | 1630 | # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to 1631 | # external symbols imported via tag files in a separate window. 1632 | # The default value is: NO. 1633 | # This tag requires that the tag GENERATE_HTML is set to YES. 1634 | 1635 | EXT_LINKS_IN_WINDOW = NO 1636 | 1637 | # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg 1638 | # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see 1639 | # https://inkscape.org) to generate formulas as SVG images instead of PNGs for 1640 | # the HTML output. These images will generally look nicer at scaled resolutions. 1641 | # Possible values are: png (the default) and svg (looks nicer but requires the 1642 | # pdf2svg or inkscape tool). 1643 | # The default value is: png. 1644 | # This tag requires that the tag GENERATE_HTML is set to YES. 1645 | 1646 | HTML_FORMULA_FORMAT = png 1647 | 1648 | # Use this tag to change the font size of LaTeX formulas included as images in 1649 | # the HTML documentation. When you change the font size after a successful 1650 | # doxygen run you need to manually remove any form_*.png images from the HTML 1651 | # output directory to force them to be regenerated. 1652 | # Minimum value: 8, maximum value: 50, default value: 10. 1653 | # This tag requires that the tag GENERATE_HTML is set to YES. 1654 | 1655 | FORMULA_FONTSIZE = 10 1656 | 1657 | # Use the FORMULA_TRANSPARENT tag to determine whether or not the images 1658 | # generated for formulas are transparent PNGs. Transparent PNGs are not 1659 | # supported properly for IE 6.0, but are supported on all modern browsers. 1660 | # 1661 | # Note that when changing this option you need to delete any form_*.png files in 1662 | # the HTML output directory before the changes have effect. 1663 | # The default value is: YES. 1664 | # This tag requires that the tag GENERATE_HTML is set to YES. 1665 | 1666 | FORMULA_TRANSPARENT = YES 1667 | 1668 | # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands 1669 | # to create new LaTeX commands to be used in formulas as building blocks. See 1670 | # the section "Including formulas" for details. 1671 | 1672 | FORMULA_MACROFILE = 1673 | 1674 | # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see 1675 | # https://www.mathjax.org) which uses client side JavaScript for the rendering 1676 | # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX 1677 | # installed or if you want to formulas look prettier in the HTML output. When 1678 | # enabled you may also need to install MathJax separately and configure the path 1679 | # to it using the MATHJAX_RELPATH option. 1680 | # The default value is: NO. 1681 | # This tag requires that the tag GENERATE_HTML is set to YES. 1682 | 1683 | USE_MATHJAX = NO 1684 | 1685 | # With MATHJAX_VERSION it is possible to specify the MathJax version to be used. 1686 | # Note that the different versions of MathJax have different requirements with 1687 | # regards to the different settings, so it is possible that also other MathJax 1688 | # settings have to be changed when switching between the different MathJax 1689 | # versions. 1690 | # Possible values are: MathJax_2 and MathJax_3. 1691 | # The default value is: MathJax_2. 1692 | # This tag requires that the tag USE_MATHJAX is set to YES. 1693 | 1694 | MATHJAX_VERSION = MathJax_2 1695 | 1696 | # When MathJax is enabled you can set the default output format to be used for 1697 | # the MathJax output. For more details about the output format see MathJax 1698 | # version 2 (see: 1699 | # http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 1700 | # (see: 1701 | # http://docs.mathjax.org/en/latest/web/components/output.html). 1702 | # Possible values are: HTML-CSS (which is slower, but has the best 1703 | # compatibility. This is the name for Mathjax version 2, for MathJax version 3 1704 | # this will be translated into chtml), NativeMML (i.e. MathML. Only supported 1705 | # for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This 1706 | # is the name for Mathjax version 3, for MathJax version 2 this will be 1707 | # translated into HTML-CSS) and SVG. 1708 | # The default value is: HTML-CSS. 1709 | # This tag requires that the tag USE_MATHJAX is set to YES. 1710 | 1711 | MATHJAX_FORMAT = HTML-CSS 1712 | 1713 | # When MathJax is enabled you need to specify the location relative to the HTML 1714 | # output directory using the MATHJAX_RELPATH option. The destination directory 1715 | # should contain the MathJax.js script. For instance, if the mathjax directory 1716 | # is located at the same level as the HTML output directory, then 1717 | # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax 1718 | # Content Delivery Network so you can quickly see the result without installing 1719 | # MathJax. However, it is strongly recommended to install a local copy of 1720 | # MathJax from https://www.mathjax.org before deployment. The default value is: 1721 | # - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 1722 | # - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 1723 | # This tag requires that the tag USE_MATHJAX is set to YES. 1724 | 1725 | MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ 1726 | 1727 | # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax 1728 | # extension names that should be enabled during MathJax rendering. For example 1729 | # for MathJax version 2 (see 1730 | # https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): 1731 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols 1732 | # For example for MathJax version 3 (see 1733 | # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): 1734 | # MATHJAX_EXTENSIONS = ams 1735 | # This tag requires that the tag USE_MATHJAX is set to YES. 1736 | 1737 | MATHJAX_EXTENSIONS = 1738 | 1739 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces 1740 | # of code that will be used on startup of the MathJax code. See the MathJax site 1741 | # (see: 1742 | # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an 1743 | # example see the documentation. 1744 | # This tag requires that the tag USE_MATHJAX is set to YES. 1745 | 1746 | MATHJAX_CODEFILE = 1747 | 1748 | # When the SEARCHENGINE tag is enabled doxygen will generate a search box for 1749 | # the HTML output. The underlying search engine uses javascript and DHTML and 1750 | # should work on any modern browser. Note that when using HTML help 1751 | # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) 1752 | # there is already a search function so this one should typically be disabled. 1753 | # For large projects the javascript based search engine can be slow, then 1754 | # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to 1755 | # search using the keyboard; to jump to the search box use + S 1756 | # (what the is depends on the OS and browser, but it is typically 1757 | # , /